stm32 PWM输出学习
STM32 的定時(shí)器除了 TIM6 和 7,其他的定時(shí)器都可以用來產(chǎn)生 PWM 輸出。其中高級(jí)定時(shí)器 TIM1 和 TIM8 可以同時(shí)產(chǎn)生多達(dá) 7 路的 PWM 輸出。通用定時(shí)器也能同時(shí)產(chǎn)生多達(dá) 4路的 PWM 輸出。
今天的實(shí)驗(yàn),我們僅利用 TIM3的 CH2 通道產(chǎn)生一路 PWM 輸出。
1.相關(guān)寄存器介紹
1)捕獲/比較模式寄存器 (TIMx_CCMR1/2)?
捕獲/比較模式寄存器(TIMx_CCMR1/2),該寄存器總共有 2 個(gè),TIMx ?_CCMR1和 TIMx _CCMR2。TIMx_CCMR1 控制 CH1 和 CH2,而 TIMx_CCMR2 控制 CH3 和 CH4。
OCxx描述了通道在輸出模式下的功能(上行),ICxx描述了通道在輸出模式下的功能(下行)。因此必須注意,同一個(gè)位在輸出模式和輸入模式下的功能是不同的。?
這里我們需要說明的是模式設(shè)置位 OCxM,此部分由 3 位組成。總共可以配置成 7 種模式,我們使用的是 PWM 模式,所以這 3 位必須設(shè)置為 110/111。這兩種PWM 模式的區(qū)別就是輸出電平的極性相反。?
這里的有效電平或者無效電平是可以配置的。
2)?捕獲/比較使能寄存器(TIMx_CCER)?
3)捕獲/比較寄存器(TIMx_CCR1~4)
該寄存器總共有 4 個(gè),對(duì)應(yīng) 4 個(gè)通道 CH1~CH4。因?yàn)檫@ 4 個(gè)寄存器都差不多,我們僅以 TIMx_CCR1 為例介紹。
我們通過修改這個(gè)寄存器的值,就可以控制 PWM 的輸出脈寬。
2.?TIM3_REMAP 重映射
我們要利用 TIM3 的 CH2 輸出 PWM 來控制 LED的亮度,但是 TIM3_CH2 默認(rèn)是接在 PA7上面的,而我們的 LED接在 PB5 上面,如果是普通 MCU,可能就只能用飛線把 PA7 飛到 PB5上;不過,我們用的是 STM32,可以通過重映射功能,把 TIM3_CH2映射到 PB5 上。?
3.代碼難點(diǎn)分析
1)RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);//使能TIM3時(shí)鐘
? ? ? RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); ?
//使能GPIOB時(shí)鐘(PB5連接LED)和AFIO復(fù)用功能時(shí)鐘
為什么要使能RCC_APB2Periph_AFIO呢?
參考手冊(cè)上說:
對(duì)寄存器AFIO_EVCR(事件控制寄存器),AFIO_MAPR(?復(fù)用重映射和調(diào)試I/O配置寄存器),AFIO_EXTICRX(外部中斷配置寄存器)進(jìn)行讀寫操作前,應(yīng)當(dāng)首先打開AFIO的時(shí)鐘。
因?yàn)槲覀冊(cè)谶@個(gè)實(shí)驗(yàn)中用到了AFIO_MAPR,所以要打開AFIO時(shí)鐘。
2)GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射,TIM3_CH2->PB5?
3)GPIO配置
//設(shè)置該引腳為復(fù)用輸出功能,輸出TIM3-CH2的PWM波形
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;?
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; ?//推挽復(fù)用輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
4)TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;?
? ? ?可以參考捕獲/比較使能寄存器(TIMx_CCER)位0, 輸出使能。
5)TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;?
? ? ?可以參考捕獲/比較使能寄存器(TIMx_CCER)位1, 高/低 電平有效。
6)TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); 預(yù)裝載使能
? ? ?可以參考捕獲/比較模式寄存器 (TIMx_CCMR1/2) 位3.
7)TIM_SetCompare2(TIM3,300);
參考捕獲/比較寄存器(TIMx_CCR1~4),這里設(shè)置比較值為300.
4. 代碼參考
//PWM輸出初始化函數(shù) //arr:自動(dòng)重裝載值 //psc: 預(yù)分頻系數(shù) void TIM3_PWM_Init(u16 arr,u16 psc) { GPIO_InitTypeDef GPIO_InitStructure;TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_OCInitTypeDef TIM_OCInitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能TIM3時(shí)鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); //使能GPIOB時(shí)鐘(PB5連接LED)和AFIO復(fù)用功能時(shí)鐘GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射,TIM3_CH2->PB5 //設(shè)置該引腳為復(fù)用輸出功能,輸出TIM3-CH2的PWM波形GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復(fù)用推挽輸出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化TIM3TIM_TimeBaseStructure.TIM_Period = arr; TIM_TimeBaseStructure.TIM_Prescaler = psc; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上計(jì)數(shù)TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //TIM3 Channel2 PWM 初始化TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //PWM2模式TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //捕獲/比較使能寄存器(TIMx_CCER) 輸出使能TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //高電平有效TIM_OC2Init(TIM3, &TIM_OCInitStructure); TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //預(yù)裝載使能TIM_Cmd(TIM3, ENABLE); //開啟TIM3}
main函數(shù)如下
int main(void) { TIM3_PWM_Init(999,71); //72/(71+1)=1MHz, T=1us*(999+1) = 1msTIM_SetCompare2(TIM3,300); //脈寬= 300/1000 *1ms = 0.3mswhile(1){; } }
仿真說明:我們的代碼設(shè)置為:
PWM2模式,向上計(jì)數(shù),高電平有效。
所以,TIMx_CNT<TIMx_CCRx時(shí)通道x為低,否則為高。
5.仿真效果圖如下
6. 疑問
如果調(diào)換main函數(shù)兩句的順序,則無法達(dá)到預(yù)期效果。
<span style="font-size:18px;">int main(void) //實(shí)驗(yàn)失敗 { TIM_SetCompare2(TIM3,300); //脈寬= 300/1000 *1ms = 0.3msTIM3_PWM_Init(999,71); //72/(71+1)=1MHz, T=1us*(999+1) = 1mswhile(1){; } }</span>至于原因,這里不討論,留待以后思考。
7. 用PWM控制LED的亮度
int main(void) { u16 led0pwmval = 0; //比較值u8 dir = 1; delay_init(); TIM3_PWM_Init(899,0); while(1){delay_ms(10); if(dir)led0pwmval++;else led0pwmval--;if(led0pwmval>300)dir=0;if(led0pwmval==0)dir=1; TIM_SetCompare2(TIM3,led0pwmval); } }
這里,我們將 led0pwmval 這個(gè)值設(shè)置為 PWM 比較值,也就是通過 led0pwmval 來控制 PWM 的占空比,進(jìn)而控制LED的平均電流,達(dá)到控制LED亮度的目的。
?led0pwmval 的值從 0 變到 301,然后又從 301 變到 0,如此循環(huán),LED的亮度也會(huì)跟著從暗變到亮,然后又從亮變到暗。至于這里的值,我們?yōu)槭裁慈?300,是因?yàn)?PWM 的輸出占空比達(dá)到并且超過這個(gè)值的時(shí)候, LED 亮度變化就不明顯了。
總結(jié)
以上是生活随笔為你收集整理的stm32 PWM输出学习的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 做产品,大公司克制,小公司放纵
- 下一篇: 2020年小红书美妆行业品牌投放数据报告