|
增加一些注释吧,这个代码能帮上忙就行。 ________________________________________________________ 实在受不了中断了。 这里使用DMA循环方式接收串口数据,不用中断,空闲时间去查询DMA状态,然后拷贝数据即可。 F407的部分代码如下,F103的类似: // 宏定义 #define USART3_RXBUF_SIZ 256 /* UART接收缓冲,必须为2^n,增加这个数值可以放宽处理UART接收数据的时间间隔 */ #define USART3_RX_DMA_CHANNEL DMA_Channel_4 /* UART接收通道 */ #define USART3_RX_DMA_STREAM DMA1_Stream1 /* UART接收DMA */ // 全局缓冲区 static uint8_t gl_Usart3Rxbuf[USART3_RXBUF_SIZ] = { 0, }; // 初始化串口和DMA.. static void MX_Uart_Init(void) { USART_InitTypeDef USART_InitStruct; DMA_InitTypeDef DMA_InitStruct; // 初始化USART3的通讯 ---------------------------------------------------------- USART_StructInit(&USART_InitStruct); USART_InitStruct.USART_BaudRate = 115200; USART_InitStruct.USART_WordLength = USART_WordLength_8b; USART_InitStruct.USART_StopBits = USART_StopBits_1; USART_InitStruct.USART_Parity = USART_Parity_No; USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART3, &USART_InitStruct); /* 配置UART为DMA循环接收方式,即DMA按照RingBuffer方式写入UART接收缓冲,CPU不参与UART接收 */ DMA_StructInit(&DMA_InitStruct); DMA_InitStruct.DMA_BufferSize = sizeof(gl_Usart3Rxbuf) ; DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Disable ; DMA_InitStruct.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull ; DMA_InitStruct.DMA_MemoryBurst = DMA_MemoryBurst_Single ; DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStruct.DMA_Mode = DMA_Mode_Circular; DMA_InitStruct.DMA_PeripheralBaseAddr =(uint32_t) (&(USART3->DR)) ; DMA_InitStruct.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStruct.DMA_Priority = DMA_Priority_Medium; DMA_InitStruct.DMA_Channel = USART3_RX_DMA_CHANNEL; DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralToMemory; DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t)gl_Usart3Rxbuf; DMA_Init(USART3_RX_DMA_STREAM, &DMA_InitStruct); USART_DMACmd(USART3, USART_DMAReq_Rx, ENABLE); DMA_Cmd(USART3_RX_DMA_STREAM, ENABLE); USART_Cmd(USART3, ENABLE); } // 处理接收的串口数据 void Idle_Proc(void) { static uint16_t lastDataCounter = 0; /* 保存已处理的UARt接收数据index */ static char line[256]; static int ncin = 0; uint16_t currDataCounter; bool newLine = false; uint8_t ch; // 处理USART3接收的数据 ---------------------------------------------------- /* 获取DMA中数据计数,用于计算当前所接收字符的index */ do { currDataCounter = DMA_GetCurrDataCounter(USART3_RX_DMA_STREAM); } while (currDataCounter != DMA_GetCurrDataCounter(USART3_RX_DMA_STREAM)); currDataCounter = sizeof(gl_Usart3Rxbuf) - currDataCounter; /* 计算当前UART接收的index */ while (((currDataCounter - lastDataCounter) & (USART3_RXBUF_SIZ - 1)) != 0) { /* 一直处理到已接收的index */ ch = gl_Usart3Rxbuf[lastDataCounter++ & (USART3_RXBUF_SIZ - 1)]; /* 拷贝已接收的UART数据,所保存的index增长 */ ...... } } /* 增加主函数 */ int main(void) { for (;;) { process1(); process2(); process3(); ... process99(); Idle_Proc(); } } 其他的诸如时钟初始化、GPIO初始化等这个就不贴了。 PS:中断是个好东西,但是,...,能不用就不用吧。。。,还有别把程序写成阻塞的。 |
微信公众号
手机版
既然用DMA了,为何不用串口空闲中断+DMA呢,这就不用频繁的查询了,一次能接收不定长的一帧数据。
这个方法貌似不错,下次试试
你的理由是什么呢?
这应该是串口接收数据比较好的方法之一的,中断的方法和这个没法比。
没有查询串口,是查询DMA的状态,DMA的设置自行完成了RingBuffer的功能。
串口接收的缓冲长度决定了读取RingBuffer的时间裕度。