在STM32C8T6系统板,在调平衡小车时,用标准库,通过串口怎么实现将PID_OUT,Target_Speed,Vertical_Kp,Vertical_Kd,Velocity_Kp,这几个数据打印到VOFA+软件上,形成波形图,并可以实现实时调参
时间: 2025-06-14 20:11:49 浏览: 21
<think>好的,我现在要解决的问题是用户如何在STM32C8T6上使用标准库通过串口将PID参数发送到VOFA+软件,生成波形图并实时调整。首先,我需要回顾用户提供的参考信息,然后逐步分析所需的步骤。
用户提到他们使用的是STM32C8T6系统板,并且参考了正点原子的代码,其中MPU6050和OLED的底层代码已经移植。他们的平衡小车控制逻辑涉及PID算法,直立环和速度环的输出通过中断函数处理,然后驱动电机。现在的问题是如何通过串口发送这些数据到VOFA+,实现波形显示和实时调参。
首先,我需要明确VOFA+的要求。VOFA+通常支持多种数据协议,比如FireWater协议,它使用特定的数据格式,比如以“:”分隔数据,以“\n”结尾。用户需要将PID_OUT、目标速度、Vertical_Kp等变量按照这种格式发送,才能在VOFA+中正确显示波形。
接下来,我需要考虑STM32端的实现。用户使用标准库,所以需要配置USART,设置合适的波特率(比如115200),并确保发送函数正确。可能需要使用DMA或中断方式发送数据,但如果是实时调参,可能发送频率不需要太高,所以查询方式发送可能足够,但需注意不要阻塞主程序。
然后是数据打包的问题。如何将浮点型数据转换成字节流发送。通常,可以将浮点数转换为字节数组,然后通过串口发送。例如,使用联合体(union)或者指针的方式将float分解为四个字节,然后发送。同时,需要按照VOFA+的协议格式来组织数据,比如每个变量之间用冒号分隔,最后加换行符。
另外,实时调参需要STM32能够接收来自VOFA+的数据,比如新的PID参数。这需要实现串口接收中断,解析接收到的数据,并更新相应的变量。例如,当VOFA+发送“Kp=1.5,Kd=0.2”这样的字符串时,STM32需要解析这些参数并更新Vertical_Kp和Vertical_Kd的值。
可能需要注意的问题包括:数据同步问题,比如如何确保发送的数据在VOFA+中正确对应各个通道;浮点数传输的精度问题;以及如何避免串口缓冲区溢出。此外,波特率设置需要匹配,数据发送的频率不能过高,否则可能导致丢数据。
总结步骤应该是:
1. 配置USART,初始化串口通信。
2. 实现数据打包函数,将PID参数按照VOFA+的协议格式打包。
3. 定时或在控制循环中发送数据。
4. 实现串口接收中断,解析接收到的参数并更新变量。
5. 在VOFA+中设置对应的协议和波形显示。
需要验证的地方包括:数据是否正确发送,VOFA+是否能正确解析,参数调整是否能实时生效,以及是否影响控制循环的实时性。
可能还需要考虑使用DMA发送以减少CPU负担,但需要根据具体情况判断。此外,使用标准库的函数,如USART_SendData,可能需要循环发送每个字节,尤其是当数据长度超过单个字节时。</think>### 实现步骤及代码示例
#### 1. 配置串口通信(USART)
在STM32C8T6上启用USART(如USART1),配置波特率为115200,8位数据位,无校验,1位停止位。使用标准库函数初始化:
```c
// 串口初始化配置(以USART1为例)
void USART1_Init(void) {
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);
// 配置TX(PA9)和RX(PA10)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);
}
```
#### 2. 数据打包与发送
将PID参数按VOFA+的**FireWater协议**格式发送,例如:
`PID_OUT:Target_Speed:Vertical_Kp:Vertical_Kd:Velocity_Kp\n`
```c
// 发送函数(浮点转字节流)
void Send_Data_To_VOFA(float pid_out, float target_speed, float kp_v, float kd_v, float kp_vel) {
uint8_t buffer[50];
int len = sprintf((char*)buffer, "%.2f:%.2f:%.2f:%.2f:%.2f\n", pid_out, target_speed, kp_v, kd_v, kp_vel);
for (int i = 0; i < len; i++) {
USART_SendData(USART1, buffer[i]);
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}
}
```
#### 3. 在控制循环中调用发送函数
在平衡小车的主循环或中断中周期性地发送数据(建议频率50-100Hz):
```c
// 示例:直立环控制中调用发送
void Vertical_Control(void) {
// ...PID计算...
Send_Data_To_VOFA(PID_OUT, Target_Speed, Vertical_Kp, Vertical_Kd, Velocity_Kp);
}
```
#### 4. 实现实时调参(接收VOFA+指令)
配置串口接收中断,解析参数指令(如`Kp=1.2,Kd=0.5`):
```c
// 串口接收中断服务函数
uint8_t rx_buf[64];
uint8_t rx_index = 0;
void USART1_IRQHandler(void) {
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
uint8_t ch = USART_ReceiveData(USART1);
if (ch == '\n') { // 指令结束符
rx_buf[rx_index] = '\0';
Parse_Command((char*)rx_buf); // 解析指令
rx_index = 0;
} else {
rx_buf[rx_index++] = ch;
}
}
}
// 解析指令并更新参数
void Parse_Command(char* cmd) {
char *token = strtok(cmd, ",");
while (token != NULL) {
if (strstr(token, "Kp=")) {
sscanf(token, "Kp=%f", &Vertical_Kp);
} else if (strstr(token, "Kd=")) {
sscanf(token, "Kd=%f", &Vertical_Kd);
}
token = strtok(NULL, ",");
}
}
```
#### 5. VOFA+配置
1. 打开VOFA+,选择串口端口并设置相同的波特率(115200)。
2. 在控件面板中添加**Waveform**组件,绑定对应通道(PID_OUT、Target_Speed等)。
3. 添加**TextCommand**控件,设置发送格式为`Kp=1.2,Kd=0.5\n`,点击发送实时更新参数。
---
### 注意事项
1. **数据同步**:确保发送频率与VOFA+采样率匹配,避免波形抖动。
2. **浮点精度**:使用`%.2f`限制小数位数以减少数据量。
3. **中断优先级**:串口接收中断优先级需低于控制中断(如MPU6050中断)[^1]。
4. **数据校验**:可在协议中添加校验字节(如CRC8)提高可靠性。
---
阅读全文
相关推荐


















