当前位置:网站首页>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);
}
}
边栏推荐
- Four basic strategies for migrating cloud computing workloads
- This is the report that leaders like! Learn dynamic visual charts, promotion and salary increase are indispensable
- PR second training
- SAP ui5 beginner tutorial 20 - explanation of expression binding usage of SAP ui5
- matlab 使用 audioread 、 sound 读取和播放 wav 文件
- Matlab uses audiorecorder and recordblocking to record sound, play to play sound, and audiobook to save sound
- Post infiltration flow encryption
- 如何用一款产品推动「品牌的惊险一跃」?
- What is the MySQL column to row function
- Failed to transform file 'xxx' to match attributes
猜你喜欢

Golang lock

What are the skills of spot gold analysis?

k线图形态这样记(口诀篇)

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
![[Video] Markov chain Monte Carlo method MCMC principle and R language implementation | data sharing](/img/ba/dcb276768b1a9cc84099f093677d29.png)
[Video] Markov chain Monte Carlo method MCMC principle and R language implementation | data sharing

Opengauss database backup and recovery guide

MySQL view concept, create view, view, modify view, delete view

Implementation of Weibo system based on SSM

matlab 使用 audioread 、 sound 读取和播放 wav 文件

leetcode2305. Fair distribution of biscuits (medium, weekly, shaped pressure DP)
随机推荐
剑指 Offer 29. 顺时针打印矩阵
Feature extraction and detection 16 brisk feature detection and matching
Experimental reproduction of variable image compression with a scale hyperprior
Which is a good Bluetooth headset of about 300? 2022 high cost performance Bluetooth headset inventory
From January 11, 2007 to January 11, 2022, I have been in SAP Chengdu Research Institute for 15 years
Redis环境搭建和使用的方法
"C language programming", 4th Edition, edited by he Qinming and Yan Hui, after class exercise answers Chapter 3 branch structure
剑指 Offer 31. 栈的压入、弹出序列
479. Additive binary tree (interval DP on the tree)
321. Chessboard segmentation (2D interval DP)
电子协会 C语言 1级 32、计算2的幂
* and & symbols in C language
Based on configured schedule, the given trigger will never fire
TSINGSEE青犀平台如何实现同一节点同时播放多个视频?
Selection of field types for creating tables in MySQL database
Openssl3.0 learning XXI provider encoder
[Video] visual interpretation of Markov chain principle and Mrs example of R language region conversion | data sharing
[Maya] the error of importing Maya into Metahuman
剑指 Offer 42. 连续子数组的最大和
How to debug apps remotely and online?