STM32F103单片机制作的智能小车

需要实现的项目内容

1.材料清单

材料数量

电机

2
万向轮1
轮胎2
循迹模块2
超声波、舵机1
STM32F103学习板或者最小系统1
L298N1
12V可充电锂电池1
蓝牙模块HC-061

 

1.2图片

                                                          

2.L298N电机驱动(重点)

2.1L298N原理

如上图所示: 输出A和输出B接到电机。12V供电接到锂电池正极,5V接到单片机正极(注意单片机上的5V丝印层字样),GND单片机和锂电池共用。拔掉通道A使能和通道B使能,各接到单片机PC6和PC7口(PWM控制电机速度,用的是TIM3,开启复用模式,详细看PWM输出实验详细示例),IN1IN2为一组( IN1是PA0; //左电机正转,      IN2 = PA1;  //左电机反转),接到单片机P2对应OutA(输出A); IN3IN4为一组(IN3 是PA2;     //右电机正转 ,IN4 是PC3;             //右电机反转),对应OutB(输出B)。注意自己的L298N的IN1IN2IN3IN4驱动电子的方向。ENA和ENB是用来控制小车速度的,给高电平有效。

正反转逻辑(0为低电平,1为高电平)

IN1IN2IN3IN4电机
1001向前
0110向后
0001左转
1000向后
1111停止
0000停止

PWM,STM32的I/O口PC6和PC7,TIM_SetCompare1(TIM3,PWM1)中PWM1控制小车转速即占空比。

2.2代码:

PWM.C

#include "To.h"

void PWM_Init(void)
{
	
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_OCInitTypeDef TIM_OCInitStruct;
	GPIO_InitTypeDef GPIO_InitStruct;
	
/***************时钟使能*******************/	
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	
/***************TIM使能*******************/	
	TIM_TimeBaseInitStruct.TIM_Period= 100-1;//重装载值
	TIM_TimeBaseInitStruct.TIM_Prescaler = 720-1;//预分频数
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);
/***************PWM使能*******************/	
	TIM_OCStructInit(&TIM_OCInitStruct);//给结构体成员赋初始值
	TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;//PWM1模式
	TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;//设置极性
	TIM_OCInitStruct.TIM_Pulse = 50;//占空比
	TIM_OCInitStruct.TIM_OutputState= TIM_OutputState_Enable;//使能/失能
	TIM_OC2Init(TIM3,&TIM_OCInitStruct);
	TIM_OC1Init(TIM3,&TIM_OCInitStruct);
	TIM_Cmd(TIM3,ENABLE);
}

TO.h  总头文件

#ifndef _TO_H
#define _TO_H

#include "stm32f10x.h"  

//管脚初始化
void GPIOx_cofing(void);


//delay
void delay_init(void);
void delay_ms(u16 nms);
void delay_us(u32 nus);
void delay_s(int s);

//PWM
void PWM_Init(void);


//控制电机
void qj(int PWM1,int PWM2);
void zz(int PWM1,int PWM2);
void yz(int PWM1,int PWM2);
void ht(int PWM1,int PWM2);
void tz(int PWM1,int PWM2);

//循迹
void XJ(void);


//蓝牙通信
void usart_Initconfig(void);
void USART_SendByte(USART_TypeDef* USARTx, uint16_t Data);
uint8_t USART_ReceiveByte(USART_TypeDef* USARTx);

extern uint16_t temp;


//遥控
void YKXC(void);

#endif

3.车轮的控制和初始化代码

motor.c

#include "To.h"  
//车轮方向控制
void qj(int PWM1,int PWM2)//前进
{
	TIM_SetCompare1(TIM3,PWM1);
	GPIO_SetBits(GPIOA,GPIO_Pin_0);
	GPIO_ResetBits(GPIOA,GPIO_Pin_1);
	
	TIM_SetCompare2(TIM3,PWM2);
	GPIO_SetBits(GPIOA,GPIO_Pin_2);
	GPIO_ResetBits(GPIOA,GPIO_Pin_3);
}

void zz(int PWM1,int PWM2)//左转
{
	TIM_SetCompare1(TIM3,PWM1);
	GPIO_SetBits(GPIOA,GPIO_Pin_0);
	GPIO_ResetBits(GPIOA,GPIO_Pin_1);
	
	TIM_SetCompare2(TIM3,PWM2);
	GPIO_SetBits(GPIOA,GPIO_Pin_2);
	GPIO_ResetBits(GPIOA,GPIO_Pin_3);
}

void yz(int PWM1,int PWM2)//右转
{
	TIM_SetCompare1(TIM3,PWM1);
	GPIO_SetBits(GPIOA,GPIO_Pin_0);
	GPIO_ResetBits(GPIOA,GPIO_Pin_1);
	
	TIM_SetCompare2(TIM3,PWM2);
	GPIO_SetBits(GPIOA,GPIO_Pin_2);
	GPIO_ResetBits(GPIOA,GPIO_Pin_3);
}

void ht(int PWM1,int PWM2)//后退
{
	TIM_SetCompare1(TIM3,PWM1);
	GPIO_ResetBits(GPIOA,GPIO_Pin_0);
	GPIO_SetBits(GPIOA,GPIO_Pin_1);
	
	TIM_SetCompare2(TIM3,PWM2);
	GPIO_ResetBits(GPIOA,GPIO_Pin_2);
	GPIO_SetBits(GPIOA,GPIO_Pin_3);
}

void tz(int PWM1,int PWM2)//停止
{
	TIM_SetCompare1(TIM3,PWM1);
	GPIO_ResetBits(GPIOA,GPIO_Pin_0);
	GPIO_ResetBits(GPIOA,GPIO_Pin_1);
	
	TIM_SetCompare2(TIM3,PWM2);
	GPIO_ResetBits(GPIOA,GPIO_Pin_2);
	GPIO_ResetBits(GPIOA,GPIO_Pin_3);
}

4.管脚初始化代码

GPIOX.c  I/O口初始化代码

#include "To.h"      
  
void GPIOx_cofing(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE);
	
	//小车车轮接口
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStruct);
	
	//LED
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC, &GPIO_InitStruct);
	
	//小车循迹接口
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0| GPIO_Pin_1|GPIO_Pin_10| GPIO_Pin_11;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStruct);
	
	
	//pwm输出/串口
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_9;  //GPIO_Pin_9 //TX
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;	
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	 
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;               //GPIO_Pin_10
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; 
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
}

5.循迹

5.1循迹模块的选择

循迹模块有模拟量和数字量的,初学者建议选择数字量,但循迹不丝滑,它的循迹原理就是接收到信号来转向。

5.2循迹代码

#include "To.h" 

void XJ(void)
{
	if( GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)==0&& GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0)==0)
	{
		qj(23,23);
	}
	
	
	else if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)==1&&GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0)==0)
	{
		zz(13,25);

	}
	                                                                                                      
	else if(	GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)==0&&GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0)==1)
	{
		yz(25,13);
	}

	
	else if(	GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)==1&&GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0)==1)
	{
		tz(0,0);
	}
}

6.蓝牙通信

6.1蓝牙的接线方法

请看VCR

Stm32 基于蓝牙的串口通信 详细篇

HC-05蓝牙模块--------手机与STM32通信(代码编写)(上位机配置)保姆级教程

STM32+HC-05蓝牙模块学习与使用

我这里用RCC_APB2Periph_USART1,波特率9600,PA9是TX,PA9接到蓝牙模块的RX,PA10是RX,PA10接到蓝牙模块的TX,单片机和蓝牙模块的这两个口反接。

#include "To.h"

uint16_t temp;
void usart_Initconfig(void)
{
	USART_InitTypeDef USART_InitStruct;
	NVIC_InitTypeDef NVIC_InitStruct;
	RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1,ENABLE);
	
	
	USART_InitStruct.USART_BaudRate = 9600;//波特率
	USART_InitStruct.USART_WordLength = USART_WordLength_8b;//数据位
	USART_InitStruct.USART_StopBits = USART_StopBits_1;//停止位长度
	USART_InitStruct.USART_Parity = USART_Parity_No;//校验位;无
	USART_InitStruct.USART_Mode = USART_Mode_Tx|USART_Mode_Rx;//发送/接收
	USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//硬件流控
	USART_Init(USART1,&USART_InitStruct);
	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//使能usart1的中断
	USART_Cmd(USART1, ENABLE);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority =0 ;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
	NVIC_InitStruct.NVIC_IRQChannelCmd =ENABLE;
	NVIC_Init(&NVIC_InitStruct);
}

void USART1_IRQHandler()
{
	//判断是否接收到数据
	if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
	{
		temp=USART_ReceiveByte(USART1);
		//USART_SendByte(USART1,temp);
		USART_ClearITPendingBit(USART1,USART_IT_RXNE);
	}
}



void USART_SendByte(USART_TypeDef* USARTx, uint16_t Data)
{
  assert_param(IS_USART_ALL_PERIPH(USARTx));
  assert_param(IS_USART_DATA(Data)); 
    
  USARTx->DR = (Data & (uint16_t)0x01FF);
  while(USART_GetFlagStatus(USART1, USART_FLAG_TXE)==0);
}



uint8_t USART_ReceiveByte(USART_TypeDef* USARTx)
{
	while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE)==0);//为0表示没有收到数据;为1表示收到数据

    return (uint8_t)USART_ReceiveData(USART1);
}

6.2蓝牙控制代码

#include "To.h" 

void YKXC(void)
{
	if(temp == 'w')  //控制w十六进制为“0x77”,temp == 0x77 也可以
	{
		qj(25,26);
	}
	
	else if(temp == 'a')
	{
		zz(22,30);
	}
	else if(temp == 'd')
	{
		yz(30,22);
	}
	else if(temp == 's')
	{
		ht(25,25);
	}
	else if(temp == 't')
	{
		tz(0,0);
	}
	else if(temp == 'x')
	{
		XJ();
	}
}	

7.舵机

7.1舵机的接法

信号线(黄色)、正极(红色)、负极(棕色)

信号线连接到P3^4,用定时器0,0.1ms中断一次,0.1*6(中断次数)=1ms(指向右边);0.1*15(中断次数)=1.5ms(舵机指向中间);0.1*20(中断次数)=2ms(舵机指向左边)

180度舵机控制参数
角度脉冲周期脉冲高电平时间占空比
020ms0.5ms2.50%
4520ms1ms5.00%
9020ms1.5ms7.50%
14520ms2ms10.00%
18020ms2.5ms12.50%

7.2例子代码:暂无

8.超声波

8.1超声波接线:

超声波和舵机是接在一起的,一般网上买都有连接材料,超声波可以随便连接I/O口,我这里接的是EchoPin = P3^6;//超声波模块Echo    接收端;TrigPin = P3^5;//超声波模块Trig    控制端。

8.2例子代码:暂无

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值