stm32f103 简易4路红外寻迹小车(2)----2023西南交大电赛校赛(pcb原理图,代码及分析)

目录

一。材料准备。

二。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。浮空输入

二。PCB原理图 

学校发了最小系统板所有没有自己做驱动板直接把最小系统板插上去用了。

三。逻辑状态图

四。代码部分

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();}
      }}

五。文件下载:(代码+pcb原理图)

https://pan.baidu.com/s/1YfZJb8128TMIqJpYZ9hwDA   提取码:0435

第一次参加单片机比赛 第一次学习stm32 虽然最后小车还是拿了校一 但是学习较浅 代码不足之处还请见谅。

后面省赛国赛我还会继续分享自己的历程,多多支持我这个初学者哦。

  • 20
    点赞
  • 204
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 43
    评论
#include #include "qudong.h" #include "duankou.h" #include "lcd1602.h" #include "celv.h" #define uchar unsigned char #define uint unsigned int #define CPU_F ((double)8000000) #define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0)) #define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0)) //****************************************************************************** //全局变量 //****************************************************************************** float voltage=6.0; //实际电压值 int RS1=100; int LS1=100; int RS0=100; int LS0=100; char heixian=0x03; //不等于0x03表示检测到信号,等于0x03表示没检测到信号 char ji_shu=0; //表示第几次检测到黑线 char youxinhao=0; //=1表示检测到信号,=0表示没有检测到信号 uint total_time_count=0;//时间相关变量 uint start_low_speed=0; uint end_low_speed=0; uint end_all=0; uint start_all=0; uint LM_cap_new=0; //测速相关变量 uint LM_cap_old=0; uint LM_cap_count=0; uint LM_mai_kuai=0; float real_LM_speed=0.0; float top_speed=0; float average_speed=0; uint RM_cap_new=0; uint RM_cap_old=0; uint RM_cap_count=0; uint RM_mai_kuai=0; float real_RM_speed=0.0; float total_distance=0; //测量值转化为实际值相关变量 float dis1=0; float dis0=0; uint low_speed_time=0; uint total_time=0; //****************************************************************************** //系统时钟初始化,aclk=32768k,mclk=XT2,SMCLK = XT2。 //****************************************************************************** void Init_clock(void) { DCOCTL = DCO0 + DCO1 + DCO2; // Max DCO数字晶振最高频率 BCSCTL1 = RSEL0 + RSEL1 + RSEL2; // XT2on, max RSEL选择高速晶振最高频率 BCSCTL2 |=SELM_2+SELS; //MCLK=8M,SMCLK = XT2,系统主时钟选择高速晶振 do //清除振荡器失效标志,等振荡器稳定。 { IFG1&=~OFIFG; for(unsigned int i=0XFF;i>0;i--); } while((IFG1&OFIFG)!=0); } #pragma vector=ADC_VECTOR //ADC12 interrupt service routine __interrupt void ADC12_ISR (void) { if(ADC12MEM0<2816)P6OUT&=~BIT3; //欠压指示灯亮 else P6OUT|=BIT3; } //*************************

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风也为你欣动

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值