自己建個(gè)網(wǎng)站做優(yōu)化百度云盤資源搜索
目錄
一、輸出比較簡(jiǎn)介
二、PWM簡(jiǎn)介
三、輸出比較模式實(shí)現(xiàn)
1.輸出比較框圖(以通用定時(shí)器為例)
2.PWM基本結(jié)構(gòu)
四、固件庫(kù)實(shí)現(xiàn)
1.程序1:PWM呼吸燈
?2.程序2:PWM驅(qū)動(dòng)直流電機(jī)
3.程序3:控制舵機(jī)?
一、輸出比較簡(jiǎn)介
死區(qū)生成和互補(bǔ)輸出一般用于對(duì)電機(jī)的控制??
二、PWM簡(jiǎn)介
?慣性系統(tǒng):即要能使人眼產(chǎn)生視覺停留的系統(tǒng)
三、輸出比較模式實(shí)現(xiàn)
1.輸出比較框圖(以通用定時(shí)器為例)


?
?高級(jí)定時(shí)器比通用定時(shí)器多了個(gè)互補(bǔ)輸出和死區(qū)生成
如右圖,兩個(gè)mos管構(gòu)成了推挽電路,上管導(dǎo)通下管關(guān)閉輸出高電平,下管導(dǎo)通上管關(guān)閉輸出低電平,兩管都關(guān)閉為高阻態(tài),兩管都導(dǎo)通為短路,會(huì)對(duì)元器件造成損傷,所以兩管不能同時(shí)導(dǎo)通
互補(bǔ)輸出:當(dāng)單片機(jī)要控制這個(gè)電路時(shí),就需要兩個(gè)輸出端口,且二者電平要相反,即互補(bǔ),而這里OC1和OC1N就是互補(bǔ)的兩個(gè)端口,即互補(bǔ)輸出
死區(qū)發(fā)生器:但是若在上管關(guān)閉的瞬間下管就導(dǎo)通,很可能由于器件的不理想而出現(xiàn)上下管都導(dǎo)通的情況,為了避免這種情況發(fā)生,于是又是死區(qū)發(fā)生器,即他可以在上管關(guān)閉后延遲一段時(shí)間再導(dǎo)通下管,避免同時(shí)導(dǎo)通
2.PWM基本結(jié)構(gòu)
四、固件庫(kù)實(shí)現(xiàn)
1.程序1:PWM呼吸燈
1.我使用的是TIM3的CH2的重定義引腳PB5,所以要打開AFIO時(shí)鐘
2.開啟TIM3和GPIO的時(shí)鐘
3.初始化GPIO結(jié)構(gòu)體。注意:要記得使用庫(kù)函數(shù)進(jìn)行重定義
4.選擇TIM3的時(shí)鐘輸入,可以為內(nèi)部時(shí)鐘,外部時(shí)鐘模式1和2,
????????外部時(shí)鐘模式1:來源可以是ITR(其他定時(shí)器,多用于定時(shí)器級(jí)聯(lián)),可以是ETR(外部時(shí)? 鐘),可以是CH1引腳的邊沿,CH1引腳和CH2引腳(多用于輸入捕獲測(cè)頻率)
? ? ? ? 外部時(shí)鐘模式2:ETR的觸發(fā)控制模式
5.初始化TIM3結(jié)構(gòu)體--配置PSC,ARR,計(jì)數(shù)模式,等等
6.初始化OC結(jié)構(gòu)體--PWM模式選擇,CCR,輸出ref的有效電平
7.定時(shí)器使能
//使用TIM3的通道2的重定義引腳PB5-指南者上面是紅燈
//我們配置
void PWM_Config()
{//首先開啟GPIO時(shí)鐘//開啟AFIO時(shí)鐘,因?yàn)橛玫搅酥囟xRCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO,ENABLE);//開啟定時(shí)器的時(shí)鐘RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//重定義引腳//選擇部分重定義GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3,ENABLE);//初始化GPIO結(jié)構(gòu)體-PB5-輸出比較GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;//復(fù)用推挽,手冊(cè)可看GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;GPIO_Init(GPIOB,&GPIO_InitStruct);//選擇TIM3的時(shí)鐘輸入TIM_InternalClockConfig(TIM3);//我們直接使用內(nèi)部時(shí)鐘//配置TIM結(jié)構(gòu)體TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;TIM_TimeBaseInitStruct.TIM_Prescaler = 72-1;//PSCTIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//計(jì)數(shù)模式TIM_TimeBaseInitStruct.TIM_Period = 100-1;//ARRTIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;//輸入濾波器的分頻TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;//重復(fù)計(jì)數(shù)器,只有高級(jí)定時(shí)器才有TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);//初始化OC結(jié)構(gòu)體TIM_OCInitTypeDef TIM_OCInitStruct;TIM_OCStructInit(&TIM_OCInitStruct);//先賦初值,因?yàn)槲覀儧]有把結(jié)構(gòu)體配置完全TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;//模式選擇-PWM1TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;//輸出使能TIM_OCInitStruct.TIM_Pulse = 0;//CCR,這里我們不配置CCR的值,后面用一個(gè)庫(kù)函數(shù)直接在主函數(shù) 里面配置,實(shí)現(xiàn)呼吸燈TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;//輸出ref極性,選擇有效電平,即ref有效時(shí)輸出高電平//TIM_OCInitStruct.TIM_OCNPolarity = ;//TIM_OCInitStruct.TIM_OCIdleState = ;//TIM_OCInitStruct.TIM_OCNIdleState = ;//TIM_OCInitStruct.TIM_OutputNState = ;TIM_OC2Init(TIM3,&TIM_OCInitStruct);//啟動(dòng)定時(shí)器TIM_Cmd(TIM3,ENABLE);}void PWM_SetCompare2(uint16_t Compare)
{TIM_SetCompare2(TIM3,Compare);
}
main.c#include "stm32f10x.h" // Device header
#include "bsp_led.h"
#include ".\tim\bsp_tim.h"extern uint16_t Num;//定時(shí)器都是16位的int i;
void Delay(u32 i)
{u32 temp;SysTick->LOAD=9000*i; //設(shè)置重裝數(shù)值, 72MHZ時(shí)SysTick->CTRL=0X01; //使能,減到零是無動(dòng)作,采用外部時(shí)鐘源SysTick->VAL=0; //清零計(jì)數(shù)器do{temp=SysTick->CTRL; //讀取當(dāng)前倒計(jì)數(shù)值}while((temp&0x01)&&(!(temp&(1<<16)))); //等待時(shí)間到達(dá)SysTick->CTRL=0; //關(guān)閉計(jì)數(shù)器SysTick->VAL=0; //清空計(jì)數(shù)器
}//ARR=99-->PWM一個(gè)周期是100,那么分辨率為1%
//占空比 = CCR/(ARR+1)
//頻率 = 計(jì)數(shù)器溢出頻率 = CK_PSC/(PSC+1)/(ARR+1) = 72M/720/100= 1000HZ ->1ms
int main()
{LED_GPIO_Config();PWM_Config();while(1){for(i=0;i<=100;i++){PWM_SetCompare2(i);Delay(10);}for(i=100;i>=0;i--){PWM_SetCompare2(i);Delay(10);}}
}
?2.程序2:PWM驅(qū)動(dòng)直流電機(jī)
具體TIM的配置過程同呼吸燈一樣,同樣是輸出不同的PWM占空比來實(shí)現(xiàn)電機(jī)的不同速度
我們需要三個(gè)引腳,一個(gè)輸出PWM給電機(jī),兩個(gè)接電機(jī)的控制引腳
- 使用PA2輸出PWM,AIN1/2接到PA4/5
- 頻率設(shè)置為1KHZ(可以自己隨便設(shè)置)
- 定義一個(gè)八位有符號(hào)的變量Speed,+:正轉(zhuǎn)? -:反轉(zhuǎn)
- 使用GPIO_SetBits/ResetBits();來設(shè)置AIN1/2的電平高低
- 使用按鍵來改變轉(zhuǎn)速
void PWM_Config()
{//開啟時(shí)鐘//使用TIM2的CH3的PA2RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//開啟PWM引腳//初始化GPIOGPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;//復(fù)用推挽,手冊(cè)可看GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_4 | GPIO_Pin_5 ;GPIO_Init(GPIOA,&GPIO_InitStruct);//選擇時(shí)基單元的時(shí)鐘-為內(nèi)部時(shí)鐘--定時(shí)器上電后默認(rèn)是內(nèi)部時(shí)鐘,故不寫這一個(gè)也行TIM_InternalClockConfig(TIM2);//初始化時(shí)基單元TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;//配置1KHZ的PWMTIM_TimeBaseInitStruct.TIM_Prescaler = 720-1;//PSC-預(yù)分頻器TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//向上計(jì)數(shù) TIM_TimeBaseInitStruct.TIM_Period = 100-1;//ARR寄存器-重裝載寄存器TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;/*不分頻----濾波器的采樣頻率,可以由內(nèi)部時(shí)鐘直接提供,也可以由內(nèi)部時(shí)鐘加一個(gè)時(shí)鐘分頻而來,分頻系數(shù)就是由TIM_ClockDivision決定*/TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;//重復(fù)計(jì)數(shù)器,只有高級(jí)定時(shí)器才有TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);//初始化OC-輸出比較結(jié)構(gòu)體TIM_OCInitTypeDef TIM_OCInitStruct;TIM_OCStructInit(&TIM_OCInitStruct);//因?yàn)榻Y(jié)構(gòu)體里面的成員有些是高級(jí)定時(shí)器采用得到,所以這里就先全部初始化一遍,然后再配置具體的值TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;//輸出比較模式TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;//TIM_OCInitStruct.TIM_Pulse = 50;//CRR TIM_OCInitStruct.TIM_Pulse = 0;//輸出要求波型,這里的CRR就不需要了,用固件庫(kù)的一個(gè)函數(shù) TIM_SetCompare3 直接配置CRRTIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;//輸出比較極性TIM_OC3Init(TIM2,&TIM_OCInitStruct);//CH3通道//啟動(dòng)定時(shí)器TIM_Cmd(TIM2,ENABLE);}
//電機(jī)控制函數(shù)void Motor_SetSpeed(int8_t Speed)//+:正轉(zhuǎn) -:反轉(zhuǎn)
{if(Speed >= 0){GPIO_SetBits(GPIOA,GPIO_Pin_4);GPIO_ResetBits(GPIOA,GPIO_Pin_5);TIM_SetCompare3(TIM3,Speed);}else {GPIO_ResetBits(GPIOA,GPIO_Pin_4);GPIO_SetBits(GPIOA,GPIO_Pin_5);TIM_SetCompare3(TIM3,-Speed);}
}
//主函數(shù)#include "stm32f10x.h" // Device header
#include ".\tim\bsp_tim.h"
#include ".\KEY\bsp_key.h"uint8_t KeyNum;
int8_t Speed;int main()
{KEY_GPIO_Config();PWM_Config();while(1){KeyNum = Key_Scan();if(KeyNum == 0){Speed += 20;if(Speed > 100){Speed = -100;}}else if(KeyNum == 1){Speed -= 20;if(Speed < -100){Speed = 100;}}Motor_SetSpeed(Speed);}
}
3.程序3:控制舵機(jī)?
-TB6612驅(qū)動(dòng)板
VM->STLINK的5v
VCC->面包板3.3v
GND->面包板負(fù)極
AO1 AO2 接電機(jī)
STBY->待機(jī)控制引腳,這里不需要待機(jī),接面包3.3v
AIN1/2-> 任意接兩個(gè)引腳
PWMA->PWM輸出控制引腳
驅(qū)動(dòng)VM放在左下角使用PA2輸出PWM,AIN1/2接到PA4/5
- 要點(diǎn):輸出如上圖右側(cè)所示的PWM波型
- 指南者的PA0引腳為按鍵1,所以使用TIM2的CH3通道的PA2
- PWM要求頻率為50HZ,即總時(shí)間20ms,高電平占0.5~2.5ms,這里我們可以給ARR配置20000-1,PSC配置72-1
- 封裝Angle轉(zhuǎn)換函數(shù)0-50? 180->2500?? -->y=Angle/180*2500+50, Angle使用浮點(diǎn)型,利于計(jì)算
- 使用按鍵來改變角度
#include "bsp_tim.h"void PWM_Config()
{//開啟時(shí)鐘//使用TIM2的CH3的PA2RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//開啟PWM引腳//初始化GPIOGPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;//復(fù)用推挽,手冊(cè)可看GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2;GPIO_Init(GPIOA,&GPIO_InitStruct);//選擇時(shí)基單元的時(shí)鐘-為內(nèi)部時(shí)鐘--定時(shí)器上電后默認(rèn)是內(nèi)部時(shí)鐘,故不寫這一個(gè)也行TIM_InternalClockConfig(TIM2);//初始化時(shí)基單元TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;TIM_TimeBaseInitStruct.TIM_Prescaler = 72-1;//PSC-預(yù)分頻器TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//向上計(jì)數(shù) TIM_TimeBaseInitStruct.TIM_Period = 20000-1;//ARR寄存器-重裝載寄存器TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;/*不分頻----濾波器的采樣頻率,可以由內(nèi)部時(shí)鐘直接提供,也可以由內(nèi)部時(shí)鐘加一個(gè)時(shí)鐘分頻而來,分頻系數(shù)就是由TIM_ClockDivision決定*/TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;//重復(fù)計(jì)數(shù)器,只有高級(jí)定時(shí)器才有TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);//初始化OC-輸出比較結(jié)構(gòu)體TIM_OCInitTypeDef TIM_OCInitStruct;TIM_OCStructInit(&TIM_OCInitStruct);//因?yàn)榻Y(jié)構(gòu)體里面的成員有些是高級(jí)定時(shí)器采用得到,所以這里就先全部初始化一遍,然后再配置具體的值TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;//輸出比較模式TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;//TIM_OCInitStruct.TIM_Pulse = 50;//CRR --舵機(jī)要求設(shè)置頻率50HZ-即總時(shí)間20ms,高電平時(shí)間在0.5~2.5ms之間的PWM波型即CCR->500~2500TIM_OCInitStruct.TIM_Pulse = 0;//輸出要求波型,這里的CRR就不需要了,用固件庫(kù)的一個(gè)函數(shù) TIM_SetCompare3 直接配置CRRTIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;//輸出比較極性TIM_OC3Init(TIM2,&TIM_OCInitStruct);//CH3通道//啟動(dòng)定時(shí)器TIM_Cmd(TIM2,ENABLE);
}
//0.5ms-0度 2.5ms-180度
//0度 CCR=500
//180度 CCR=2500
//舵機(jī)設(shè)置角度,范圍0~180
void Servo_SetAngle(float Angle)
{TIM_SetCompare3(TIM2,Angle*2000/180+500);
}void PWM_SetCompare3(uint16_t Compare)//設(shè)置CRR
{TIM_SetCompare3(TIM2,Compare);
}
#include "stm32f10x.h" // Device header
#include ".\tim\bsp_tim.h"
#include ".\KEY\bsp_key.h"
uint8_t KeyNum;
float Angle;int main()
{KEY_GPIO_Config();LED_GPIO_Config();PWM_Config();while(1){KeyNum = Key_Scan();if(KeyNum == 0){Angle+=30;if(Angle>180){Angle = 0;}}else if(KeyNum == 1){Angle-=30;if(Angle<0){Angle = 180;}}Servo_SetAngle(Angle);}
}