备战18届智能车视觉组-移植野火PID调试助手问题解决方案分享

问题一:上传数据时,无法显示波形
        我分析出来的原因是 数据发送是正确的,因为数据格式的问题,假设上位机只解析10个字节,正确的是我下位机也发送10个字节,因为结构体分配内存原因,下位机发送了12个字节,相当于发送一样的数据,因为1个字节的数据占了4个字节的内存,相当于占格子了。如下图

      

                                                图一:正确的数据格式 (在别的博客找的)  

                                          图二:错误的数据格式 (我的)  

        我猜测时野火定义结构体时出现的问题 ,可能是编译器版本的问题 下面两种结构体定义 
 A: typedef struct __packed 
 B: typedef  __packed  struct 

 野火的通信协议原来是B的写法,但是在编译器V6的下会报错只能使用A的写法(只能用v6版本,逐飞最新的库只能使用编译器v6版本)
两个结构体的定义区别就是 给变量分配内存的问题 
A:这样定义 结构体会自动分配变量内存
B:这样定义 结构体不会自动对变量分配内存
举个列子:

typedef struct __packed  结构体这样定义的话 
{
  uint32_t head;    // 包头 4个字节
  uint8_t ch;       // 通道	4个字节
  uint32_t len;     // 包长	4个字节
  uint8_t cmd;      // 命令	4个字节
}packet_head_t;

typedef  __packed  struct  结构体这样定义的话 
{
  uint32_t head;    // 包头 4个字节
  uint8_t ch;       // 通道	1个字节
  uint32_t len;     // 包长	4个字节
  uint8_t cmd;      // 命令	1个字节
}packet_head_t;

所以最后解决方法是不使用结构体,采用定义变量的方式,自己定义变量内存。        

//这是我用逐飞库改的
void set_computer_value(uint8_t cmd, uint8_t ch, void *data, uint8_t num)
{

  uint8_t sum = 0;    // 校验和
  num *= 4;           // 一个参数 4 个字节
  
  static packet_head_t set_packet;
 
  set_packet.head = FRAME_HEADER;     // 包头 0x59485A53
  set_packet.len  = 0x0B + num;      // 包长
  set_packet.ch   = ch;              // 设置通道
  set_packet.cmd  = cmd;             // 设置命令
  
        //下面这四句话是我写的 原本是没有的
	head_plus=FRAME_HEADER; // head_plus:定义的是uint32_t
	ch_plus  =ch;            // ch_plus  :定义的是uint8_t
	len_plus = 0x0B + num;  // len_plus :定义的是uint32_t
	cmd_plus =cmd;          // cmd_plus :定义的是uint8_t
	
  sum = check_sum(0, (uint8_t *)&set_packet, sizeof(set_packet));       // 计算包头校验和
  sum = check_sum(sum, (uint8_t *)data, num);                           // 计算参数校验和
  
	//用逐飞库改的发送函数,用的是数组的形式发送
	uart_write_buffer(UART_1,(uint8_t *)&head_plus,sizeof(head_plus));   // 发送数据头
	uart_write_buffer(UART_1,(uint8_t *)&ch_plus, sizeof(ch_plus));// 发送通道
	uart_write_buffer(UART_1,(uint8_t *)&len_plus, sizeof(len_plus));//发送包长
	uart_write_buffer(UART_1,(uint8_t *)&cmd_plus, sizeof(cmd_plus));//发送命令
	uart_write_buffer(UART_1,(uint8_t *)data, sizeof(data));         // 发送参数
	uart_write_buffer(UART_1,(uint8_t *)&sum, sizeof(sum));         // 发送校验和
}

                                                    图三:这是我改完之后的函数

   

void set_computer_value(uint8_t cmd, uint8_t ch, void *data, uint8_t num)
{
	static packet_head_t set_packet;

	uint8_t sum = 0;    // 校验和
	num *= 4;           // 一个参数 4 个字节

	set_packet.head = FRAME_HEADER;     // 包头 0x59485A53
	set_packet.ch   = ch;              // 设置通道
	set_packet.len  = 0x0B + num;      // 包长
	set_packet.cmd  = cmd;             // 设置命令

	sum = check_sum(0, (uint8_t *)&set_packet, sizeof(set_packet));       // 计算包头校验和
	sum = check_sum(sum, (uint8_t *)data, num);                           // 计算参数校验和

	usart1_send((uint8_t *)&set_packet, sizeof(set_packet));    // 发送数据头
	usart1_send((uint8_t *)data, num);                          // 发送参数
	usart1_send((uint8_t *)&sum, sizeof(sum));                  // 发送校验和
}

                

 图四:原来的函数

问题二:上位机发送pid和目标值时 ,出现 目标值发送出去了,但是下位机没有做出响应。

解决方法:串口接收中断的优先级要高于定时器计算pid的优先级,还要把上位机解析数据的函数放到接收数据的后面。

问题三:上位机发送目标值要连续点击两次才能发送成功,原因不知道是什么,

解决方法最后我使用逐飞的FIFO库更换了数据缓存区的写法。

uint8 fifo_get_data[64]; // fifo 读取数据的缓冲区
uint32 fifo_data_count = 0;
void LPUART1_IRQHandler(void)
{
#if (DEBUG_UART_USE_INTERRUPT && PID_ASSISTANT_EN) //  debug 串口中断

 debug_interrupr_handler();   // 调用 debug 串口接收处理函数 数据会被 debug 环形缓冲区读取

 //读取FIFO并将数据放进<fifo_get_data>最后清理缓存
fifo_data_count = debug_read_ring_buffer(fifo_get_data);             
                                                   
    if (fifo_data_count != 0)
    {
        protocol_data_recv(fifo_get_data, fifo_data_count);
        receiving_process();
    }
#endif
    LPUART_ClearStatusFlags(LPUART1, kLPUART_RxOverrunFlag); // 不允许删除
}

  图五:改成FIFO缓存写法

uint8_t Recv1[128]={0};//串口接收缓存
uint8_t rx_cnt=0;//接收数据个数计数变量
int sizecopy=128;
uint8_t dr;
void LPUART1_IRQHandler(void)
{
	#if (PID_ASSISTANT_EN)
	uint8_t data;//接收数据暂存变量
	uint8_t bufcopy[128];//最多只取前64个数据
	
	if(kLPUART_RxDataRegFullFlag & LPUART_GetStatusFlags(LPUART1)) //接收中断
	{
			dr=uart_read_byte(UART_1);
			Recv1[rx_cnt++]=dr;//接收的数据存入接收数组 
	}
	LPUART_ClearStatusFlags(LPUART1, kLPUART_RxOverrunFlag);    // 不允许删除
	
	if(kLPUART_IdleLineFlag & LPUART_GetStatusFlags(LPUART1)) //空闲中断
	{
        LPUART_ClearStatusFlags(LPUART1, kLPUART_IdleLineFlag);    // 不允许删除
		//清空本地接收数组
		memset(bufcopy,0,sizecopy);
		memcpy(bufcopy,Recv1,rx_cnt);//有几个复制几个
		protocol_data_recv(bufcopy, rx_cnt);
        receiving_process();
		memset(Recv1,0,sizecopy);
		rx_cnt=0;
	}
	#endif
}

                                                           图六:垃圾写法

物联沃分享整理
物联沃-IOTWORD物联网 » 备战18届智能车视觉组-移植野火PID调试助手问题解决方案分享

发表回复