第一部分、初始化配置
步骤1、数据引擎选择JustFloat
步骤2、数据接口选择串口
步骤3、端口号选择下位机的端口
步骤4、波特率选择kiel中串口的波特率(需要一致,否则接收到的数据是乱码)
第二部分、获取下位机的波形
我读取的是MPU6050陀螺仪数据
第三部分、增加控件命令
步骤1、创建命令
我创建的命令(供参考)
步骤2、绑定命令
步骤3、设置菜单
第四部分、下位机(stm32F407)代码部分(以串口2为例)
USART2.c
#include "USART2.h"
float Serial_RxFlag_USART2;
uint16_t Serial_RxPacket_USART2[8];
uint16_t units,tens,hundreds,decimal_Firs,decimal_Sec;
int32_t P, P_integer, P_decimal, I, I_integer, I_decimal, D, D_integer, D_decimal;
void USART2_Init(int BaudRate)
{
GPIO_InitTypeDef GPIO_InitStruct;
// 1. 启用串口时钟和GPIO时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOD, &GPIO_InitStruct);
// 2. 配置串口引脚
GPIO_PinAFConfig(GPIOD, GPIO_PinSource5, GPIO_AF_USART2); // TX
GPIO_PinAFConfig(GPIOD, GPIO_PinSource6, GPIO_AF_USART2); // RX
// 3. 初始化串口设置
USART_InitTypeDef USART_InitStruct;
USART_InitStruct.USART_BaudRate = BaudRate;
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
USART_InitStruct.USART_StopBits = USART_StopBits_1;
USART_InitStruct.USART_Parity = USART_Parity_No;
USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init(USART2, &USART_InitStruct);
// 4. 配置串口中断
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); // 使能接收中断
// 5. 使能串口
USART_Cmd(USART2, ENABLE);
}
void Serial_SendByte_USART2(uint8_t Byte) //串口发送一个字节
{
USART_SendData(USART2, Byte);
while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
}
void Serial_SendArray_USART2(uint8_t *Array, uint16_t Length) //串口发送一个数组(在串口助手中一般使用HEX模式)
{
uint16_t i;
for (i = 0; i < Length; i ++)
{
Serial_SendByte_USART2(Array[i]);
}
}
void USART_SendString_USART2(char *String) //串口发送一个字符串(与发送数组类似)(在串口助手中使用一般使用文本模式)
{
uint8_t i;
for (i = 0; String[i] != '\0'; i ++)
{
Serial_SendByte_USART2(String[i]);
}
}
uint32_t Serial_Pow(uint32_t X, uint32_t Y)
{
uint32_t Result = 1;
while (Y --)
{
Result *= X;
}
return Result;
}
void Serial_SendNumber_USART2(uint32_t Number, uint8_t Length) //发送字符形式的数字
{
uint8_t i;
for (i = 0; i < Length; i ++)
{
Serial_SendByte_USART2(Number / Serial_Pow(10, Length - i - 1) % 10 + '0'); //数字的类型与字符型的相差0x30("0")
}
}
uint8_t Serial_GetRxFlag_USART2(void) //接收标志位
{
if (Serial_RxFlag_USART2 == 1)
{
Serial_RxFlag_USART2 = 0;
return 1;
}
return 0;
}
typedef union
{
float fdata; // 浮点数
unsigned long ldata; // 无符号长整型(通常是32位)
} FloatLongType;
void vofa_To_four(float x,unsigned char byte[]) /*vofa上位机,将参数X转化为四个8位数据*/
{
FloatLongType fl;
fl.fdata=x;
byte[0] = (unsigned char)fl.ldata;
byte[1] = (unsigned char)(fl.ldata >> 8);
byte[2] = (unsigned char)(fl.ldata >> 16);
byte[3] = (unsigned char)(fl.ldata >> 24);
}
void Send_vofa(float x)
{
u8 vofa[4] = {0};
u8 tail[4] = {0x00, 0x00, 0x80, 0x7f};
vofa_To_four(x, vofa);
Serial_SendArray_USART2(vofa, 4);
Serial_SendArray_USART2(tail, 4);
}
void USART2_IRQHandler(void) //设置一个标志位
{
static uint8_t flag_P, flag_I, flag_D; //静态变量只在本函数中使用,初始化一次
static uint8_t pRxPacket = 0;
if (USART_GetITStatus(USART2, USART_IT_RXNE) == SET)
{
uint16_t RxData = USART_ReceiveData(USART2);
if(RxData == 80) /*获取VOFA上位机P的值*/
{
flag_P = 1;
}
else if(flag_P == 1)
{
Serial_RxPacket_USART2[pRxPacket] = RxData;
pRxPacket ++;
if((Serial_RxPacket_USART2[6] == 64)||(Serial_RxPacket_USART2[5] == 64)||(Serial_RxPacket_USART2[4] == 64))
{
if(pRxPacket == 7)
{
hundreds = Serial_RxPacket_USART2[0] - '0';
tens = Serial_RxPacket_USART2[1] - '0';
units = Serial_RxPacket_USART2[2] - '0';
decimal_Firs = Serial_RxPacket_USART2[4] - '0';
decimal_Sec = Serial_RxPacket_USART2[5] - '0';
P_decimal = decimal_Firs * 10 + decimal_Sec;
P_integer = hundreds * 100 + tens * 10 + units;
P = P_integer + P_decimal / 100;
flag_P = 0;
pRxPacket=0;
Serial_RxPacket_USART2[6]='0';
}
else if(pRxPacket == 6)
{
tens = Serial_RxPacket_USART2[0] - '0';
units = Serial_RxPacket_USART2[1] - '0';
decimal_Firs = Serial_RxPacket_USART2[3] - '0';
decimal_Sec = Serial_RxPacket_USART2[4] - '0';
P_integer = tens * 10 + units;
P_decimal = decimal_Firs * 10 + decimal_Sec;
P = P_integer + P_decimal / 100;
flag_P = 0;
pRxPacket=0;
Serial_RxPacket_USART2[5]='0' ;
}
else if(pRxPacket == 5)
{
units = Serial_RxPacket_USART2[0] - '0';
decimal_Firs = Serial_RxPacket_USART2[2] - '0';
decimal_Sec = Serial_RxPacket_USART2[3] - '0';
P_integer = units;
P_decimal = decimal_Firs * 10 + decimal_Sec;
P = P_integer + P_decimal / 100;
flag_P = 0;
pRxPacket=0;
Serial_RxPacket_USART2[4]='0' ;
}
}
}
if(RxData == 73) /*获取VOFA上位机I的值*/
{
flag_I = 1;
}
else if(flag_I == 1)
{
Serial_RxPacket_USART2[pRxPacket] = RxData;
pRxPacket ++;
if((Serial_RxPacket_USART2[6] == 64)||(Serial_RxPacket_USART2[5] == 64)||(Serial_RxPacket_USART2[4] == 64))
{
if(pRxPacket == 7)
{
hundreds = Serial_RxPacket_USART2[0] - '0';
tens = Serial_RxPacket_USART2[1] - '0';
units = Serial_RxPacket_USART2[2] - '0';
decimal_Firs = Serial_RxPacket_USART2[4] - '0';
decimal_Sec = Serial_RxPacket_USART2[5] - '0';
I_decimal = decimal_Firs * 10 + decimal_Sec;
I_integer = hundreds * 100 + tens * 10 + units;
I = I_integer + I_decimal / 100;
flag_I = 0;
pRxPacket=0;
Serial_RxPacket_USART2[6]='0';
}
else if(pRxPacket == 6)
{
tens = Serial_RxPacket_USART2[0] - '0';
units = Serial_RxPacket_USART2[1] - '0';
decimal_Firs = Serial_RxPacket_USART2[3] - '0';
decimal_Sec = Serial_RxPacket_USART2[4] - '0';
I_integer = tens * 10 + units;
I_decimal = decimal_Firs * 10 + decimal_Sec;
I = I_integer + I_decimal / 100;
flag_I = 0;
pRxPacket=0;
Serial_RxPacket_USART2[5]='0' ;
}
else if(pRxPacket == 5)
{
units = Serial_RxPacket_USART2[0] - '0';
decimal_Firs = Serial_RxPacket_USART2[2] - '0';
decimal_Sec = Serial_RxPacket_USART2[3] - '0';
I_integer = units;
I_decimal = decimal_Firs * 10 + decimal_Sec;
I = I_integer + I_decimal / 100;
flag_I = 0;
pRxPacket=0;
Serial_RxPacket_USART2[4]='0' ;
}
}
}
if(RxData == 68) /*获取VOFA上位机D的值*/
{
flag_D = 1;
}
else if(flag_D == 1)
{
Serial_RxPacket_USART2[pRxPacket] = RxData;
pRxPacket ++;
if((Serial_RxPacket_USART2[6] == 64)||(Serial_RxPacket_USART2[5] == 64)||(Serial_RxPacket_USART2[4] == 64))
{
if(pRxPacket == 7)
{
hundreds = Serial_RxPacket_USART2[0] - '0';
tens = Serial_RxPacket_USART2[1] - '0';
units = Serial_RxPacket_USART2[2] - '0';
decimal_Firs = Serial_RxPacket_USART2[4] - '0';
decimal_Sec = Serial_RxPacket_USART2[5] - '0';
D_decimal = decimal_Firs * 10 + decimal_Sec;
D_integer = hundreds * 100 + tens * 10 + units;
D = D_integer + D_decimal / 100;
flag_D = 0;
pRxPacket=0;
Serial_RxPacket_USART2[6]='0';
}
else if(pRxPacket == 6)
{
tens = Serial_RxPacket_USART2[0] - '0';
units = Serial_RxPacket_USART2[1] - '0';
decimal_Firs = Serial_RxPacket_USART2[3] - '0';
decimal_Sec = Serial_RxPacket_USART2[4] - '0';
D_integer = tens * 10 + units;
D_decimal = decimal_Firs * 10 + decimal_Sec;
D = D_integer + D_decimal / 100;
flag_D = 0;
pRxPacket=0;
Serial_RxPacket_USART2[5]='0' ;
}
else if(pRxPacket == 5)
{
units = Serial_RxPacket_USART2[0] - '0';
decimal_Firs = Serial_RxPacket_USART2[2] - '0';
decimal_Sec = Serial_RxPacket_USART2[3] - '0';
D_integer = units;
D_decimal = decimal_Firs * 10 + decimal_Sec;
D = D_integer + D_decimal / 100;
flag_D = 0;
pRxPacket=0;
Serial_RxPacket_USART2[4]='0' ;
}
}
}
USART_ClearITPendingBit(USART2, USART_IT_RXNE);
}
}
USART2.h
#ifndef _USART2_H_
#define _USART2_H_
#include "stm32f4xx.h"
#include "board.h"
#include "stdio.h"
void USART2_Init(int BaudRate);
void Serial_SendByte_USART2(uint8_t Byte);
void USART_SendString_USART2(char *String);
void send_pack_USART2(long int * sendbuf);
void Serial_SendNumber_USART2(uint32_t Number, uint8_t Length);
char USART2_ReceiveChar(void);
void Serial_SendArray_USART2(uint8_t *Array, uint16_t Length);
void vofa_To_four(float x,unsigned char byte[]);
void Send_vofa(float x);
#endif
main.c(测试代码)
#include "bsp_mpu6050.h"
#include <stdio.h>
#include "board.h"
#include "inv_mpu.h"
#include "OLED.h"
#include "USART2.h"
extern int32_t P, P_integer, P_decimal, I, I_integer, I_decimal, D, D_integer, D_decimal; //vofa上位机调试的PID,P整数,P小数
float pitch = 0, roll = 0, yaw = 0;
int main(void)
{
USART2_Init(115200);
board_init();
OLED_Init();
//MPU6050初始化
MPU6050_Init();
//DMP初始化
while( mpu_dmp_init() )
{
delay_ms(200);
}
while(1)
{
OLED_Refresh();
OLED_ShowString(36, 0, "P: .", 16, 1);
OLED_ShowNum(49, 0, P, 3, 16, 1, 1);
OLED_ShowNum(86, 0, P_decimal, 2, 16, 1, 1);
OLED_ShowString(36, 17, "I: .", 16, 1);
OLED_ShowNum(49, 17, I, 3, 16, 1, 1);
OLED_ShowNum(86, 17, I_decimal, 2, 16, 1, 1);
OLED_ShowString(36, 33, "D: .", 16, 1);
OLED_ShowNum(49, 33, D, 3, 16, 1, 1);
OLED_ShowNum(86, 33, D_decimal, 2, 16, 1, 1);
OLED_Refresh();
if( mpu_dmp_get_data(&pitch,&roll,&yaw) == 0 )
{
Send_vofa(roll); //发送翻滚角为例
}
}
}
程序运行成功图片
串口中断的代码还能更优化,这里就不过多阐述,USART.c文件有与上位机的通信协议,想要更深了解VOFA上位机,可以去找VOFA上位机的官方网站进行查看,感谢支持。