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

🚗🚗🚗🚗🚗
博客就当作学习过程中的笔记
博客提供了几乎所有需要敲的代码
可以借鉴,但不要面向「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/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,每天锻炼,加油
  • 62
    点赞
  • 389
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
1.时钟源 外部时钟 2.GPIO (实验:点亮LED灯,获取引脚的电平高低,将对应引脚置高置低)。 3.PWM-脉宽调制 主要是调节占空比(在小车中用来实现小车的加减速)。 4.TIMX定时器 5.红外遥控 主要运用了EXTI(外部中断/事件控制器),系统延时(系统滴答定时器SysTick)。 6.超声波避障 了解了超声波工作的原理,主要运用了TIM2定时器(用来定时测距),GPIO口。 7.红外探测 通过对障碍物和光的感应来返回电平的状态,从而达到避障和巡线效果。 8.测速码盘 (通过检测码盘上的凹槽数来获取脉冲数,通过计算公式得到小车当前速度) TIM3定时器(定时测速)。 9.PID算法 为了使小车的速度更快的达到目标值,获取更稳定的速度。 10.系统的使用 我们在小车内加入系统,对小车的数据获取,状态实现任务化,使小车内的运作更加有序。我们主要使用μC/OS-II系统内核来实现系统。在实现过程中,我们了解了系统的任务调度以及任务运行和处理器之间的关系(多任务同时运行)。 μC/OS-II内核中的任务控制块,任务状态,以及多任务和任务的优先级类似操作系统中的进程操作。 11.任务间的通信 主要用到信号量(主要就是PV操作 P操作:占用资源。V操作:释放资源);邮箱(邮箱可以使一个任务或者中断服务子程序向另一个任务发送指针型的变量,通常该指针指向包含了“消息”特定的数据结构)。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值