实验条件
STM32F103开发板
TB6612电机驱动模块
参考代码:
#include "car.h"
//初始化定时器,实现PWM输出
void PWM_Init(u16 arr,u16 psc){
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //①使能定时器 3 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO, ENABLE); //①使能 GPIO 和 AFIO 复用功能时钟
GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE); //②重映射 TIM3_CH2->PB5
//设置该引脚为复用输出功能,输出 TIM3 CH2 的 PWM 脉冲波形 GPIOB.5
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; //TIM_CH2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure); //①初始化 GPIO
//初始化 TIM3
TIM_TimeBaseStructure.TIM_Period = arr; //设置在自动重装载周期值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM 向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //③初始化 TIMx
//初始化 TIM3 Channel2 PWM 模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择 PWM 模式 2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性高
TIM_OC1Init(TIM3, &TIM_OCInitStructure); //④初始化外设 TIM3 OC2
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能预装载寄存器
TIM_OC2Init(TIM3, &TIM_OCInitStructure); //④初始化外设 TIM3 OC2
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能预装载寄存器
TIM_Cmd(TIM3, ENABLE); //⑤使能 TIM3
}
/**************************************************************************
函数功能:电机的正反转
入口参数:mode mode=0时为正转 mode=1时反转 mode=2是停止
返回 值:无
**************************************************************************/
void MOTO(int mode)
{
if(mode==PosMode )//正转
{
GPIO_SetBits(GPIOB, GPIO_Pin_13); // 高电平
GPIO_ResetBits(GPIOB, GPIO_Pin_14); // 低电平}
GPIO_SetBits(GPIOA, GPIO_Pin_4); // 高电平
GPIO_ResetBits(GPIOA, GPIO_Pin_5); // 低电平
}
if(mode==NegMode)//反转
{
GPIO_ResetBits(GPIOB, GPIO_Pin_13); // 低电平
GPIO_SetBits(GPIOB, GPIO_Pin_14); // 高电平
GPIO_ResetBits(GPIOA, GPIO_Pin_4); // 低电平
GPIO_SetBits(GPIOA, GPIO_Pin_5); // 高电平
}
if(mode==StopMode)//停止
{
GPIO_ResetBits(GPIOB, GPIO_Pin_13); // 低电平
GPIO_ResetBits(GPIOB, GPIO_Pin_14); // 低电平}
GPIO_ResetBits(GPIOA, GPIO_Pin_4); // 低电平
GPIO_ResetBits(GPIOA, GPIO_Pin_5); // 低电平
}
}
//初始化所需GPIO
void CAR_Gpio_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //定义结构体GPIO_InitStructure
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE); // 使能PB端口时钟
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE); // 使能PA端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13| GPIO_Pin_14; //PB4 PB3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽,增大电流输出能力
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度
GPIO_Init(GPIOB, &GPIO_InitStructure); //GBIOB初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4| GPIO_Pin_5; //PB4 PB5
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽,增大电流输出能力
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度
GPIO_Init(GPIOA, &GPIO_InitStructure); //GBIOA初始化
}
void CAR_Speed(u16 speed){
TIM_SetCompare1(TIM3,speed);
TIM_SetCompare2(TIM3,speed);
}
主函数参考代码:
#include "stm32f10x.h"
#include "lcd.h"
#include "delay.h"
#include "remote.h"
#include "motor.h"
#include "key.h"
#include "led.h"
#include "usart.h"
#define MAXSPEED 7000
#define MINSPEED 1000
#define FILTERNUM 20
int main(void)
{
u8 Remote_key;//遥控器键值
u8 Key;//按键值
u8 *str=0;//遥控器显示
u16 speed=1000;
u16 PWM=0;
u16 filter=FILTERNUM;
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
uart_init(115200); //串口初始化为115200
LCD_Init();//初始化LCD功能; 320*240
Remote_Init(); //红外接收初始化
LED_Init(); //LED端口初始化
//TIM3_PWM_Init(7199,0); //不分频。PWM频率=72000000/900=80Khz
PWM_Init(7199,0);
KEY_Init();
CAR_Gpio_Init();
LCD_ShowString(30,60,300,16,16,"My RoBot");
LCD_ShowString(30,80,300,16,16,"MOTOR TEST:");
LCD_ShowString(30,100,300,16,16,"PWM: %");
MOTO(PosMode);
CAR_Speed(speed);//设置速度
while(1){
Remote_key=Remote_Scan();
Key=KEY_Scan(0);
//TIM_SetCompare2(TIM3,led0pwmval);
if(Remote_key)
{ switch(Remote_key)
{
case 0:str="ERROR";break;
case 162:
str="STOP";
MOTO(StopMode);
break;
case 98:str="UP";break;
case 2:str="PLAY";break;
case 226:
str="Go!";
MOTO(PosMode);
break;
case 194:str="RIGHT";break;
case 34:str="LEFT";break;
case 224:
str="VOL-";
filter--;
if(!filter){
filter=FILTERNUM;
speed-=1000;
if(speed<1000){
speed=MINSPEED;
}
}
break;
case 168:str="DOWN";break;
case 144:
str="VOL+";
filter--;
if(!filter){
filter=FILTERNUM;
speed+=500;
if(speed>7000){
speed=MAXSPEED;
}
}
break;
case 104:str="1";break;
case 152:str="2";break;
case 176:str="3";break;
case 48:str="4";break;
case 24:str="5";break;
case 122:str="6";break;
case 16:str="7";break;
case 56:str="8";break;
case 90:str="9";break;
case 66:str="0";break;
case 82:str="DELETE";break;
}
}else delay_ms(10);
if(Key==KEY0_PRES){//减速
speed-=1000;
if(speed<1000){
speed=MINSPEED;
}
}else if(Key==KEY1_PRES){
//加速
speed+=500;
if(speed>7000){
speed=MAXSPEED;
}
}
CAR_Speed(speed);
LCD_Fill(30+12*8,80,300,80+16,WHITE); //清楚之前的显示
LCD_ShowString(30+12*8,80,300,16,16,str); //显示SYMBOL
PWM=speed*100/7200;
LCD_ShowNum(30+4*8, 100, PWM, 2, 16);
}
}
引脚连接:
A01——电机负
B01——电机正
PC6——PWMA
PC7——PWMB
AIN1——PB14
AIN2——PB13
BIN1——PA5
BIN2——PA4
TB6612逻辑电源、使能信号-由降压3V3提供
单片机电源5V5OUT连接降压源3V3
编码器连线:
PA9——右轮B
PA8——右轮A
PA0——左轮B
PA1——左轮A
编码器参考代码:
#include "encoder.h"
/**************************************************************************
函数功能:把TIM1初始化为编码器接口模式
入口参数:无
返回 值:无
**************************************************************************/
void Encoder_Init_TIM1(void)
{
TIM_TimeBaseInitTypeDef TIM1_TimeBaseStructure;
TIM_ICInitTypeDef TIM1_ICInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA ,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9; //端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOA
TIM_TimeBaseStructInit(&TIM1_TimeBaseStructure);
TIM1_TimeBaseStructure.TIM_Prescaler = 0x0; // 预分频器
TIM1_TimeBaseStructure.TIM_Period = ENCODER_TIM_PERIOD; //设定计数器自动重装值
TIM1_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择时钟分频:不分频
TIM1_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM向上计数
TIM_TimeBaseInit(TIM1, &TIM1_TimeBaseStructure);
TIM_EncoderInterfaceConfig(TIM1, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
TIM_ICStructInit(&TIM1_ICInitStructure);
TIM1_ICInitStructure.TIM_ICFilter = 10;
TIM_ICInit(TIM1, &TIM1_ICInitStructure);//根据TIM_ICInitStruct中指定的参数初始化TIM
TIM_ClearFlag(TIM1, TIM_FLAG_Update);//清除TIM的更新标志位
TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE); //使能或者失能指定的TIM中断
TIM_SetCounter(TIM1,0);
TIM_Cmd(TIM1, ENABLE); //使能或者使能TIMx外设
}
void Encoder_Init_TIM2(void)
{
NVIC_InitTypeDef NVIC_InitStruct;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//使能定时器2的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能PA端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1; //端口配置 PA0 PA1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOA
NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn; //定时器2中断
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; //使能IRQ通道
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级1
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 3; //响应优先级3
NVIC_Init(&NVIC_InitStruct);
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Prescaler = 0x0; // 预分频器
TIM_TimeBaseStructure.TIM_Period = ENCODER_TIM_PERIOD; //设定计数器自动重装值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择时钟分频:不分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//边沿计数模式
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //初始化定时器
TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式3
TIM_ICStructInit(&TIM_ICInitStructure); //把TIM_ICInitStruct 中的每一个参数按缺省值填入
TIM_ICInitStructure.TIM_ICFilter = 10; //设置滤波器长度
TIM_ICInit(TIM2, &TIM_ICInitStructure);//根据 TIM_ICInitStruct 的参数初始化外设 TIMx
TIM_ClearFlag(TIM2, TIM_FLAG_Update);//清除TIM的更新标志位
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);//使能定时器中断
TIM_SetCounter(TIM2,0);
TIM_Cmd(TIM2, ENABLE); //使能定时器
}
/**************************************************************************
函数功能:单位时间读取编码器计数
入口参数:定时器
返回 值:速度值
**************************************************************************/
int Read_Velocity(u8 TIMX)
{
int Encoder_TIM;
switch(TIMX)
{
case 1: Encoder_TIM= (short)TIM1 -> CNT; TIM1->CNT=0; break;
case 2: Encoder_TIM= (short)TIM2 -> CNT; TIM2->CNT=0; break;
default: Encoder_TIM=0;
}
return Encoder_TIM;
}
void TIM1_IRQHandler(void)//中断处理函数为空,清除中断标志位后结束中断
{
if(TIM_GetFlagStatus(TIM2,TIM_FLAG_Update)==SET)//溢出中断
{
}
TIM_ClearITPendingBit(TIM2,TIM_IT_Update); //清除中断标志位
}
void TIM2_IRQHandler(void)//中断处理函数为空,清除中断标志位后结束中断
{
if(TIM_GetFlagStatus(TIM2,TIM_FLAG_Update)==SET)//溢出中断
{
}
TIM_ClearITPendingBit(TIM2,TIM_IT_Update); //清除中断标志位
}
参考主函数:
#include "stm32f10x.h"
#include "lcd.h"
#include "delay.h"
#include "remote.h"
#include "motor.h"
#include "key.h"
#include "led.h"
#include "usart.h"
#include "encoder.h"
#define MAXSPEED 7000
#define MINSPEED 1000
#define FILTERNUM 20
int main(void)
{
u8 Remote_key;//遥控器键值
u8 Key;//按键值
u8 *str=0;//遥控器显示
u16 speed=1000;
u16 PWM=0;
u16 filter=FILTERNUM;
int Encoder_TIM=0;
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
uart_init(115200); //串口初始化为115200
LCD_Init();//初始化LCD功能; 320*240
Remote_Init(); //红外接收初始化
LED_Init(); //LED端口初始化
//TIM3_PWM_Init(7199,0); //不分频。PWM频率=72000000/900=80Khz
PWM_Init(7199,0);
KEY_Init();
CAR_Gpio_Init();
Encoder_Init_TIM1();
Encoder_Init_TIM2();
LCD_ShowString(30,60,300,16,16,"My RoBot");
LCD_ShowString(30,80,300,16,16,"MOTOR TEST:");
LCD_ShowString(30,100,300,16,16,"PWM: %");
MOTO(PosMode);
CAR_Speed(speed);//设置速度
while(1){
Encoder_TIM=Read_Velocity(1);
LCD_ShowxNum(30, 120,Encoder_TIM , 4, 16,0);
USART_SendData(USART2,Encoder_TIM);
//printf("TIM1=%d\n\r",Encoder_TIM);
Encoder_TIM=Rea/d_Velocity(2);
//printf("TIM2=%d\n\r",Encoder_TIM);
USART_SendData(USART2,Encoder_TIM);
LCD_ShowxNum(30, 140,Encoder_TIM , 4, 16,0);
Remote_key=Remote_Scan();
Key=KEY_Scan(0);
//TIM_SetCompare2(TIM3,led0pwmval);
if(Remote_key)
{ switch(Remote_key)
{
case 0:str="ERROR";break;
case 162:
str="STOP";
MOTO(StopMode);
break;
case 98:str="UP";break;
case 2:str="PLAY";break;
case 226:
str="Go!";
MOTO(PosMode);
break;
case 194:str="RIGHT";break;
case 34:str="LEFT";break;
case 224:
str="VOL-";
filter--;
if(!filter){
filter=FILTERNUM;
speed-=1000;
if(speed<1000){
speed=MINSPEED;
}
}
break;
case 168:str="DOWN";break;
case 144:
str="VOL+";
filter--;
if(!filter){
filter=FILTERNUM;
speed+=500;
if(speed>7000){
speed=MAXSPEED;
}
}
break;
case 104:str="1";break;
case 152:str="2";break;
case 176:str="3";break;
case 48:str="4";break;
case 24:str="5";break;
case 122:str="6";break;
case 16:str="7";break;
case 56:str="8";break;
case 90:str="9";break;
case 66:str="0";break;
case 82:str="DELETE";break;
}
}else delay_ms(10);
if(Key==KEY0_PRES){//减速
speed-=1000;
if(speed<1000){
speed=MINSPEED;
}
}else if(Key==KEY1_PRES){
//加速
speed+=500;
if(speed>7000){
speed=MAXSPEED;
}
}
CAR_Speed(speed);
LCD_Fill(30+12*8,80,300,80+16,WHITE); //清楚之前的显示
LCD_ShowString(30+12*8,80,300,16,16,str); //显示SYMBOL
PWM=speed*100/7200;
LCD_ShowNum(30+4*8, 100, PWM, 2, 16);
}
}