对于匿名四轴上位机,我相信玩四轴的小伙伴们应该不会陌生。个人觉得,这款软件最为强大的部分便是拿来调试pid,从
观察波形
到在线调参
简直一气呵成,极为便利。
但是,我们也经常会碰到其他系统的pid调节,这时候,把匿名上位机变成一款普遍适用的pid参数调试软件
就很有必要了。
本文利用匿名上位机的高级收码
功能,接收stm32获取的ds18b20温度传感器的数据,并绘制其曲线
。
1. 数据格式
保证上位机与STM32能够正常通信,必须采用规定的格式来发送数据,总结一下,就是:帧头+功能字+长度+数据+校验
。匿名提供了一些特殊的功能字用于飞控数据的传输。我们这里采用高级收码
。帧头是AAAA
,功能字是F1到FA
,也就是说最多可以接受十个用户自定义的数据类型。
几点说明:
▲SUM等于从该数据帧第一字节开始,也就是帧头开始,至该帧数据的最后一字节所有字节的和
,只保留低八位
,高位舍去。
▲协议中长度字节LEN表示该数据帧内包含数据
的字节总长度,不包括帧头、功能字、长度字节和最后的校验位,只是数据的字节长度和
。比如该帧数据内容为3个int16型数据,那么LEN等于6
上位机高级收码设置界面
2. 代码实现
- 数据发送至串口
/*Send_Data函数是协议中所有发送数据功能使用到的发送函数*/
//移植时,用户应根据自身应用的情况,根据使用的通信方式,实现此函数,这里就采用有线连接,发送至串口2了
void ANO_DT_Send_Data(uint8_t *dataToSend , uint8_t length)
{
Usart_Send(dataToSend, length);
}
/
void Usart_Send(uint8_t *data, uint8_t length)
{
uint8_t i;
for(i=0;i<length;i++)
{
USART_SendData(USART1, *(data+i));
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
{}
}
}
值得说明的一个问题是,使用USART_SendData()函数非连续发送单个字符是没有问题的;当连续发送字符时(两个字符间没有延时),就会发现发送缓冲区有溢出现象。若发送的数据量很小时,此时串口发送的只是最后一个字符,当发送数据量大时,就会导致发送的数据莫名其妙的丢失。
所以,在这里我们在每一个字符发送后检测状态位。
USART_SendData(USART1, RxBuffer[TxCounter]);
while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET){} //等待发送缓冲区空才能发送下一个字符
- 处理发送数据请求
结合定时器,设置各个数据发送标志位,可以定期发送各种数据到上位机。这里为了简单,只发送DS18B20读取的温度数据了。
//Data_Exchange函数处理各种数据发送请求,比如想实现每5ms发送一次传感器数据至上位机,即在此函数内实现
//此函数每1ms调用一次
void ANO_DT_Data_Exchange(void)
{
static uint8_t cnt = 0;
cnt++;
if(cnt>=10)//10MS
{
cnt = 0;
send_flag = 1;
}
/
if(send_flag)
{
send_flag = 0;
ANO_DT_Send_temperature(temperature);
}
}
- 将数据按照格式发送
void ANO_DT_Send_temperature(short temperature)
{
u8 _cnt=0,sum = 0,i;
short _temp;
data_to_send[_cnt++]=0xAA;
data_to_send[_cnt++]=0xAA;
data_to_send[_cnt++]=0xF1; //自定义帧1
data_to_send[_cnt++]=0;
_temp=temperature;
data_to_send[_cnt++]=BYTE1(_temp);
data_to_send[_cnt++]=BYTE0(_temp);//数据部分
data_to_send[3] = _cnt-4;//长度位
for(i=0;i<_cnt;i++)
sum += data_to_send[i];
data_to_send[_cnt++]=sum;//校验位
ANO_DT_Send_Data(data_to_send, _cnt);
}
- 上位机界面
温度数据被放大了10倍