初级会员

- 积分
- 90
- 金钱
- 90
- 注册时间
- 2015-1-6
- 在线时间
- 10 小时
|
1金钱
本帖最后由 124756828 于 2020-12-2 18:33 编辑
开发板:STM32F103问题描述:用UART空闲中断+DMA接收数据会存在丢数据的现象
具体现象:用PC串口工具每隔10ms发送640byte数据,
如果如下代码接收数据在main函数中,只做数据接收长度累加,那么接受不会有问题
但是我一旦在USART2_IRQHandler中做一系列的动作,比如把接收的数据copy到ringbuffer中,就会丢数据,求助
1)代码初始化,波特率设置为921600
- uint8_t hw_uart_init(uint32_t baud_rate)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- USART_InitTypeDef USART_InitStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
- /* Enable USART2,GPIOA,DMA1 RCC clock */
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
- USART_DeInit(USART2);
- USART_Cmd(USART2, DISABLE);
- /* Initialize the GPIOA0,GPIOA1,GPIOA2,GPIOA3 */
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_3;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- /* Data format :1:8:1, no parity check, hardware flow control */
- USART_InitStructure.USART_BaudRate = baud_rate;
- 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_RTS_CTS;
- USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
- /* Enable USART interrupts, mainly for idle interrupts */
- NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=BT_PREE_PRIO;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = BT_SUB_PRIO;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- /* Initializes USART2 to enable USART,USART idle interrupts, and USART RX DMA */
- USART_Init(USART2, &USART_InitStructure);
- USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);
- USART_DMACmd(USART2,USART_DMAReq_Rx,ENABLE);
- USART_Cmd(USART2, ENABLE);
- /* Initializes DMA and enables it */
- hw_memset(&DMA_UART2,0,sizeof(DMA_InitTypeDef));
- DMA_DeInit(DMA1_Channel6);
- DMA_UART2.DMA_PeripheralBaseAddr = (uint32_t)&USART2->DR;
- DMA_UART2.DMA_MemoryBaseAddr = (uint32_t)bt_dma_rx_buf;
- DMA_UART2.DMA_DIR = DMA_DIR_PeripheralSRC;
- DMA_UART2.DMA_BufferSize = BT_DMA_BUF_SIZE;
- DMA_UART2.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
- DMA_UART2.DMA_MemoryInc = DMA_MemoryInc_Enable;
- DMA_UART2.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
- DMA_UART2.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
- DMA_UART2.DMA_Mode = DMA_Mode_Normal;
- DMA_UART2.DMA_Priority = DMA_Priority_VeryHigh;
- DMA_UART2.DMA_M2M = DMA_M2M_Disable;
- DMA_Init(DMA1_Channel6, &DMA_UART2);
- DMA_Cmd(DMA1_Channel6, ENABLE);
- return BT_ERR_OK;
- }
复制代码 2)UART空闲中断接受数据
- void USART2_IRQHandler(void)
- {
-
- if(USART_GetITStatus(USART2, USART_IT_IDLE) != RESET)
- {
- DMA_Cmd(DMA1_Channel6, DISABLE);
- /* Without this, the interrupt cannot be cleared and continues into the interrupt */
- USART_ReceiveData(USART2);
- /* Clear the interrupt and reset DMA */
- USART_ClearITPendingBit(USART2,USART_IT_IDLE);
- recv2_len += BT_DMA_BUF_SIZE - DMA_GetCurrDataCounter(DMA1_Channel6);
- uart2_dma_enable(DMA1_Channel6);
- }
- }
复制代码- void uart2_dma_enable(DMA_Channel_TypeDef*DMA_CHx)
- {
- //DMA_Cmd(DMA_CHx, DISABLE );
- DMA_UART2.DMA_MemoryBaseAddr = (uint32_t)bt_dma_rx_buf;
- DMA_UART2.DMA_BufferSize = BT_DMA_BUF_SIZE;
- DMA_Init(DMA1_Channel6, &DMA_UART2);
- DMA_Cmd(DMA_CHx, ENABLE);
- }
复制代码
|
最佳答案
查看完整内容[请看2#楼]
首先,中断里拷贝数据到ringbuf是正常处理,这个操作耗时很短,没有问题;其次这个数据量和波特率很小,对于103来说毫无压力。参考以建议:
1、DMA接收应该设置为“DMA_Mode_Circular”(连续模式),非单次模式,如果数据连续来,就可能丢失数据;
2、使用上串口空闲中断、DMA接收半满中断、DMA接收完成中断,三者接收处理函数,缺一不可;
3、如果主函数(线程)任务量比较大,需增加DMA 接收buf和ringbuf大小。
参考F0/F1 D ...
|