STM32小車——PWM電機調速

PWM電機調速(寄存器版)

我的上一篇博客已經寫了如何用定時器產生PWM來實現LED燈的呼吸燈效果,當我想實現PWM來控制電機調速時,網上翻閱了很多的資料但是大多數是在呼吸燈的基礎上改一下代碼實現的,沒有一定的代表性。並且基本上是隻產生兩路PWM
網上更多的代碼是庫函數版本的,對於剛學完51上手32的人來說可能不太適應。最近剛好學習了STM32的PWM,同時用來做一輛4輪小車來練練手。只有動手才能知道自己的問題出在哪裏會還是不會。那麼我就分享一下我做小車的經驗。

一、定時器的兩路通道產生兩路PWM

這裏我用的是定時器3通道1通道3,主要步驟如下:
1、開啓 TIM3 時鐘,配置 PB0和PA0 爲複用輸出
要使用 TIM3,我們必須先開啓 TIM3 的時鐘(通過 APB1ENR 設置),這裏我們還要配置 PB0和PA6爲複用輸出,這是因爲 TIM3_CH1 通道將映射到 PB0上,TIM3-CH3映射到PA6上此時, PB0和PA6屬於複用功能輸出。
2、設置 TIM3 的 ARR 和 PSC
在開啓了 TIM3 的時鐘之後,我們要設置 ARR 和 PSC 兩個寄存器的值來控制輸出 PWM 的週期。當 PWM 週期太慢(低於 50Hz)的時候,我們就會明顯感覺到閃爍了。因此, PWM 週期在這裏不宜設置的太小。
3、設置 TIM3_CH1和TIM3_CH3 的 PWM 模式
接下來,我們要設置 TIM3_CH1 和TIM3_CH3爲 PWM 模式(默認是凍結的),因爲我們的電機是低電平轉的快,而我們希望當 CCR1 和CCR3的值小的時候, 就暗, CCR1和CCR2值大的時候,電機的轉速就快,所以我們要通過配置 TIM3_CCMR1 的相關位來控制 TIM3_CH1的模式,通過TIM_CCMR2的相關位來控制TIM3_CH3的模式。
4、使能 TIM3 的 CH2 輸出,使能 TIM3
在完成以上設置了之後,我們需要開啓TIM3 的通道 1和通道3輸出以及 TIM3。前者通過TIM3_CCER1和TIM_CCMR2 來設置,是單個通道的開關,而後者則通過 TIM3_CR1 來設置,是整個 TIM3 的總開關。只有設置了這兩個寄存器,這樣我們才能在 TIM3 的通道1和通道3 上看到 PWM 波輸出。
5、修改 TIM3_CCR1和TIM_CCR3 來控制佔空比。
最後,在經過以上設置之後, PWM 其實已經開始輸出了,只是其佔空比和頻率都是固定的,而我們通過修改 TIM3_CCR1和TIM_CCR3則可以控制 CH1和CH2的輸出佔空比。繼而控制 兩個電機的速度。
通過以上 65個步驟,我們就可以控制 TIM3 的 CH1CH3輸出 PWM 波了。 這裏特別提醒一下大家,高級定時器雖然和通用定時器類似,但是高級定時器要想輸出 PWM,必須還要設置一個MOE 位(TIMx_BDTR 的第 15 位),以使能主輸出,否則不會輸出 PWM!!
兩路PWM代碼片:
1、配置定時器3
在該工程下新建一個文件夾命名爲TIMER,裏面包括兩個文件:timer.c和timer.h.
timer.c主要包括以下兩段代碼定時器3的初始化和PWM的初始化。
(1)定時器3初識化

void TIM3_Int_Init(u16 arr,u16 psc)
{
	RCC->APB1ENR|=1<<1;	//TIM3時鐘使能    
 	TIM3->ARR=arr;  	//設定計數器自動重裝值//剛好1ms    
	TIM3->PSC=psc;  	//預分頻器7200,得到10Khz的計數時鐘		  
	TIM3->DIER|=1<<0;   //允許更新中斷	  
	TIM3->CR1|=0x01;    //使能定時器3
 	 MY_NVIC_Init(1,3,TIM3_IRQn,2);//搶佔1,子優先級3,組2									 
}

(2)TIM3 PWM初始化:

void TIM3_PWM_Init(u16 arr,u16 psc)
{		 					 
	//此部分需手動修改IO口設置
	RCC->APB1ENR|=1<<1; 		//TIM3時鐘使能    
	RCC->APB2ENR|=1<<3;    	//使能PORTB時鐘	
	RCC->APB2ENR|=1<<2; 		//使能PORTA時鐘
	GPIOB->CRL&=0XFFFFFFF0;	//PB0輸出
	GPIOB->CRL|=0X0000000B;	//複用功能輸出 
	GPIOA->CRL&=0XF0FFFFFF;	//PA6輸出
	GPIOA->CRL|=0X0B000000; //複用輸出

	TIM3->ARR=arr;			//設定計數器自動重裝值 
	TIM3->PSC=psc;			//預分頻器不分頻
	
	TIM3->CCMR1|=6<<4;  	//CH1 PWM2模式		 
	TIM3->CCMR1|=1<<3; 		//CH1預裝載使能	
	TIM3->CCMR2|=6<<4;		//CH3預裝載使能 
	TIM3->CCMR2|=1<<3;    //CH3輸出使能
	TIM3->CCER|=1<<0;   	//OC1 輸出使能	 
	TIM3->CCER|=1<<8; 
	TIM3->CR1=0x0080;   	//ARPE使能 
	TIM3->CR1|=0x01;    	//使能定時器3 	

	STBY=1;
}

timer.h代碼如下:

#ifndef __TIMER_H
#define __TIMER_H
#include "sys.h"
//1,增加TIM3_PWM_Init函數。
//2,增加left和right宏定義,控制TIM3_CH1脈寬									  
//通過改變TIM3->CCR1和TIM->CR3的值來改變佔空比,從而控制電機的速度
#define left TIM3->CCR1 
#define right TIM3->CCR3

void TIM3_Int_Init(u16 arr,u16 psc);
void TIM3_PWM_Init(u16 arr,u16 psc);
#endif

2.電機模塊IO口初識化:
在該工程下新建一個文件夾命名爲MOTER,裏面包括兩個文件:moter.c和moter.h,moter.c代碼如下

#include "moter.h"
void MOTER_Init(void)
{
	RCC->APB2ENR|=1<<2;         //使能PORTA時鐘
	RCC->APB2ENR|=1<<3;		 //使能PORTB時鐘
	RCC->APB2ENR|=1<<4; 		//使能PORTC時鐘
	
	GPIOA->CRL&=0XFF0FFFFF;
  	GPIOA->CRL|=0X00300000;
    GPIOA->ODR|=1<<5;      
	
	GPIOA->CRL&=0X0FFFFFFF;
    GPIOA->CRL|=0X30000000;
	GPIOA->ODR|=1<<7; 
	
	GPIOB->CRL&=0XFFFFFF0F;
    GPIOB->CRL|=0X00000030;
	GPIOB->ODR|=1<<1;
	
	GPIOB->CRL&=0XFFFFF0FF;
    GPIOB->CRL|=0X00000300;
	GPIOB->ODR|=1<<2;
	GPIOB->CRL&=0XFFFF0FFF;
    GPIOB->CRL|=0X00003000;
	GPIOB->ODR|=1<<3;
	GPIOB->CRL&=0XFFF0FFFF;
    GPIOB->CRL|=0X00030000;
	GPIOB->ODR|=1<<4; 	
	
	GPIOC->CRL&=0XFFF0FFFF;
    GPIOC->CRL|=0X00030000;
	GPIOC->ODR|=1<<4; 	
	
	GPIOC->CRL&=0XFF0FFFFF;
    GPIOC->CRL|=0X00300000;
	GPIOC->ODR|=1<<5; 	
}

moter.h代碼如下:

#ifndef __MOTER_H
#define __MOTER_H	 
#include "sys.h"
//電機端口定義(PWMA  PB0  PWMB  PA6)  
#define AIN2 PBout(1)
#define AIN1 PBout(2)
#define STBY PBout(3)
#define BIN2 PCout(5)
#define BIN1 PCout(4)
void MOTER_Init(void);	//初始化		 				    
#endif

3.test.c
主要包括小車前進、後退、左右的一些函數,然後再通過改變left和right的值來改變TIM3->CCR1和TIM3->CR3的值來改變電機的速度:

#include "sys.h"
#include "delay.h"
#include "usart.h" 
#include "moter.h" 
#include "timer.h" 

void HOU(void)//定義後退函數
{
	AIN1=0;
	AIN2=1;
	BIN1=0;
	BIN2=1;
}

void STOP(void)//停
{
	AIN1=0;
	AIN2=0;
	BIN1=1;
	BIN2=1;
}

void YOU(void)//右拐
{
	AIN1=1;
	AIN2=0;
	BIN1=1;
	BIN2=1;
}

void ZUO(void)//左拐
{
	AIN1=0;
	AIN2=0;
	BIN1=1;
	BIN2=0;
}

void GO(void)//前進
{
	AIN1=1;
	AIN2=0;
	BIN1=1;
	BIN2=0;
}

int main(void)
{					   
	Stm32_Clock_Init(9);	//系統時鐘設置
	uart_init(72,115200);	//串口初始化爲115200
	delay_init(72);	   	 	//延時初始化 
  	TIM3_PWM_Init(899,0);	//不分頻。PWM頻率=72000/(899+1)=80Khz
	MOTER_Init();
  	while(1)
	{
		left=400;
		right=400;
		GO();
	}
}

通過以上的程序可以實現電機前進調速。希望對大家有所幫助。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章