目录
一。材料准备。
二。PCB原理图
三。逻辑状态图
四。代码部分
五。文件下载:
接上:stm32f103 简易4路红外寻迹小车(1)----2023西南交大电赛校赛(含stm32中文资料)
小车测试视频:
stm32小车寻迹小车
材料资料图片见上:stm32f103 简易4路红外寻迹小车(1)----2023西南交大电赛校赛(含stm32中文资料)
电机驱动MX1919L
VCC统一接stm32系统板的3.3v。VDD接7.4V电源。电容连接如图。左侧和右侧两轮分别接2通道。
利用pwm波改变占空比控制电机转速,逻辑输入接可以产生pwm的PA6,PA7,PB0,PB1(TIM3),复用推挽输出。
红外寻迹模块
接PB4,PB5,PB6,PB7。浮空输入
学校发了最小系统板所有没有自己做驱动板直接把最小系统板插上去用了。
pwm.c
启用TIM3时钟 输出pwm波使用的是TIM3的4个通道(A6 A7 B0 B1)分别连接电机驱动的Vina1 Vinb1 Vina2 Vinb2。
设置为复用推挽输出。
#include "stm32f10x.h"
#include "pwm.h"
#include "delay.h"
void pwm_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM3,ENABLE);
RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}
//T(s)周期/溢出时间=(arr溢出值+1)(psc分频系数+1)/Tclk
//Tlck为通用定时器的时钟,如果APB1没有分频,则就为系统时钟,72Mhz
//PWM时钟频率=1/T
//TIM_SetCompare3(TIM3,1500);//改变比较值TIM3->CCR2达到调节占空比的效果
void pwm(u16 arr,u16 ccr){
//2个结构体的定义
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_DeInit(TIM3);//TIM3设置为缺省值
TIM_TimeBaseStructure.TIM_Period= arr-1; //自动重装载寄存器的值 因为从0开始计到arr-1 共arr个数
TIM_TimeBaseStructure.TIM_Prescaler= 1;//时钟预分频数
TIM_TimeBaseStructure.TIM_ClockDivision=0x0;//采样分频
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;//向上计数
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1 ; //TIM的PWM1模式 PWM1 PMW2
TIM_OCInitStructure.TIM_OutputState= TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse=ccr-1; //设置占空比
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//TIM输出比较极性高 High Low
TIM_OC1Init(TIM3,&TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Enable);
TIM_OC2Init(TIM3,&TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable);
TIM_OC3Init(TIM3,&TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIM3,TIM_OCPreload_Enable);
TIM_OC4Init(TIM3,&TIM_OCInitStructure);
TIM_OC4PreloadConfig(TIM3,TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM3,ENABLE);//使能定时器TIM3在ARR上的预装载寄存器
TIM_Cmd (TIM3,ENABLE);//使能定时器3
}
xunkun.c 读取红外信号
TC表示从左到右红外显示的红外寻迹信号 如1111 表示全部检测的黑线
#include "xunkun.h"
//#define LL1 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_1)//读取 PB4
//#define LL2 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2)//读取 PB5
//#define RR2 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3)//读取 PB6
//#define RR1 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_4)//读取 PB7
//#define TC 1000*LL1+100*LL2+10*RR2+1*RR1
void xunkun_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB ,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}
diankun.c 电机驱动调速部分,TIM_SetCompareX(TIMX,X);改变TIMX时钟的某一通道的ccr,从而改变占空比。
#include "stm32f10x.h"
#include "diankun.h"
#include "delay.h"
void diankun_Z1(void){//快速直走
TIM_SetCompare1(TIM3,1);
TIM_SetCompare2(TIM3,2000);
TIM_SetCompare3(TIM3,1);
TIM_SetCompare4(TIM3,2000);
delay_ms(10);}
void diankun_L1(void){//快速左转
TIM_SetCompare1(TIM3,1);
TIM_SetCompare2(TIM3,1750);
TIM_SetCompare3(TIM3,1);
TIM_SetCompare4(TIM3,2000);
delay_ms(10);}
void diankun_L2(void){//中速左转
TIM_SetCompare1(TIM3,1);
TIM_SetCompare2(TIM3,1500);
TIM_SetCompare3(TIM3,1);
TIM_SetCompare4(TIM3,2000);
delay_ms(10);}
void diankun_L3(void){//慢速左转
TIM_SetCompare1(TIM3,1);
TIM_SetCompare2(TIM3,1000);
TIM_SetCompare3(TIM3,1);
TIM_SetCompare4(TIM3,2000);
delay_ms(10);}
void diankun_R1(void){//快速右转
TIM_SetCompare1(TIM3,1);
TIM_SetCompare2(TIM3,2000);
TIM_SetCompare3(TIM3,1);
TIM_SetCompare4(TIM3,1750);
delay_ms(10);}
void diankun_R2(void){//中速右转
TIM_SetCompare1(TIM3,1);
TIM_SetCompare2(TIM3,2000);
TIM_SetCompare3(TIM3,1);
TIM_SetCompare4(TIM3,1500);
delay_ms(10);}
void diankun_R3(void){//慢速右转
TIM_SetCompare1(TIM3,1);
TIM_SetCompare2(TIM3,2000);
TIM_SetCompare3(TIM3,1);
TIM_SetCompare4(TIM3,1000);
delay_ms(10);}
void diankun_LL(void){//向左旋转
TIM_SetCompare1(TIM3,1500);
TIM_SetCompare2(TIM3,1);
TIM_SetCompare3(TIM3,1);
TIM_SetCompare4(TIM3,1650);
delay_ms(8);}
void diankun_LL2(void){//向左旋转
TIM_SetCompare1(TIM3,1500);
TIM_SetCompare2(TIM3,1500);
TIM_SetCompare3(TIM3,1);
TIM_SetCompare4(TIM3,2000);
delay_ms(8);}
void diankun_RR(void){//向右旋转
TIM_SetCompare1(TIM3,1);
TIM_SetCompare2(TIM3,1650);
TIM_SetCompare3(TIM3,1500);
TIM_SetCompare4(TIM3,1);
delay_ms(8);}
void diankun_RR2(void){//向右旋转
TIM_SetCompare1(TIM3,1);
TIM_SetCompare2(TIM3,2000);
TIM_SetCompare3(TIM3,1500);
TIM_SetCompare4(TIM3,1500);
delay_ms(8);}
void diankun_X1(void){//快速制动
TIM_SetCompare1(TIM3,1800);
TIM_SetCompare2(TIM3,1800);
TIM_SetCompare3(TIM3,1800);
TIM_SetCompare4(TIM3,1800);
delay_ms(10);}
main.c
SD识别赛道,用与入库出库和更圆滑的通过弧线弯道,本代码是小车开始识别不到黑线则判定为竞速赛道,这里也可以使用开关来调节小车模式
RL是记录小车最左侧和最右侧的最后一次检测信号,用于当小车冲出赛道(识别不到黑线)应该向什么方向旋转。
#include "stm32f10x.h"
#include "sys.h"
#include "delay.h"
#include "pwm.h"
#include "diankun.h"
#include "xunkun.h"
int main(void)
{
xunkun_init();
pwm_init();
pwm(2000,1);//初始pwm值
u8 RL=0;//R=0,L=1,确定0000前最后一次转弯方向
u8 SD=0;//识别是否为竞速赛道
delay_ms(20);//等待设备稳定
if(TC==0){//0000识别赛道起点
diankun_RR();
SD=1;//改变RR和LL为RR2和LL2
delay_ms(450);}
while(1){
//入库
if(TC==1111&&SD==1){//1111
diankun_Z1();
delay_ms(80);
if(TC==0) {
diankun_RR();
delay_ms(560);
while(1) diankun_X1();}}
//旋转
if(TC==0){//0000
if(SD==0)diankun_X1();
while(TC==0&&SD==0){
if(RL) diankun_LL();
else diankun_RR();}
while(TC==0&&SD==1){
if(RL) diankun_LL2();
else diankun_RR2();} }
//直走
if(TC==1001||TC==110|TC==1111){//1001,0110,1111
diankun_Z1();}
//右转
if(TC==1011||TC==111){//1011,0111
RL=0;
diankun_R1();}
if(TC==11||TC==1010){//0011,1010
RL=0;
diankun_R2();}
if(TC==1){//0001
RL=0;
diankun_R3();}
if(TC==10){//0010
diankun_R1();}
//左转
if(TC==1101||TC==1110){//1101,1110
RL=1;
diankun_L1();}
if(TC==1100||TC==101){//1100,0101
RL=1;
diankun_L2();}
if(TC==1000){//1000
RL=1;
diankun_L3();}
if(TC==100){//0100
diankun_L1();}
}}
https://pan.baidu.com/s/1YfZJb8128TMIqJpYZ9hwDA 提取码:0435
第一次参加单片机比赛 第一次学习stm32 虽然最后小车还是拿了校一 但是学习较浅 代码不足之处还请见谅。
后面省赛国赛我还会继续分享自己的历程,多多支持我这个初学者哦。