|
例程目的:通过串口6和DMA,开启串口6的空闲中断,接收不定长数据
采用串口6空闲中断和DMA进行不定长接收,如果DMA选择正常模式,代码如下
usart配置
- void RS232_USART_Config(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- USART_InitTypeDef USART_InitStructure;
-
- RCC_AHB1PeriphClockCmd( RS232_USART_RX_GPIO_CLK|RS232_USART_TX_GPIO_CLK, ENABLE);
- /* 使能 UART 时钟 */
- RCC_APB2PeriphClockCmd(RS232_USART_CLK, ENABLE);
-
- /* 连接 PXx 到 USARTx_Tx*/
- GPIO_PinAFConfig(RS232_USART_RX_GPIO_PORT,RS232_USART_RX_SOURCE, RS232_USART_RX_AF);
- /* 连接 PXx 到 USARTx__Rx*/
- GPIO_PinAFConfig(RS232_USART_TX_GPIO_PORT,RS232_USART_TX_SOURCE,RS232_USART_TX_AF);
- /* 配置Tx引脚为复用功能 */
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
- GPIO_InitStructure.GPIO_Pin = RS232_USART_TX_PIN ;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(RS232_USART_TX_GPIO_PORT, &GPIO_InitStructure);
- /* 配置Rx引脚为复用功能 */
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
- GPIO_InitStructure.GPIO_Pin = RS232_USART_RX_PIN;
- GPIO_Init(RS232_USART_RX_GPIO_PORT, &GPIO_InitStructure);
-
- /* 配置串口RS232_USART 模式 */
- USART_InitStructure.USART_BaudRate = RS232_USART_BAUDRATE;
- USART_InitStructure.USART_WordLength = USART_WordLength_8b;
- USART_InitStructure.USART_StopBits = USART_StopBits_1;
- USART_InitStructure.USART_Parity = USART_Parity_No ;
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
- USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
- USART_Init(RS232_USART, &USART_InitStructure);
-
- NVIC_Configuration();
- /*配置串口接收中断手册上说,使用DMA接收,不要使能RXNEIE*/
- // USART_ITConfig(RS232_USART, USART_IT_RXNE, ENABLE);
- USART_ITConfig(RS232_USART, USART_IT_IDLE, ENABLE);
-
- USART_Cmd(RS232_USART, ENABLE);
- }
复制代码 DMA配置
- void RS232_DMA_Cfg(void)
- {
- DMA_InitTypeDef DMA_InitStructure;
-
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
-
- DMA_InitStructure.DMA_BufferSize = 256;//是缓冲数组的2倍
- /*usart6发送是数据流6通道5,接收是数据流1通道5*/
- DMA_InitStructure.DMA_Channel = DMA_Channel_5;
- DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
- DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
- DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;//FIFO没用,这个没影响
- DMA_InitStructure.DMA_Memory0BaseAddr = (u32)(&RX_Buff);
- DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
- DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
- DMA_InitStructure.DMA_PeripheralBaseAddr= (u32)(USART6_BASE+0x04);//USART6->DR;
- DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
- DMA_InitStructure.DMA_PeripheralDataSize= DMA_PeripheralDataSize_Byte;
- DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
- DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
-
-
- /*USART6在DMA2的通道5,数据流1和数据流2*/
- DMA_Init(DMA2_Stream1, &DMA_InitStructure);
-
- DMA_Cmd(DMA2_Stream1, ENABLE);
-
- while(DMA_GetCmdStatus(DMA2_Stream1) != SET);
- }
复制代码 串口6的中断服务函数
- void RS232_USART_IRQHandler(void)
- {
- u8 data;
- //没有RXNE中断,直接IDLE中断
- if(USART_GetITStatus(RS232_USART, USART_IT_IDLE) != RESET)
- {
-
- //清除空闲标志位
- data = USART6->SR;
- data = USART6->DR;
- /*得到接收到的数值 = 缓冲区总量 - 缓冲区剩余*/
- RXBuffCNT = BUFFLEN - DMA_GetCurrDataCounter(DMA2_Stream1);
- RXFlag = 1;
- /*把缓冲区的内容发送出去,也可以放在main函数中实验*/
-
-
- DMA_Cmd(DMA2_Stream1, DISABLE); //先关闭DMA,才能设置它
- while (DMA_GetCmdStatus(DMA2_Stream1) != DISABLE){} //等待传输结束
- USART_DMACmd( RS232_USART, USART_DMAReq_Rx,DISABLE);
- // /* 设置DMA为循环模式时,这一句加不加没有影响,可以正常接收;
- // DMA正常模式,添加这句,第一次正常,后续回显第一个字符
- // DMA正常模式,去掉这一句,第一次正常,后续发送不同内容,但是缓冲区的数据不变
- // */
- // DMA_SetCurrDataCounter(DMA2_Stream1,BUFFLEN);//可以去掉设置传输数据长度
- DMA_Cmd(DMA2_Stream1, ENABLE); //开启DMA
- //DMA工作在正常模式下需要清除这些标志位,否则有问题
- DMA_ClearFlag(DMA2_Stream1,DMA_FLAG_TCIF1 |DMA_FLAG_FEIF1 | DMA_FLAG_DMEIF1 | DMA_FLAG_TEIF1 | DMA_FLAG_HTIF1);//
- USART_DMACmd( RS232_USART, USART_DMAReq_Rx,ENABLE);
- }
- }
复制代码 有如下问题:
- 如果选择正常模式,需要清除一堆DMA的标志位,不知道为什么虽然我接收的数据只有几位,外设到内存的内存空间有256字节,正常来说这些标志位都没有影响的,但是不清除就不行
- DMA工作模式normal,当第二次发送的内容和第一次不同时,串口回显的内容不会立刻改变,而是下一次才开始改变,如图,之前都是bbbbbbb当发送qqqqqq时,在main函数中的发送函数表明接收到的还是bbbbbbbbb;第二次,之前都是qqqqq,我发送yyyyy时,在main函数中的发送函数表明接收到的还是qqqqqqq,等到下一次才显示正常。
这个更明显,通过调试发现,我发送的是b,但是缓冲数组里还是之前的a,感觉DMA的缓冲慢半拍,不知道大家有没有碰到这样的问题,谢谢大家。
|
|