关于DR16数据的获取和处理

DR16

关于DR16数据的获取和处理

DR16&DT7

采用DBUS协议数据

  1. 波特率要调至100kbps
  2. 单位数据长度 8
  3. 奇偶校验位 偶校验
  4. 结束位 1
  5. 流控 无

注意!!!

cubemx配置的时候,长度要配成9

因为那个是包括校验位的

遥控器不同遥杆传输的数据类型

关于DR16数据的获取和处理_第1张图片鼠标及按键信息

关于DR16数据的获取和处理_第2张图片

遥控器通道与控制开关

关于DR16数据的获取和处理_第3张图片

控制代码

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空闲中断接收

  1. cubemx配置

串口2接收配置

关于DR16数据的获取和处理_第4张图片

串口2 dma接收配置

关于DR16数据的获取和处理_第5张图片

串口1 发送到上位机配置

关于DR16数据的获取和处理_第6张图片

串口1 dma发送配置

因为我用的上位机内部函数有写好要用dma发送,所以才开了dma

4b9RmV.png

  1. 串口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);
		}
	}
}
  1. 用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); //发送数据到上位机
		}
	}
}`

出现的问题

  1. 本来想外加queue.cqueue.h文件

    原因:对freertos的功能概念等不清,不明白队列的含义(这个会在关于freertos那张笔记进行介绍)

  2. 在接收回调函数里面把数据放到队列以后用memset()usart2_rx__buffer这个数组进行清零操作

    原因

    1. 没有考虑到这样子做由于传的是地址,清空会导致freertos在执行对数据进行解包的任务时,数据发生丢失。
    2. 下次写入数据时它本身便会对已有数据进行一个覆盖,根本就不需要清空

你可能感兴趣的:(stm32)