4965 字
25 分钟
【电赛】02 - 2024H题自动行驶小车
注意:CCS Theia编译可能无法找到报错位置,建议每次小幅修改后就立即编译
主要问题:
-
如何进行调参?
-
如何设计一个完整的系统?
-
小车如何走直线?
- PID速度环
- 陀螺仪
-
小车在循迹时如何保证沿中线行驶?
-
如何解决陀螺仪漂移的问题
- 滤波算法
-
如何避免/减少场地干扰?
-
如何提高速度的同时保证行驶稳定?
程序结构-底层驱动
一、基础电机控制
源文件
#include "motor.h"#include <iso646.h>
/** * @brief 电机启动 * @param None * @retval None */void Motor_On(void){ DL_GPIO_setPins(GPIO_MOTOR_PIN_FSTBY_PORT, GPIO_MOTOR_PIN_FSTBY_PIN);//置位对应端口->引脚电平,STBY}
/** * @brief 电机关闭 * @param None * @retval None */void Motor_Off(void){ DL_GPIO_clearPins(GPIO_MOTOR_PIN_FSTBY_PORT, GPIO_MOTOR_PIN_FSTBY_PIN);//清除对应端口->引脚电平,STBY //逻辑口电平清除 DL_GPIO_clearPins(GPIO_MOTOR_PIN_FL1_PORT, GPIO_MOTOR_PIN_FL1_PIN); DL_GPIO_clearPins(GPIO_MOTOR_PIN_FL2_PORT, GPIO_MOTOR_PIN_FL2_PIN); DL_GPIO_clearPins(GPIO_MOTOR_PIN_FR1_PORT, GPIO_MOTOR_PIN_FR1_PIN); DL_GPIO_clearPins(GPIO_MOTOR_PIN_FR2_PORT, GPIO_MOTOR_PIN_FR2_PIN);}
/** * @brief 速度设置 * @param 左右轮占空比(百分值) * @retval None */void Set_Speed(float duty1,float duty2){ uint32_t compareValue = 0;//比较值最大为3199,最小值为0 if(duty1 < 0) { //PWM定时器向下计数,比较值计算 compareValue = 3199 - 3199 * (-duty1/100.0); //比较值设置 DL_TimerA_setCaptureCompareValue(PWM_MOTOR_INST, compareValue, DL_TIMER_CC_0_INDEX); //电机逻辑引脚设置 DL_GPIO_setPins(GPIO_MOTOR_PIN_FL2_PORT, GPIO_MOTOR_PIN_FL2_PIN); DL_GPIO_clearPins(GPIO_MOTOR_PIN_FL1_PORT, GPIO_MOTOR_PIN_FL1_PIN);
} else if(duty1 > 0) { compareValue = 3199 - 3199 * (duty1/100.0); DL_TimerA_setCaptureCompareValue(PWM_MOTOR_INST, compareValue, DL_TIMER_CC_0_INDEX); DL_GPIO_setPins(GPIO_MOTOR_PIN_FL1_PORT, GPIO_MOTOR_PIN_FL1_PIN); DL_GPIO_clearPins(GPIO_MOTOR_PIN_FL2_PORT, GPIO_MOTOR_PIN_FL2_PIN); } else { DL_GPIO_clearPins(GPIO_MOTOR_PIN_FL1_PORT, GPIO_MOTOR_PIN_FL1_PIN); DL_GPIO_clearPins(GPIO_MOTOR_PIN_FL2_PORT, GPIO_MOTOR_PIN_FL2_PIN); }
if(duty2 < 0) { compareValue = 3199 - 3199 * (-duty2/100.0); DL_TimerA_setCaptureCompareValue(PWM_MOTOR_INST, compareValue, DL_TIMER_CC_1_INDEX); DL_GPIO_setPins(GPIO_MOTOR_PIN_FR2_PORT, GPIO_MOTOR_PIN_FR2_PIN); DL_GPIO_clearPins(GPIO_MOTOR_PIN_FR1_PORT, GPIO_MOTOR_PIN_FR1_PIN);
} else if(duty2 > 0) { compareValue = 3199 - 3199 * (duty2/100.0); DL_TimerA_setCaptureCompareValue(PWM_MOTOR_INST, compareValue, DL_TIMER_CC_1_INDEX); DL_GPIO_setPins(GPIO_MOTOR_PIN_FR1_PORT, GPIO_MOTOR_PIN_FR1_PIN); DL_GPIO_clearPins(GPIO_MOTOR_PIN_FR2_PORT, GPIO_MOTOR_PIN_FR2_PIN); } else { DL_GPIO_clearPins(GPIO_MOTOR_PIN_FR1_PORT, GPIO_MOTOR_PIN_FR1_PIN); DL_GPIO_clearPins(GPIO_MOTOR_PIN_FR2_PORT, GPIO_MOTOR_PIN_FR2_PIN); }}头文件
#include "ti_msp_dl_config.h"
//宏定义简化写法#define AIN1(x) x?DL_GPIO_setPins(GPIO_MOTOR_PIN_FL1_PORT, GPIO_MOTOR_PIN_FL1_PIN):DL_GPIO_clearPins(GPIO_MOTOR_PIN_FL1_PORT, GPIO_MOTOR_PIN_FL1_PIN)#define AIN2(x) x?DL_GPIO_setPins(GPIO_MOTOR_PIN_FL2_PORT, GPIO_MOTOR_PIN_FL2_PIN):DL_GPIO_clearPins(GPIO_MOTOR_PIN_FL2_PORT, GPIO_MOTOR_PIN_FL2_PIN)#define BIN1(x) x?DL_GPIO_setPins(GPIO_MOTOR_PIN_FR1_PORT, GPIO_MOTOR_PIN_FR1_PIN):DL_GPIO_clearPins(GPIO_MOTOR_PIN_FR1_PORT, GPIO_MOTOR_PIN_FR1_PIN)#define BIN2(x) x?DL_GPIO_setPins(GPIO_MOTOR_PIN_FR2_PORT, GPIO_MOTOR_PIN_FR2_PIN):DL_GPIO_clearPins(GPIO_MOTOR_PIN_FR2_PORT, GPIO_MOTOR_PIN_FR2_PIN)
void Motor_On(void);void Motor_Off(void);void Set_Speed(float duty1,float duty2);二、PID控制算法
参数定义
#include "PID.h"#include "Serial.h"#include "main.h"#include "math.h"#include "ti_msp_dl_config.h"
uint8_t Trace_Byte;//循迹总状态uint8_t Angle_PID_Flag =0;//角度环开启标志位uint8_t CV_flag=0;//视觉循迹开启标志位uint8_t Test_pid_flag=0;//PID调试标志位float K_trace = 0.0615;//减速系数float Speed_midset = 30;//预设直线速度
/*灰度GPIO口宏定义*/#define Read_Huidu_IO1 ((DL_GPIO_readPins(GPIO_TRACE_PIN_TRACE_0_PORT,GPIO_TRACE_PIN_TRACE_0_PIN)结构体类型
创建结构体类型的方法,方便进行同类型变量元素组的创建,减少代码重复度。
这里定义了PID类型结构体,在之后新建其他用于PID控制的变量组时,只要用PID类型定义变量即可、
/*结构体类型定义*/typedef struct{ float Kp; float Ki; float Kd; float error; float last_error; float error_sum; float error_difference; float velocity_sum;}PID;PID初始化相关函数
/*PID类型变量声明*/PID Velocity;PID Velocity_L;PID trace_hd;
/*速度环PID*/
void Velocity_PID_Init(){ Velocity.Kp = -1.33; Velocity.Kd = -0.22; Velocity.Ki = -0.012;}
void Velocity_L_PID_Init(){ Velocity_L.Kp = -1.34; Velocity_L.Kd = -0.22; Velocity_L.Ki = -0.012;}
/*循迹环PID*/void trace_hd_PID_Init(){ trace_hd.Kp = -1.75; trace_hd.Kd = -0.65; trace_hd.Ki = 0;}
/*PID初始化*/void PID_Init(){ Velocity_PID_Init(); Velocity_L_PID_Init(); trace_hd_PID_Init();}
/*限幅函数*/void I_amplitude_limiting(float number,float *Error_sum){ if(*Error_sum > number) { *Error_sum = number; }
if(*Error_sum <- number) { *Error_sum = -number; }}辅助函数
/*限幅函数*/void I_amplitude_limiting(float number,float *Error_sum){ if(*Error_sum > number) { *Error_sum = number; }
if(*Error_sum <- number) { *Error_sum = -number; }}
/** * @brief 获取灰度巡线路数 * @param 无 * @retval 识别路数 */char Huidu_Counter(){ uint8_t hd_sum = 0;
for(int i=0;i<7;i++)//灰度循迹个数统计 { if(((~Trace_Byte)>>i)&0x01) hd_sum++; }
return hd_sum;}
/** * @brief 灰度状态读取函数 * @param 无 * @retval 无 */void Get_TraceData(){ Trace_Byte = (Read_Huidu_IO1<<7) + (Read_Huidu_IO2 << 6) + (Read_Huidu_IO3 << 5) + (Read_Huidu_IO4 <<4) + (Read_Huidu_IO5 << 3) +(Read_Huidu_IO6 <<2) +(Read_Huidu_IO7 <<1) + Read_Huidu_IO8;//8路灰度循迹状态}1.循迹控制(PD控制+自适应曲线减速)
此函数包含:
- 循迹路数统计:可用于判断小车是否脱线、循线、特征值检测
- 适用于圆弧的循迹状态穷举
- 自适应的曲线减速函数,提高循迹的稳定性
- PD环控制,提高循迹的抗干扰能力与拟合程度
/*八路循迹环PID控制器*/float Turn_hd_PID(){ uint8_t temp_hd_sum = 0;
temp_hd_sum = Huidu_Counter();
if(temp_hd_sum <=2)//差速循迹 { switch(Trace_Byte) { case 0xE7: // 1110 0111 case 0xC3: // 1100 0011 trace_hd.error = 0; break; case 0x00: // 0000 0000 case 0x0F: // 0000 1111 case 0x07: // 0000 0111 trace_hd.error = -9; break; case 0xF0: // 1111 0000 case 0xE0: // 1110 0000 trace_hd.error = 9; break; case 0xE3: // 1110 0011 case 0xF7: // 1111 0111 trace_hd.error = 2; break; case 0xC1: // 1100 0001 trace_hd.error = 1; break; case 0xF3: // 1111 0011 trace_hd.error = 4; break; case 0xF1: // 1111 0001 case 0xFB: // 1111 1011 trace_hd.error = 6; break; case 0xF9: // 1111 1001 case 0xFD: // 1111 1101 trace_hd.error = 8; break; case 0xF8: // 1111 1000 trace_hd.error = 10; break; case 0xFC: // 1111 1100 trace_hd.error = 12; break; case 0xFE: // 1111 1110 trace_hd.error = 14; break; case 0x87: // 1000 0111 trace_hd.error = -2; break; case 0xC7: // 1100 0111 trace_hd.error = -1; break; case 0xEF: // 1110 1111 trace_hd.error = -2; break; case 0xCF: // 1100 1111 trace_hd.error = -4; break; case 0x8F: // 1000 1111 case 0xDF: // 1101 1111 trace_hd.error = -6; break; case 0x9F: // 1001 1111 case 0xBF: // 1011 1111 trace_hd.error = -8; break; case 0x1F: // 0001 1111 trace_hd.error = -10; break; case 0x3F: // 0011 1111 trace_hd.error = -12; break; case 0x7F: // 0111 1111 trace_hd.error = -14; break; case 0xFF: // 1111 1111 trace_hd.error = trace_hd.last_error > 0 ? 16 : -16; break; default: trace_hd.error = 0; break; } } else if(temp_hd_sum >= 6 && temp_hd_sum <= 8)//掉头 { //Angle_PID_Flag = 1; } else//停车 {
}
trace_hd.error_difference = trace_hd.error - trace_hd.last_error; trace_hd.error_sum += trace_hd.error;//误差累加量 trace_hd.last_error = trace_hd.error; I_amplitude_limiting(1000,&trace_hd.error_sum);//误差累加量限幅
K_trace = 1/16.0 * pow((1-(20/Speed_midset)),0.5);//弯道减速系数 MID_Speed = Speed_midset * (1 - (uint8_t)(trace_hd.error)*K_trace) * (1 + (uint8_t)(trace_hd.error)*K_trace);//基准速度变换
return trace_hd.error*trace_hd.Kp + trace_hd.error_difference * trace_hd.Kd;//PD环循迹,比例+积分}2.陀螺仪角度环(小车姿态控制)
此函数功能:
- 输入陀螺仪传感器测量的姿态,进行PID解算
- PD环控制,确保小车转向迅速并且稳定。
/*转向环PID控制器*/float Turn_imu_PID(int yaw, int caclu_yaw){ float Kp = -1.35; float Kd = -9.5; float Ki = 0;
static float error ; static float last_error; static float error_diff; static float error_sum;
error = yaw -caclu_yaw; error_sum += error;
I_amplitude_limiting(1000,&error_sum);//误差累加量限幅
error_diff = error-last_error; last_error = error;
if (error > 180) // 防止小车转到180度时一直旋转的问题 error = error - 360; if (error < -180) error = error + 360;
return Kp * error + Kd * error_diff + Ki*error_sum;}PID头文件
#include"ti_msp_dl_config.h"extern uint8_t Trace_Byte;extern uint8_t Angle_PID_Flag;extern uint8_t Test_pid_flag;extern float Speed_midset;//预设直线速度
float Turn_cv_PID(int measure, int caclu);float Turn_hd_PID();float Turn_hd_PID_Seven();float Velocity_PID_L(float velocity,float velocity_calcu);float Velocity_PID_R(float velocity,float velocity_calcu);void PID_Init();void Get_TraceData();float Turn_imu_PID(int yaw, int caclu_yaw);char Huidu_Counter();三、陀螺仪串口通信
#include "ti_msp_dl_config.h"#include "Delay.h"
// 定义接收变量uint8_t RollL, RollH, PitchL, PitchH, YawL, YawH, VL, VH, SUM;float Pitch,Roll,Yaw;// 串口接收状态标识#define WAIT_HEADER1 0#define WAIT_HEADER2 1#define RECEIVE_DATA 2
uint8_t RxState_JY = WAIT_HEADER1;uint8_t receivedData[9];uint8_t dataIndex = 0;
//发送置偏航角置零命令void Serial_JY61P_Zero_Yaw(void){ DL_UART_Main_transmitDataBlocking(UART_JY61P_INST,0XFF); DL_UART_Main_transmitDataBlocking(UART_JY61P_INST,0XAA); DL_UART_Main_transmitDataBlocking(UART_JY61P_INST,0X69); DL_UART_Main_transmitDataBlocking(UART_JY61P_INST,0X88); DL_UART_Main_transmitDataBlocking(UART_JY61P_INST,0XB5); delay_ms(100); DL_UART_Main_transmitDataBlocking(UART_JY61P_INST,0XFF); DL_UART_Main_transmitDataBlocking(UART_JY61P_INST,0XAA); DL_UART_Main_transmitDataBlocking(UART_JY61P_INST,0X01); DL_UART_Main_transmitDataBlocking(UART_JY61P_INST,0X04); DL_UART_Main_transmitDataBlocking(UART_JY61P_INST,0X00); delay_ms(100); DL_UART_Main_transmitDataBlocking(UART_JY61P_INST,0XFF); DL_UART_Main_transmitDataBlocking(UART_JY61P_INST,0XAA); DL_UART_Main_transmitDataBlocking(UART_JY61P_INST,0X00); DL_UART_Main_transmitDataBlocking(UART_JY61P_INST,0X00); DL_UART_Main_transmitDataBlocking(UART_JY61P_INST,0X00);
}头文件
#ifndef __JY61P_H#define __JY61P_H
void Serial_JY61P_Zero_Yaw(void);void UART_JY61P_INST_IRQHandler(void);extern float Pitch,Roll,Yaw;#endif四、常规外设串口通信
1. 变量声明
#include "stdio.h"#include "string.h"#include "ti_msp_dl_config.h"#include "main.h"#define BUFFER_SIZE 256 // 定义缓冲区大小
uint8_t Serial_RxPacket[100];/*PID调试*/float Test_Kp;//比例float Test_Ki;//积分float Test_Kd;//微分float Test_Ks;//目标速度
/*系统调试串口变量*/uint8_t Serial_RxFlag;uint8_t RxState = 0;uint8_t pRxState;//表示当前接收的是第几个变量uint8_t RxData_type;
/*上位机串口变量*/uint8_t Soc_RxFlag;uint8_t RxState_SOC = 0;uint8_t SOC_RxData_type;uint8_t SOC_pRxState;//串口接收数据索引号
/*串口屏串口变量*/uint8_t Screen_RxFlag;uint8_t RxState_Screen;uint8_t Screen_RxData_type;uint8_t Screen_pRxState;//串口接收数据索引号
uint8_t Serial_RxPacket[100];2. 辅助函数
//系统串口初始化void SYS_UART0_Init(void){ NVIC_ClearPendingIRQ(UART_0_INST_INT_IRQN); NVIC_EnableIRQ(UART_0_INST_INT_IRQN); DL_UART_clearInterruptStatus(UART_0_INST,DL_UART_INTERRUPT_RX);//清除中断标志位}
//SOC通信串口初始化void SOC_UART1_Init(void){ NVIC_ClearPendingIRQ(UART_SOC_INST_INT_IRQN); NVIC_EnableIRQ(UART_SOC_INST_INT_IRQN); DL_UART_clearInterruptStatus(UART_SOC_INST,DL_UART_INTERRUPT_RX);//清除中断标志位}
//发送字符串给SOCvoid SOC_SendString(char *str){ while(*str != '\0') { DL_UART_Main_transmitDataBlocking(UART_SOC_INST, *str++); }}
//串口屏通信串口初始化void Screen_UART2_Init(void){ NVIC_ClearPendingIRQ(UART_Screen_INST_INT_IRQN); NVIC_EnableIRQ(UART_Screen_INST_INT_IRQN); DL_UART_clearInterruptStatus(UART_Screen_INST,DL_UART_INTERRUPT_RX);//清除中断标志位}
//发送字符串给串口屏void Screen_SendString(char *str){ while(*str != '\0') { DL_UART_Main_transmitDataBlocking(UART_Screen_INST, *str++); }}
void int_to_binary_string(uint32_t value, char *binary_str, int max_bits){ // 生成二进制字符串 for (int i = max_bits - 1; i >= 0; --i) { binary_str[i] = (value & (1U << i)) ? '1' : '0'; } binary_str[max_bits] = '\0'; // 确保字符串以 null 结尾}
// 将浮点数转换为字符串void float_to_string(float value, char *str, size_t size){ snprintf(str, size, "%.2f", value); // 格式化为两位小数}
void HMI_send_string(char *name, char *showdata){ char buffer[BUFFER_SIZE]; int length;
// 构造要发送的字符串,确保缓冲区足够大 length = snprintf(buffer, sizeof(buffer), "%s=\"%s\"\xff\xff\xff", name, showdata);
// 检查是否发生了缓冲区溢出 if (length >= sizeof(buffer)) { // 缓冲区溢出处理,例如可以通过截断字符串或者增加缓冲区大小来解决 // 这里只是简单地截断字符串以确保不会发送超出缓冲区的内容 buffer[sizeof(buffer) - 1] = '\0'; // 确保字符串以 null 结尾 }
// 使用 Screen_SendString 发送构造好的字符串 Screen_SendString(buffer);}
void HMI_send_number(char* name, int num){ char buffer[BUFFER_SIZE]; int length = snprintf(buffer, sizeof(buffer), "%s=%d\xff\xff\xff", name, num); if (length >= BUFFER_SIZE) { // 缓冲区溢出处理 } Screen_SendString(buffer);}
void HMI_send_float(char* name, float num){ char buffer[BUFFER_SIZE]; int num_int = (int)(num * 100); int length = snprintf(buffer, sizeof(buffer), "%s=%d\xff\xff\xff", name, num_int); if (length >= BUFFER_SIZE) { // 缓冲区溢出处理 } Screen_SendString(buffer);}
void HMI_Wave(char* name, int ch, int val){ char buffer[BUFFER_SIZE]; int length = snprintf(buffer, sizeof(buffer), "add %s,%d,%d\xff\xff\xff", name, ch, val); if (length >= BUFFER_SIZE) { // 缓冲区溢出处理 } Screen_SendString(buffer);}
void HMI_Wave_Fast(char* name, int ch, int count, int* show_data){ char buffer[BUFFER_SIZE]; int length = snprintf(buffer, sizeof(buffer), "addt %s,%d,%d\xff\xff\xff", name, ch, count); if (length >= BUFFER_SIZE) { // 缓冲区溢出处理 } Screen_SendString(buffer);
delay_ms(100);
for (int i = 0; i < count; i++) { // 发送每个字符 DL_UART_Main_transmitDataBlocking(UART_Screen_INST, (char)show_data[i]); } // 发送结束标志 Screen_SendString("\xff\xff\xff");}
void HMI_Wave_Clear(char* name, int ch){ char buffer[BUFFER_SIZE]; int length = snprintf(buffer, sizeof(buffer), "cle %s,%d\xff\xff\xff", name, ch); if (length >= BUFFER_SIZE) { // 缓冲区溢出处理 } Screen_SendString(buffer);}程序结构-中断服务函数
1.常规串口中断
- Uart0: 系统串口,用作与计算机通信调试
- Uart_Screen:串口屏串口,用于和串口屏进行通信调试,串口屏可以直接控制小车,也可以显示小车实时参数
void UART_0_INST_IRQHandler(void){ switch (DL_UART_Main_getPendingInterrupt(UART_0_INST)) {//判断中断的类型,DL_UART_Main_getPendingInterrupt(UART_0_INST)调用具有清空标志位的功能? case DL_UART_MAIN_IIDX_RX://如果触发串口接收事件 RxData = DL_UART_Main_receiveData(UART_0_INST); if(RxState2. 陀螺仪串口中断函数
用于处理从陀螺仪传感器接收到的通信数据,其中主要的部分是Roll,Pitch,Yaw角
// 串口中断处理函数void UART_JY61P_INST_IRQHandler(void) { uint8_t uartdata = DL_UART_Main_receiveData(UART_JY61P_INST); // 接收一个uint8_t数据
switch (RxState_JY) { case WAIT_HEADER1: if (uartdata程序结构-任务进程
在此文件中,定义各种不同的任务
#include "Process.h"
/**************************串口进程*********************************//*系统串口(UART1)解码进程*/void SYS_RxPro(){ /*PID调试*/ if(Serial_RxFlag) { switch(RxData_type)//判断数据帧的数据类型 { case 1: if(pRxState程序结构-路径规划
1. 路径1
/*******************************路线进程***********************************///要求1void LX_Proc_1(){ uint8_t temp_hd_sum; static uint8_t LX_state = 0;
temp_hd_sum = Huidu_Counter();
if(LX_state ==0) { Speed_midset = 30 - NEncoder.right_motor_total_cnt/8000 * 15.0;
if(temp_hd_sum >=1) { beep_flag = 1; LX_state = 1; Motor_Off(); } }}2. 路径2
//要求2void LX_Proc_2(){ uint8_t temp_hd_sum; static uint8_t LX_state = 0; static uint32_t LuChen_Counter;
temp_hd_sum = Huidu_Counter();
//LuChen_Counter = (NEncoder.left_motor_total_cnt + NEncoder.right_motor_total_cnt)/2;
if(LX_state3. 路径3
//要求3void LX_Proc_3(){ uint8_t temp_hd_sum; static uint8_t LX_state = 0; static uint8_t i;
temp_hd_sum = Huidu_Counter();
if(LX_state4. 路径4
//要求4void LX_Proc_4(){ uint8_t temp_hd_sum; static uint8_t LX_state = 0; static uint8_t i;
temp_hd_sum = Huidu_Counter(); K_ZX = 1-(20/Speed_ZX);
if(LX_state程序结构-主程序
1. 参数声明
#include "main.h"#include "OLED.h"#include "Serial.h"#include "nqei.h"#include "ti/driverlib/dl_gpio.h"#include "ti_msp_dl_config.h"#include <stdlib.h>#include "Path.c"
uint32_t Key_Number;//按键调试uint8_t Key_Val,Key_Down,Key_Up,Key_Old;
//PS:PWM可调范围,0~100以内任意浮点数float MT_L = 20.0;//左轮速度初值float MT_R = 20.0;//右轮速度初值
uint8_t RxData;//串口接收寄存器存储变量uint8_t MID_Speed;//基准速度
float yaw_val;//记录Yaw角float yaw_detect;//预测yaw角
static float Velocity_IL,Velocity_IR;//左右轮速度环PID输入static float Dif_Out;//差速环PID输出
uint8_t Motor_flag;//电机使能标志位
float M_Speed_L;//左轮测速float M_Speed_R;//右轮测速
uint32_t Timer_Angel_Sleep;uint8_t Timer_Angel_Sleep_flag;
//外设列表://1.GPIO LED//2.PWM 定时器G0,两路PWM//3.定时器 定时器A0//4.串口 USART0:调试串口//5.按键//6.OLED 硬件IIC//7.MPU6050 硬件IIC//8.串口屏//9.陀螺仪串口
uint8_t beep_flag = 0;//声光提示标志位uint8_t beep_key_flag;//按键提示音uint8_t beep_timer = 0;//声光提示持续时间
uint8_t flag = 0;char hmi_speed[]="n1.txt";//测速char hmi_yaw[]="n2.txt";//测角度char hmi_trace[]="n3.txt";//测循迹char hmi_totol[]="n4.txt";//测里程char hmi_imu[]="n5.txt";//测记忆角度char data_HMI[]="";//串口屏数据存储空间uint8_t Key_Timer;
uint32_t Timer_1ms_counter;uint8_t System_Mode;
uint8_t WD_Protect_Flag;uint8_t WD_Protect_time;uint8_t WD_Protect_err;
float K_ZX = 0;/*初始加速函数*/void Speed_InitPro(uint8_t x){ uint8_t temp; uint8_t i; for(i=0;i<x;i++) { Set_Speed(i,i); }}2. 主循环
执行系统所需要的初始化部分,注意初始化的顺序。
用于显示的部分放在主循环中。
/*初始加速函数*/void Speed_InitPro(uint8_t x){ uint8_t temp; uint8_t i; for(i=0;i<x;i++) { Set_Speed(i,i); }}
/*开启系统时钟中断,会导致串口工作异常或者程序卡死*/int main(void){ SYSCFG_DL_init();//syscfg初始化 delay_ms(100);//等待初始化稳定 OLED_Init();//OLED初始化 OLED_ShowString(16,8,"OK",8); delay_ms(100);//等待陀螺仪稳定 Motor_Off();//初始电机关闭,等待按键控制
SYS_UART0_Init();//串口0初始化 Screen_UART2_Init();//串口2初始化
BP_Encoder_Init();//编码器初始化 PID_Init(); delay_ms(1000);//等待初始化稳定 //Speed_InitPro(Speed_midset*0.8);
//编码器中断使能 delay_ms(50);//等待初始化稳定 TIMER_1_Init();//定时器1初始化 TIMER_2_Init();
NVIC_EnableIRQ(UART_JY61P_INST_INT_IRQN); while (1) { Oled_Proc(); HMI_Proc(); }}维特陀螺仪
一、通信协议

1.1 读格式

代码实现(仅读取角度):
// 定义接收变量uint8_t RollL, RollH, PitchL, PitchH, YawL, YawH, VL, VH, SUM;float Pitch,Roll,Yaw;
// 串口接收状态标识#define WAIT_HEADER1 0#define WAIT_HEADER2 1#define RECEIVE_DATA 2
uint8_t RxState_JY = WAIT_HEADER1;uint8_t receivedData[9];//接收数据储存数组uint8_t dataIndex = 0;
// 串口中断处理函数void UART_JY61P_INST_IRQHandler(void) { uint8_t uartdata = DL_UART_Main_receiveData(UART_JY61P_INST); // 接收一个uint8_t数据 switch (RxState_JY) { case WAIT_HEADER1: if (uartdata1.2 写格式

代码实现(Z轴置零):
//发送置偏航角置零命令void Serial_JY61P_Zero_Yaw(void){
/*解锁指令*/ DL_UART_Main_transmitDataBlocking(UART_JY61P_INST,0XFF); DL_UART_Main_transmitDataBlocking(UART_JY61P_INST,0XAA); DL_UART_Main_transmitDataBlocking(UART_JY61P_INST,0X69); DL_UART_Main_transmitDataBlocking(UART_JY61P_INST,0X88); DL_UART_Main_transmitDataBlocking(UART_JY61P_INST,0XB5);
delay_ms(200);//延迟200ms
/*修改指令(Z轴置零)*/ DL_UART_Main_transmitDataBlocking(UART_JY61P_INST,0XFF); DL_UART_Main_transmitDataBlocking(UART_JY61P_INST,0XAA); DL_UART_Main_transmitDataBlocking(UART_JY61P_INST,0X01); DL_UART_Main_transmitDataBlocking(UART_JY61P_INST,0X04); DL_UART_Main_transmitDataBlocking(UART_JY61P_INST,0X00);
delay_ms(3000);//延迟3秒
/*保存指令*/ DL_UART_Main_transmitDataBlocking(UART_JY61P_INST,0XFF); DL_UART_Main_transmitDataBlocking(UART_JY61P_INST,0XAA); DL_UART_Main_transmitDataBlocking(UART_JY61P_INST,0X00); DL_UART_Main_transmitDataBlocking(UART_JY61P_INST,0X00); DL_UART_Main_transmitDataBlocking(UART_JY61P_INST,0X00);
} 【电赛】02 - 2024H题自动行驶小车
http://www.turinblog.cn/posts/电赛02---2024h题自动行驶小车/