完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
1.使用STM32Cube 直接先配置串口1的基础信息。
2.然后配置DMA传输 3.就是启动了,在串口初始化之后默认是没有开启串口DMA接收的。所以增加几行代码如下图所示 4.写串口1中断函数: 这个函数就是实现不等长的精髓所在了。这里用到了类似环形队列的方法,至于什么是环形队列这个不知道童鞋自行Google了。 void USART1_IRQHandler(void) { if(__HAL_UART_GET_FLAG(&systemUart, UART_FLAG_IDLE) != RESET) { __HAL_UART_FLUSH_DRREGISTER(&systemUart); //清除 IDLE中断 } HAL_UART_IRQHandler(&systemUart); } 首先将中断函数写出来,如上所示了。这时候帧中断的时候会进这个中断,数据用DMA接收。 第二步建立对应变量 #define UART1_DMA_DATA_LEN 100//数据最大长度 static UART_HandleTypeDef systemUart; DMA_HandleTypeDef hdma_usart1_rx; static uint8_t _uartDmaDataBuffer[UART1_DMA_DATA_LEN]; //缓冲区就是初始化的时候用到的 static int dmaDataTail = 0; //将DMA数据传输Buffer 虚拟成一个队列缓冲区 static int dmaDataHead = 0; static int dmaDataLenght = 0; 第三步实现类似环形队列功能 void USART1_IRQHandler(void) { if(__HAL_UART_GET_FLAG(&systemUart, UART_FLAG_IDLE) != RESET) { __HAL_UART_FLUSH_DRREGISTER(&systemUart); //清除 IDLE中断 dmaDataTail = hdma_usart1_rx.Instance->NDTR; dmaDataTail = UART1_DMA_DATA_LEN - dmaDataTail; dmaDataLenght = (dmaDataTail - dmaDataHead+UART1_DMA_DATA_LEN) % UART1_DMA_DATA_LEN; //求数据长度 } HAL_UART_IRQHandler(&systemUart); } 注意里面 hdma_usart1_rx.Instance->NDTR的NDTR不同的型号可能不同可以在DMA的结构体里找到对应的名字,如下图所示 这个NDTR的值是从UART1_DMA_DATA_LEN开始递减的,因为启动DMA的时候设置了传输长度为UART1_DMA_DATA_LEN 所以我们接收到当前的数据下标就是UART1_DMA_DATA_LEN - hdma_usart1_rx.Instance->NDTR这个。这个其实就是当前接收到数据的结束下标。有了数据结束下标,我们还需要数据起始下标,以及数据长度。 ①数据起始下标: 等于上一次的dmaDataTail 所以每次处理完数据都有dmaDataHead = dmaDataTail; ②数据长度:这个利用环形队列求长度的做法: dmaDataLenght = (dmaDataTail - dmaDataHead+UART1_DMA_DATA_LEN) % UART1_DMA_DATA_LEN; 现在我们有了数据起始下标 数据长度那么我们就可以访问我们的数据了。当然方法也和环形队列差不多 完成的中断函数就是这样的。可以接收什么返回什么了,要想自己处理可以在这里增加缓冲区或者调用处理函数了。 void USART1_IRQHandler(void) { if(__HAL_UART_GET_FLAG(&systemUart, UART_FLAG_IDLE) != RESET) { __HAL_UART_FLUSH_DRREGISTER(&systemUart); //清除 IDLE中断 dmaDataTail = hdma_usart1_rx.Instance->NDTR; dmaDataTail = UART1_DMA_DATA_LEN - dmaDataTail; dmaDataLenght = (dmaDataTail - dmaDataHead+UART1_DMA_DATA_LEN) % UART1_DMA_DATA_LEN; //求数据长度 for(int i = 0; i < dmaDataLenght; i++) { int index = (dmaDataHead+i)%UART1_DMA_DATA_LEN; printf("%c",_uartDmaDataBuffer[index]); } printf("rn"); dmaDataHead = dmaDataTail; } HAL_UART_IRQHandler(&systemUart); } 最后来张测试结果图分别是一顿乱操作发不同的数据长度和数据 最后注意一点的就是这个程序如果你一下子发超过100个字节那估计就不行了。因为超了缓冲区长度数据被覆盖了,当然增加长度就可以解决了。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1907 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1678 浏览 1 评论
1171 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
770 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1730 浏览 2 评论
1970浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
806浏览 4评论
stm32f4下spi+dma读取数据不对是什么原因导致的?
253浏览 3评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
623浏览 3评论
634浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-23 04:03 , Processed in 0.619316 second(s), Total 45, Slave 39 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号