STM32 ------ 智能小车(串口-----蓝牙、wifi、4g 循迹------pwm调速、避障-----超声波 舵机、跟随、测速并显示在OLED上、语音小车)

串口控制小车、wifi、4g则需要发送响应指令使连接成功后才可以用串口控制
# include "string.h"
# include "stdio.h"
# include "motor.h"
// 串口接收缓存( 1 字节)
uint8_t buf = 0 ;
// 定义最大接收字节数 200 ,可根据需求调整
# define UART1_REC_LEN 200
// 接收缓冲 , 串口接收到的数据放在这个数组里,最大 UART1_REC_LEN 个字节
uint8_t UART1_RX_Buffer [ UART1_REC_LEN ];
// 接收状态
// bit15 , 接收完成标志
// bit14 , 接收到 0x0d
// bit13~0 , 接收到的有效字节数目
uint16_t UART1_RX_STA = 0 ;
# define SIZE 12
char buffer [ SIZE ];
// 接收完成回调函数,收到一个数据后,在这里处理
void HAL_UART_RxCpltCallback ( UART_HandleTypeDef * huart )
{
// 判断中断是由哪个串口触发的
if ( huart -> Instance == USART1 )
{
// 判断接收是否完成( UART1_RX_STA bit15 位是否为 1
if (( UART1_RX_STA & 0x8000 ) == 0 )
{
// 如果已经收到了 0x0d (回车),
if ( UART1_RX_STA & 0x4000 )
{
// 则接着判断是否收到 0x0a (换行)
if ( buf == 0x0a )
{
// 如果 0x0a 0x0d 都收到,则将 bit15 位置为 1
UART1_RX_STA |= 0x8000 ;
// 灯控指令
if ( ! strcmp ( UART1_RX_Buffer , "M1" ))
goForward ();
else if ( ! strcmp ( UART1_RX_Buffer , "M2" ))
goBack ();
else if ( ! strcmp ( UART1_RX_Buffer , "M3" ))
goLeft ();
else if ( ! strcmp ( UART1_RX_Buffer , "M4" ))
goRight (); else
stop ();
memset ( UART1_RX_Buffer , 0 , UART1_REC_LEN );
UART1_RX_STA = 0 ;
}
else
// 否则认为接收错误,重新开始
UART1_RX_STA = 0 ;
}
else // 如果没有收到了 0x0d (回车)
{
// 则先判断收到的这个字符是否是 0x0d (回车)
if ( buf == 0x0d )
{
// 是的话则将 bit14 位置为 1
UART1_RX_STA |= 0x4000 ;
}
else
{
// 否则将接收到的数据保存在缓存数组里
UART1_RX_Buffer [ UART1_RX_STA & 0X3FFF ] = buf ;
UART1_RX_STA ++ ;
// 如果接收数据大于 UART1_REC_LEN 200 字节),则重新开始接收
if ( UART1_RX_STA > UART1_REC_LEN - 1 )
UART1_RX_STA = 0 ;
}
}
}
// 重新开启中断
HAL_UART_Receive_IT ( & huart1 , & buf , 1 );
}
}
int fputc ( int ch , FILE * f )
{
unsigned char temp [ 1 ] = { ch };
HAL_UART_Transmit ( & huart1 , temp , 1 , 0xffff );
return ch ;
}
main.c # include "motor.h"
extern uint8_t buf ;
//main 函数
HAL_UART_Receive_IT ( & huart1 , & buf , 1 );
点动控制小车

 

PWM调速小车 开启定时器配置时间、模式 注意有效电平是高低电平、则车子另一个轮电平要相反才能驱动

 在时间内 有效电平越多 能量越大则越快

 循迹小车---

  循迹小车--- 通过PWM  解决平滑拐弯问题

 

跟随小车  模仿循迹小车

 

摇头避障小车------SG90、超声波 要用到两个定时器

SG90配置

 

 超声波配置一个1us的定时器 计数一次则是1us

 

避障完整

 

测速小车(两个中断 gpio中断 和定时器中断)

:测速模块周长知道 有20格子 每个电平转变一次就是1cm 用中断计数   配置定时器中断1s产生中断 计算出中断count++的值除以时间1s   ==== 速度

 

 将速度显示在OLED屏幕上 code MX配置I2C 连接oled屏幕

 

 语音小车 低高高 高低高 低高高 代码整合,引脚合理配置。

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
由于GPS循迹小车的代码涉及到硬件和软件的部分,需要根据具体的硬件电路和功能需求进行编写,所以无法给出一份完整的代码。不过,以下是一个基本的搭配neo-6m和mpu-6050模块的GPS循迹小车的代码框架,供参考: ``` #include "stm32f10x.h" #include "stdio.h" #include "stdlib.h" #include "math.h" #define MPU6050_ADDRESS 0xD0 #define NEO6M_ADDRESS 0x42 // 定义MPU6050寄存器地址 #define MPU6050_SMPLRT_DIV 0x19 #define MPU6050_CONFIG 0x1A #define MPU6050_GYRO_CONFIG 0x1B #define MPU6050_ACCEL_CONFIG 0x1C #define MPU6050_ACCEL_XOUT_H 0x3B #define MPU6050_ACCEL_XOUT_L 0x3C #define MPU6050_ACCEL_YOUT_H 0x3D #define MPU6050_ACCEL_YOUT_L 0x3E #define MPU6050_ACCEL_ZOUT_H 0x3F #define MPU6050_ACCEL_ZOUT_L 0x40 #define MPU6050_TEMP_OUT_H 0x41 #define MPU6050_TEMP_OUT_L 0x42 #define MPU6050_GYRO_XOUT_H 0x43 #define MPU6050_GYRO_XOUT_L 0x44 #define MPU6050_GYRO_YOUT_H 0x45 #define MPU6050_GYRO_YOUT_L 0x46 #define MPU6050_GYRO_ZOUT_H 0x47 #define MPU6050_GYRO_ZOUT_L 0x48 // 定义NEO-6M寄存器地址 #define NEO6M_GPRMC 0x01 // 定义串口波特率 #define BAUDRATE 9600 // 定义小车控制接口 #define LEFT_FORWARD_GPIO GPIO_Pin_0 #define LEFT_BACKWARD_GPIO GPIO_Pin_1 #define RIGHT_FORWARD_GPIO GPIO_Pin_2 #define RIGHT_BACKWARD_GPIO GPIO_Pin_3 // 定义小车速度 #define SPEED 50 // 定义小车方向 #define LEFT 0 #define RIGHT 1 // 定义PI控制参数 #define KP 1 #define KI 0.5 // 定义角度转弧度的常量 #define DEG_TO_RAD 0.01745329251994329576923690768489 // 定义全局变量 float gyro_x, gyro_y, gyro_z; // 陀螺仪数据 float accel_x, accel_y, accel_z; // 加速度计数据 float pitch, roll, yaw; // 欧拉角 float target_yaw; // 目标航向角 float error_yaw; // 航向角误差 float integral_error_yaw; // 航向角误差积分 float pwm_left, pwm_right; // 左右轮PWM输出 // 定义函数原型 void TIM2_IRQHandler(void); void TIM3_IRQHandler(void); void USART1_IRQHandler(void); void init_GPIO(void); void init_USART1(void); void init_I2C(void); void init_TIM2(void); void init_TIM3(void); void read_MPU6050(void); void read_NEO6M(void); void control_car(void); float get_yaw(void); int main(void) { // 初始化GPIO、USART1、I2C、TIM2、TIM3 init_GPIO(); init_USART1(); init_I2C(); init_TIM2(); init_TIM3(); // 启动TIM2、TIM3 TIM_Cmd(TIM2, ENABLE); TIM_Cmd(TIM3, ENABLE); while(1) { // 读取MPU6050、NEO-6M数据 read_MPU6050(); read_NEO6M(); // 控制小车 control_car(); } } // TIM2中断服务函数 void TIM2_IRQHandler(void) { // 清除更新中断标志位 TIM_ClearITPendingBit(TIM2, TIM_IT_Update); // 读取陀螺仪数据 I2C_AcknowledgeConfig(I2C1, ENABLE); I2C_GenerateSTART(I2C1, ENABLE); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2C1, MPU6050_ADDRESS, I2C_Direction_Transmitter); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); I2C_SendData(I2C1, MPU6050_GYRO_XOUT_H); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); I2C_GenerateSTART(I2C1, ENABLE); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2C1, MPU6050_ADDRESS, I2C_Direction_Receiver); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); gyro_x = (I2C_ReceiveData(I2C1) << 8 | I2C_ReceiveData(I2C1)); gyro_y = (I2C_ReceiveData(I2C1) << 8 | I2C_ReceiveData(I2C1)); gyro_z = (I2C_ReceiveData(I2C1) << 8 | I2C_ReceiveData(I2C1)); I2C_GenerateSTOP(I2C1, ENABLE); // 计算欧拉角 roll = atan2(accel_y, accel_z) * 180 / M_PI; pitch = atan2(-accel_x, sqrt(accel_y * accel_y + accel_z * accel_z)) * 180 / M_PI; yaw = get_yaw(); // 获取航向角 } // TIM3中断服务函数 void TIM3_IRQHandler(void) { // 清除更新中断标志位 TIM_ClearITPendingBit(TIM3, TIM_IT_Update); // 控制小车 control_car(); } // USART1中断服务函数 void USART1_IRQHandler(void) { // ... } // 初始化GPIO void init_GPIO(void) { // ... } // 初始化USART1 void init_USART1(void) { // ... } // 初始化I2C void init_I2C(void) { // ... } // 初始化TIM2 void init_TIM2(void) { // ... } // 初始化TIM3 void init_TIM3(void) { // ... } // 读取MPU6050数据 void read_MPU6050(void) { // ... } // 读取NEO-6M数据 void read_NEO6M(void) { // ... } // 控制小车 void control_car(void) { // ... } // 获取航向角 float get_yaw(void) { // ... } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值