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函数如图
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的分享