小言_互联网的博客

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

388人阅读  评论(0)

🚗🚗🚗🚗🚗
博客就当作学习过程中的笔记
博客提供了几乎所有需要敲的代码
可以借鉴,但不要面向「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/L0R1
	LIN1=0;LIN2=1;
	RIN1=1;RIN2=0;
}

void turnRIGHT(void) {
	//TURN RIGHT/L1R0
	LIN1=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 c5
	RCC->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  ‰≥ˆ∏fl
    GPIOB->ODR|=1<<13;
		GPIOB->ODR|=1<<14;
	
    TIM4->ARR=arr;         //…Ë∂®º∆ ˝∆˜◊‘∂Ø÷ÿ◊∞÷µ
    TIM4->PSC=psc;         //‘§∑÷∆µ∆˜
	
	TIM4->CCMR1|=1<<0;     //CC1S=01 —°‘Ò ‰»Î∂ÀIC1”≥…‰µΩTI1
    TIM4->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”≥…‰µΩTI1
    TIM4->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”≥…‰µΩTI1
    TIM4->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”≥…‰µΩTI1
    TIM4->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;       // πƒ‹∂® ±∆˜2
    MY_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);
	}
	else
		GO();
	}
}

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);//µ√µΩUSARTDIV
	mantissa=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;   //∏¥Œª¥Æø⁄3
	RCC->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,每天锻炼,加油

转载:https://blog.csdn.net/KANGYICHEN1/article/details/108985671
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场