本程序是在keil5軟件下使用標(biāo)準(zhǔn)庫(kù)編程的,純自己手打,包含詳細(xì)的代碼注釋。
首先就是PWM模塊,次模塊用于改變小車(chē)的轉(zhuǎn)速,本項(xiàng)目用一個(gè)L98N電機(jī)驅(qū)動(dòng)模塊,將左邊的兩個(gè)輪子連接在一個(gè)L98N電機(jī)驅(qū)動(dòng)模塊輸出引腳,將坐標(biāo)的兩個(gè)輪子連接在L298N的另外一個(gè)輸出引腳,由此控制四個(gè)輪子的轉(zhuǎn)動(dòng)。
下面是PWM模塊的代碼
PWM.c
#include "stm32f10x.h" // Device header
//用兩個(gè)定時(shí)器產(chǎn)生PWM波形,分別控制兩側(cè)電機(jī)
//PA6、PA7、PA8、PA9四個(gè)引腳分別產(chǎn)生四個(gè)PWM波形控制左輪前進(jìn)調(diào)速、左輪后退調(diào)速、右輪前進(jìn)調(diào)速、右輪后退調(diào)速
//其中輪子的前進(jìn)和后退輸出的PWM波形必須相同
//初始化TIM1時(shí)鐘,控制PA8、PA9上的電機(jī),也就是右側(cè)電機(jī)
void TIM1_PWM_Init(void)
{
//RCC開(kāi)啟時(shí)鐘
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;// 復(fù)用推挽輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//配置時(shí)基單元
TIM_InternalClockConfig(TIM1);
//配置時(shí)基單元//初始化時(shí)基單元
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//自動(dòng)重裝值,當(dāng)?shù)?00時(shí)執(zhí)行一次中斷
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);//給結(jié)構(gòu)體變量賦初始值
TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;//設(shè)置輸出比較模式
TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;//設(shè)置輸出比較極性
TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;//設(shè)置輸出使能
TIM_OCInitStruct.TIM_Pulse=0;//設(shè)置CCR
//ARR=100-1,PSC=720-1,CCR=50。此時(shí)就是頻率為1KHz,占空比為50%的PWM波形
TIM_OC1Init(TIM1,&TIM_OCInitStruct);
TIM_OC2Init(TIM1,&TIM_OCInitStruct);
TIM_ARRPreloadConfig(TIM1,ENABLE); // 使能TIM1的自動(dòng)重裝載寄存器
TIM_CtrlPWMOutputs(TIM1,ENABLE); // 主輸出使能
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); // 使能TIM1在OC1上的預(yù)裝載寄存器
TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable); // 使能TIM1在OC2上的預(yù)裝載寄存器
//運(yùn)行控制,啟動(dòng)計(jì)數(shù)器
TIM_Cmd(TIM1,ENABLE);
}
//初始化TIM3時(shí)鐘,控制PA6、PA7上的電機(jī),也就是左側(cè)電機(jī)
void TIM3_PWM_Init(void)
{
//RCC開(kāi)啟時(shí)鐘
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;// 復(fù)用推挽輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//配置時(shí)基單元
TIM_InternalClockConfig(TIM3);
//配置時(shí)基單元//初始化時(shí)基單元
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//自動(dòng)重裝值,當(dāng)?shù)?00時(shí)執(zhí)行一次中斷
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);//給結(jié)構(gòu)體變量賦初始值
TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;//設(shè)置輸出比較模式
TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;//設(shè)置輸出比較極性
TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;//設(shè)置輸出使能
TIM_OCInitStruct.TIM_Pulse=0;//設(shè)置CCR
//ARR=100-1,PSC=720-1,CCR=50。此時(shí)就是頻率為1KHz,占空比為50%的PWM波形
TIM_OC1Init(TIM3,&TIM_OCInitStruct);
TIM_OC2Init(TIM3,&TIM_OCInitStruct);
TIM_ARRPreloadConfig(TIM3,ENABLE); // 使能TIM1的自動(dòng)重裝載寄存器
TIM_CtrlPWMOutputs(TIM3,ENABLE); // 主輸出使能
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); // 使能TIM1在OC1上的預(yù)裝載寄存器
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); // 使能TIM1在OC2上的預(yù)裝載寄存器
//運(yùn)行控制,啟動(dòng)計(jì)數(shù)器
TIM_Cmd(TIM3,ENABLE);
}
PWM.h
#ifndef __PWM_H
#define __PWM_H
#include "stm32f10x.h"
void TIM1_PWM_Init(void);//初始化TIM1時(shí)鐘,控制PA8、PA9上的電機(jī),也就是右側(cè)電機(jī)
void TIM3_PWM_Init(void);//初始化TIM3時(shí)鐘,控制PA6、PA7上的電機(jī),也就是左側(cè)電機(jī)
#endif
接下來(lái)是電機(jī)控制的代碼
Motor.c
#include "stm32f10x.h" // Device header
#include "PWM.h"
//電機(jī)初始化
void Motor_Init(void)
{
TIM1_PWM_Init();
TIM3_PWM_Init();
}
//設(shè)置左輪的速度
void Motor_SetLeftSpeed(int8_t Speed)
{
if(Speed>0)//前進(jìn)
{
GPIO_SetBits(GPIOA,GPIO_Pin_6);//產(chǎn)生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);//產(chǎn)生PWM波形
GPIO_ResetBits(GPIOA,GPIO_Pin_6);
TIM_SetCompare2(TIM3,-Speed);//PA7連接TIM3_CH2通道
}
}
//設(shè)置右輪的速度
void Motor_SetRightSpeed(int8_t Speed)
{
if(Speed>0)//前進(jìn)
{
GPIO_SetBits(GPIOA,GPIO_Pin_8);//產(chǎn)生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);//產(chǎn)生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);//電機(jī)初始化
void Motor_SetLeftSpeed(int8_t Speed);//設(shè)置左輪的速度//Speed>0前進(jìn),<0后退
void Motor_SetRightSpeed(int8_t Speed);//設(shè)置右輪的速度//Speed>0前進(jìn),<0后退
#endif
接下來(lái)是控制小車(chē)模塊的代碼
Car.c
#include "stm32f10x.h" // Device header
#include "PWM.h"
#include "Motor.h"
#include "Delay.h"
//小車(chē)初始化
void Car_Init(void)
{
Motor_Init();
}
//前進(jìn)調(diào)速
void Go_Ahead(int8_t Speed)
{
Motor_SetLeftSpeed(-Speed);
Motor_SetRightSpeed(-Speed);
}
//后退調(diào)速
void Go_Back(int8_t Speed)
{
Motor_SetLeftSpeed(Speed);
Motor_SetRightSpeed(Speed);
}
//右轉(zhuǎn)
void Turn_Left(void)
{
Motor_SetLeftSpeed(-40);
Motor_SetRightSpeed(80);
}
//左轉(zhuǎn)
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);//小車(chē)初始化
void Go_Ahead(int8_t Speed);//前進(jìn)調(diào)速//Speed>0前進(jìn),<0后退
void Go_Back(int8_t Speed);//后退調(diào)速//Speed>0前進(jìn),<0后退
void Turn_Left(void);//右轉(zhuǎn)
void Turn_Right(void);//左轉(zhuǎn)
void Car_stop(void);//停止
#endif
本項(xiàng)目可以使用藍(lán)牙控制小車(chē)的前進(jìn)后退轉(zhuǎn)彎等,接下來(lái)是藍(lán)牙模塊的代碼
lanya.c
#include "stm32f10x.h" // Device header
#include <stdio.h>
#include <stdarg.h>
uint8_t Serial_RXData;//定義一個(gè)變量,用于存儲(chǔ)接收的數(shù)據(jù)
uint8_t Serila_RXFlag;//接收變量標(biāo)志位
void Serial_Init(void)
{
//開(kāi)啟時(shí)鐘
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;//復(fù)用推挽輸出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;//初始化PA9引腳,用于串口發(fā)送//32的發(fā)送端//電腦的接收端
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的接收端//電腦的發(fā)送端
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//配置USART
USART_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;//發(fā)送+接收模式
USART_InitStruct.USART_Parity=USART_Parity_No;//不需要校驗(yàn)位
USART_InitStruct.USART_StopBits=USART_StopBits_1;//停止位//1位停止位
USART_InitStruct.USART_WordLength=USART_WordLength_8b;//選擇八位字長(zhǎng)
USART_Init(USART2,&USART_InitStruct);
//開(kāi)啟中斷
USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);//開(kāi)啟RXNE標(biāo)志位到NVIC的輸出
//配置NVIC
NVIC_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);
//開(kāi)啟USART
USART_Cmd(USART2,ENABLE);
}
//發(fā)送字節(jié)
void Seral_SendByte(uint8_t Byte)
{
USART_SendData(USART2,Byte);//將串口的數(shù)據(jù)發(fā)送到電腦上
while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);//等待傳輸完成
}
//發(fā)送數(shù)組
void Seril_SendArray(uint8_t *Array,uint16_t Length)
{
uint16_t i;
for(i=0;i<Length;i++)
{
Seral_SendByte(Array[i]);//通過(guò)for循環(huán)一位一位的發(fā)送數(shù)組中的數(shù)據(jù)
}
}
//發(fā)送字符串
void Seril_SendString(char *String)
{
uint8_t i;
for(i=0;String[i]!='\0';i++)
{
Seral_SendByte(String[i]);//通過(guò)for循環(huán)一位一位的發(fā)送數(shù)組中的數(shù)據(jù)
}
}
uint32_t Seril_Pow(uint32_t X,uint32_t Y)
{
uint32_t Result=1;
while(Y--)
{
Result*=X;
}
return Result;
}
//發(fā)送數(shù)字
void Seril_SendNumber(uint32_t Number,uint8_t Length)
{
uint8_t i;
for(i=0;i<Length;i++)
{
Seral_SendByte(Number/Seril_Pow(10,Length-i-1)%10+'0');
}
}
int fputc(int ch,FILE *f)//將fputc函數(shù)重定向到串口
{
Seral_SendByte(ch);
return ch;
}
//打印
void Serial_Printf(char *format, ...)
{
char String[100];
va_list arg;
va_start(arg, format);
vsprintf(String, format, arg);
va_end(arg);
Seril_SendString(String);
}
//清除標(biāo)志位函數(shù),自動(dòng)清除標(biāo)志位
uint8_t Serial_GetRxFlag(void)
{
if(Serila_RXFlag==1)//如果接收標(biāo)志位為1,則清除接收標(biāo)志位,并且函數(shù)返回1
{
Serila_RXFlag=0;
return 1;
}
return 0;
}
//這個(gè)函數(shù)用于返回接收到的數(shù)據(jù)
uint8_t Serial_GetRxData(void)
{
return Serial_RXData;
}
//中斷函數(shù)
void USART2_IRQHandler(void)
{
if(USART_GetITStatus(USART2,USART_IT_RXNE)==SET)//如果這個(gè)函數(shù)為1,說(shuō)明接收數(shù)據(jù)的發(fā)生
{
Serial_RXData=USART_ReceiveData(USART2);//將數(shù)據(jù)存儲(chǔ)在變量Serial_RXData中
Serila_RXFlag=1;//接收標(biāo)志位置1
USART_ClearITPendingBit(USART2,USART_IT_RXNE);//清除接收標(biāo)志位
}
}
lanya.h
#ifndef __LANYA_H
#define __LANYA_H
#include "stm32f10x.h"
#include <stdio.h>
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
最后就是主函數(shù)了
main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "Car.h"
#include "lanya.h"
#include "OLED.h"
uint8_t Date;//定義一個(gè)變量,用于存儲(chǔ)接收的數(shù)據(jù)、
uint8_t Go_Ahead_flag=0;//0表示沒(méi)有前進(jìn),1前進(jìn)50,2前進(jìn)100
uint8_t Go_Back_flag=0;//0表示沒(méi)有前進(jìn),1前進(jìn)50,2前進(jìn)100
int main(void)
{
Car_Init();//初始化小車(chē)
Serial_Init();//初始化藍(lán)牙串口
OLED_Init();//初始化OLED
OLED_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說(shuō)明有數(shù)據(jù)接收的發(fā)生
{
Date=Serial_GetRxData();//將接收到的數(shù)據(jù)傳到變量RxDate中
OLED_ShowHexNum(2,9,Date,2);//在OLED上顯示接收到的數(shù)據(jù)
if(Date==02)//前進(jìn)
{
Car_Init();
Seril_SendString("Go_Ahead");//將對(duì)應(yīng)的命令返回到手機(jī)上
OLED_ShowString(3,9,"Go_Ahead");//將對(duì)應(yīng)的命令在怕屏幕上顯示
OLED_ShowNum(4,9,50,2);
Go_Ahead(100);//前進(jìn)50
}
if(Date==00)//后退
{
Car_Init();
Seril_SendString("Go_Back");//將對(duì)應(yīng)的命令返回到手機(jī)上
OLED_ShowString(3,9,"Go_Back");//將對(duì)應(yīng)的命令在怕屏幕上顯示
OLED_ShowNum(4,9,50,2);
Go_Back(50);//后退50
}
if(Date==06)//右轉(zhuǎn)
{
Car_Init();
Seril_SendString("TurnRight");//將對(duì)應(yīng)的命令返回到手機(jī)上
OLED_ShowString(3,9,"TurnRight");//將對(duì)應(yīng)的命令在怕屏幕上顯示
Turn_Right();
OLED_ShowNum(4,9,00,2);
}
if(Date==04)//左轉(zhuǎn)
{
Car_Init();
Seril_SendString("TurnLeft");//將對(duì)應(yīng)的命令返回到手機(jī)上
OLED_ShowString(3,9,"TurnLeft");//將對(duì)應(yīng)的命令在怕屏幕上顯示
Turn_Left();
OLED_ShowNum(4,9,00,2);
}
if(Date==07)//停止
{
Car_Init();
Seril_SendString("Car_stop");//將對(duì)應(yīng)的命令返回到手機(jī)上
OLED_ShowString(3,9,"Car_stop");//將對(duì)應(yīng)的命令在怕屏幕上顯示
Car_stop();//停止
OLED_ShowNum(4,9,00,2);
}
}
}
}
使用藍(lán)牙調(diào)試軟件(各大手機(jī)應(yīng)用商店都有下載),連接藍(lán)牙模塊后,想藍(lán)牙模塊發(fā)送相應(yīng)代碼,小車(chē)就可以執(zhí)行相應(yīng)的命令。
到此本項(xiàng)目就暫時(shí)分享完了,如果需要完成的工程軟件評(píng)論我,我發(fā)給你。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-754006.html
PS:本人熟悉51單片機(jī)與STM32的操作與使用,如有關(guān)于單片機(jī)(51、STM32)的作業(yè)、課設(shè)、畢業(yè)設(shè)計(jì)皆可詢問(wèn)本人。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-754006.html
到了這里,關(guān)于STM32C8T6控制智能小車(chē)代碼的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!