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 口就行了,问题不大👌
超声波模块
HC-SR04
红外模块
FC-03
蓝牙模块
唔,我找不到了哈哈哈🤦♂️
二、原理
1、电机
通过 TB6612FNG 来驱动电机,因为该模块是双驱动,所以只需一个即可驱动一对电机
- VM:连接 12V 以内电源
- VCC:连接 5V 以内电源
- GND:连接电源负极
- STBY:该口清零则两组电机全部停转,置1后通过 AIN、BIN 控制正反转
- PWMA、PWMB:分别连接控制左右电机 PWM 输出的 IO 口
- AO、BO:1、2分别连接连接电机正负极
- AIN、BIN:
接口 | 停止 | 正转 | 反转 |
---|---|---|---|
AIN1 | 0 | 0 | 1 |
AIN2 | 0 | 1 | 0 |
接口 | 停止 | 正转 | 反转 |
---|---|---|---|
BIN1 | 0 | 0 | 1 |
BIN2 | 0 | 1 | 0 |
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,每天锻炼,加油