STM32F103C8T6 Bluetooth smart car

Table of contents

1. Motor drive function

left and right motor

Left and right motor speed regulation

2. Output comparison (PWM)

3. Bluetooth code

Fourth, the main function

Summarize


The OLED display code part is not given, and this part is more commonly used and easy to obtain, so it is not given. The codes of other parts are given in full, which will not affect the use.

Recommended STM32 learning link:

[9-6] FlyMcu serial port download & STLINK Utility_哔哩哔哩_bilibili [9-6] FlyMcu serial port download & STLINK Utility is the 29th episode of STM32 introductory tutorial - 2022 continuous update video, the collection has a total of 29 episodes, video collection Or pay attention to the UP master to learn more about related video content in time. https://www.bilibili.com/video/BV1th411z7sn/?p=29&vd_source=ed36b2700bbc2bac7746c270bc391540

 Bluetooth APP production:

Bluetooth APP production (App inventor develops APP, AT command configures Bluetooth module ) Some simple AT commands, 54472 video views, 81 bullet screens, 1169 likes, 850 coin tosses, 2866 bookmarks, 623 reposts, video author Chu Ming Yiming, author profile PPT and code warehouse: https: //gitee.com/hello-nccya will send out good things after learning, related videos: [Bluetooth APP] Phase 1: AT command to configure Bluetooth module HC05; APP presses the button to send data, self-made Android App, APP inventor basic Operation introduction, the making process of a simple app, App Inventor making Bluetooth control app, Bluetooth APP2 (APP receives and displays the data sent by Bluetooth), Wifi module--esp8266 (AT command version), serial Bluetooth app production, STM32 fourth The first training (serial port), [Bluetooth APP] the third period: the use of the timer, the APP receives the data and displays it, the seventh training of STM32 (steering gear: PWM), STM32 application (Bluetooth APP controls the motor speed and steering) https: / /www.bilibili.com/video/BV1Cy4y1h7ma/?spm_id_from=333.1007.top_right_bar_window_default_collection.content.click

OLED display code:

 STM32F103C8T6 delay function and OLED display code_HX091624's Blog-CSDN Blog

1. Motor drive function

Using L298N

IN1, IN2 and IN3, IN4 are paired to control the forward rotation, reverse rotation and stop of the motor, and the two speed control terminals respectively control the speed regulation of the two motors

left and right motor

#include "stm32f10x.h"                 
#include "PWM.h"

void Motor_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	//电机控制
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	//控制左电机->PA0 PA1 控制右电机->PA4 PA5
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1|GPIO_Pin_4 | GPIO_Pin_5;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	PWM_Init();
}

//右边电机向前
void Right_moto_go(void)
{
	//正转
	GPIO_SetBits(GPIOA, GPIO_Pin_4);
	GPIO_ResetBits(GPIOA, GPIO_Pin_5);
}
//右边电机向后
void Right_moto_back(void)
{
	//反转
	GPIO_ResetBits(GPIOA, GPIO_Pin_4);
	GPIO_SetBits(GPIOA, GPIO_Pin_5);
}
//右边电机停止
void Right_moto_Stop(void)
{
	//停车
	GPIO_ResetBits(GPIOA, GPIO_Pin_4);
	GPIO_ResetBits(GPIOA, GPIO_Pin_5);
}
//左边电机向前
void Left_moto_go(void)
{
	//正转
	GPIO_SetBits(GPIOA, GPIO_Pin_0);
	GPIO_ResetBits(GPIOA, GPIO_Pin_1);
}
//左边电机向后
void Left_moto_back(void)
{
	//反转
	GPIO_ResetBits(GPIOA, GPIO_Pin_0);
	GPIO_SetBits(GPIOA, GPIO_Pin_1);
}
//左边电机停止
void Left_moto_Stop(void)
{
	//停车
	GPIO_ResetBits(GPIOA, GPIO_Pin_0);
	GPIO_ResetBits(GPIOA, GPIO_Pin_1);
}

Left and right motor speed regulation

#include "stm32f10x.h"                  // Device header
#include "Motor.h"
#include "PWM.h"

//小车调速函数
void Speed_Control(uint16_t Compare)
{
	Compare*=200; //100->20000
	PWM_SetCompare1(Compare); //调速
	PWM_SetCompare2(Compare);
}

//小车前进函数
void  run(uint16_t Compare)          //小车前进函数
{
	Speed_Control(Compare);
	Left_moto_go();      //左电机往前
	Right_moto_go();       //右电机往前
}

//小车后退函数
void  backrun(uint16_t Compare)      //小车后退函数
{
	Speed_Control(Compare);
	Left_moto_back();      //左电机往后
	Right_moto_back();     //右电机往后
}

//小车左转函数
void  leftrun(uint16_t Compare)      //小车左转函数
{	 
	Speed_Control(Compare);
	Left_moto_back();      //左电机往后
	Right_moto_go();       //右电机往前
}

//小车右转函数
void  rightrun(uint16_t Compare)     //小车右转函数
{ 
	Speed_Control(Compare);
	Right_moto_back();     //右电机向后
	Left_moto_go();        //左电机向前
}

//小车左倒车函数
void leftback(uint16_t Compare)
{	 
	Speed_Control(Compare);
	Left_moto_go();      		//左电机往前
	Right_moto_back();       	//右电机往后
}

//小车右倒车函数
void rightback(uint16_t Compare)
{
	Speed_Control(Compare);
	Right_moto_go();     		//右电机向前
	Left_moto_back();        	//左电机向后
}

//小车停车函数
void  stop(void)         //小车停车函数
{   	
	Left_moto_Stop();      //左电机停止
	Right_moto_Stop();     //右电机停止
}

2. Output comparison (PWM)

#include "stm32f10x.h"                  // Device header
//定时器3PWM调速  周期20MS  计一个数->1US
void PWM_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	//电动机PWM输出 PA6 PA7
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	//舵机PWM输出 PB0
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	TIM_InternalClockConfig(TIM3);
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 20000 - 1;		//ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;		//PSC
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
	
	TIM_OCInitTypeDef TIM_OCInitStructure;
	TIM_OCStructInit(&TIM_OCInitStructure);
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_Pulse = 0;		//CCR
	TIM_OC1Init(TIM3, &TIM_OCInitStructure); //PWM输出引脚
	TIM_OC2Init(TIM3, &TIM_OCInitStructure);
	TIM_OC3Init(TIM3, &TIM_OCInitStructure);
	
	TIM_Cmd(TIM3, ENABLE);
}
//左右电机输出比较
void PWM_SetCompare1(uint16_t Compare)
{
	TIM_SetCompare1(TIM3, Compare);
}

void PWM_SetCompare2(uint16_t Compare)
{
	TIM_SetCompare2(TIM3, Compare);
}

3. Bluetooth code

Using JDY-31

#include "stm32f10x.h"              

uint8_t Serial_RxData;
uint8_t Serial_RxFlag;

void Serial_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	//串口波形空闲状态是高电平,所以不使用下拉输入
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	USART_InitTypeDef USART_InitStructure;
	USART_InitStructure.USART_BaudRate = 9600;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;//发送和接受
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_Init(USART1, &USART_InitStructure);
	//查询的流程是,在主函数里不断判断RXNE标志位,置1说明接受到数据了
	//再调用ReceiveData,读取DR寄存器  自动清除标志位
	//接受需要中断
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//RXNE的中断
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
	
	USART_Cmd(USART1, ENABLE);
}

void Serial_SendByte(uint8_t Byte)
{
	USART_SendData(USART1, Byte);
	while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}

uint8_t Serial_GetRxFlag(void)
{
	if (Serial_RxFlag == 1)
	{
		Serial_RxFlag = 0;
		return 1;
	}
	return 0;
}

uint8_t Serial_GetRxData(void)
{
	return Serial_RxData;
}
//中断
void USART1_IRQHandler(void)
{
	//目前只支持一个字节的接受
	if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
	{
		Serial_RxData = USART_ReceiveData(USART1);
		Serial_RxFlag = 1;
		USART_ClearITPendingBit(USART1, USART_IT_RXNE);
	}
}

Fourth, the main function

#include "stm32f10x.h"           
#include "OLED.h"
#include "Serial.h"
#include "Motor.h"
#include "MotorRun.h"

uint8_t RxFlag;
uint8_t RxData;
uint16_t Speed=20;

int main(void)
{
	OLED_Init();
	Serial_Init();
	Motor_Init();
	OLED_ShowString(1, 1, "RxData:");
	OLED_ShowString(2, 1, "Speed:");
	
	while (1)
	{
		RxFlag = Serial_GetRxFlag();
		if (RxFlag == 1)
		{
			RxData = Serial_GetRxData();
			Serial_SendByte(RxData);
			switch(RxData)
			{
				case 1:run(Speed);		//前进
					break;
				case 2:backrun(Speed);	//后退
					break;
				case 3:leftrun(Speed);	//左转
					break;
				case 4:rightrun(Speed);	//右转
					break;
				case 5:stop();			//停车
					break;				
			}	
			OLED_ShowNum(1,8,RxData,1);
		}
		OLED_ShowNum (2,7,Speed,2);    	//显示速度
	}
}

Summarize

Introduction and usage of power supply and L298N:

https://blog.csdn.net/m0_47278454/article/details/117792924

The 12V power supply can choose 18650 lithium battery

 

I hope you will leave a lot of comments. If you have any questions, you can leave a message in the comment area. If you need the source code, you can leave a QQ mailbox. 

Guess you like

Origin blog.csdn.net/HX091624/article/details/127322994