STM32串口使用说明-DMA方式
STM32串口DMA方式与普通串口收发方式配置不同之处:
增加串口发送DMA配置,DMA发送函数,DMA发送中断函数;串口接收DMA配置;以及串口中断函数处理有所不同。
1、串口引脚配置、串口参数配置、串口中断优先级
同前文相同。
2、接收中断函数
void USART6_IRQHandler(void)
//串口6接收中断函数
void USART6_IRQHandler(void)
{
if(USART_GetITStatus(USART6, USART_IT_IDLE) != RESET)
{
DMA_Cmd(DMA2_Stream1, DISABLE); //禁止接收
//清除IDLE中断
(void)USART6->SR;
(void)USART6->DR;
RxBuf_Lenth = DMA_GetCurrDataCounter(DMA2_Stream1); //获取传输数据长度
RxFinish = TRUE;//接收完成标志
DMA_ClearFlag(DMA2_Stream1,DMA_FLAG_TCIF1 |
DMA_FLAG_FEIF1 |
DMA_FLAG_DMEIF1|
DMA_FLAG_TEIF1 |
DMA_FLAG_HTIF1);
DMA_SetCurrDataCounter(DMA2_Stream1, ControlBuf_MAX);
DMA_Cmd(DMA2_Stream1, ENABLE);
}
}
3、串口发送DMA配置
void DMA2_USART6_Tx_Init(void)
//串口6DMA发送配置
void DMA2_USART6_Tx_Init(void)
{
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE); 使能DMA2时钟
/*DMA2 Stream 6 Channel 5 Usart6_Tx */
DMA_DeInit(DMA2_Stream6); //将DMA的发送数据流设置为缺省值
while (DMA_GetCmdStatus(DMA2_Stream6) != DISABLE); //等待DMA的发送数据流可配置
DMA_InitStructure.DMA_Channel = DMA_Channel_5; //通道选择
DMA_InitStructure.DMA_PeripheralBaseAddr = (DWORD)&USART6->DR; //DMA址地设外
DMA_InitStructure.DMA_Memory0BaseAddr = (u32)SerialBuf.ControlBuf; //DMA储存器0地址
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; //存储器到外设模式
DMA_InitStructure.DMA_BufferSize = Buf_MAX; //数据传输量
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设非增量模式
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //存储器增量模式
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_Medium; //中等优先级
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; //FIFO模式
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; //FIFO阈值
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; //存储器突发单次传输
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; //外设突发单次传输
DMA_Init(DMA2_Stream6, &DMA_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream6_IRQn; //DMA发送数据流中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //子优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure);
DMA_ITConfig(DMA2_Stream6,DMA_IT_TC,ENABLE); //使能DMA发送数据流中断
}
4、串口接收DMA配置
void DMA2_USART6_Rx_Init(void)
//串口接收DMA配置
void DMA2_USART6_Rx_Init(void)
{
DMA_InitTypeDef DMA_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); //DMA2时钟使能
DMA_DeInit(DMA2_Stream1); //
while (DMA_GetCmdStatus(DMA2_Stream1) != DISABLE); //等待数据流可设
DMA_InitStructure.DMA_Channel = DMA_Channel_5; //通道
DMA_InitStructure.DMA_PeripheralBaseAddr = (DWORD)&USART6->DR; //DMA外设地址
DMA_InitStructure.DMA_Memory0BaseAddr = (u32)SerialBuf.ControlBuf; //DMA存储0地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory ; //外设到存储器模式
DMA_InitStructure.DMA_BufferSize = Buf_MAX; //数据传输量
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //(同DMA发送xxx)
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //xxx
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //xxx
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //xxx
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //xxx
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //xxx
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; //xxx
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; //xxx
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; //xxx
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; //xxx
DMA_Init(DMA2_Stream1, &DMA_InitStructure);
USART_DMACmd(USART6,USART_DMAReq_Rx,ENABLE); //使能串口DMA接收
DMA_Cmd(DMA2_Stream1, ENABLE); //开启DMA传输
}
5、DMA发送函数
void DMA2_Usart6_Tx_Enable(WORD Size)
//串口6 DMA发送使能
void DMA2_Usart6_Tx_Enable(WORD Size)
{
DMA_Cmd(DMA2_Stream6, DISABLE); //关闭DMA传输
while (DMA_GetCmdStatus(DMA2_Stream6) != DISABLE){} //确保DMA可以被设置
DMA_SetCurrDataCounter(DMA2_Stream6, Size); //数据传输量
DMA_Cmd(DMA2_Stream6, ENABLE); //开启DMA传输
}
6、DMA发送中断函数
void DMA2_Stream6_IRQHandler(void)
//DMA传输中断函数
void DMA2_Stream6_IRQHandler(void)
{
if(DMA_GetFlagStatus(DMA2_Stream6,DMA_FLAG_TCIF6)!=RESET) //等待传输完成中断标志
{
DMA_ClearFlag(DMA2_Stream6, DMA_FLAG_TCIF6); //清除中断标志
delay_ms(3);
DMA_Cmd(DMA2_Stream1, ENABLE); //打开DMA接收
}
}
明月别枝惊鹊,清风半夜鸣蝉。
——《西江月 夜行黄沙道中》宋朝·辛弃疾