目录
OLED显示屏代码部分没有给出,该部分较为常用和容易获取就不给出了 ,其他部分的代码都完整给出了,不影响使用。
推荐STM32学习链接:
蓝牙APP制作:
OLED显示屏代码:
STM32F103C8T6延时函数和OLED显示屏代码_HX091624的博客-CSDN博客
一、电机驱动函数
使用的是L298N
IN1、IN2和IN3、IN4两两一对控制电机的正转、反转和停止,两个调速端分别控制两个电机调速
左右电机
#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);
}
左右电机调速
#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(); //右电机停止
}
二、输出比较(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);
}
三、蓝牙代码
使用的是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);
}
}
四、主函数
#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); //显示速度
}
}
总结
关于电源和L298N的介绍和用法:
https://blog.csdn.net/m0_47278454/article/details/117792924
其中的12V电源可以选用18650锂电池
希望大家多多留言,有任何问题都可以在评论区留言,需要源代码的可以留下QQ邮箱。