国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

(STM32)PWM輸出控制電機(jī)旋轉(zhuǎn)并且使用編碼器讀取脈沖數(shù)

這篇具有很好參考價(jià)值的文章主要介紹了(STM32)PWM輸出控制電機(jī)旋轉(zhuǎn)并且使用編碼器讀取脈沖數(shù)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

目錄

?前言

一、pwm輸出讓電機(jī)轉(zhuǎn)?

1.電機(jī)的接線說(shuō)明

2.驅(qū)動(dòng)的接線說(shuō)明

3.pwm輸出代碼

?pwm.c

pwm.h

4.輸出pwm控制電機(jī)旋轉(zhuǎn)

二、配置定時(shí)器編碼器模式

1.定時(shí)器編碼器模式

編碼器原理

編碼器相關(guān)的概念

2.編碼器模式——代碼部分

3.獲取脈沖數(shù)

三、定時(shí)讀取編碼器讀取的脈沖數(shù)

四、計(jì)算速度(本篇最重要部分)

1.速度計(jì)算原理

2. 速度計(jì)算代碼


?前言

正文之前先介紹一下我使用的主控芯片、電機(jī)以及驅(qū)動(dòng)。

主控芯片是STM32F103C8T6(這個(gè)芯片比較普遍、便宜,這款芯片使用熟練之后,我的建議是轉(zhuǎn)到CH32V307VCT6);

這里我還想在說(shuō)一點(diǎn)就是C8T6內(nèi)的定時(shí)器只有4個(gè)(TIM1、TIM2、TIM3、TIM4),資源比較少。

電機(jī)是JGB37-520霍爾編碼器直流減速電機(jī)(DC:12V)(530rpm);

磁環(huán)轉(zhuǎn)一圈是11個(gè)脈沖(即11線);

電機(jī)的減速比為19;

pwm脈沖捕獲脈沖數(shù),stm32,單片機(jī)

驅(qū)動(dòng)是TB6612FNG(這種驅(qū)動(dòng)比較穩(wěn)定,但是特別容易燒,注意一定不要接錯(cuò)線)

pwm脈沖捕獲脈沖數(shù),stm32,單片機(jī)

一、pwm輸出讓電機(jī)轉(zhuǎn)?

1.電機(jī)的接線說(shuō)明

電機(jī)電源線(紅線和白線)接AO1、AO2(或者BO1、BO2);

編碼器電源線(黑線和藍(lán)線)接地和5V,一定不要接錯(cuò),不然電機(jī)上的編碼器會(huì)出問(wèn)題;

編碼器信號(hào)線(黃線和綠線)接定時(shí)器編碼器接口;

2.驅(qū)動(dòng)的接線說(shuō)明

PWMA接PA0;PWMB接PA1;

AIN1、AIN2、BIN1、BIN2接單片機(jī)IO口;

STBY接5V;VM接12V;VCC接5V;

AO1、AO2、BO1、BO2接電機(jī)電源線(兩輪);

電機(jī)和驅(qū)動(dòng)的具體接線原理圖如下:

pwm脈沖捕獲脈沖數(shù),stm32,單片機(jī)

pwm脈沖捕獲脈沖數(shù),stm32,單片機(jī)?

pwm脈沖捕獲脈沖數(shù),stm32,單片機(jī)?

提醒:

1.電機(jī)電源線接線問(wèn)題:正接反接影響的是輪子的正轉(zhuǎn)反轉(zhuǎn)(自己可以按照實(shí)測(cè)一下);

2.編碼器信號(hào)線接線問(wèn)題:正接反接影響的是脈沖數(shù)的讀取的正負(fù)(畫(huà)板子的時(shí)候自己得重點(diǎn)注意);

3.pwm輸出代碼

?使用#define,可以方便我們修改IO口。

  • ?pwm.c

#include "pwm.h"

void AIN_GPIO_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	//AIN1
	RCC_APB2PeriphClockCmd(AIN1_GPIO_CLK,ENABLE);		 //開(kāi)啟時(shí)鐘
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;    //推挽輸出
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;	 //50MHz
	GPIO_InitStruct.GPIO_Pin = AIN1_GPIO_PIN;
	GPIO_Init(AIN1_GPIO_PORT ,&GPIO_InitStruct);
	GPIO_SetBits(AIN1_GPIO_PORT,GPIO_Pin_All);			//初始化			
	//AIN2
	RCC_APB2PeriphClockCmd(AIN2_GPIO_CLK,ENABLE);
	GPIO_InitStruct.GPIO_Pin = AIN2_GPIO_PIN;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(AIN2_GPIO_PORT ,&GPIO_InitStruct);
	GPIO_SetBits(AIN2_GPIO_PORT,GPIO_Pin_All);
	//BIN1
	RCC_APB2PeriphClockCmd(BIN1_GPIO_CLK,ENABLE);
	GPIO_InitStruct.GPIO_Pin = BIN1_GPIO_PIN;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(BIN1_GPIO_PORT ,&GPIO_InitStruct);
	GPIO_SetBits(BIN1_GPIO_PORT,GPIO_Pin_All);
	//BIN2
	RCC_APB2PeriphClockCmd(BIN2_GPIO_CLK,ENABLE);
	GPIO_InitStruct.GPIO_Pin = BIN2_GPIO_PIN;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(BIN2_GPIO_PORT ,&GPIO_InitStruct);
	GPIO_SetBits(BIN2_GPIO_PORT,GPIO_Pin_All);
}
static void GENERAL_TIM_GPIO_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
	//輸出比較通道1GPIO初始化
	RCC_APB2PeriphClockCmd(GENERAL_TIM_CH1_GPIO_CLK, ENABLE);
	GPIO_InitStructure.GPIO_Pin   = GENERAL_TIM_CH1_PIN;
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;    // 復(fù)用推挽輸出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GENERAL_TIM_CH1_PORT, &GPIO_InitStructure);
	//輸出比較通道2GPIO初始化
	RCC_APB2PeriphClockCmd(GENERAL_TIM_CH2_GPIO_CLK, ENABLE);
	GPIO_InitStructure.GPIO_Pin   = GENERAL_TIM_CH2_PIN;
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;    // 復(fù)用推挽輸出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GENERAL_TIM_CH2_PORT, &GPIO_InitStructure);
}
static void GENERAL_TIM_Mode_Config(void)
{
	// 開(kāi)啟定時(shí)器時(shí)鐘,即內(nèi)部時(shí)鐘CK_INT=72M
	GENERAL_TIM_APBxClock_FUN(GENERAL_TIM_CLK,ENABLE);
    /*--------------------時(shí)基結(jié)構(gòu)體初始化-------------------------*/
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	// 自動(dòng)重裝載寄存器的值,累計(jì)TIM_Period+1個(gè)頻率后產(chǎn)生一個(gè)更新或者中斷
	TIM_TimeBaseStructure.TIM_Period = GENERAL_TIM_PERIOD;	
	// 驅(qū)動(dòng)CNT計(jì)數(shù)器的時(shí)鐘 = Fck_int/(psc+1)
	TIM_TimeBaseStructure.TIM_Prescaler = GENERAL_TIM_PSC;	
	// 初始化定時(shí)器
	TIM_TimeBaseInit(GENERAL_TIM, &TIM_TimeBaseStructure);
	/*--------------------輸出比較結(jié)構(gòu)體初始化-------------------*/		
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	// 配置為PWM模式1
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	// 輸出使能
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	// 輸出通道電平極性配置
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	// 設(shè)置占空比大小GENERAL_TIM_CH1_PULSE=2000
	TIM_OCInitStructure.TIM_Pulse = GENERAL_TIM_CH1_PULSE;
	TIM_OC1Init(GENERAL_TIM, &TIM_OCInitStructure);
	TIM_OC1PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);
	// 設(shè)置占空比大小GENERAL_TIM_CH2_PULSE=4000
	TIM_OCInitStructure.TIM_Pulse = GENERAL_TIM_CH2_PULSE;
	TIM_OC2Init(GENERAL_TIM, &TIM_OCInitStructure);
	TIM_OC2PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);
	// 使能計(jì)數(shù)器
	TIM_Cmd(GENERAL_TIM, ENABLE);	
}
void GENERAL_TIM_Init(void)
{
	GENERAL_TIM_Mode_Config();
	GENERAL_TIM_GPIO_Config(); 
}
/*正負(fù)表示正轉(zhuǎn)和反轉(zhuǎn),0表示停止
	PERIOD = 8000-1固定
	*/
void GENERAL_TIM_Change_PULSE(int lun, int direction, int input_PULSE)
{
	
	int PULSE = (GENERAL_TIM_PERIOD + 1) * input_PULSE / 100;//input_PULSE設(shè)置為最高為100

	if(lun == 1)
	{
//		TIM_SetCompare1(TIM2, input_PULSE);
		GENERAL_TIM->CCR1 = PULSE;	
		if(direction == 0)//停止
		{
			GPIO_WriteBit(AIN1_GPIO_PORT,AIN1_GPIO_PIN,Bit_RESET);
			GPIO_WriteBit(AIN2_GPIO_PORT,AIN2_GPIO_PIN,Bit_RESET);
		}
		else if(direction == 1)//正轉(zhuǎn)
		{
			GPIO_WriteBit(AIN1_GPIO_PORT,AIN1_GPIO_PIN,Bit_RESET);
			GPIO_WriteBit(AIN2_GPIO_PORT,AIN2_GPIO_PIN,Bit_SET);
		}
		else if(direction == -1)//反轉(zhuǎn)
		{
			GPIO_WriteBit(AIN1_GPIO_PORT,AIN1_GPIO_PIN,Bit_SET);
			GPIO_WriteBit(AIN2_GPIO_PORT,AIN2_GPIO_PIN,Bit_RESET);
		}
	}
	if(lun == 2)
	{
//		TIM_SetCompare2(TIM2, input_PULSE);
		GENERAL_TIM->CCR2 = PULSE;
		if(direction == 0)//停止
		{
			GPIO_WriteBit(BIN1_GPIO_PORT,BIN1_GPIO_PIN,Bit_RESET);
			GPIO_WriteBit(BIN2_GPIO_PORT,BIN2_GPIO_PIN,Bit_RESET);
		}
		else if(direction == 1)//正轉(zhuǎn)
		{
			GPIO_WriteBit(BIN1_GPIO_PORT,BIN1_GPIO_PIN,Bit_RESET);
			GPIO_WriteBit(BIN2_GPIO_PORT,BIN2_GPIO_PIN,Bit_SET);
		}
		else if(direction == -1)//反轉(zhuǎn)
		{
			GPIO_WriteBit(BIN1_GPIO_PORT,BIN1_GPIO_PIN,Bit_SET);
			GPIO_WriteBit(BIN2_GPIO_PORT,BIN2_GPIO_PIN,Bit_RESET);
		}
	}
}



  • pwm.h

#ifndef _PWM_H
#define _PWM_H

#include "stm32f10x.h"

// 這里我們使用通用定時(shí)器TIM2

#define            GENERAL_TIM                   TIM2
#define            GENERAL_TIM_APBxClock_FUN     RCC_APB1PeriphClockCmd
#define            GENERAL_TIM_CLK               RCC_APB1Periph_TIM2
// PWM 信號(hào)的頻率 F = TIM_CLK/{(ARR+1)*(PSC+1)}
// 占空比是 PULSE / (PERIOD+1)
#define            GENERAL_TIM_PERIOD            (8000-1)
#define            GENERAL_TIM_PSC               (9-1)
#define            GENERAL_TIM_CH1_PULSE         2000
#define            GENERAL_TIM_CH2_PULSE         4000

#define            GENERAL_TIM_IRQ               TIM2_UP_IRQn
#define            GENERAL_TIM_IRQHandler        TIM2_UP_IRQHandler

//輸出通道1
#define            GENERAL_TIM_CH1_GPIO_CLK      RCC_APB2Periph_GPIOA
#define            GENERAL_TIM_CH1_PORT          GPIOA
#define            GENERAL_TIM_CH1_PIN           GPIO_Pin_0
//輸出通道2
#define            GENERAL_TIM_CH2_GPIO_CLK      RCC_APB2Periph_GPIOA
#define            GENERAL_TIM_CH2_PORT          GPIOA
#define            GENERAL_TIM_CH2_PIN           GPIO_Pin_1
//對(duì)PA0初始化---AIN1
#define            AIN1_GPIO_CLK                 RCC_APB2Periph_GPIOB
#define            AIN1_GPIO_PORT				 GPIOB
#define 	   	   AIN1_GPIO_PIN                 GPIO_Pin_14
//對(duì)PA1初始化---AIN2
#define            AIN2_GPIO_CLK				 RCC_APB2Periph_GPIOB
#define            AIN2_GPIO_PORT                GPIOB
#define 		   AIN2_GPIO_PIN                 GPIO_Pin_15

//對(duì)PB0初始化---BIN1
#define            BIN1_GPIO_CLK                 RCC_APB2Periph_GPIOB
#define            BIN1_GPIO_PORT				 GPIOB
#define 		   BIN1_GPIO_PIN                 GPIO_Pin_13
//對(duì)PB1初始化---BIN2
#define            BIN2_GPIO_CLK                 RCC_APB2Periph_GPIOB
#define            BIN2_GPIO_PORT				 GPIOB
#define 		   BIN2_GPIO_PIN                 GPIO_Pin_12

void AIN_GPIO_Config(void);
void GENERAL_TIM_Init(void);
void GENERAL_TIM_Change_PULSE(int lun, int direction, int input_PULSE);

#endif

4.輸出pwm控制電機(jī)旋轉(zhuǎn)

?這里把控制電機(jī)旋轉(zhuǎn)的函數(shù)提取出來(lái),讓大家看得更明白。

void GENERAL_TIM_Change_PULSE(int lun, int direction, int input_PULSE)
{
	
	int PULSE = (GENERAL_TIM_PERIOD + 1) * input_PULSE / 100;//input_PULSE設(shè)置為最高為100

	if(lun == 1)
	{
//		TIM_SetCompare1(TIM2, input_PULSE);
		GENERAL_TIM->CCR1 = PULSE;	
		if(direction == 0)//停止
		{
			GPIO_WriteBit(AIN1_GPIO_PORT,AIN1_GPIO_PIN,Bit_RESET);
			GPIO_WriteBit(AIN2_GPIO_PORT,AIN2_GPIO_PIN,Bit_RESET);
		}
		else if(direction == 1)//正轉(zhuǎn)
		{
			GPIO_WriteBit(AIN1_GPIO_PORT,AIN1_GPIO_PIN,Bit_RESET);
			GPIO_WriteBit(AIN2_GPIO_PORT,AIN2_GPIO_PIN,Bit_SET);
		}
		else if(direction == -1)//反轉(zhuǎn)
		{
			GPIO_WriteBit(AIN1_GPIO_PORT,AIN1_GPIO_PIN,Bit_SET);
			GPIO_WriteBit(AIN2_GPIO_PORT,AIN2_GPIO_PIN,Bit_RESET);
		}
	}
	if(lun == 2)
	{
//		TIM_SetCompare2(TIM2, input_PULSE);
		GENERAL_TIM->CCR2 = PULSE;
		if(direction == 0)//停止
		{
			GPIO_WriteBit(BIN1_GPIO_PORT,BIN1_GPIO_PIN,Bit_RESET);
			GPIO_WriteBit(BIN2_GPIO_PORT,BIN2_GPIO_PIN,Bit_RESET);
		}
		else if(direction == 1)//正轉(zhuǎn)
		{
			GPIO_WriteBit(BIN1_GPIO_PORT,BIN1_GPIO_PIN,Bit_RESET);
			GPIO_WriteBit(BIN2_GPIO_PORT,BIN2_GPIO_PIN,Bit_SET);
		}
		else if(direction == -1)//反轉(zhuǎn)
		{
			GPIO_WriteBit(BIN1_GPIO_PORT,BIN1_GPIO_PIN,Bit_SET);
			GPIO_WriteBit(BIN2_GPIO_PORT,BIN2_GPIO_PIN,Bit_RESET);
		}
	}
}

在這個(gè)函數(shù)中設(shè)定了三個(gè)參數(shù),分別是電機(jī)(A或B)、旋轉(zhuǎn)方向(正轉(zhuǎn)反轉(zhuǎn)停止)、占空比(以百分比的形式);

可以先下面代碼中這樣使用:

	GENERAL_TIM_Change_PULSE(1, 1, 25);
	GENERAL_TIM_Change_PULSE(2, -1, 35);

二、配置定時(shí)器編碼器模式

這里先介紹一下定時(shí)器編碼器模式

1.定時(shí)器編碼器模式

編碼器原理

????????如果倆個(gè)相位差為90度,這倆個(gè)信號(hào)稱(chēng)為正交。由于倆個(gè)信號(hào)相差90度,可以根據(jù)倆個(gè)信號(hào)那個(gè)先那個(gè)后判斷方向,根據(jù)編碼器的脈沖數(shù)量及編碼輪的周長(zhǎng)可以算出行駛的距離。加上一個(gè)定時(shí)器去計(jì)數(shù)單位時(shí)間內(nèi)采集到的編碼脈沖數(shù)量就可以算出電機(jī)的速度。

編碼器相關(guān)的概念

1.分辨率:編碼器的軸每轉(zhuǎn)一圈所輸出的脈沖數(shù)。編碼器以每旋轉(zhuǎn)360度提供多少的通或暗刻線稱(chēng)為分辨率,也稱(chēng)解析分度、或直接稱(chēng)多少線,一般在每轉(zhuǎn)分度5~10000線。

2.最大響應(yīng)頻率:編碼器在1秒鐘內(nèi)能響應(yīng)的最大脈沖數(shù)。其公式為: 最高響應(yīng)頻率(Hz) = ?編碼器分辨率 × 軸的轉(zhuǎn)速(r/min)/60 ?另稱(chēng)PPS

3.最大轉(zhuǎn)速:是指編碼器機(jī)械系統(tǒng)能夠承受的最高轉(zhuǎn)速。

4.絕對(duì)編碼器信號(hào)傳輸方式:并行、串行輸出或總線型輸出。輸出電路與增量編碼器相似,有集電極開(kāi)路PNP、NPN型、差分驅(qū)動(dòng)、推挽式。

2.編碼器模式——代碼部分

?兩個(gè)霍爾編碼器于是就使用了兩個(gè)定時(shí)器(TIM3和TIM4)

/*下面是編譯器配置函數(shù)*/
//編碼器1初始化函數(shù)
void Encoder_TIM3_Init(void)
{
	//結(jié)構(gòu)體定義
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	GPIO_InitTypeDef GPIO_InitStruct;
	TIM_ICInitTypeDef TIM_ICInitStruct;
	NVIC_InitTypeDef  NVIC_InitStructure;
	//時(shí)鐘配置
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3 ,ENABLE);  // 開(kāi)啟定時(shí)器3時(shí)鐘
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE); // 開(kāi)啟GPIO時(shí)鐘
	
    //GPIO配置
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;    // 浮空輸入
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;   // 編碼器1:PA0/PA1
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA ,&GPIO_InitStruct);
	//定時(shí)器配置
	TIM_TimeBaseStructInit(&TIM_TimeBaseInitStruct);
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;        // 不分頻
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;    //向上計(jì)數(shù)
	TIM_TimeBaseInitStruct.TIM_Period = 65535;											 
    //重裝載值65535
	TIM_TimeBaseInitStruct.TIM_Prescaler = 0;												 
    //分頻系數(shù)0(自動(dòng)加1)
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);
	//編碼器配置:定時(shí)器3,模式3,上升沿
	 TIM_EncoderInterfaceConfig(TIM3,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising,TIM_ICPolarity_Rising); 
	//輸入捕獲配置
	TIM_ICStructInit(&TIM_ICInitStruct);
	TIM_ICInitStruct.TIM_ICFilter = 10;			//濾波器設(shè)置為10
	TIM_ICInit(TIM3,&TIM_ICInitStruct);
	
	NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn;                   //定時(shí)器3中斷分組配置
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;                   //使能
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01;      //搶占優(yōu)先級(jí)1
	NVIC_InitStructure.NVIC_IRQChannelSubPriority =0x02;            //響應(yīng)優(yōu)先級(jí)2
	NVIC_Init(&NVIC_InitStructure);                                 //配置定時(shí)器3
	//清除定時(shí)器溢出更新標(biāo)志位(清除計(jì)數(shù)值)
	TIM_ClearFlag(TIM3,TIM_FLAG_Update);
	//定時(shí)器3,溢出更新,使能
	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); 
	//定時(shí)數(shù)據(jù)清零(輸入捕獲的值從0開(kāi)始計(jì)數(shù))
	TIM_SetCounter(TIM3,0);
	//定時(shí)器3使能
	TIM_Cmd(TIM3,ENABLE);
}
void Encoder_TIM4_Init(void)
{
	//結(jié)構(gòu)體定義
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	GPIO_InitTypeDef GPIO_InitStruct;
	TIM_ICInitTypeDef TIM_ICInitStruct;
	NVIC_InitTypeDef  NVIC_InitStructure;
	
	//時(shí)鐘配置
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);  //開(kāi)啟定時(shí)器4時(shí)鐘
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE); //開(kāi)啟GPIO時(shí)鐘
	
	//GPIO配置
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;  //浮空輸入
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;		//編碼器2:PB6/PB7
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB ,&GPIO_InitStruct);
	
	//定時(shí)器配置
	TIM_TimeBaseStructInit(&TIM_TimeBaseInitStruct);
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;        // 不分頻
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;    //向上計(jì)數(shù)
	TIM_TimeBaseInitStruct.TIM_Period = 65535;											//重裝載值65535
	TIM_TimeBaseInitStruct.TIM_Prescaler = 0;												//分頻系數(shù)0(自動(dòng)加1)
	TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStruct);
	//編碼器配置:定時(shí)器4,模式3,上升沿
	TIM_EncoderInterfaceConfig(TIM4,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising,TIM_ICPolarity_Rising); 
	//輸入捕獲配置
	TIM_ICStructInit(&TIM_ICInitStruct);
	TIM_ICInitStruct.TIM_ICFilter = 10;			//濾波器設(shè)置為10
	TIM_ICInit(TIM4,&TIM_ICInitStruct);
	
	NVIC_InitStructure.NVIC_IRQChannel=TIM4_IRQn;                   //定時(shí)器4中斷分組配置
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;                   //使能
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01;      //搶占優(yōu)先級(jí)1
	NVIC_InitStructure.NVIC_IRQChannelSubPriority =0x03;            //響應(yīng)優(yōu)先級(jí)2
	NVIC_Init(&NVIC_InitStructure);                                 //配置定時(shí)器4
	
	//清除定時(shí)器溢出更新標(biāo)志位(清除計(jì)數(shù)值)
	TIM_ClearFlag(TIM4,TIM_FLAG_Update);
	//定時(shí)器4,溢出更新,使能
	TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE); 
	//定時(shí)數(shù)據(jù)清零(輸入捕獲的值從0開(kāi)始計(jì)數(shù))
	TIM_SetCounter(TIM4,0);
	//定時(shí)器4使能
	TIM_Cmd(TIM4,ENABLE);
}
// 定時(shí)器3中斷服務(wù)函數(shù)
void TIM3_IRQHandler(void)
{
  if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET)  // 中斷標(biāo)志位置1
  {
    TIM_ClearITPendingBit(TIM3,TIM_IT_Update);  // 清楚中斷標(biāo)志位
  }
}

// 定時(shí)器4中斷服務(wù)函數(shù)
void TIM4_IRQHandler(void)
{
  if(TIM_GetITStatus(TIM4,TIM_IT_Update)==SET)  // 中斷標(biāo)志位置1
  {
    TIM_ClearITPendingBit(TIM4,TIM_IT_Update);  // 清楚中斷標(biāo)志位
  }
}

3.獲取脈沖數(shù)

?配置好定時(shí)器的編碼器模式后并且能夠很好的運(yùn)行,就可以進(jìn)行下一步,來(lái)讀取編碼器的計(jì)數(shù)值。

下面是代碼:

// 編碼器速度讀取函數(shù)
// 入口參數(shù):定時(shí)器
// 編碼器產(chǎn)生的是脈沖,計(jì)數(shù)器計(jì)脈沖數(shù)(位移)
int Read_Speed(int x)
{
  int value_1;
  switch(x)
  {
    case 3:
      // 單周期位移作為速度值
      value_1 = (short)TIM_GetCounter(TIM3);  // 采集編碼器的計(jì)數(shù)值并保存
      TIM_SetCounter(TIM3,0);                 // 將定時(shí)器的計(jì)數(shù)值清零
      break;
    case 4:
      // 單周期位移作為速度值
      value_1 = (short)TIM_GetCounter(TIM4);  // 采集編碼器的計(jì)數(shù)值并保存
      TIM_SetCounter(TIM4,0);                 // 將定時(shí)器的計(jì)數(shù)值清零
      break; 
    default: value_1 = 0;
  }
  return value_1;
}

這個(gè)函數(shù)比較簡(jiǎn)單,但是我還是想提一下下面兩個(gè)函數(shù),必須要認(rèn)真去理解兩個(gè)函數(shù)里的內(nèi)容!

uint16_t TIM_GetCounter(TIM_TypeDef* TIMx);

void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter);

三、定時(shí)讀取編碼器讀取的脈沖數(shù)

?之所以要定時(shí)來(lái)讀取值,是因?yàn)槲覀冊(cè)谟?jì)算速度的時(shí)候必須要有個(gè)時(shí)間,很簡(jiǎn)單的原理我就不解釋了。

這部分又涉及到定時(shí)器中斷的問(wèn)題,我使用的是TIM2;

在這里跟大家說(shuō)一下定時(shí)器pwm輸出和定時(shí)器中斷能不能使用一個(gè)定時(shí)器來(lái)運(yùn)行的問(wèn)題。

答案是可以的,但是需要注意一個(gè)問(wèn)題,就是pwm輸出和中斷兩者的定時(shí)器頻率一定要相同,不然會(huì)影響實(shí)際的運(yùn)行。什么是定時(shí)器頻率大家應(yīng)該知道吧就是對(duì)arr與psc的配置。

再補(bǔ)充說(shuō)一下,定時(shí)器中斷與串口中斷能不能同時(shí)運(yùn)行?

我測(cè)試過(guò),是不能夠同時(shí)運(yùn)行的,具體什么原因我就不知道了,上次因?yàn)檫@個(gè)問(wèn)題糾纏我很久!

回歸正文,下面是TIM2定時(shí)器代碼:

#include "TIME.h"

/*********************************************陀螺儀數(shù)據(jù)讀取,PID計(jì)算刷新時(shí)鐘2***********************************/
void TIM2_Getsample_Int(u16 arr,u16 psc)
{
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //時(shí)鐘使能

	TIM_TimeBaseStructure.TIM_Period = arr; //設(shè)置在下一個(gè)更新事件裝入活動(dòng)的自動(dòng)重裝載寄存器周期的值	 計(jì)數(shù)到5000為500ms
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //設(shè)置用來(lái)作為T(mén)IMx時(shí)鐘頻率除數(shù)的預(yù)分頻值  10Khz的計(jì)數(shù)頻率  
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //設(shè)置時(shí)鐘分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上計(jì)數(shù)模式
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根據(jù)TIM_TimeBaseInitStruct中指定的參數(shù)初始化TIMx的時(shí)間基數(shù)單位
 
	TIM_ITConfig( TIM2,TIM_IT_Update|TIM_IT_Trigger,ENABLE);//使能定時(shí)器2更新觸發(fā)中斷
 
	TIM_Cmd(TIM2, ENABLE);  //使能TIMx外設(shè)
 	
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;  //TIM2中斷
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占優(yōu)先級(jí)0級(jí)
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //從優(yōu)先級(jí)3級(jí)
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure); 
}
//***************TIME2的中斷*******************/
void TIM2_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET) //溢出中斷
	{
		i++;
		if(i == 100)
		{
			i = 0;	
			count1 = abs(Read_Speed(3));			//讀取脈沖數(shù)(TIM3)
			count2 = abs(Read_Speed(4));			//讀取脈沖數(shù)(TIM4)
			speed1 = Speed_calculate(count1);
			speed2 = Speed_calculate(count2);
			/*最初的閉環(huán)控制
			PWM1 = Velocity_Control(Target,count1); //速度環(huán)閉環(huán)控制
			TIM_SetCompare1(TIM2, PWM1/100);
			PWM2 = Velocity_Control(Target,count2); //速度環(huán)閉環(huán)控制
			TIM_SetCompare2(TIM2, PWM2/100);
			*/
		}	
	}	
	TIM_ClearITPendingBit(TIM2,TIM_IT_Update);  //清除中斷標(biāo)志位
}

我在主函數(shù)里定時(shí)器初始化為1ms中斷一次,很容易看出讀取脈沖數(shù)的間隔時(shí)間是100ms;

在這里我們就讀取到了編碼器上的脈沖數(shù)了,接下來(lái)我們就進(jìn)入本篇文章最重要的計(jì)算速度的部分!

四、計(jì)算速度(本篇最重要部分)

1.速度計(jì)算原理

?定時(shí)器編碼器模式使用的是四倍頻(具體的編碼器模式還請(qǐng)大家去CSDN上搜搜),所以電機(jī)轉(zhuǎn)一圈的脈沖數(shù)應(yīng)該是11×19×4=836;

假設(shè)編碼器讀取的脈沖數(shù)為x,速度,這里的t等于100ms,相當(dāng)于Speed=p*0.0119617224880383;

這樣就可以寫(xiě)速度計(jì)算函數(shù)了

2. 速度計(jì)算代碼

?注意:得出來(lái)的值一定要是float型的,這樣更加精確!

float Speed_calculate(int y)
{
	float value_2;
	value_2 = (float)y * 0.0119617224880383;		//100ms
	return value_2;
}

這個(gè)時(shí)候就可以把這個(gè)函數(shù)寫(xiě)到定時(shí)器中斷函數(shù)里面了,這樣就可以計(jì)算出速度。

這里還是要提醒一下,此函數(shù)計(jì)算出來(lái)的速度的單位是r/s,想要轉(zhuǎn)換成m/s就需要輪子的直徑,大家都會(huì)算,再寫(xiě)一個(gè)計(jì)算函數(shù)罷了。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-772679.html

到了這里,關(guān)于(STM32)PWM輸出控制電機(jī)旋轉(zhuǎn)并且使用編碼器讀取脈沖數(shù)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • AS5600步進(jìn)電機(jī)編碼器(原理圖+pcb+stm32控制代碼)

    AS5600步進(jìn)電機(jī)編碼器(原理圖+pcb+stm32控制代碼)

    AS5600是一個(gè)易于編程的磁性旋轉(zhuǎn)位置傳感器,具有高分辨率的12位模擬或PWM輸出。這種非接觸式系統(tǒng)測(cè)量一個(gè)直徑磁化的軸上磁鐵的絕對(duì)角度。 引腳如下圖 他有兩種供電模式:5V和3.3V 我們?yōu)榱撕蛃tm32F103C8T6單片機(jī)的電壓一致,也使用3.3V供電,然后開(kāi)始畫(huà)PCB。 使用嘉立創(chuàng)EDA畫(huà)

    2024年02月03日
    瀏覽(201)
  • 基于STM32F103C8T6使用Arduino IDE編程閉環(huán)控制4個(gè)帶編碼器的有刷直流電機(jī)

    基于STM32F103C8T6使用Arduino IDE編程閉環(huán)控制4個(gè)帶編碼器的有刷直流電機(jī)

    題記:標(biāo)題有點(diǎn)長(zhǎng)了,純粹為了方便被檢索到~~~本貼主要用于支持南方科技大學(xué)SDIM學(xué)院工業(yè)設(shè)計(jì)專(zhuān)業(yè)大三綜合項(xiàng)目移動(dòng)底盤(pán)學(xué)習(xí),也是我自己按照費(fèi)曼學(xué)習(xí)方法的一次嘗試,用從底層搭建一個(gè)機(jī)器人底盤(pán)來(lái)復(fù)習(xí)自動(dòng)控制原理。 ? ? ? ? 由于工業(yè)設(shè)計(jì)專(zhuān)業(yè)沒(méi)有開(kāi)設(shè)嵌入式課程

    2024年02月05日
    瀏覽(27)
  • STM32PWM控制直流電機(jī)

    STM32PWM控制直流電機(jī)

    PWM介紹 脈沖寬度調(diào)制(PWM),是英文“Pulse Width Modulation”的縮寫(xiě),簡(jiǎn)稱(chēng)脈寬調(diào)制,是利用 微處理器的數(shù)字輸出來(lái)對(duì)模擬電路進(jìn)行控制的一種非常有效的技術(shù)。簡(jiǎn)單一點(diǎn),就是對(duì)脈沖寬 度的控制 PWM的原理: 假定定時(shí)器工作在向上計(jì)數(shù) PWM 模式,且當(dāng) CNT=CCRx 時(shí)輸出 1。那么就可以

    2024年02月08日
    瀏覽(17)
  • STM32第八課:PWM控制直流電機(jī)

    STM32第八課:PWM控制直流電機(jī)

    ????????TB6612FNG是一款新型驅(qū)動(dòng)器件,能獨(dú)立雙向控制2個(gè)直流電機(jī),它具有很高的集成度,同時(shí)能提供足夠的輸出能力,運(yùn)行性能和能耗方面也具有優(yōu)勢(shì)因此在集成化、小型化的電機(jī)控制系統(tǒng)中,它可以作為理想的電機(jī)驅(qū)動(dòng)器件。 ??????????????????????????

    2024年03月24日
    瀏覽(21)
  • 一文搞懂如何使用STM32驅(qū)動(dòng)直流電機(jī)(普通PWM輸出和L298N、高級(jí)定時(shí)器輸出帶死區(qū)雙通道互補(bǔ)PWM和IR2110S及自舉電路、H橋電路和電機(jī)正反轉(zhuǎn))

    一文搞懂如何使用STM32驅(qū)動(dòng)直流電機(jī)(普通PWM輸出和L298N、高級(jí)定時(shí)器輸出帶死區(qū)雙通道互補(bǔ)PWM和IR2110S及自舉電路、H橋電路和電機(jī)正反轉(zhuǎn))

    筆者從開(kāi)始接觸嵌入式單片機(jī)開(kāi)始,就和驅(qū)動(dòng)電機(jī)相伴而走。從最開(kāi)始的直接買(mǎi)L298N驅(qū)動(dòng)模塊直接驅(qū)動(dòng)直流電機(jī),到現(xiàn)在自己設(shè)計(jì)PCB電路板驅(qū)動(dòng)直流電機(jī),可以說(shuō)是和電機(jī)驅(qū)動(dòng)共同成長(zhǎng)了?,F(xiàn)在筆者將這一過(guò)程的收獲記錄下來(lái),希望對(duì)大家有所幫助。 不用詳細(xì)了解L298N芯片和

    2024年02月02日
    瀏覽(22)
  • 搭建stm32電機(jī)控制代碼框架(五)——Stm32CubeMx配置PWM

    搭建stm32電機(jī)控制代碼框架(五)——Stm32CubeMx配置PWM

    采樣配置完成后,進(jìn)行PWM的配置。PWM的生成依賴于STM32的TIM1定時(shí)器,其功能完備如下圖所示,電機(jī)控制中主要應(yīng)用其PWM生成功能。 我們當(dāng)前階段的目標(biāo)是生成占空比為50%的三路PWM,其開(kāi)關(guān)頻率為10kHz。 那么開(kāi)始CubeMx的配置,依據(jù)stm32f405數(shù)據(jù)手冊(cè)中地址總線部分內(nèi)容,TIM1是掛

    2024年02月16日
    瀏覽(27)
  • 搭建stm32電機(jī)控制代碼框架(四)——單路PWM生成

    搭建stm32電機(jī)控制代碼框架(四)——單路PWM生成

    STM32中單路PWM的生成一般是基于某一個(gè)通用定時(shí)器,本次小實(shí)驗(yàn)選取TIM2通用定時(shí)器,選擇PA5作為PWM端口輸出。配置步驟如下: 第一步:配置外部晶振與基本的時(shí)鐘,如下圖所示。 (1)選擇外部晶振 ?(2)配置時(shí)鐘樹(shù),如下圖所示,TIM2的時(shí)鐘總線掛在ABP1上,此時(shí)時(shí)鐘源為

    2024年02月07日
    瀏覽(22)
  • STM32-微項(xiàng)目03-pwm控制直流電機(jī)運(yùn)行

    STM32-微項(xiàng)目03-pwm控制直流電機(jī)運(yùn)行

    一,項(xiàng)目目標(biāo) 實(shí)現(xiàn)利用STM32F103C8T6+TB6612,輸出不同占空比輸出的PWM波,從而實(shí)現(xiàn)電機(jī)不同轉(zhuǎn)速的運(yùn)行、正反轉(zhuǎn)的功能; ? ?二、硬件涉及 1,STM32核心板 2,TB6612直流電機(jī)驅(qū)動(dòng)模塊 3,直流電機(jī)? 三、硬件接線涉及 1,先看TB6612直流電機(jī)驅(qū)動(dòng)模塊: ①驅(qū)動(dòng)模塊是具備兩路PWM輸入

    2024年02月04日
    瀏覽(19)
  • 用STM32定時(shí)器中斷產(chǎn)生PWM控制步進(jìn)電機(jī)

    用STM32定時(shí)器中斷產(chǎn)生PWM控制步進(jìn)電機(jī)

    控制步進(jìn)電機(jī)可以使用PWM、定時(shí)器中斷、延時(shí),這里用的就是 定時(shí)器中斷來(lái)讓它轉(zhuǎn)動(dòng)。 板子用的是正點(diǎn)原子的STM32F103 mini板,驅(qū)動(dòng)器是DM420(DM420驅(qū)動(dòng)器資料),用開(kāi)關(guān)電源供電,電機(jī)就是普通的42步進(jìn)電機(jī),步距角為1.8°,雖然按照?qǐng)D片來(lái)看它是個(gè)蠕動(dòng)泵。如下圖 PUL+——PB0,

    2023年04月09日
    瀏覽(20)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包