STM32循迹小车
第一天:硬件平台介绍
硬件平台:
控制模块:正点原子STM32精英开发板
驱动模块:L298N两路电机驱动模块,两路pwm控制,正反转控制
转向控制:S3010舵机,由20ms脉宽pwm信号控制转向
循迹模块:5路光电对管循迹模块RS016
蓝牙模块:待定
小车平台:10年前飞思卡尔比赛车模
软件设计平台:
STM32程序开发:MDK5 Keil uVision5
Android APP开发:AndroidStudio2.2.2
预计实现功能:
1、遥控模式,通过红外遥控控制前进后退停止转向,连续调速
2、自动模式,通过循迹模块自动检测黑线并跟踪行驶
3、手机控制,通过Android定制APP控制小车前进后退停止转向,连续调速
已经实现功能:遥控模式,下附主要源代码:
#define MIN_zou 1000 //向左
#define Z_qian 1200 //向前
#define MAX_you 1400 //向右
/*
循迹车引脚接线:
PG13/PG14引脚控制车前进(1,0)/倒退(0,1),接L298控制引脚IN4/IN3
定时器3通道2对应引脚PB5控制舵机转向,由20ms脉宽920-2120高电平控制。黑线(接地),红线(电源线),白色(控制线)
定时器3通道4对应引脚PB1控制车驱动电机转速
*/
//pwm波输出 开发板验证
void TIM3_PWM_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStrcut;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStrcut;
TIM_OCInitTypeDef TIM_OCInitStrcut;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //复用端口需要使能AFIO时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //使能TIM3时钟
GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3,ENABLE); //端口部分重映射
//设置该引脚为复用输出功能,输出 TIM3 CH2 的 PWM 脉冲波形 GPIOB.5
GPIO_InitStrcut.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStrcut.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_1; //
GPIO_InitStrcut.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStrcut);
//定时器初始化
TIM_TimeBaseInitStrcut.TIM_CounterMode=TIM_CounterMode_Up;//计数模式
TIM_TimeBaseInitStrcut.TIM_Period=arr; //重装值
TIM_TimeBaseInitStrcut.TIM_Prescaler=psc; //分频值
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStrcut);
//PWM相关寄存器初始化
TIM_OCInitStrcut.TIM_OCMode = TIM_OCMode_PWM2; //选择 PWM 模式 2
TIM_OCInitStrcut.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStrcut.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性高
TIM_OC2Init(TIM3, &TIM_OCInitStrcut); //初始化外设 TIM3 OC2通道2
TIM_OC4Init(TIM3, &TIM_OCInitStrcut); //初始化外设 TIM3 OC2通道4
TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable); //装载预装值
TIM_Cmd(TIM3,ENABLE); //使能定时器3
}
void Init_GPIO1(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE); //使能PB,PE端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14; //LED0-->PB.5 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
GPIO_Init(GPIOG, &GPIO_InitStructure); //根据设定参数初始化GPIOB.5
}
int main(void)
{
u8 key; //键值
u16 led0pwmval=Z_qian,pwm_sudu=0;
u8 *str=0;
delay_init(); //延时函数初始化
Init_GPIO1();
LCD_Init(); //初始化LCD
W25QXX_Init(); //初始化W25Q128
Remote_Init();
TIM3_PWM_Init(14399,99);
TIM_SetCompare2(TIM3,led0pwmval);
TIM_SetCompare4(TIM3,pwm_sudu);
POINT_COLOR=RED;
while(font_init()) //检查字库
{
LCD_ShowString(30,50,16,"Font Error!",0);
delay_ms(200);
LCD_Fill(30,50,240,66,WHITE);//清除显示
delay_ms(200);
}
Show_Str(30,30,200,16,"循迹小车调试界面",16,0);
Show_Str(30,70,200,16,"PWM捕获寄存器值:",16,0);
Show_Str(30,100,200,16,"遥控接收值:",16,0);
Show_Str(30,130,200,16,"按键连按次数:",16,0);
Show_Str(30,160,200,16,"按键键值:",16,0);
Show_Str(30,190,200,16,"速度PWM值:",16,0);
POINT_COLOR=BLUE;
Show_Str(30,210,200,64,"|<< :向左 2 :前进",16,0);
Show_Str(30,230,200,64,">>| :向右 8 :倒退",16,0);
Show_Str(30,250,200,64,">|| :向前 5 :停止",16,0);
Show_Str(30,270,200,64,"VOL+/- :快/慢",16,0);
Show_Str(30,300,200,64,"上/下 :左/右",16,0);
// Show_Str(30,350,200,64,"2 :前进",16,0);
// Show_Str(30,370,200,64,"8 :倒退",16,0);
// Show_Str(30,390,200,64,"5 :停止",16,0);
while(1)
{
key=Remote_Scan();
if(key)
{
switch(key)
{
case 98:
{
str="UP";
led0pwmval += 20;
if(led0pwmval >= MAX_you)led0pwmval=MAX_you;
TIM_SetCompare2(TIM3,led0pwmval);
}break;
case 194:
{
str="RIGHT";
led0pwmval = MIN_zou;
TIM_SetCompare2(TIM3,led0pwmval);
}break;
case 34:
{
str="LEFT";
led0pwmval = MAX_you;
TIM_SetCompare2(TIM3,led0pwmval);
}break;
case 168:
{
str="DOWN";
if(led0pwmval >= (MIN_zou+20))led0pwmval -= 20;
else led0pwmval = MIN_zou;
TIM_SetCompare2(TIM3,led0pwmval);
}break;
case 2:
{
str="PLAY";
led0pwmval=Z_qian;
TIM_SetCompare2(TIM3,led0pwmval);
}break;
case 224:
{
str="VOL-";
if(pwm_sudu >=100)pwm_sudu-=100;
else pwm_sudu=0;
TIM_SetCompare4(TIM3,pwm_sudu);
}break;
case 144:
{
str="VOL+";
if(pwm_sudu <= 8000)pwm_sudu+=100;
else pwm_sudu=8000;
TIM_SetCompare4(TIM3,pwm_sudu);
}break;
case 56:
{
str="8";
TIM_SetCompare4(TIM3,pwm_sudu);
delay_ms(100);
PGout(13) = 0;
PGout(14) = 1;
}break;
case 152:
{
str="2";
TIM_SetCompare4(TIM3,pwm_sudu);
delay_ms(100);
PGout(13) = 1;
PGout(14) = 0;
}break;
case 24:
{
str="5";
if(pwm_sudu>=3000){
TIM_SetCompare4(TIM3,pwm_sudu/2);
delay_ms(200);
}
PGout(13) = 0;
PGout(14) = 0;
delay_ms(20);
}break;
}
LCD_ShowNum(30+8*16,70,led0pwmval,5,16);
LCD_ShowNum(30+8*10,100,key,4,16);
LCD_ShowNum(30+8*14,130,RmtCnt,3,16);
LCD_ShowString(30+8*10,160,16," ",0);
LCD_ShowString(30+8*10,160,16,str,0);
LCD_ShowNum(30+8*14,190,pwm_sudu,5,16);
}
delay_ms(150);
}
}
后续功能开发待续,不定时更新,业余作品,预计一个月左右更新完成。
源码开发过程中随时会修正更改,暂时不提供完整代码。