完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
创建项目:
打钩,生成模块,不然clion检测不到 不要勾,勾了之后写入不立即执行 配置DMA及遇到的问题: 示例代码 导入common_uart.h // // Created by Kaijun on 2020/6/8. // #ifndef HEIMAROBOT4WD_COMMON_UART_H #define HEIMAROBOT4WD_COMMON_UART_H #ifdef __cplusplus extern "C" { #endif #include "usart.h" #include "stm32f1xx_hal.h" extern DMA_HandleTypeDef hdma_usart1_rx; extern UART_HandleTypeDef huart1; void common_uart_init(); void common_uart_idle_handle(UART_HandleTypeDef *huart1); void common_uart_send(uint8_t *data, uint16_t size); __weak void common_uart_idle_callback(uint8_t receive_buf[],uint16_t receive_len); #ifdef __cplusplus } #endif #endif //HEIMAROBOT4WD_COMMON_UART_H common_uart.c // // Created by Kaijun on 2020/6/8. // #include "common_uart.h" #include #include #include "stm32f1xx_hal.h" // 定义缓冲区的大小 const uint32_t BUFFER_SIZE = 255; // 声明缓冲区 static uint8_t uart_rx_buff[255]; /** * 串口的初始化操作 */ void common_uart_init(){ // 开启DMA接收数据 HAL_UART_Receive_DMA(&huart1, (uint8_t*)uart_rx_buff, BUFFER_SIZE); // 开启空闲中断处理 __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); // 开启通信异常处理 __HAL_UART_ENABLE_IT(&huart1,UART_IT_ERR); } /** * 需要将这个函数放到stm32f1xx_it.c 文件中的void USART1_IRQHandler(void)函数中调用 * @param huart1 */ void common_uart_idle_handle(UART_HandleTypeDef* huart1){ if(USART1 == huart1->Instance) { // 判断是否是空闲中断 if (RESET != __HAL_UART_GET_FLAG(huart1, UART_FLAG_IDLE)) { // 计算接收到的数据长度 uint32_t data_length = BUFFER_SIZE - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx); __HAL_UART_CLEAR_IDLEFLAG(huart1); // 停止本次DMA传输 HAL_UART_DMAStop(huart1); // 将数据丢给外部去处理 while (HAL_UART_Receive_DMA(huart1, uart_rx_buff, BUFFER_SIZE) != HAL_OK) { huart1->RxState = HAL_UART_STATE_READY; __HAL_UNLOCK(huart1); } // 数据处理的回调 common_uart_idle_callback(uart_rx_buff,data_length); } } } /** * 将数据使用DMA的方式发送出去 * @param data * @param size */ void common_uart_send(uint8_t* data ,uint16_t size){ // 直到DMA空闲,才进行数据的发送 while (HAL_UART_GetState(&huart1) == HAL_UART_STATE_BUSY_TX_RX); while (HAL_UART_Transmit_DMA(&huart1, data, size) != HAL_OK); } /* 中断错误处理函数,在此处理overrun错误 */ void HAL_UART_ErrorCallback1(UART_HandleTypeDef *huart) { if(__HAL_UART_GET_FLAG(huart,UART_FLAG_PE) != RESET) { __HAL_UART_CLEAR_OREFLAG(huart); } if(__HAL_UART_GET_FLAG(huart,UART_FLAG_FE) != RESET) { __HAL_UART_CLEAR_FEFLAG(huart); } if(__HAL_UART_GET_FLAG(huart,UART_FLAG_NE) != RESET) { __HAL_UART_CLEAR_NEFLAG(huart); } if(__HAL_UART_GET_FLAG(huart,UART_FLAG_ORE) != RESET) { __HAL_UART_CLEAR_OREFLAG(huart); } common_uart_init(); } // 定义缓冲区的大小 const uint32_t BUFFER_SIZE = 255; // 声明缓冲区 static uint8_t uart_rx_buff[255]; /** * 串口的初始化操作 */ void common_uart_init(){ // 开启DMA接收数据 HAL_UART_Receive_DMA(&huart1, (uint8_t*)uart_rx_buff, BUFFER_SIZE); // 开启空闲中断处理 __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); // 开启通信异常处理 __HAL_UART_ENABLE_IT(&huart1,UART_IT_ERR); } /** * 需要将这个函数放到stm32f1xx_it.c 文件中的void USART1_IRQHandler(void)函数中调用 * @param huart1 */ void common_uart_idle_handle(UART_HandleTypeDef* huart1){ if(USART1 == huart1->Instance) { // 判断是否是空闲中断 if(RESET != __HAL_UART_GET_FLAG(huart1, UART_FLAG_IDLE)) { // 计算接收到的数据长度 uint8_t data_length = BUFFER_SIZE - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx); // 清除空闲中断标志(否则会一直不断进入中断) __HAL_UART_CLEAR_IDLEFLAG(huart1); // 停止本次DMA传输 HAL_UART_DMAStop(huart1); // 将数据丢给外部去处理 common_uart_idle_callback(uart_rx_buff,data_length); // 清零接收缓冲区 memset(uart_rx_buff,0,data_length); // 重启开始DMA传输 每次255字节数据 HAL_UART_Receive_DMA(huart1, (uint8_t*)uart_rx_buff, BUFFER_SIZE); } } } /** * 将数据使用DMA的方式发送出去 * @param data * @param size */ void common_uart_send(uint8_t* data ,uint16_t size){ // 直到DMA空闲,才进行数据的发送 while (HAL_UART_GetState(&huart1) == HAL_UART_STATE_BUSY_TX_RX){} HAL_UART_Transmit_DMA(&huart1,data, size); } /* 中断错误处理函数,在此处理overrun错误 */ void HAL_UART_ErrorCallback1(UART_HandleTypeDef *huart) { if(__HAL_UART_GET_FLAG(huart,UART_FLAG_PE) != RESET) { __HAL_UART_CLEAR_OREFLAG(huart); } if(__HAL_UART_GET_FLAG(huart,UART_FLAG_FE) != RESET) { __HAL_UART_CLEAR_FEFLAG(huart); } if(__HAL_UART_GET_FLAG(huart,UART_FLAG_NE) != RESET) { __HAL_UART_CLEAR_NEFLAG(huart); } if(__HAL_UART_GET_FLAG(huart,UART_FLAG_ORE) != RESET) { __HAL_UART_CLEAR_OREFLAG(huart); } common_uart_init(); } 自定义协议 #define FLAG_HEAD0 0xce #define FLAG_HEAD1 0xfa #define FLAG_TAIL 0xaa #pragma pack(1) // 数据按1字节对齐 typedef struct TxProtocol{ uint8_t head0; uint8_t head1; uint8_t type; uint8_t len; short temprature; short ax; short ay; short az; short gx; short gy; short gz; short mx; short my; short mz; short v; short w; }; 声明完成之后,我们只需要往这个里面填充数据,然后调用已封装的API发送即可 truct TxProtocol protocol; protocol.head0 = FLAG_HEAD0; protocol.head1 = FLAG_HEAD1; ............... common_uart_send((uint8_t*)&protocol, sizeof(protocol)) 解析协议 在这一小节,我们主要来学习如何解析串口发送过来的数据协议. 关于数据协议解析的步骤如下: 读取数据缓冲区和接收到的数据长度 找到数据的起始标志位 因为当前情况下,我们是固定长度的协议,所以直接从起始标志位向后读取协议长度数据 判断数据结尾标志位是否正确 如果上述都没有问题,根据协议类型做出相应的处理 void common_uart_idle_callback(uint8_t receive_buf[],uint16_t receive_len){ uint8_t i = 0; while(i < receive_len-2){ // 找到head0 + head1 if(receive_buf == FLAG_HEAD0){ if(receive_buf[i+1] == FLAG_HEAD1){ // 说明匹配到了帧头 if(receive_buf[i+2] == 0x04){ //类型匹配成功 //判断数据数据长度是否足够 if(i + receive_buf[i+3] < receive_len){ uint8_t v_low = receive_buf[i+4]; uint8_t v_high = receive_buf[i+5]; short v = v_high<<8|v_low; uint8_t w_low = receive_buf[i+6]; uint8_t w_high = receive_buf[i+7]; short w = w_high<<8|w_low; HAL_GPIO_TogglePin(GPIOE,GPIO_PIN_10); } } } } i++; } }* short类型转换的示例代码: temp = struct.unpack('h', bytearray([0xde ,0x0e]))[0]print(temp)print(0x0e<<8|0xde);temp = bytearray(struct.pack('h',int(1.02*1000)));print(temp) 遇到的问题: cubemx的bug DMA接收及发送不了数据: |
|
|
|
只有小组成员才能发言,加入小组>>
3278 浏览 9 评论
2955 浏览 16 评论
3455 浏览 1 评论
8987 浏览 16 评论
4050 浏览 18 评论
1100浏览 3评论
570浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
568浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2300浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1856浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-21 19:03 , Processed in 1.099393 second(s), Total 79, Slave 59 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号