DR16
关于DR16数据的获取和处理
DR16&DT7
采用DBUS协议数据
- 波特率要调至100kbps
- 单位数据长度 8
- 奇偶校验位 偶校验
- 结束位 1
- 流控 无
注意!!!
cubemx配置的时候,长度要配成9
因为那个是包括校验位的
遥控器不同遥杆传输的数据类型
鼠标及按键信息
遥控器通道与控制开关
控制代码
1.定义相应结构体
typedef struct
{
struct
{
int16_t ch0;
int16_t ch1;
int16_t ch2;
int16_t ch3;
int8_t s1;
int8_t s2;
}remote;
struct
{
int16_t x;
int16_t y;
int16_t z;
int8_t press_left;
int8_t press_right;
}mouse;
union {
uint16_t key_code;
struct
{
uint16_t W :1;
uint16_t S :1;
uint16_t A :1;
uint16_t D :1;
uint16_t Q :1;
uint16_t E :1;
uint16_t Shift :1;
uint16_t Ctrl :1;
}bit;
}key;
}RC_Ctrl_t;
2.写它的解包函数
减掉1024是想要把初始值变为0
`void Get_DR16_Data(uint8_t *Buff)
{
RC_CtrlData.remote .ch0 =(Buff[0]|Buff[1]<<8)&0x07FF;
RC_CtrlData.remote .ch0 -=1024;
RC_CtrlData.remote .ch1 =(Buff [1]>>3|Buff[2]<<5)&0x07FF;
RC_CtrlData.remote .ch1 -=1024;
RC_CtrlData.remote .ch2 =(Buff[2]>>6|Buff[3]<<2|Buff[4]<<10)&0x07FF;
RC_CtrlData.remote .ch2 -=1024;
RC_CtrlData.remote .ch3 =(Buff[4]>>1|Buff[5]<<7)&0x07FF;
RC_CtrlData.remote .ch3 -=1024;
RC_CtrlData.remote .s1 =(Buff[5]>>4&0x000C)>>2;
RC_CtrlData.remote .s2 =(Buff[5]>>4&0x003);
RC_CtrlData.mouse .x =(Buff[6]|Buff[7]<<8);
RC_CtrlData.mouse .y =(Buff[8]|Buff[9]<<8);
RC_CtrlData.mouse .z =(Buff[10]|Buff[11]<<8);
RC_CtrlData.mouse .press_left =(Buff[12]);
RC_CtrlData.mouse .press_right =(Buff[13]);
}`
串口1接收原始数据并进行储存
串口dma空闲中断接收
- cubemx配置
串口2接收配置
串口2 dma接收配置
串口1 发送到上位机配置
串口1 dma发送配置
因为我用的上位机内部函数有写好要用dma发送,所以才开了dma
- 串口2dma不定长收
串口2中断函数
`if(__HAL_UART_GET_FLAG(&huart2,UART_FLAG_IDLE))
{
USART_Receive_IDLE(&huart2);
}
RecHandle(usart2_rx__buffer,usart2_tx__len);`
另外USART_Receive_IDLE()定义如下
void USART_Receive_IDLE(UART_HandleTypeDef *huart)
{
uint16_t i=0;
BaseType_t pxHigherPriorityTaskWoken = pdFALSE;
static USART_COB Usart_RxCOB;
if(__HAL_UART_ENABLE_IT(&huart2 ,UART_IT_IDLE)!=RESET ) //触发空闲中断
{
if(huart->Instance ==USART2 ) //判断是串口2
{
__HAL_UART_CLEAR_FEFLAG(&huart2); //清除中断标志位
HAL_UART_DMAStop (&huart2); //关闭dma
i= huart->Instance->SR; //软件序列清零 先SR后DR
i= huart->Instance->DR;
i=hdma_usart2_rx.Instance->NDTR; //计算dma里未传输的数目
usart2_tx__len=128-i; //计算dma传输的数目
/*用队列替代简单的mencpy操作*/
if(USART_RXPORT != NULL)
{
Usart_RxCOB.port_num=1;
Usart_RxCOB.len = usart2_tx__len;
Usart_RxCOB.address = usart2_rx__buffer;
xQueueSendFromISR(USART_RXPORT,&Usart_RxCOB,&pxHigherPriorityTaskWoken);
}
/*本来是利用简单的将usart2_rx__buffer copy到usart1_tx__buffer中,将其作为一个缓存
if(usart2_rx__flag==0)
{
//把接收到的东西发送出去
memcpy(usart1_tx__buffer,usart2_rx__buffer,usart2_tx__len);
usart2_rx__flag =1;
}
*/
HAL_UART_Receive_DMA(huart,(uint8_t *)usart2_rx__buffer,128);
}
}
}
- 用freertos的队列暂存串口2中接受的数据,并在任务中解包并发送至上位机
`/*对DR16的数据进行处理,然后发送到上位机*/
TaskHandle_t Freertos_DR16_Data_Handle;
void Freertos_DR16_Data(void * argument);
void Freertos_DR16_Data_Init(void)
{
xTaskCreate(Freertos_DR16_Data , "Freertos_DR16_Data",128 ,NULL ,6,&Freertos_DR16_Data_Handle);
}
void Freertos_DR16_Data(void * argument)
{
static USART_COB Usart_RxCOB;
TickType_t xLastWakeTime_t = xTaskGetTickCount();
TickType_t _xTicksToWait = pdMS_TO_TICKS(1);
for(;;)
{
// if( usart2_rx__flag==1)`
`//启用队列处理函数
if(xQueueReceive(USART_RXPORT,&Usart_RxCOB,portMAX_DELAY) == pdPASS)
{
Get_DR16_Data(Usart_RxCOB.address); //解包得到的DR16的数据
vTaskDelayUntil(&xLastWakeTime_t, _xTicksToWait);
// usart2_rx__flag = 0;
Sent_Contorl(&huart1); //发送数据到上位机
}
}
}`
出现的问题
-
本来想外加
queue.c
和queue.h
文件原因:对
freertos
的功能概念等不清,不明白队列的含义(这个会在关于freertos
那张笔记进行介绍) -
在接收回调函数里面把数据放到队列以后用
memset()
将usart2_rx__buffer
这个数组进行清零操作原因:
- 没有考虑到这样子做由于传的是地址,清空会导致
freertos
在执行对数据进行解包的任务时,数据发生丢失。 - 下次写入数据时它本身便会对已有数据进行一个覆盖,根本就不需要清空
- 没有考虑到这样子做由于传的是地址,清空会导致