作为一个备赛电赛控制题,智能小车制造爱好者,山外调试助手肯定是必不可少的一个软件(最近也看到了有大佬自己开发的UI界面也有虚拟示波器选项,好像调参也贼方便,闲了研究一下。感觉我也可以做一个类似的,等我研究一下哈)。首先,山外调试助手好,好就好在他的虚拟示波器功能,简直就是PID调参好伙伴,当然山外还有其它很多功能,但是我还没用到过(手动狗头)。
闲话少说,我们先大概了解一下虚拟示波器的逻辑,虚拟示波器实际上是通过串口,将数据打印出来(比如我可以用read函数读io电平然后显示到虚拟示波器上)这样看上去就很像使用实际的示波器的效果,对于我们PID调参是非常重要的,可以帮助我们调出更完美的波形。
既然是上下位机(上位机电脑,下位机是你的板子)通信,就肯定需要一个通信的协议,山外调试助手的通信协议是这样的
帧头:0x03,0xFC
帧尾:0xFC,0x03
帧头帧尾之间就是若干个数据(注意,因为用的是串口,所以是八位数据(一个字节),也就是(0-255),那问题来了,我们的数据如果大于255呢?难道不能显示嘛?)
其实不是的,山外虚拟示波器支持int8,uint8,int16,uint16等等,所以完全够用,只不过当我们 的数据大于255时,我们需要对数据进行一个解码。举个例子
我这里的数据是uint16,也就是无符号整形,那我现在如何转化成uint8呢,只需要这样
void jiema(uint16_t a,uint16_t b)//
{
PWM1_8low = a&0x00FF; //取低8八位
PWM1_8high = (a&0xFF00)>>8; //取高8八位
PWM2_8low = b&0x00FF; //取低8八位
PWM2_8high = (b&0xFF00)>>8; //取高8八位}
这样我就可以把俩个uint16型变成四个uint8的数啦,然后按照先低后高的原则依次传输,并在山外调试助手中选择数据类型为uint16,就可以啦。
如果选择uint16,那帧头帧尾间就是俩个字节转成一个有效数据,如果是uint8,那就是一个字节的数据转化成一个。
再然后就是主要的代码了,前提概要:本位代码基于STM32F103C8T6,使用HAL库开发,软件平台基于STM32cubeIDE。使用定时器3计时一秒的中断用来更新波形(大家自用的时候可以修改初始化部分的分频系数获得一个更高的频率,我主要是嫌调试的时候频率太高影响我观感),使用定时器2的通道1,2来生成PWM波形。
下面是主要代码:
uint8_t array_head[2]={0x03,0xFC};//山外通讯协议必须为:0x03,0xFC,数据,数据.....0xFC,0x03
uint8_t array_end[2] ={0xFC,0X03};
uint8_t PWM_VALUE[4] ={};
uint16_t PWM1_16,PWM2_16;//声明PWM1,PWM2的uint16型
uint8_t PWM1_8low,PWM1_8high,PWM2_8low,PWM2_8high;//声明PWM1,PWM2的uint8型(分别为低八位和高八位)
/* USER CODE BEGIN PFP */
static void jiema(uint16_t a,uint16_t b);//a为�?�道1的�?�,b为�?�道2的�??
/* USER CODE END PFP */
/* USER CODE BEGIN 2 */
PWM1_16=500;
PWM2_16=600;
jiema(PWM1_16,PWM2_16);
HAL_TIM_Base_Start_IT(&htim3);
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);
/* USER CODE END 2 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim == (&htim3))
{
jiema(PWM1_16,PWM2_16);
array_head[0]=0x03;
array_head[1]=0xFC;
PWM_VALUE[0]=PWM1_8low;
PWM_VALUE[1]=PWM1_8high;
PWM_VALUE[2]=PWM2_8low;
PWM_VALUE[3]=PWM2_8high;
array_end[0]=0xFC;
array_end[1]=0x03;
// HAL_UART_Transmit(&huart1, array[0], 1, 10); //注:此处第二个参数必须必须必须为一个地址地址地址!!!!!!array[0]是一个数组
// HAL_UART_Transmit(&huart1, array, 8, 10);
HAL_UART_Transmit(&huart1, array_head, 2, 100);
HAL_UART_Transmit(&huart1, PWM_VALUE, 4, 100);
HAL_UART_Transmit(&huart1, array_end, 2, 100);
}
}
在这里,特别特别特别特别强调!!!!HAL_UART_Transimt这个函数的第二个参数(*pdata)必须是一个地址,这也是我调了一下午报错的罪魁祸首,C语言中数组如果的name可以表示他的地址,但是如果具体到某位数,一定是要记得是地址,不然就会发现串口发的数是错的。老规矩,有问题评论区,ヾ( ̄▽ ̄)Bye~Bye~