如果想要参考我的工程和代码可以给我留言
用CUBE MX生成了工程,我用的是Keil5.25。配置如下:
遇到的几个问题:
- 使用DMA接收数据,不进中断回调函数:能够进USART3 中断,如果将回调函数中的内容写在串口中断里,就可以处理中断,但是如果放在单独的回调函数里,就进不去HAL_UART_RxCpltCallback,这个令我很苦恼。
- 如果HAL_UART_Receive_DMA(&huart3, (u8*)receive_buff, BLE_DATA_LEN);这个函数中的BLE_DATA_LEN == 1,就能够收到完成的数据,如果大于1就只能收到第一个数据;
- HAL_UART_Transmit 和HAL_UART_Transmit_IT都可以将数据发送出去,但是HAL_UART_Transmit_DMA不能发送数据,一直返回tx_busy.
苦恼了一个下午,晚上请教了高人,将这些问题一一解决:
在启动DMA接收和中断中使用过程中,HAL_UART_Receive_DMA(&huart3, (u8*)receive_buff, BLE_DATA_LEN),这个BLE_DATA_LEN长度要保持一致,另外,并且要在串口初始化之后开启,中间不要有延时。
- 回答第一个问题,在串口初始化之后,很多网上的教程会把 这4句话其中的一部分或者全部放到MX_USART3_UART_Init初始化函数中,这个有点多余,因为HAL_UART_Receive_DMA这个函数中已经打开了前面三个的中断,所以只保留最后一个就可以了。
HAL_UART_Receive_IT(&huart3, (u8 *)receive_buff, BLE_DATA_LEN);
__HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE);
__HAL_UART_ENABLE_IT(&huart3, UART_IT_RXNE);
HAL_UART_Receive_DMA(&huart3, (u8*)receive_buff, BLE_DATA_LEN);
开启了DMA之后,中断进去的应该是DMA中断处理函数 DMA1_Stream1_IRQHandler,这里面的中断处理函数HAL_DMA_IRQHandler会在接收完成设定长度的数据后调用回调函数HAL_UART_RxCpltCallback,在这里完成数据处理即可。这时候也会进入到对应的串口中断,但是不会调用回调函数。
这里不进回调函数是令我最苦恼的,请教了原厂的支持后,带我梳理了一遍MX的配置:建议将DMA开启时钟的时间和系统时钟临近,这样早点开启DMA时钟。经过几轮折腾,终于都实现了,也能用DMA发数据了。
这也是今天学到的技能,原来main中外设的初始化顺序是可以在ADVANCED SETTING中进行修改顺序的,右上角的那两个不起眼的箭头就是干这个用的。
明后天开始折腾CAN和其它的串口,项目中一共用到了3个串口,加油干!