当前位置:网站首页>STM32F103——两路PWM控制电机
STM32F103——两路PWM控制电机
2022-07-02 01:59:00 【SummerLoverQy】
实验条件
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);
}
}
边栏推荐
- MySQL中一条SQL是怎么执行的
- Opengauss database backup and recovery guide
- 基于SSM实现微博系统
- Construction and maintenance of business websites [14]
- SQLite 3 of embedded database
- Matlab uses resample to complete resampling
- The concepts and differences between MySQL stored procedures and stored functions, as well as how to create them, the role of delimiter, the viewing, modification, deletion of stored procedures and fu
- What is the MySQL column to row function
- MySQL主从延迟问题怎么解决
- Selection of field types for creating tables in MySQL database
猜你喜欢
Develop those things: how to use go singleton mode to ensure the security of high concurrency of streaming media?
The role of artificial intelligence in network security
【毕业季】研究生学长分享怎样让本科更有意义
leetcode2310. The one digit number is the sum of integers of K (medium, weekly)
matlab 实现语音信号重采样和归一化,并播放比对效果
How to execute an SQL in MySQL
【视频】马尔可夫链原理可视化解释与R语言区制转换MRS实例|数据分享
OpenCASCADE7.6编译
Discussion on the idea of platform construction
Golang lock
随机推荐
D discard the virtual recovery method
Word search applet design report based on cloud development +ppt+ project source code + demonstration video
Construction and maintenance of business websites [14]
Niuke - Huawei question bank (51~60)
OpenCASCADE7.6编译
花一个星期时间呕心沥血整理出高频软件测试/自动化测试面试题和答案
New news, Wuhan Yangluo international port, filled with black technology, refreshes your understanding of the port
Should enterprises choose server free computing?
This is the report that leaders like! Learn dynamic visual charts, promotion and salary increase are indispensable
剑指 Offer 31. 栈的压入、弹出序列
【视频】马尔可夫链原理可视化解释与R语言区制转换MRS实例|数据分享
【毕业季】研究生学长分享怎样让本科更有意义
Pyldavis installation and use | attributeerror: module 'pyldavis' has no attribute' gensim '| visual results are exported as separate web pages
[技术发展-21]:网络与通信技术的应用与发展快速概览-1- 互联网网络技术
The role of artificial intelligence in network security
并发编程的三大核心问题
Golang lock
This is the report that leaders like! Learn dynamic visual charts, promotion and salary increase are indispensable
Matlab uses resample to complete resampling
【视频】马尔可夫链蒙特卡罗方法MCMC原理与R语言实现|数据分享