STM32C8T6控制智能小车代码

本程序是在keil5软件下使用标准库编程的,纯自己手打,包含详细的代码注释。

首先就是PWM模块,次模块用于改变小车的转速,本项目用一个L98N电机驱动模块,将左边的两个轮子连接在一个L98N电机驱动模块输出引脚,将坐标的两个轮子连接在L298N的另外一个输出引脚,由此控制四个轮子的转动。

下面是PWM模块的代码

PWM.c

#include "stm32f10x.h"                  // Device header//用两个定时器产生PWM波形,分别控制两侧电机
//PA6、PA7、PA8、PA9四个引脚分别产生四个PWM波形控制左轮前进调速、左轮后退调速、右轮前进调速、右轮后退调速
//其中轮子的前进和后退输出的PWM波形必须相同//初始化TIM1时钟,控制PA8、PA9上的电机,也就是右侧电机
void TIM1_PWM_Init(void)
{//RCC开启时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9;	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;// 复用推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);//配置时基单元TIM_InternalClockConfig(TIM1);//配置时基单元//初始化时基单元TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;TIM_TimeBaseInitStruct.TIM_Period=100-1;//ARR//自动重装值,当到100时执行一次中断TIM_TimeBaseInitStruct.TIM_Prescaler=720-1;//PSC//将72HMZ分为720份TIM_TimeBaseInitStruct.TIM_RepetitionCounter=0;TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStruct);//配置输出比较单元TIM_OCInitTypeDef TIM_OCInitStruct;TIM_OCStructInit(&TIM_OCInitStruct);//给结构体变量赋初始值TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;//设置输出比较模式TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;//设置输出比较极性TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;//设置输出使能TIM_OCInitStruct.TIM_Pulse=0;//设置CCR//ARR=100-1,PSC=720-1,CCR=50。此时就是频率为1KHz,占空比为50%的PWM波形TIM_OC1Init(TIM1,&TIM_OCInitStruct);TIM_OC2Init(TIM1,&TIM_OCInitStruct);TIM_ARRPreloadConfig(TIM1,ENABLE);								   // 使能TIM1的自动重装载寄存器TIM_CtrlPWMOutputs(TIM1,ENABLE);								// 主输出使能TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);  				// 使能TIM1在OC1上的预装载寄存器TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);				// 使能TIM1在OC2上的预装载寄存器	//运行控制,启动计数器TIM_Cmd(TIM1,ENABLE);
}//初始化TIM3时钟,控制PA6、PA7上的电机,也就是左侧电机
void TIM3_PWM_Init(void)
{//RCC开启时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;// 复用推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);							//配置时基单元TIM_InternalClockConfig(TIM3);//配置时基单元//初始化时基单元TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;TIM_TimeBaseInitStruct.TIM_Period=100-1;//ARR//自动重装值,当到100时执行一次中断TIM_TimeBaseInitStruct.TIM_Prescaler=720-1;//PSC//将72HMZ分为720份TIM_TimeBaseInitStruct.TIM_RepetitionCounter=0;TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);//配置输出比较单元TIM_OCInitTypeDef TIM_OCInitStruct;TIM_OCStructInit(&TIM_OCInitStruct);//给结构体变量赋初始值TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;//设置输出比较模式TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;//设置输出比较极性TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;//设置输出使能TIM_OCInitStruct.TIM_Pulse=0;//设置CCR//ARR=100-1,PSC=720-1,CCR=50。此时就是频率为1KHz,占空比为50%的PWM波形TIM_OC1Init(TIM3,&TIM_OCInitStruct);TIM_OC2Init(TIM3,&TIM_OCInitStruct);TIM_ARRPreloadConfig(TIM3,ENABLE);								   // 使能TIM1的自动重装载寄存器TIM_CtrlPWMOutputs(TIM3,ENABLE);								// 主输出使能TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);  				// 使能TIM1在OC1上的预装载寄存器TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);				// 使能TIM1在OC2上的预装载寄存器	//运行控制,启动计数器TIM_Cmd(TIM3,ENABLE);
}

PWM.h

#ifndef __PWM_H
#define __PWM_H
#include "stm32f10x.h" void TIM1_PWM_Init(void);//初始化TIM1时钟,控制PA8、PA9上的电机,也就是右侧电机
void TIM3_PWM_Init(void);//初始化TIM3时钟,控制PA6、PA7上的电机,也就是左侧电机#endif

接下来是电机控制的代码

Motor.c

#include "stm32f10x.h"                  // Device header
#include "PWM.h"//电机初始化
void Motor_Init(void)
{TIM1_PWM_Init();TIM3_PWM_Init();
}//设置左轮的速度
void Motor_SetLeftSpeed(int8_t Speed)
{if(Speed>0)//前进{	GPIO_SetBits(GPIOA,GPIO_Pin_6);//产生PWM波形GPIO_ResetBits(GPIOA,GPIO_Pin_7);TIM_SetCompare1(TIM3,Speed);//PA6连接TIM3_CH1通道}else if(Speed==0)//停止{GPIO_SetBits(GPIOA,GPIO_Pin_7);GPIO_SetBits(GPIOA,GPIO_Pin_6);}else //后退{GPIO_SetBits(GPIOA,GPIO_Pin_7);//产生PWM波形GPIO_ResetBits(GPIOA,GPIO_Pin_6);TIM_SetCompare2(TIM3,-Speed);//PA7连接TIM3_CH2通道}
}//设置右轮的速度
void Motor_SetRightSpeed(int8_t Speed)
{if(Speed>0)//前进{	GPIO_SetBits(GPIOA,GPIO_Pin_8);//产生PWM波形GPIO_ResetBits(GPIOA,GPIO_Pin_9);TIM_SetCompare1(TIM1,Speed);//PA8连接TIM1_CH1通道}else if(Speed==0)//停止{GPIO_SetBits(GPIOA,GPIO_Pin_8);GPIO_SetBits(GPIOA,GPIO_Pin_9);}else //后退{GPIO_SetBits(GPIOA,GPIO_Pin_9);//产生PWM波形GPIO_ResetBits(GPIOA,GPIO_Pin_8);TIM_SetCompare2(TIM1,-Speed);//PA9连接TIM1_CH2通道}
}

Motor.h

#ifndef __MOTOR_H
#define __MOTOR_H
#include "stm32f10x.h" void Motor_Init(void);//电机初始化
void Motor_SetLeftSpeed(int8_t Speed);//设置左轮的速度//Speed>0前进,<0后退
void Motor_SetRightSpeed(int8_t Speed);//设置右轮的速度//Speed>0前进,<0后退#endif

接下来是控制小车模块的代码

Car.c

#include "stm32f10x.h"                  // Device header
#include "PWM.h"
#include "Motor.h"
#include "Delay.h"//小车初始化
void Car_Init(void)
{Motor_Init();
}//前进调速
void Go_Ahead(int8_t Speed)
{Motor_SetLeftSpeed(-Speed);Motor_SetRightSpeed(-Speed);
}//后退调速
void Go_Back(int8_t Speed)
{Motor_SetLeftSpeed(Speed);Motor_SetRightSpeed(Speed);
}//右转
void Turn_Left(void)
{Motor_SetLeftSpeed(-40);Motor_SetRightSpeed(80);
}//左转
void Turn_Right(void)
{Motor_SetLeftSpeed(80);Motor_SetRightSpeed(-40);
}//停止
void Car_stop(void)
{Motor_SetLeftSpeed(0);Motor_SetRightSpeed(0);
}

Car.h

#ifndef __CAR_H
#define __CAR_H
#include "stm32f10x.h" void Car_Init(void);//小车初始化
void Go_Ahead(int8_t Speed);//前进调速//Speed>0前进,<0后退
void Go_Back(int8_t Speed);//后退调速//Speed>0前进,<0后退
void Turn_Left(void);//右转
void Turn_Right(void);//左转
void Car_stop(void);//停止#endif

本项目可以使用蓝牙控制小车的前进后退转弯等,接下来是蓝牙模块的代码

lanya.c

#include "stm32f10x.h"                  // Device header
#include 
#include uint8_t Serial_RXData;//定义一个变量,用于存储接收的数据
uint8_t Serila_RXFlag;//接收变量标志位void Serial_Init(void)
{//开启时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//GPIO初始化GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;//初始化PA9引脚,用于串口发送//32的发送端//电脑的接收端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_3;//初始化PA10引脚,用于串口接收//32的接收端//电脑的发送端GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);//配置USARTUSART_InitTypeDef USART_InitStruct;USART_InitStruct.USART_BaudRate=9600;//波特率USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_RTS;//硬件流控制//不需要控制流USART_InitStruct.USART_Mode=USART_Mode_Tx | USART_Mode_Rx;//发送+接收模式USART_InitStruct.USART_Parity=USART_Parity_No;//不需要校验位USART_InitStruct.USART_StopBits=USART_StopBits_1;//停止位//1位停止位USART_InitStruct.USART_WordLength=USART_WordLength_8b;//选择八位字长USART_Init(USART2,&USART_InitStruct);//开启中断USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);//开启RXNE标志位到NVIC的输出//配置NVICNVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//初始化NVIC的USART1通道NVIC_InitTypeDef NVIC_InitStruct;NVIC_InitStruct.NVIC_IRQChannel=USART2_IRQn;NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1;NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;NVIC_Init(&NVIC_InitStruct);//开启USARTUSART_Cmd(USART2,ENABLE);
}//发送字节
void Seral_SendByte(uint8_t Byte)
{USART_SendData(USART2,Byte);//将串口的数据发送到电脑上while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);//等待传输完成
}//发送数组
void Seril_SendArray(uint8_t *Array,uint16_t Length)
{uint16_t i;for(i=0;i

lanya.h

#ifndef __LANYA_H
#define __LANYA_H
#include "stm32f10x.h"
#include void Serial_Init(void);
void Seral_SendByte(uint8_t Byte);
void Seril_SendArray(uint8_t *Array,uint16_t Length);
void Seril_SendString(char *String);
void Seril_SendNumber(uint32_t Number,uint8_t Length);
void Serial_Printf(char *format, ...);
uint8_t Serial_GetRxFlag(void);
uint8_t Serial_GetRxData(void);#endif

最后就是主函数了

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "Car.h"
#include "lanya.h"
#include "OLED.h"uint8_t Date;//定义一个变量,用于存储接收的数据、
uint8_t Go_Ahead_flag=0;//0表示没有前进,1前进50,2前进100
uint8_t Go_Back_flag=0;//0表示没有前进,1前进50,2前进100int main(void)
{Car_Init();//初始化小车Serial_Init();//初始化蓝牙串口OLED_Init();//初始化OLEDOLED_ShowString(1,4,"Car control");OLED_ShowString(2,1,"Data:");OLED_ShowString(3,1,"Command:");OLED_ShowString(4,1,"Speed:");while (1){		if(Serial_GetRxFlag()==1)//如果Serial_GetRxFlag()返回值是1说明有数据接收的发生{Date=Serial_GetRxData();//将接收到的数据传到变量RxDate中OLED_ShowHexNum(2,9,Date,2);//在OLED上显示接收到的数据if(Date==02)//前进{Car_Init();Seril_SendString("Go_Ahead");//将对应的命令返回到手机上OLED_ShowString(3,9,"Go_Ahead");//将对应的命令在怕屏幕上显示OLED_ShowNum(4,9,50,2);Go_Ahead(100);//前进50}	if(Date==00)//后退{Car_Init();Seril_SendString("Go_Back");//将对应的命令返回到手机上OLED_ShowString(3,9,"Go_Back");//将对应的命令在怕屏幕上显示OLED_ShowNum(4,9,50,2);Go_Back(50);//后退50}if(Date==06)//右转{Car_Init();Seril_SendString("TurnRight");//将对应的命令返回到手机上OLED_ShowString(3,9,"TurnRight");//将对应的命令在怕屏幕上显示Turn_Right();OLED_ShowNum(4,9,00,2);}	if(Date==04)//左转{Car_Init();Seril_SendString("TurnLeft");//将对应的命令返回到手机上OLED_ShowString(3,9,"TurnLeft");//将对应的命令在怕屏幕上显示Turn_Left();OLED_ShowNum(4,9,00,2);}if(Date==07)//停止{Car_Init();Seril_SendString("Car_stop");//将对应的命令返回到手机上OLED_ShowString(3,9,"Car_stop");//将对应的命令在怕屏幕上显示Car_stop();//停止OLED_ShowNum(4,9,00,2);}}}
}

使用蓝牙调试软件(各大手机应用商店都有下载),连接蓝牙模块后,想蓝牙模块发送相应代码,小车就可以执行相应的命令。

到此本项目就暂时分享完了,如果需要完成的工程软件评论我,我发给你。

PS:本人熟悉51单片机与STM32的操作与使用,如有关于单片机(51、STM32)的作业、课设、毕业设计皆可询问本人。


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部