STM32硬件开发——智能小车(超声波避障 红外循迹 蓝牙遥控)

news/2024/11/30 12:39:39/

STM32 小车——三路超声波避障+红外循迹+蓝牙遥控

  • 前言(BB Time)
  • 硬件
    • 一、选型
      • 1、开发板
      • 2、其他元件
    • 二、原理
      • 1、电机
      • 2、超声波
      • 3、红外
      • 4、蓝牙
  • 功能
    • 一、车轮滚滚
      • 1、原理
      • 2、代码
      • 3、注意
    • 二、按键切换功能
      • 1、原理
      • 2、代码
    • 三、通过三路超声波实现避障
      • 1、代码
    • 四、通过两个红外模块实现黑线循迹
      • 1、原理
      • 2、代码
      • 3、注意
    • 五、通过手机蓝牙遥控车辆
      • 1、代码
  • 总结

🚗🚗🚗🚗🚗
博客就当作学习过程中的笔记
博客提供了几乎所有需要敲的代码
可以借鉴,但不要面向「CSDN 编程」哦
奶奶要努力变强💪

在这里插入图片描述


前言(BB Time)

疫情假期的时候开始学习 STM32 ,因为在家所以疯狂划水,进度落下了很多,所以非常感谢返校后学长还有组内其他小伙伴的协助。
小车自然是嵌入式学习过程中的第一个「大项目」。从看「正点原子」的样例代码,实现相近功能,到自己动手做一辆小车车 着实是不小的跨步。
@万里羊 和 @nidie508 两位学长的博客对我提供了非常大的帮助(哈哈哈,面向 CSDN 编程),也是看了他们的博客让我下定决心认真写博客,记录自己所学,毕竟要对得起资料里的「5年码龄」😂。


👇BB 结束,正片开始👇

硬件

一、选型

1、开发板

小板子
实验室提供的 Mini STM32

开发板图片

寄存器版本
学长说库函数可能相对比较简单(我并没有这么觉得 微笑.jpg),而且后期的话一些功能使用库函数不方便(小声BB,我可能前期就被现实锤爆了根本没有后期 哈哈哈

2、其他元件

底盘和小车轮
不知名的脏兮兮底盘和两个可爱的小电机

底盘图片

电机驱动模块
TB6612,噗嗤小伙伴焊的时候焊反了,但记住 IO 口就行了,问题不大👌

TB6612 图片

超声波模块
HC-SR04

HC-SR04 图片

红外模块
FC-03

FC-03 图片

蓝牙模块
唔,我找不到了哈哈哈🤦‍♂️

二、原理

1、电机

通过 TB6612FNG 来驱动电机,因为该模块是双驱动,所以只需一个即可驱动一对电机

  • VM:连接 12V 以内电源
  • VCC:连接 5V 以内电源
  • GND:连接电源负极
  • STBY:该口清零则两组电机全部停转,置1后通过 AIN、BIN 控制正反转
  • PWMA、PWMB:分别连接控制左右电机 PWM 输出的 IO 口
  • AO、BO:1、2分别连接连接电机正负极
  • AIN、BIN:
接口停止正转反转
AIN1001
AIN2010
接口停止正转反转
BIN1001
BIN2010

2、超声波

  • VCC:连接 5V 以内电源
  • GND:连接电源负极
  • TRLG:连接开发板上控制超声波发射的 IO 口
  • ECHO:连接开发板上处理超声波接收信号的 IO 口

3、红外

红外发射端发射光线到地面,红外光线遇到白色被反射,接收端检测到反射光线后输出低电平;遇到黑色被吸收,接收端未检测到反射光线,输出高电平

  • VCC:连接开发板 5V 电源
  • GND:连接电源负极
  • D0:连接开发板接收红外信号的 IO 口
颜色电平
白色0
黑色1

4、蓝牙

小伙伴的部分


功能

我和小伙伴合作的小车主要有三个功能,不同的功能通过 STM32 开发板上的按键进行切换。

一、车轮滚滚

1、原理

  • 直行:左轮和右轮同时正转
  • 后退:左轮和右轮同时反转
  • 停止:左轮和右轮同时停止
  • 左转:左轮反转,右轮正转
  • 右转:左轮正转,右轮反转

2、代码

wheel.h

#ifndef __WHEEL_H
#define __WHEEL_H#include "sys.h"//TB6612连接
#define LEFT PAout(2)
#define LIN1 PAout(0)
#define LIN2 PAout(1)#define RIGHT PAout(3)
#define RIN1 PAout(4)
#define RIN2 PAout(5)//#define STBY PBout(0)		//因为 STBY 直接连接到 3.3V 电源了,所以不需要使用 IO 口#define left_PWM  TIM2->CCR3//占空比
#define right_PWM  TIM2->CCR4//占空比 void Wheel_Init(u16 arr,u16 psc);void GO(void);//执行直行操作
void STOP(void);//执行停止操作
void BACK(void);//执行后退操作
void turnLEFT(void);//执行左转操作
void turnRIGHT(void);//执行右转操作#endif

wheel.c

#include "wheel.h"
#include "delay.h"void Wheel_Init(u16 arr,u16 psc) {RCC->APB1ENR |=1<<0;//TIM2时钟使能RCC->APB2ENR |=1<<2;GPIOA->CRL &=0XFF000000;//PA2,3复用输出GPIOA->CRL |=0X0033BB33;//PA0,1,4,5推挽输出TIM2->ARR=arr;//自动重装载值TIM2->PSC=psc;//预分频系数TIM2->CCMR2|=7<<4; //CH3 PWM2 模式//比较捕获模式配置寄存器TIM2->CCER|=1<<8;   	//输出使能	//捕获/比较使能寄存器TIM2->CCMR2|=7<<12; //CH4 PWM2 模式//比较捕获模式配置寄存器TIM2->CCER|=1<<12;   	//输出使能	//捕获/比较使能寄存器TIM2->CR1 |=0X0001;//使能定时器2
}void GO(void) {LIN1=0;LIN2=1;RIN1=0;RIN2=1;
}void STOP(void) {LIN1=0;LIN2=0;RIN1=0;RIN2=0;
}void BACK(void) {LIN1=1;LIN2=0;RIN1=1;RIN2=0;
}void turnLEFT(void) {//TURN LEFT/L0R1LIN1=0;LIN2=1;RIN1=1;RIN2=0;
}void turnRIGHT(void) {//TURN RIGHT/L1R0LIN1=1;LIN2=0;RIN1=0;RIN2=1;
}

3、注意

  • 电机连接时正负极方向

二、按键切换功能

1、原理

这里有两种思路:

  • 思路一 在主函数中设置两个死循环,第一个循环负责扫描按键,接收到输入之后确定使用的功能,进入第二个循环执行功能。这种方法缺点是 切换功能之前需要通过复位键重置
  • 思路二 将上述两个循环放在一起,设置 modeNUM 代表功能选择,每循环过程中检查 modeNUM 数值执行对应操作。若接收到按键输入则改变 modeNUM 为对应数值

我使用的是方法一

2、代码

key.h

#ifndef __KEY_H
#define __KEY_H	 
#include "sys.h"#define KEY0_PRES	1
#define KEY1_PRES	2
#define WKUP_PRES	3#define KEY0 PCin(5)
#define KEY1 PAin(15)
#define WK_UP PAin(0)void KEY_Init(void);
int KEY_Scan(u8 mode);#endif

key.c

#include "key.h"
#include "delay.h"void KEY_Init(void) {	//初始化按键 a0 a15 c5RCC->APB2ENR|=1<<2;RCC->APB2ENR|=1<<4;GPIOA->CRL&=0xFFFFFFF0;GPIOA->CRL|=0x00000008;GPIOA->CRH&=0x0FFFFFFF;GPIOA->CRH|=0x80000000;GPIOA->ODR|=1<<15;GPIOC->CRL&=0xFF0FFFFF;GPIOC->CRL|=0x00800000;GPIOC->ODR|=1<<5;
}int KEY_Scan(u8 mode) {	//扫描按键static u8 key_up=1;//按键按松开标志	  if(KEY0==0||KEY1==0||WK_UP==1) {delay_ms(10);//去抖动 key_up=0;if(KEY0==0)return KEY0_PRES;else if(KEY1==0)return KEY1_PRES;else if(WK_UP==1)return WKUP_PRES; }else if(KEY0==1&&KEY1==1&&WK_UP==0)key_up=1; 	     return 0;// 无按键按下
}

test.c 按键切换部分

	while(1){key=KEY_Scan(0);switch(key) {case	KEY0_PRES:GO1();break;case KEY1_PRES:GO2();break;case WKUP_PRES:				GO3();break;default:delay_ms(10);	}}

三、通过三路超声波实现避障

1、代码

hc6.h

#ifndef __HC6_H
#define __HC6_H
#include "sys.h"void HCSR04_Init(u16 arr,u16 psc);
u32 DIS_Init(u8 *STA,u16 VAL);
void Ultrasound(void);#endif

hc6.c

#include "hc6.h"
#include "sys.h"
#include "delay.h"
#include "wheel.h"
#include "usart.h"void HCSR04_Init(u16 arr,u16 psc)
{RCC->APB1ENR|=1<<2;    //TIM4 ±÷” πƒ‹RCC->APB2ENR|=1<<2;    // πƒ‹PORTA ±÷”RCC->APB2ENR|=1<<3;	 // πƒ‹PORTB ±÷”RCC->APB2ENR|=1<<4; 	// πƒ‹PORTC ±÷”GPIOB->CRL&=0X00FFFFFF;//PB6~9«Â≥˝÷Æ«∞…Ë÷√GPIOB->CRL|=0X88000000;//PB6~9∏°ø’ ‰»ÎGPIOB->CRH&=0XF000FF00;GPIOB->CRH|=0X03330088;GPIOB->ODR|=0<<6;GPIOB->ODR|=0<<7;      //PB7œ¬¿≠GPIOB->ODR|=0<<8;GPIOB->ODR|=0<<9;GPIOB->ODR|=1<<12;      //PB4  ‰≥ˆ∏flGPIOB->ODR|=1<<13;GPIOB->ODR|=1<<14;TIM4->ARR=arr;         //…Ë∂®º∆ ˝∆˜◊‘∂Ø÷ÿ◊∞÷µTIM4->PSC=psc;         //‘§∑÷∆µ∆˜TIM4->CCMR1|=1<<0;     //CC1S=01 —°‘Ò ‰»Î∂ÀIC1”≥…‰µΩTI1TIM4->CCMR1|=1<<4;     //IC1F=0001 ≈‰÷√¬À≤®∆˜ “‘Fck_int≤…—˘£¨¡Ω∏ˆ ¬º˛∫Û”––ßTIM4->CCMR1|=0<<2;    //IC1PS=00 ≈‰÷√ ‰»Î∑÷∆µ£¨≤ª∑÷∆µTIM4->CCER|=0<<1;      //CC1P=0 …œ…˝—ÿ≤∂ªÒTIM4->CCER|=1<<0;      //CC1E=1 ‘ –Ì≤∂ªÒº∆ ˝∆˜µƒ÷µµΩ≤∂ªÒºƒ¥Ê∆˜÷–TIM4->CCMR1|=1<<8;     //CC2S=01 —°‘Ò ‰»Î∂ÀIC1”≥…‰µΩTI1TIM4->CCMR1|=1<<12;     //IC2F=0001 ≈‰÷√¬À≤®∆˜ “‘Fck_int≤…—˘£¨¡Ω∏ˆ ¬º˛∫Û”––ßTIM4->CCMR1|=0<<10;    //IC2PS=00 ≈‰÷√ ‰»Î∑÷∆µ£¨≤ª∑÷∆µTIM4->CCER|=0<<5;      //CC2P=0 …œ…˝—ÿ≤∂ªÒTIM4->CCER|=1<<4;      //CC2E=1 ‘ –Ì≤∂ªÒº∆ ˝∆˜µƒ÷µµΩ≤∂ªÒºƒ¥Ê∆˜÷–TIM4->CCMR2|=1<<0;     //CC3S=01 —°‘Ò ‰»Î∂ÀIC1”≥…‰µΩTI1TIM4->CCMR2|=1<<4;     //IC3F=0001 ≈‰÷√¬À≤®∆˜ “‘Fck_int≤…—˘£¨¡Ω∏ˆ ¬º˛∫Û”––ßTIM4->CCMR2|=0<<2;    //IC3PS=00 ≈‰÷√ ‰»Î∑÷∆µ£¨≤ª∑÷∆µTIM4->CCER|=0<<9;      //CC3P=0 …œ…˝—ÿ≤∂ªÒTIM4->CCER|=1<<8;      //CC3E=1 ‘ –Ì≤∂ªÒº∆ ˝∆˜µƒ÷µµΩ≤∂ªÒºƒ¥Ê∆˜÷–TIM4->CCMR2|=1<<8;     //CC4S=01 —°‘Ò ‰»Î∂ÀIC1”≥…‰µΩTI1TIM4->CCMR2|=1<<12;     //IC4F=0001 ≈‰÷√¬À≤®∆˜ “‘Fck_int≤…—˘£¨¡Ω∏ˆ ¬º˛∫Û”––ßTIM4->CCMR2|=0<<10;    //IC4PS=00 ≈‰÷√ ‰»Î∑÷∆µ£¨≤ª∑÷∆µTIM4->CCER|=0<<13;      //CC4P=0 …œ…˝—ÿ≤∂ªÒTIM4->CCER|=1<<12;      //CC4E=1 ‘ –Ì≤∂ªÒº∆ ˝∆˜µƒ÷µµΩ≤∂ªÒºƒ¥Ê∆˜÷–TIM4->DIER|=1<<1;TIM4->DIER|=1<<2;      //‘ –Ì≤∂ªÒ÷–∂œTIM4->DIER|=1<<3;      //‘ –Ì≤∂ªÒ÷–∂œTIM4->DIER|=1<<4;      //‘ –Ì≤∂ªÒ÷–∂œTIM4->DIER|=1<<0;      //‘ –Ì∏¸–¬÷–∂œTIM4->CR1|=0X01;       // πƒ‹∂® ±∆˜2MY_NVIC_Init(2,0,TIM4_IRQn,2);//«¿’º2£¨◊””≈œ»º∂0£¨◊È2
}u8 TIM4CH1_CAPTURE_STA=0; // ‰»Î≤∂ªÒ◊¥Ã¨
u16 TIM4CH1_CAPTURE_VAL;  // ‰»Î≤∂ªÒ÷µu8 TIM4CH2_CAPTURE_STA=0; // ‰»Î≤∂ªÒ◊¥Ã¨
u16 TIM4CH2_CAPTURE_VAL;  // ‰»Î≤∂ªÒ÷µu8 TIM4CH3_CAPTURE_STA=0; // ‰»Î≤∂ªÒ◊¥Ã¨
u16 TIM4CH3_CAPTURE_VAL;  // ‰»Î≤∂ªÒ÷µu8 TIM4CH4_CAPTURE_STA=0; // ‰»Î≤∂ªÒ◊¥Ã¨
u16 TIM4CH4_CAPTURE_VAL;  // ‰»Î≤∂ªÒ÷µ//∂® ±∆˜4÷–∂œ∑˛ŒÒ≥ÖÚ
void TIM4_IRQHandler(void)
{u16 tsr;tsr=TIM4->SR;if((TIM4CH1_CAPTURE_STA&0X80)==0)//ªπŒ¥≥…π¶≤∂ªÒ{if(tsr&0X01)//“Á≥ˆ{if(TIM4CH1_CAPTURE_STA&0X40)//“—æ≠≤∂ªÒµΩ∏flµÁ∆Ω¡À{if((TIM4CH1_CAPTURE_STA&0X3F)==0X3F)//∏flµÁ∆Ωô≥§¡À{TIM4CH1_CAPTURE_STA|=0X80;//±Íº«≥…π¶≤∂ªÒ¡À“ª¥ŒTIM4CH1_CAPTURE_VAL=0XFFFF;}else TIM4CH1_CAPTURE_STA++;}}if(tsr&0x02)//≤∂ªÒ1∑¢…˙≤∂ªÒ ¬º˛{if(TIM4CH1_CAPTURE_STA&0X40) //≤∂ªÒµΩ“ª∏ˆœ¬Ωµ—ÿ{TIM4CH1_CAPTURE_STA|=0X80; //±Íº«≥…π¶≤∂ªÒµΩ“ª¥Œ∏flµÁ∆Ω¬ˆøÌTIM4CH1_CAPTURE_VAL=TIM4->CCR1;//ªÒ»°µ±«∞µƒ≤∂ªÒ÷µTIM4->CCER&=~(1<<1);    //CC1P=0 …Ë÷√Œ™…œ…˝—ÿ≤∂ªÒ}else                       //ªπŒ¥ø™ º£¨µ⁄“ª¥Œ≤∂ªÒ…œ…˝—ÿ{TIM4CH1_CAPTURE_VAL=0;TIM4CH1_CAPTURE_STA=0X40; //±Íº«≤∂ªÒµΩ¡À…œ…˝—ÿTIM4->CNT=0;             //º∆ ˝∆˜«Âø’TIM4->CCER|=1<<1;        //CC1P=1 …Ë÷√Œ™œ¬Ωµ—ÿ≤∂ªÒ}}}if((TIM4CH2_CAPTURE_STA&0X80)==0)//ªπŒ¥≥…π¶≤∂ªÒ{if(tsr&0X01)//“Á≥ˆ{if(TIM4CH2_CAPTURE_STA&0X40)//“—æ≠≤∂ªÒµΩ∏flµÁ∆Ω¡À{if((TIM4CH2_CAPTURE_STA&0X3F)==0X3F)//∏flµÁ∆Ωô≥§¡À{TIM4CH2_CAPTURE_STA|=0X80;//±Íº«≥…π¶≤∂ªÒ¡À“ª¥ŒTIM4CH2_CAPTURE_VAL=0XFFFF;}else TIM4CH2_CAPTURE_STA++;}}if(tsr&0x04)//≤∂ªÒ1∑¢…˙≤∂ªÒ ¬º˛{if(TIM4CH2_CAPTURE_STA&0X40) //≤∂ªÒµΩ“ª∏ˆœ¬Ωµ—ÿ{TIM4CH2_CAPTURE_STA|=0X80; //±Íº«≥…π¶≤∂ªÒµΩ“ª¥Œ∏flµÁ∆Ω¬ˆøÌTIM4CH2_CAPTURE_VAL=TIM4->CCR2;//ªÒ»°µ±«∞µƒ≤∂ªÒ÷µTIM4->CCER&=~(1<<5);    //CC1P=0 …Ë÷√Œ™…œ…˝—ÿ≤∂ªÒ}else                       //ªπŒ¥ø™ º£¨µ⁄“ª¥Œ≤∂ªÒ…œ…˝—ÿ{TIM4CH2_CAPTURE_VAL=0;TIM4CH2_CAPTURE_STA=0X40; //±Íº«≤∂ªÒµΩ¡À…œ…˝—ÿTIM4->CNT=0;             //º∆ ˝∆˜«Âø’TIM4->CCER|=1<<5;        //CC1P=1 …Ë÷√Œ™œ¬Ωµ—ÿ≤∂ªÒTIM4->CR1|=0x01;}}}if((TIM4CH3_CAPTURE_STA&0X80)==0)//ªπŒ¥≥…π¶≤∂ªÒ{if(tsr&0X01)//“Á≥ˆ{if(TIM4CH3_CAPTURE_STA&0X40)//“—æ≠≤∂ªÒµΩ∏flµÁ∆Ω¡À{if((TIM4CH3_CAPTURE_STA&0X3F)==0X3F)//∏flµÁ∆Ωô≥§¡À{TIM4CH3_CAPTURE_STA|=0X80;//±Íº«≥…π¶≤∂ªÒ¡À“ª¥ŒTIM4CH3_CAPTURE_VAL=0XFFFF;}else TIM4CH3_CAPTURE_STA++;}}if(tsr&0x08)//≤∂ªÒ1∑¢…˙≤∂ªÒ ¬º˛{if(TIM4CH3_CAPTURE_STA&0X40) //≤∂ªÒµΩ“ª∏ˆœ¬Ωµ—ÿ{TIM4CH3_CAPTURE_STA|=0X80; //±Íº«≥…π¶≤∂ªÒµΩ“ª¥Œ∏flµÁ∆Ω¬ˆøÌTIM4CH3_CAPTURE_VAL=TIM4->CCR3;//ªÒ»°µ±«∞µƒ≤∂ªÒ÷µTIM4->CCER&=~(1<<9);    //CC1P=0 …Ë÷√Œ™…œ…˝—ÿ≤∂ªÒ}else                       //ªπŒ¥ø™ º£¨µ⁄“ª¥Œ≤∂ªÒ…œ…˝—ÿ{TIM4CH3_CAPTURE_VAL=0;TIM4CH3_CAPTURE_STA=0X40; //±Íº«≤∂ªÒµΩ¡À…œ…˝—ÿTIM4->CNT=0;  TIM4CH3_CAPTURE_VAL=TIM4->CCR3;							//º∆ ˝∆˜«Âø’TIM4->CCER|=1<<9;        //CC1P=1 …Ë÷√Œ™œ¬Ωµ—ÿ≤∂ªÒTIM4->CR1|=0x01;}}}if((TIM4CH4_CAPTURE_STA&0X80)==0)//ªπŒ¥≥…π¶≤∂ªÒ{if(tsr&0X01)//“Á≥ˆ{if(TIM4CH4_CAPTURE_STA&0X40)//“—æ≠≤∂ªÒµΩ∏flµÁ∆Ω¡À{if((TIM4CH4_CAPTURE_STA&0X3F)==0X3F)//∏flµÁ∆Ωô≥§¡À{TIM4CH4_CAPTURE_STA|=0X80;//±Íº«≥…π¶≤∂ªÒ¡À“ª¥ŒTIM4CH4_CAPTURE_VAL=0XFFFF;}else TIM4CH4_CAPTURE_STA++;}}if(tsr&0x10)//≤∂ªÒ1∑¢…˙≤∂ªÒ ¬º˛{if(TIM4CH4_CAPTURE_STA&0X40) //≤∂ªÒµΩ“ª∏ˆœ¬Ωµ—ÿ{TIM4CH4_CAPTURE_STA|=0X80; //±Íº«≥…π¶≤∂ªÒµΩ“ª¥Œ∏flµÁ∆Ω¬ˆøÌTIM4CH4_CAPTURE_VAL=TIM4->CCR4;//ªÒ»°µ±«∞µƒ≤∂ªÒ÷µTIM4->CCER&=~(1<<13);    //CC1P=0 …Ë÷√Œ™…œ…˝—ÿ≤∂ªÒ}else                       //ªπŒ¥ø™ º£¨µ⁄“ª¥Œ≤∂ªÒ…œ…˝—ÿ{TIM4CH4_CAPTURE_VAL=0;TIM4CH4_CAPTURE_STA=0X40; //±Íº«≤∂ªÒµΩ¡À…œ…˝—ÿTIM4->CNT=0;             //º∆ ˝∆˜«Âø’TIM4->CCER|=1<<13;        //CC1P=1 …Ë÷√Œ™œ¬Ωµ—ÿ≤∂ªÒTIM4->CR1|=0x01;}}}				TIM4->SR=0;//«Â≥˝÷–∂œ±Í÷挪	
}u32 DIS_Init(u8 *STA,u16 VAL)//∂®“º∆À„懿Î∫Ø ˝
{u32 temp;u32 lenth;if((*STA)&0X80)//≥…π¶≤∂ªÒµΩ¡À“ª¥Œ∏flµÁ∆Ω{temp=(*STA)&0X3F;temp*=65536;               //“Á≥ˆ ±º‰◊‹∫Õtemp+=VAL; //µ√µΩ◊‹µƒ∏flµÁ∆Ω ±º‰lenth=temp*0.017;           //º∆À„≥§∂»*STA=0;     //ø™∆Ùœ¬“ª¥Œ≤∂ªÒ}return lenth;
}#define Trig1 PBout(14) // PB13
#define Trig2 PBout(13)
#define Trig3 PBout(12)extern u8 TIM4CH2_CAPTURE_STA; // ‰»Î≤∂ªÒ◊¥Ã¨
extern u16 TIM4CH2_CAPTURE_VAL;  // ‰»Î≤∂ªÒ÷µextern u8 TIM4CH3_CAPTURE_STA; // ‰»Î≤∂ªÒ◊¥Ã¨
extern u16 TIM4CH3_CAPTURE_VAL;  // ‰»Î≤∂ªÒ÷µextern u8 TIM4CH4_CAPTURE_STA; // ‰»Î≤∂ªÒ◊¥Ã¨
extern u16 TIM4CH4_CAPTURE_VAL;  // ‰»Î≤∂ªÒ÷µvoid Ultrasound(void)
{u32 lenth1;u32 lenth2;u32	lenth3;Trig1=1;delay_us(20);              // ‰»Î“ª∏ˆ20usµƒ∏flµÁ∆ΩTrig1=0;lenth1=DIS_Init(&TIM4CH2_CAPTURE_STA,TIM4CH2_CAPTURE_VAL);delay_us(20);Trig2=1;delay_us(20);              // ‰»Î“ª∏ˆ20usµƒ∏flµÁ∆ΩTrig2=0;lenth2=DIS_Init(&TIM4CH3_CAPTURE_STA,TIM4CH3_CAPTURE_VAL);delay_us(20);Trig3=1;delay_us(20);Trig3=0;lenth3=DIS_Init(&TIM4CH4_CAPTURE_STA,TIM4CH4_CAPTURE_VAL);printf("length1:%d",lenth1);printf("length2:%d",lenth2);printf("length3:%d",lenth3);if((lenth1>20)&&(lenth3>10)&&(lenth2>10)){printf("GO    \r\n");GO();}else if(lenth3<10){printf("LEFT    \r\n");turnLEFT();delay_ms(20);}else if(lenth2<10){printf("RIGHT   \r\n");turnRIGHT();delay_ms(20);}else{printf("BACK   \r\n");BACK();delay_ms(500);turnLEFT();delay_ms(300);}STOP();
}

GO2 函数

void GO2(void) {while(1)Ultrasound();
}

四、通过两个红外模块实现黑线循迹

1、原理

红外模块安装位置

如图,在小车正前方并排安装两个红外模块,确保黑线位于两个红外模块之间,若左侧检测到黑线,说明车身偏右,即执行左转操作;若右侧检测到黑线,说明车身偏左,即执行右转操作

2、代码

inred.h

#ifndef __INRED_H
#define __INRED_H
#include "sys.h"#define Linred PAin(6);
#define Rinred PAin(7);void Inred_Init(void);#endif

inred.c

#include "inred.h"void Inred_Init(void) {RCC->APB2ENR |= 1<<2;GPIOA->CRL &= 0X00FFFFFF;GPIOA->CRL |= 0X88000000;
}

GO1 函数

void GO1(void) {while(1) {if(PAin(6)==1 && PAin(7)==0) {turnRIGHT();delay_ms(50);}	else if(PAin(6)==1 && PAin(7)==1)			GO();else if(PAin(6)==0 && PAin(7)==1) {turnLEFT();delay_ms(50);}elseGO();}
}

3、注意

  • 在写 test.c 的过程中遇到了一个小问题,if(Linred == X) 语句一直在报错,后来把 Linred 改成了对应的 IO 口解决了问题,但是问题出在哪还是不太清楚
  • 通过 PWM 调节车轮转速时,值越大转速越慢
  • 左右电机存在速度差,只要调节到近似相等即可
  • @万里羊学长提醒的:开发板只需要接收红外模块检测返回后的结果即可,无需输出信息,因此使用 in 而非 out

五、通过手机蓝牙遥控车辆

1、代码

bluetooth.h

#ifndef __BLUETOOTH_H
#define __BLUETOOTH_H
#include "sys.h"
#include "stdio.h"#define USART_REC_LEN  			200  	//∂®“Â◊Ó¥ÛΩ” ’◊÷Ω⁄ ˝ 200
#define EN_USART3_RX 			1		// πƒ‹£®1£©/Ω˚÷π£®0£©¥Æø⁄1Ω” ’extern u8  USART3_RX_BUF[USART_REC_LEN]; //Ω” ’ª∫≥Â,◊Ó¥ÛUSART_REC_LEN∏ˆ◊÷Ω⁄.ƒ©◊÷Ω⁄Œ™ªª––∑˚ 
extern u16 USART3_RX_STA;         		//Ω” ’◊¥Ã¨±Íº«	
//»Áπ˚œÎ¥Æø⁄÷–∂œΩ” ’£¨«Î≤ª“™◊¢ Õ“‘œ¬∫Í∂®“Â
void uart3_init(u32 pclk2,u32 bound);void USART3_IRQHandler(void);
#endif	   

bluetooth.c

#include "bluetooth.h"	 
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "wheel.h"
#include "stdio.h"u8 BTFlag;
#if EN_USART3_RX   //»Áπ˚ πƒ‹¡ÀΩ” ’
//¥Æø⁄1÷–∂œ∑˛ŒÒ≥ÖÚ
//◊¢“‚,∂¡»°USARTx->SRƒ‹±‹√‚ƒ™√˚∆‰√Óµƒ¥ÌŒÛ   	
u8 USART3_RX_BUF[USART_REC_LEN];     //Ω” ’ª∫≥Â,◊Ó¥ÛUSART_REC_LEN∏ˆ◊÷Ω⁄.
//Ω” ’◊¥Ã¨
//bit15£¨	Ω” ’ÕÍ≥…±Í÷æ
//bit14£¨	Ω” ’µΩ0x0d
//bit13~0£¨	Ω” ’µΩµƒ”––ß◊÷Ω⁄ ˝ƒø
u16 USART3_RX_STA=0;       //Ω” ’◊¥Ã¨±Íº«	  void USART3_IRQHandler(void)
{u8 res;	//delay_ms(50);if(USART3->SR&(1<<5))	//Ω” ’µΩ ˝æ›{	//delay_ms(10);		res=USART3->DR;printf("\r\n%d",res);		if(res == 250){	GO();printf("\r\nGO");}else if(res == 253)	{BACK();printf("\r\nBack");}else if(res== 251){turnLEFT();printf("\r\nLeft");			}else if(res==255){turnRIGHT();printf("\r\nRight");}else if(res==173){STOP();printf("\r\nStop");}}
} 
#endif		//≥ı ºªØIO ¥Æø⁄3
//pclk2:PCLK2 ±÷”∆µ¬ (Mhz)
//bound:≤®Ãÿ¬  
void uart3_init(u32 pclk2,u32 bound)
{  	 float temp;u16 mantissa;u16 fraction;	   temp=(float)(pclk2*1000000)/(bound*16);//µ√µΩUSARTDIVmantissa=temp;				 //µ√µΩ’˚ ˝≤ø∑÷fraction=(temp-mantissa)*16; //µ√µΩ–° ˝≤ø∑÷	 mantissa<<=4;mantissa+=fraction; RCC->APB2ENR|=1<<3;   // πƒ‹PORTBø⁄ ±÷”  RCC->APB1ENR|=1<<18;  // πƒ‹¥Æø⁄3 ±÷” GPIOB->CRH&=0XFFFF00FF;//IO◊¥Ã¨…Ë÷√GPIOB->CRH|=0X00008B00;//IO◊¥Ã¨…Ë÷√ RCC->APB2RSTR|=1<<18;   //∏¥Œª¥Æø⁄3RCC->APB2RSTR&=~(1<<18);//Õ£÷π∏¥Œª	 //≤®Ãÿ¬ …Ë÷√USART3->BRR=mantissa; // ≤®Ãÿ¬ …Ë÷√	 USART3->CR1|=0X200C;  //1ŒªÕ£÷π,Œfi–£—ÈŒª.
//#if EN_USART1_RX		  //»Áπ˚ πƒ‹¡ÀΩ” ’// πƒ‹Ω” ’÷–∂œ//USART3->CR1|=1<<8;    //PE÷–∂œ πƒ‹USART3->CR1|=1<<5;    //Ω” ’ª∫≥«¯∑«ø’÷–∂œ πƒ‹	USART3_RX_STA=0;	MY_NVIC_Init(3,3,USART3_IRQn,2);//◊È2£¨◊ÓµÕ”≈œ»º∂ 
//#endif}

GO3 函数

void GO3(void) {USART3->CR1 |= 1<5;
}

总结

  • 多烧录实践 代码烧到板子上比干瞪眼看有效多了
  • 不耻下问 写完电机代码我瞅了半天找不到问题,大佬来看了一眼就解决了。。。唔,@是智造哎牛逼(破音~)
  • 正负极 注意正负极,注意正负极,注意正负极!!!

  • 😹Detroit: Become Human 故事太让人感动了
  • 💪买了 Ring Fit Adventure,每天锻炼,加油

http://www.ppmy.cn/news/320801.html

相关文章

基于STM32的智能行车辅助系统源码,文档,视频(自动大灯,倒车报警,自动雨刷,温湿度传感器,TFT 1.3寸LCD屏幕显示,ESP8266WIFI)

基于STM32ESP8266的智能行车辅助系统 基于STM32的智能行车辅助系统&#xff08;自动大灯&#xff0c;倒车报警&#xff0c;自动雨刷&#xff0c;温湿度传感器&#xff0c;TFT 1.3寸LCD屏幕显示&#xff0c;ESP8266WIFI&#xff09;&#xff0c;这是一个课程设计。这个题目没有…

汽车雷达 -- 车载ADAS常用中英文对照

一、术语定义 参看&#xff1a;车载ADAS常用中英文对照表 英文缩写英文全名中文全名ACCAdaptive Cruise Control主动式&#xff08;自适应&#xff09;车距控制巡航系统ADASAdvanced Driver Assistance Systems先进&#xff08;高级&#xff09;驾驶辅助系统AFBAutomatic Eme…

车载毫米波雷达信号处理中的模糊问题

说明 在毫米波雷达的信号处理中&#xff0c;测距、测速、测角是我们关注的三个核心问题&#xff0c;以chirp形式的信号工作的车载毫米波雷达&#xff0c;其最大无模糊测量距离(仅从数据处理而非能量的角度考虑)受限于接收机的中频带宽和ADC的采样率&#xff0c;其最大无模糊测量…

车载通信——基础篇

一、OSI参考模型 &#xff08;1&#xff09;物理层 节点间原始比特流传输&#xff0c;物理信号“0”与“1” 。 &#xff08;2&#xff09;数据链路层 节点间可靠的数据通信&#xff0c;数据帧形式传输。 &#xff08;3&#xff09;网络层 节点间报文传输&#xff0c;源端…

汽车LIN总线详解

1.LIN总线介绍 在汽车电子开发过程中&#xff0c;不可避免会用到LIN总线(Local Interconnect Network)。做为一个对CAN总线作为低成本辅助总线&#xff0c;LIN总线在车身控制中应用广泛&#xff0c;车门、车窗、车灯以及中控锁等都使用LIN线。其实对于不计成本新能源造车来说&a…

ToBeWritten之车辆通信

也许每个人出生的时候都以为这世界都是为他一个人而存在的&#xff0c;当他发现自己错的时候&#xff0c;他便开始长大 少走了弯路&#xff0c;也就错过了风景&#xff0c;无论如何&#xff0c;感谢经历 转移发布平台通知&#xff1a;将不再在CSDN博客发布新文章&#xff0c;敬…

基于STM32芯片的四驱循迹小车

循迹小车包括三个基本模块&#xff1a; 1.宏定义模块 2.电机驱动模块 3.红外循迹模块 4.PWM调速模块 我将代码部分分为4个模块进行模块化编程&#xff1a;interface(各个引脚口的宏定义&#xff0c;方便记忆)、motor(电机驱动模块)、timer(定时器模块)、track(红外循迹模块) 一…

车载通信——诊断刷写

一.诊断刷写基础知识 UDS&#xff08;Unified Diagnostic Services&#xff0c;统一的诊断服务&#xff09;诊断协议是在汽车电子ECU环境下的一种诊断通信协议。 诊断工具与车内的所有控制单元连接启用了UDS服务&#xff0c;使用OSI模型的第五层和第七层&#xff08;会话层和应…