【RM_EE_Note】2 串口&遥控器
简介
DT7 DR16 RM操控遥控器 通过控制 在debug里面显示对应数值的变化 日后发给机器人 实现遥控 同时还有鼠标键盘滚轮的操作
配置
CubeMX里面开串口3(特别的)可以开DMA也可以不开 后面有两套代码 然后使能中断 别的没了 注意通信协议 波特率100k 偶校验 9位 不然发不出
代码
新建ReC.c.h文件 在里面写对应的解算和回调函数 下面两个回调 一套适用于中断接收 一套适用于DMA 这里两个用了不同的缓冲区 按名称区分 都可以用
//ReC.c uint8_t RC_usart_rx_buff[RC_FRAME_LENGTH]; uint8_t RC_dma_rx_buff[RC_FRAME_LENGTH]; Remote_Control RC; Mouse M; Key K; Wheel W; void RC_USART3_IT_IRQHandler(UART_HandleTypeDef *huart) { static uint8_t rxCnt=0; if (__HAL_UART_GET_FLAG(huart, UART_FLAG_RXNE)) { __HAL_UART_CLEAR_NEFLAG(huart); RC_usart_rx_buff[rxCnt++] = huart->Instance->DR; } if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE)) { /* clear idle it flag avoid idle interrupt all the time */ __HAL_UART_CLEAR_IDLEFLAG(huart); RC_DataHandle(RC_usart_rx_buff); rxCnt = 0; } } void RC_USART3_DMA_IRQHandler(UART_HandleTypeDef *huart) { uint32_t rx_data_len = 0; if((__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE)!=RESET)) { __HAL_UART_CLEAR_IDLEFLAG(huart); (void)USART1->SR; (void)USART1->DR; __HAL_DMA_CLEAR_FLAG(huart,DMA_FLAG_TCIF2_6); HAL_UART_DMAStop(huart); rx_data_len=RC_FRAME_LENGTH-__HAL_DMA_GET_COUNTER(&hdma_usart3_rx); HAL_UART_Receive_DMA(huart, RC_dma_rx_buff, RC_FRAME_LENGTH); if(rx_data_len == RC_FRAME_LENGTH) { RC_DataHandle(RC_dma_rx_buff); } } } //解算 void RC_DataHandle(uint8_t *pData) { if(pData == NULL) { return; } RC.ch0 = ((uint16_t)pData[0] | (uint16_t)pData[1] << 8) & 0x07FF; RC.ch0 -= 1024; RC.ch1 = ((uint16_t)pData[1] >> 3 | (uint16_t)pData[2] << 5) & 0x07FF; RC.ch1 -= 1024; RC.ch2 = ((uint16_t)pData[2] >> 6 | (uint16_t)pData[3] << 2 | (uint16_t)pData[4] << 10) & 0x07FF; RC.ch2 -= 1024; RC.ch3 = ((uint16_t)pData[4] >> 1 | (uint16_t)pData[5] << 7) & 0x07FF; RC.ch3 -= 1024; //零漂 if(RC.ch0 <= 5) RC.ch0 = 0; if(RC.ch1 <= 5) RC.ch1 = 0; if(RC.ch2 <= 5) RC.ch2 = 0; if(RC.ch3 <= 5) RC.ch3 = 0; RC.s1 = ((pData[5] >> 4) & 0x0C) >>2; RC.s2 = ((pData[5] >> 4) & 0x03); //溢出 if ((ABS(RC.ch0) > 660) || (ABS(RC.ch1) > 660) || (ABS(RC.ch2) > 660) || (ABS(RC.ch3) > 660)){ memset(&RC, 0, sizeof(RC)); return; } M.x = ((int16_t)pData[6] | (int16_t)pData[7] << 8); M.y = ((int16_t)pData[8] | (int16_t)pData[9] << 8); M.z = ((int16_t)pData[10] | (int16_t)pData[11] << 8); M.press_l = pData[12]; M.press_r = pData[13]; K.k = ((int16_t)pData[14]) | ((int16_t)pData[15] << 8); W.w = ((int16_t)pData[16]) | ((int16_t)pData[17] << 8) - 1024; }
//ReC.h #include "main.h" #define RC_FRAME_LENGTH 18u #define ABS(x) ((x)>0?(x):-(x)) typedef struct { int16_t ch0; int16_t ch1; int16_t ch2; int16_t ch3; uint8_t s1; uint8_t s2; }Remote_Control; typedef struct{ int16_t x; int16_t y; int16_t z; uint8_t press_l; uint8_t press_r; }Mouse; typedef struct{ uint16_t k; }Key; typedef struct{ uint16_t w; }Wheel; extern Remote_Control RC; extern Mouse M; extern Key K; extern Wheel W; void RC_Data_Receive(void); void RC_USART3_IRQHandler(UART_HandleTypeDef *huart); void RC_DataHandle(uint8_t *pData);
在main.c开中断 把对应的回调函数塞到USART3_IRQHandler()里面 中断要开RXNE和IDLE
补充一点 关于RXNE和IDLE 接收到一个字节就产生一次RXNE中断 接收到一帧数据 就产生一次IDLE中断 一帧数据可以有多个字节连起来 比如发八个字节 就产生八次RXNE和一次IDLE
参考文献
暂时没有 可以看看参考手册和遥控器的官方手册 里面有关于解算的位运算原理 零漂和溢出那里 注意约束变量格式 以及思路清楚一点 开中断不要忘了