野火PID串口助手的移植思路(文末有源码链接)

1首先把野火的两个protocol文件复制粘贴到自己的工程文件夹里面

2野火官方文档重点讲解了以下四个函数:

/**
* @brief   接收数据处理
* @param   *data:  要计算的数据的数组.
* @param   data_len: 数据的大小
* @return  void.
*/
void protocol_data_recv(uint8_t *data, uint16_t data_len);

/**
* @brief   初始化接收协议
* @param   void
* @return  初始化结果.
*/
int32_t protocol_init(void);

/**
* @brief   接收的数据处理
* @param   void
* @return  -1:没有找到一个正确的命令.
*/
int8_t receiving_process(void);

/**
* @brief 设置上位机的值
* @param cmd:命令
* @param ch: 曲线通道
* @param data:参数指针
* @param num:参数个数
* @retval 无
*/
void set_computer_value(uint8_t cmd, uint8_t ch, void *data, uint8_t num);

这四个函数的使用方法和使用位置

该协议的思路就是在串口中断中调用protocol_data_recv()函数对串口接收到的数据进行处理。 在主循环中用receiving_process()函数对数据进行进一步处理,同时在主循环中使用set_computer_value()函数将单片机的数据发送给上位机,从而同步上位机和下位机之间的信息。最后在主循环之前加上protocol_init()协议初始化函数即可

3对于protocol文件里的函数,我们只需要改receiving_process(void)和set_computer_value(uint8_t cmd, uint8_t ch, void *data, uint8_t num)即可

4修改函数set_computer_value(uint8_t cmd, uint8_t ch, void *data, uint8_t num)的方法

将HAL库的这三行:
  HAL_UART_Transmit(&UartHandle, (uint8_t *)&set_packet, sizeof(set_packet), 0xFFFFF);    // 发送数据头
  HAL_UART_Transmit(&UartHandle, (uint8_t *)data, num, 0xFFFFF);                          // 发送参数
  HAL_UART_Transmit(&UartHandle, (uint8_t *)&sum, sizeof(sum), 0xFFFFF);                  // 发送校验和
 
改为标准库的
Serial_send((uint8_t *)&set_packet, sizeof(set_packet));    // 发送数据头
Serial_send((uint8_t *)data, num);                          // 发送参数
Serial_send((uint8_t *)&sum, sizeof(sum));                  // 发送校验和

同时加上Serial_send函数


/**
  * 函    数:用于野火串口的发送函数
  * 参    数:发送的内容,内容的长度
  * 返 回 值:无
  */
void Serial_send(u8*data, u8 len)
{
    u8 i;
    for(i=0;i

改之后的set_computer_value函数和新增的Serial_send函数如图

野火PID串口助手的移植思路(文末有源码链接)_第1张图片

野火PID串口助手的移植思路(文末有源码链接)_第2张图片

5receiving_process()函数的修改方法 

在这里我们需要把每隔case中不需要的删除掉,留下自己所需要的
同时设置PID值时要设置自己的PID的三个参数

我这里是在外面定义了KP,KI,KD和target_value
int kp=0;
int ki=0;
int kd=0;
int target_value=0;

在下面这个函数中直接对这四个变量赋值

/**
 * @brief   接收的数据处理
 * @param   void
 * @return  -1:没有找到一个正确的命令.
 */
int8_t receiving_process(void)
{
  uint8_t frame_data[128];         // 要能放下最长的帧
  uint16_t frame_len = 0;          // 帧长度
  uint8_t cmd_type = CMD_NONE;     // 命令类型
  
  while(1)
  {
    cmd_type = protocol_frame_parse(frame_data, &frame_len);
    switch (cmd_type)
    {
      case CMD_NONE:
      {
        return -1;
      }

      case SET_P_I_D_CMD:
      {
        uint32_t temp0 = COMPOUND_32BIT(&frame_data[13]);
        uint32_t temp1 = COMPOUND_32BIT(&frame_data[17]);
        uint32_t temp2 = COMPOUND_32BIT(&frame_data[21]);
        
        float p_temp, i_temp, d_temp;
        
        p_temp = *(float *)&temp0;
        i_temp = *(float *)&temp1;
        d_temp = *(float *)&temp2;
        
//        set_p_i_d(p_temp, i_temp, d_temp);    // 设置 P I D
		  kp=p_temp;
		  ki=i_temp;
		  kd=d_temp;
      }
      break;

      case SET_TARGET_CMD:
      {
        int actual_temp = COMPOUND_32BIT(&frame_data[13]);    // 得到数据
        
//        set_point = (actual_temp);    // 设置目标值
		  target_value=actual_temp;
      }
      break;
      
      case START_CMD:
      {
//        set_motor_enable();              // 启动电机
      }
      break;
      
      case STOP_CMD:
      {
//        set_motor_disable();              // 停止电机
      }
      break;
      
      case RESET_CMD:
      {
//        HAL_NVIC_SystemReset();          // 复位系统
		  NVIC_SystemReset(); 
      }
      break;
      
      case SET_PERIOD_CMD:
      {
//        uint32_t temp = COMPOUND_32BIT(&frame_data[13]);     // 周期数
//        SET_BASIC_TIM_PERIOD(temp);                             // 设置定时器周期1~1000ms
      }
      break;

      default: 
        return -1;
    }
  }
}

 6对串口中断的修改

/**
  * 函    数:USART1中断函数
  * 参    数:无
  * 返 回 值:无
  * 注意事项:此函数为中断函数,无需调用,中断触发后自动执行
  *           函数名为预留的指定名称,可以从启动文件复制
  *           请确保函数名正确,不能有任何差异,否则中断函数将不能进入
  */
void USART1_IRQHandler(void)
{
//	if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)		//判断是否是USART1的接收事件触发的中断
//	{
//		Serial_RxData = USART_ReceiveData(USART1);				//读取数据寄存器,存放在接收的数据变量
//		Serial_RxFlag = 1;										//置接收标志位变量为1
//		USART_ClearITPendingBit(USART1, USART_IT_RXNE);			//清除USART1的RXNE标志位
//																//读取数据寄存器会自动清除此标志位
//																//如果已经读取了数据寄存器,也可以不执行此代码
//	}
	
	if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)		//判断是否是USART1的接收事件触发的中断
	{
	uint8_t a=USART_ReceiveData(USART1);
	protocol_data_recv(&a,1);
	USART_ClearITPendingBit(USART1, USART_IT_RXNE);
	}	
}

7最后主函数中使用相应函数即可使用 

int main(void)
{

	/*串口初始化*/
	Serial_Init();		//串口初始化
	
	protocol_init();//协议初始化
	while (1)
	{
		receiving_process();
		
		set_computer_value(SEND_FACT_CMD, CURVES_CH1, &target_value, 1);			 // 给通道 1 发送实际值,这里target_value代替	
		//set_computer_value(SEND_TARGET_CMD, CURVES_CH1, &target_value, 1);     // 给通道 1 发送目标值
		
	

	}
}

工程链接:

通过网盘分享的文件:野火串口助手
链接: https://pan.baidu.com/s/1zjML4QHsR5RNKMqRSHU7yQ?pwd=y425 提取码: y425 
--来自百度网盘超级会员v3的分享

你可能感兴趣的:(杂项,移植代码,算法,开发语言,stm32,单片机,c#)