stm32 从机SPI DMA接收,从机一开DMA就进完成中断, 我采用SPI1为主机接到芯片上SPI2从机,进行自测试, 我在主机没有发任何数据情况下, 开启从机SPI2接收DMA, 立即就进入了DMA接收完成中断!收到的数据全是00, 在主机不发送情况, 无论从机单独开发送DMA 还是接收DMA都直接进入完成中断!
int main()
{
u8 data1[6]={17,17,17,17,17,17};
u8 data2[6]={0x00,0xFF,0x01,0x03,0x05,0x09};
RCC_HSE_Config(25,336,2,7); //将pllp=2修改为4,相当于把168M的系统时钟变为84M了
SysTick_Init(168);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断优先级分组 分2组 4个抢占 4个软件
SPI1_DMA_Master_Init();
SPI2_DMA_Master_Init();
while(1)
{
SPI2_DMA_Send(data1 ,6);
// SPI1_DMA_Send(data2 ,6);
delay_ms(1000);
}
/*******************************************************************************
**** 文件功能: SPI通信 DMA收发 初始化
**** 备 注:
*******************************************************************************
*******************************************************************************/
#include "spi.h"
SPI_Init_Parm SPI1_Parm; //SPI1参数
SPI_Init_Parm SPI2_Parm; //SPI2参数
//以下是SPI模块的初始化代码,配置成主机模式
//SPI口初始化
//这里针是对SPI1的初始化
void SPI2_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//使能GPIOB时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);//使能SPI1时钟
GPIO_PinAFConfig(GPIOB,GPIO_PinSource3,GPIO_AF_SPI1); //PB3复用为 SPI1
GPIO_PinAFConfig(GPIOB,GPIO_PinSource4,GPIO_AF_SPI1); //PB4复用为 SPI1
GPIO_PinAFConfig(GPIOB,GPIO_PinSource5,GPIO_AF_SPI1); //PB5复用为 SPI1
//GPIOFB3,4,5初始化设置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;//PB3~5复用功能输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
//这里只针对SPI口初始化
RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1,ENABLE);//复位SPI1
RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1,DISABLE);//停止复位SPI1
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //串行同步时钟的空闲状态为高电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //串行同步时钟的第二个跳变沿(上升或下降)数据被采样
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //定义波特率预分频的值:波特率预分频值为256
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式
SPI_Init(SPI1, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
SPI_Cmd(SPI1, ENABLE); //使能SPI外设
SPI1_ReadWriteByte(0xff);//启动传输
}
void SPI1_DMA_Master_Init(void) //初始化SPI1作为主机口采用DMA收发
{
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
//初始SPI1 Parm
SPI1_Parm.DMA_TxBuff_Len = sizeof(SPI1_Parm.Send_Buff); //SPI发送缓冲区大小
SPI1_Parm.DMA_RxBuff_Len = sizeof(SPI1_Parm.Recv_Buff); //SPI接收缓冲区大小
SPI1_Parm.Flag_Tx_Busy=0; //SPI正在发送
SPI1_Parm.Flag_New_Recv=0; //是否收到新数据
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能GPIOB时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);//使能SPI1时钟
GPIO_PinAFConfig(GPIOA,GPIO_PinSource5,GPIO_AF_SPI1); //引脚复用为 SPI1
GPIO_PinAFConfig(GPIOA,GPIO_PinSource6,GPIO_AF_SPI1); //
GPIO_PinAFConfig(GPIOA,GPIO_PinSource7,GPIO_AF_SPI1); //
//GPIOFA5,6,7初始化设置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;//复用功能输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化
//这里只针对SPI口初始化
RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1,ENABLE);//复位SPI1
RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1,DISABLE);//停止复位SPI1
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //串行同步时钟的空闲状态为高电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //串行同步时钟的第二个跳变沿(上升或下降)数据被采样
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //定义波特率预分频的值:波特率预分频值为256
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式
SPI_Init(SPI1, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
SPI_NSSInternalSoftwareConfig(SPI1,SPI_NSSInternalSoft_Set);
//设置SPI1 接收DMA Stream 流2为接收 通道3
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2时钟使能
DMA_DeInit(DMA2_Stream2);
while (DMA_GetCmdStatus(DMA2_Stream2) != DISABLE){}//等待DMA可配置
DMA_InitStructure.DMA_Channel = DMA_Channel_3; //通道选择
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&SPI1->DR;//DMA外设地址
DMA_InitStructure.DMA_Memory0BaseAddr = (u32)SPI1_Parm.Recv_Buff;//DMA 存储器0地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;//存储器到外设模式
DMA_InitStructure.DMA_BufferSize = SPI1_Parm.DMA_RxBuff_Len;//数据传输量
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非增量模式
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器增量模式, 递增模式就是每传输一个地址加1
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据长度:8位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//存储器数据长度:8位
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;// 使用普通模式 ,循环模式,双缓冲模式
DMA_InitStructure.DMA_Priority = DMA_Priority_High;//优先级
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//存储器突发模式与单次传输模式
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//外设突发模式与单次传输模式
DMA_Init(DMA2_Stream2, &DMA_InitStructure);//初始化DMA Stream
DMA_Cmd(DMA2_Stream2, DISABLE);
//DMA接收中断优先级配置
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
DMA_ITConfig(DMA2_Stream2,DMA_IT_TC | DMA_IT_TE,ENABLE); //开启 DMA接收完成中断
//设置SPI1 发送DMA Stream ,流3为发送 通道3
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2时钟使能
DMA_DeInit(DMA2_Stream3);
while (DMA_GetCmdStatus(DMA2_Stream3) != DISABLE){}//等待DMA可配置
DMA_InitStructure.DMA_Channel = DMA_Channel_3; //通道选择
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&SPI1->DR;//DMA外设地址
DMA_InitStructure.DMA_Memory0BaseAddr = (u32)SPI1_Parm.Send_Buff;//DMA 存储器0地址
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;//存储器到外设模式
DMA_InitStructure.DMA_BufferSize = SPI1_Parm.DMA_TxBuff_Len;//数据传输量
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非增量模式
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器增量模式, 递增模式就是每传输一个地址加1
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据长度:8位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//存储器数据长度:8位
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;// 使用普通模式 ,循环模式,双缓冲模式
DMA_InitStructure.DMA_Priority = DMA_Priority_High;//优先级
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//存储器突发模式与单次传输模式
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//外设突发模式与单次传输模式
DMA_Init(DMA2_Stream3, &DMA_InitStructure);//初始化DMA Stream
DMA_Cmd(DMA2_Stream3, DISABLE);
//DMA发送中断优先级配置
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
DMA_ITConfig(DMA2_Stream3,DMA_IT_TC | DMA_IT_TE,ENABLE); //开启 DMA接收完成中断
//使能相关功能
SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, ENABLE);
SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);
SPI_Cmd(SPI1, ENABLE); //使能SPI外设
DMA_Cmd(DMA2_Stream2, DISABLE); //接收
DMA_Cmd(DMA2_Stream3, DISABLE); //发送
}
/**************************************************************************************************
* 函 数 名: SPI1_DMA_Send
* 函数功能: 开启SPI1收发DMA 按固定字节数收发SPI
* 输 入: *send_data 发送数据指针, send_len发送数量
* 输 出: 无
**************************************************************************************************/
void SPI1_DMA_Send(u8 *send_data ,u16 send_len)
{
while (SPI1_Parm.Flag_Tx_Busy!=0){;}//判断是否正在发送中
SPI1_Parm.Flag_Tx_Busy = 1;
SPI1_Parm.DMA_TxBuff_Len=send_len;
SPI1_Parm.DMA_RxBuff_Len=send_len;
DMA_Cmd(DMA2_Stream2, DISABLE);
DMA_Cmd(DMA2_Stream3, DISABLE);
//关闭DMA传输
while (DMA_GetCmdStatus(DMA2_Stream2) != DISABLE){;} //确保DMA可以被设置
while (DMA_GetCmdStatus(DMA2_Stream3) != DISABLE){;} //确保DMA可以被设置
my_mem_cpy(SPI1_Parm.Send_Buff,send_data,(u32)send_len);
DMA_SetCurrDataCounter(DMA2_Stream2,SPI1_Parm.DMA_RxBuff_Len); //接收数据传输量
DMA_SetCurrDataCounter(DMA2_Stream3,SPI1_Parm.DMA_TxBuff_Len); //发送数据传输量
DMA_Cmd(DMA2_Stream2, ENABLE);
DMA_Cmd(DMA2_Stream3, ENABLE);
}
/**************************************************************************************************
* SPI1 DMA数据流接收完成
*函数功能: DMA 数据流2中断函数
**************************************************************************************************/
void DMA2_Stream2_IRQHandler()
{
if(DMA_GetFlagStatus(DMA2_Stream2,DMA_FLAG_TCIF2)!=0)//SPI1 DMA接收完成中断
{
DMA_ClearFlag(DMA2_Stream2,DMA_FLAG_TCIF2);
while (SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_BSY) != RESET){;}
DMA_Cmd(DMA2_Stream2,DISABLE);
my_mem_cpy(SPI1_Parm.Recv_Data,SPI1_Parm.Recv_Buff,(u32)SPI1_Parm.DMA_RxBuff_Len);
SPI1_Parm.Flag_New_Recv=SPI1_Parm.DMA_RxBuff_Len;
}
if(DMA_GetFlagStatus(DMA2_Stream2,DMA_FLAG_TEIF2)!=0) //出错
{
DMA_ClearFlag(DMA2_Stream2,DMA_FLAG_TEIF2);
DMA_Cmd(DMA2_Stream2,DISABLE);
}
}
/**************************************************************************************************
* SPI1 DMA数据流发送完成
*函数功能: DMA 数据流3中断函数
**************************************************************************************************/
void DMA2_Stream3_IRQHandler()
{
if(DMA_GetFlagStatus(DMA2_Stream3,DMA_FLAG_TCIF3)!=0)//SPI1 DMA发送完成中断
{
DMA_ClearFlag(DMA2_Stream3,DMA_FLAG_TCIF3);
while (SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_BSY) != RESET){;}
DMA_Cmd(DMA2_Stream3,DISABLE);
SPI1_Parm.Flag_Tx_Busy = 0; //清除发送忙标记
}
if(DMA_GetFlagStatus(DMA2_Stream3,DMA_FLAG_TEIF3)!=0) //出错
{
DMA_ClearFlag(DMA2_Stream3,DMA_FLAG_TEIF3); //清除标志位
DMA_Cmd(DMA2_Stream3,DISABLE);
SPI1_Parm.Flag_Tx_Busy = 0;
}
}
void SPI2_DMA_Master_Init(void) //初始化SPI2作为主机口采用DMA收发
{
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
//初始SPI2 Parm
SPI2_Parm.DMA_TxBuff_Len = sizeof(SPI2_Parm.Send_Buff); //SPI发送缓冲区大小
SPI2_Parm.DMA_RxBuff_Len = sizeof(SPI2_Parm.Recv_Buff); //SPI接收缓冲区大小
SPI2_Parm.Flag_Tx_Busy=0; //复位SPI正在发送
SPI2_Parm.Flag_New_Recv=0; //复位是否收到新数据
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//使能GPIOB时钟
RCC_APB2PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);//使能SPI2时钟
GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_SPI2); //引脚复用为 SPI2
GPIO_PinAFConfig(GPIOB,GPIO_PinSource14,GPIO_AF_SPI2); //
GPIO_PinAFConfig(GPIOB,GPIO_PinSource15,GPIO_AF_SPI2); //
//GPIOFA5,6,7初始化设置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;//复用功能输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//这里只针对SPI口初始化
RCC_APB2PeriphResetCmd(RCC_APB1Periph_SPI2,ENABLE);//复位SPI2
RCC_APB2PeriphResetCmd(RCC_APB1Periph_SPI2,DISABLE);
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128; //预分频值为128 APB1为42M APB2为84M
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式
SPI_Init(SPI2, &SPI_InitStructure);
// SPI_NSSInternalSoftwareConfig(SPI2,SPI_NSSInternalSoft_Set);
//设置SPI2 接收DMA Stream 流3为接收 通道0
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);//DMA1时钟使能
DMA_DeInit(DMA1_Stream3);
while (DMA_GetCmdStatus(DMA1_Stream3) != DISABLE){}
DMA_InitStructure.DMA_Channel = DMA_Channel_0;
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&SPI2->DR;
DMA_InitStructure.DMA_Memory0BaseAddr = (u32)SPI2_Parm.Recv_Buff;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = SPI2_Parm.DMA_RxBuff_Len;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;//优先级
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA1_Stream3, &DMA_InitStructure);
DMA_Cmd(DMA1_Stream3, DISABLE);
//DMA接收中断优先级配置
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
DMA_ITConfig(DMA1_Stream3,DMA_IT_TC | DMA_IT_TE,ENABLE); //开启 DMA接收完成中断
//设置SPI2 发送DMA Stream ,流4为发送 通道0
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);//DMA1时钟使能
DMA_DeInit(DMA1_Stream4);
while (DMA_GetCmdStatus(DMA1_Stream4) != DISABLE){}//等待DMA可配置
DMA_InitStructure.DMA_Channel = DMA_Channel_0; //通道选择
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&SPI2->DR;//DMA外设地址
DMA_InitStructure.DMA_Memory0BaseAddr = (u32)SPI2_Parm.Send_Buff;//DMA 存储器0地址
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;//存储器到外设模式
DMA_InitStructure.DMA_BufferSize = SPI2_Parm.DMA_TxBuff_Len;//数据传输量
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非增量模式
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器增量模式, 递增模式就是每传输一个地址加1
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据长度:8位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//存储器数据长度:8位
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;// 使用普通模式 ,循环模式,双缓冲模式
DMA_InitStructure.DMA_Priority = DMA_Priority_High;//优先级
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//存储器突发模式与单次传输模式
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//外设突发模式与单次传输模式
DMA_Init(DMA1_Stream4, &DMA_InitStructure);//初始化串口接收DMA Stream
DMA_Cmd(DMA1_Stream4, DISABLE);
//DMA发送中断优先级配置
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
DMA_ITConfig(DMA1_Stream4,DMA_IT_TC | DMA_IT_TE,ENABLE); //开启 DMA接收完成中断
//使能相关功能
SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, ENABLE);
SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE);
SPI_Cmd(SPI2, ENABLE); //使能SPI外设
DMA_Cmd(DMA1_Stream3, ENABLE); //接收
DMA_Cmd(DMA1_Stream4, DISABLE); //发送
}
/**************************************************************************************************
* 函 数 名: SPI2_DMA_Send
* 函数功能: 开启SPI2收发DMA 按固定字节数收发SPI
* 输 入: *send_data 发送数据指针, send_len发送数量
* 输 出: 无
**************************************************************************************************/
void SPI2_DMA_Send(u8 *send_data ,u16 send_len)
{
// while (SPI2_Parm.Flag_Tx_Busy!=0){;}//判断是否正在发送中
// SPI2_Parm.Flag_Tx_Busy = 1;
SPI2_Parm.DMA_TxBuff_Len=send_len;
SPI2_Parm.DMA_RxBuff_Len=send_len;
DMA_Cmd(DMA1_Stream3, DISABLE);
DMA_Cmd(DMA1_Stream4, DISABLE);
//关闭DMA传输
while (DMA_GetCmdStatus(DMA1_Stream3) != DISABLE){;}
while (DMA_GetCmdStatus(DMA1_Stream4) != DISABLE){;} //确保DMA可以被设置
my_mem_cpy(SPI2_Parm.Send_Buff,send_data,(u32)send_len);
DMA_SetCurrDataCounter(DMA1_Stream3,SPI2_Parm.DMA_RxBuff_Len); //接收数据传输量
DMA_SetCurrDataCounter(DMA1_Stream4,SPI2_Parm.DMA_TxBuff_Len); //发送数据传输量
DMA_Cmd(DMA1_Stream3, ENABLE);
//DMA_Cmd(DMA1_Stream4, ENABLE);
}
/**************************************************************************************************
* SPI2 DMA数据流接收完成
*函数功能: DMA 数据流2中断函数
**************************************************************************************************/
void DMA1_Stream3_IRQHandler()
{
if(DMA_GetFlagStatus(DMA1_Stream3,DMA_FLAG_TCIF3)!=0)//SPI2 DMA接收完成中断
{
DMA_ClearFlag(DMA1_Stream3,DMA_FLAG_TCIF3);
while (SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_BSY) != RESET){;}
DMA_Cmd(DMA1_Stream3,DISABLE);
my_mem_cpy(SPI2_Parm.Recv_Data,SPI2_Parm.Recv_Buff,(u32)SPI2_Parm.DMA_RxBuff_Len);
SPI2_Parm.Flag_New_Recv=SPI2_Parm.DMA_RxBuff_Len;
}
if(DMA_GetFlagStatus(DMA1_Stream3,DMA_FLAG_TEIF3)!=0) //出错
{
DMA_ClearFlag(DMA1_Stream3,DMA_FLAG_TEIF3);
DMA_Cmd(DMA1_Stream3,DISABLE);
}
}
/**************************************************************************************************
* SPI2 DMA数据流发送完成
*函数功能: DMA 数据流3中断函数
**************************************************************************************************/
void DMA1_Stream4_IRQHandler()
{
if(DMA_GetFlagStatus(DMA1_Stream4,DMA_FLAG_TCIF4)!=0)//SPI2 DMA发送完成中断
{
DMA_ClearFlag(DMA1_Stream4,DMA_FLAG_TCIF4);
while (SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_BSY) != RESET){;}
DMA_Cmd(DMA1_Stream4,DISABLE);
SPI2_Parm.Flag_Tx_Busy = 0; //清除发送忙标记
}
if(DMA_GetFlagStatus(DMA1_Stream4,DMA_FLAG_TEIF4)!=0) //出错
{
DMA_ClearFlag(DMA1_Stream4,DMA_FLAG_TEIF4); //清除标志位
DMA_Cmd(DMA1_Stream4,DISABLE);
SPI2_Parm.Flag_Tx_Busy = 0;
}
}
//SPI1速度设置函数
//SPI速度=fAPB2/分频系数
//@ref SPI_BaudRate_Prescaler:SPI_BaudRatePrescaler_2~SPI_BaudRatePrescaler_256
//fAPB2时钟一般为84Mhz:
void SPI1_SetSpeed(u8 SPI_BaudRatePrescaler)
{
SPI1->CR1&=0XFFC7;//位3-5清零,用来设置波特率
SPI1->CR1|=SPI_BaudRatePrescaler; //设置SPI1速度
SPI_Cmd(SPI1,ENABLE); //使能SPI1
}
//SPI1 读写一个字节
//TxData:要写入的字节
//返回值:读取到的字节
u8 SPI1_ReadWriteByte(u8 TxData)
{
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);//等待发送区空
SPI_I2S_SendData(SPI1, TxData); //通过外设SPIx发送一个byte 数据
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); //等待接收完一个byte
return SPI_I2S_ReceiveData(SPI1); //返回通过SPIx最近接收的数据
}
//**********************使用方法****************************************
//SPI1_Init(); //初始化SPI
//SPI1_SetSpeed(SPI_BaudRatePrescaler_256);设置速度
//*********************//*********************//*********************
一周热门 更多>