一,通信介绍
1.通信帧格式介绍
为了适应多种数据类型的传输,保证高效的通信效率,所有数据的通信,均需要遵守本通信帧格式。本格式在 确保通信高效、源码简单、可移植性高的基础上,实现数据正确性判断,有效避免数据传输过程中出现的错误数据 导致的错误解析。 具体帧格式如下:
DATA 数据内容中的数据,采用小端模式,低字节在前,高字节在后。
为了提高数据传输的效率,当有浮点数类型数据需要传输时,根据数据类型的特点,适当截取小数点后固定几 位,比如飞控姿态数据,保留角度的小数点后两位即可,比如经纬度信息,保留小数点后 7 位即可,然后通过小数 点移动(扩大 10 的 n 次方),将浮点数转化成整数类型进行传输,可缩短数据长度,并且避免浮点数传输时发生异 常,解析成非法浮点数。类似数据会在协议中著名,如 A*100,就代表将数据 A 只保留两位小数,乘以 100 进行传 输,用户使用时将收到的数据除以 100 即可。
二,stm32代码实现
首先我们要知道如何实现,我们只需要知道其通信协议以及串口的发送与接收即可实现简单数据收发波形显示
2.1.通信协议
//数据拆分宏定义,在发送大于1字节的数据类型时,比如int16、float等,需要把数据拆分成单独字节进行发送
#define BYTE0(dwTemp) ( *( (char *)(&dwTemp)) )
#define BYTE1(dwTemp) ( *( (char *)(&dwTemp) + 1) )
#define BYTE2(dwTemp) ( *( (char *)(&dwTemp) + 2) )
#define BYTE3(dwTemp) ( *( (char *)(&dwTemp) + 3) )
u8 BUFF[30];
void sent_data(u16 A,u16 B,u8 C)
{
int i;
u8 sumcheck = 0;
u8 addcheck = 0;
u8 _cnt=0;
BUFF[_cnt++]=0xAA;//帧头
BUFF[_cnt++]=0xFF;//目标地址
BUFF[_cnt++]=0XF1;//功能码
BUFF[_cnt++]=0x05;//数据长度
BUFF[_cnt++]=BYTE0(A);//数据内容,小段模式,低位在前
BUFF[_cnt++]=BYTE1(A);//需要将字节进行拆分,调用上面的宏定义即可。
BUFF[_cnt++]=BYTE0(B);
BUFF[_cnt++]=BYTE1(B);
BUFF[_cnt++]=C;
for(i=0;i<BUFF[3]+4;i++)
{
sumcheck+=BUFF[i];
addcheck+=sumcheck;
}
BUFF[_cnt++]=sumcheck;
BUFF[_cnt++]=addcheck;
ANO_DT_Send_Data(BUFF, _cnt);
}
/*Send_Data函数是协议中所有发送数据功能使用到的发送函数*/
//移植时,用户应根据自身应用的情况,根据使用的通信方式,实现此函数,这里就采用有线连接,发送至串口2了
void ANO_DT_Send_Data(uint8_t *dataToSend , uint8_t length)
{
Usart_Send(BUFF, 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)
{}
}
}
我们代码上传的数据一定要符合上位机的配置,A和B为int16、C为字符类型,否则上位机的数据读取不出来或者一直为0,后面我会讲上位机如何配置
2.2串口通信
u8 res
void USART3_Init(u32 baud)
{
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure; //声明一个结构体变量,用来初始化GPIO
//使能串口的RCC时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE); //使能UART3所在GPIOB的时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
//串口使用的GPIO口配置
// Configure USART3 Tx (PB.10) as alternate function push-pull
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// Configure USART3 Rx (PB.11) as input floating
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//串口中断配置
//Configure the NVIC Preemption Priority Bits
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
// Enable the USART3 Interrupt
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//配置串口
USART_InitStructure.USART_BaudRate = baud;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
// Configure USART3
USART_Init(USART3, &USART_InitStructure);//配置串口3
// Enable USART3 Receive interrupts 使能串口接收中断
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
// Enable the USART3
USART_Cmd(USART3, ENABLE);//使能串口3
}
void UART3_IRQHandler(void)
{
if(USART_GetITStatus(USART3,USART_IT_RXNE)!=RESET)
{
USART_ClearFlag(USART3, USART_FLAG_RXNE);
res= USART_ReceiveData(USART3);
USART_SendData(USART3,res);
}
}
当我们配置好stm32后即可打开上位机进行配置
三,上位机的配置
3.1协议解析
我们首先连接设置好波特率,点击打开连接,连接成功后点击协议解析,也可点击下面的一栏进入
有些同学可能打开之后没有显示右边这些数据栏,我们只要双击这条绿色的竖线就会显示出来.
按照我上图所设置的,使能F1,数据类型只需设置前三个为int16,int16,uint8即可。下面的userdata是为了可以显示波形,大家按照上图数据位设置即可。
3.2波形显示
需要显示哪个波形,就给那个打上勾,在波形分析那里也观看你的波形各项参数,用波形调pid会更方便一些
四,注意事项
我们使用上位机进行调试时,尽量把使用到的串口中断优先级提高一些,否则上位机没办法第一时间读取检验,就会一直出错,并且单片机初始化后过1s后再打开连接上位机,否则有时候也会读不出数据
项目文件匿名上位机代码https://download.csdn.net/download/m0_53890035/85299508