1. TIM3的GPIO口,查閱STM32F105RBT6 數(shù)據(jù)手冊,TIM3的4通道用的是PB1
2. 初始化GPIO口和定時器TIM3
2.1 相關(guān)函數(shù)
RCC_APB1PeriphClockCmd、GPIO_Init、TIM_TimeBaseInit、TIM_OC4Init、TIM_OC4PreloadConfig、NVIC_Init、TIM_ITConfig、TIM_Cmd、
void TIM3_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
TIM_TimeBaseInitTypeDef TIM_InitStruct;
TIM_OCInitTypeDef TIM_OCInitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
// Enable clock for TIM3 and GPIOB
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3 | RCC_APB2Periph_GPIOB, ENABLE);
// Initialize GPIOB to output PWM signal
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);
// Initialize TIM3 for PWM generation with interrupt on update
TIM_InitStruct.TIM_Prescaler = 0; // Set PWM frequency to 72MHz (72 MHz / (0 + 1))
TIM_InitStruct.TIM_Period = 999;
TIM_InitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_InitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_InitStruct);
TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStruct.TIM_Pulse = 500; // Duty cycle = 50%
TIM_OC4Init(TIM3, &TIM_OCInitStruct);
TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);
NVIC_InitStruct.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 4;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM3, ENABLE);
}
3. 中斷入口 TIM3_IRQHandler
3.1 在啟動文件里面找到TIM3 對應(yīng)的中斷入口函數(shù),也就是中斷服務(wù)函數(shù) TIM3_IRQHandler
4. 編寫中斷服務(wù)函數(shù)
void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) == SET) // overflow interrupt
{
printf("龍傲天說,我三歲拳打南山不老院,四歲腳踢北海幼兒園\r\n");
}
TIM_ClearITPendingBit(TIM3,TIM_IT_Update); // clear interrupt flag
// Handle interrupt by updating PWM duty cycle value
// static uint16_t duty_cycle = 500; // Initial value of 50%
// duty_cycle = duty_cycle < 950 ? duty_cycle + 50 : 0; // Increase duty cycle by 5% every period
// TIM_SetCompare4(TIM3, duty_cycle);
}
4.1 中斷服務(wù)函數(shù)需要快速地執(zhí)行完畢。中斷服務(wù)函數(shù)應(yīng)該避免執(zhí)行太多的計(jì)算復(fù)雜度較高的操作,否則可能會導(dǎo)致中斷響應(yīng)時間過長,甚至因?yàn)檠舆t而導(dǎo)致系統(tǒng)不穩(wěn)定。
4.2 如果你需要在中斷服務(wù)函數(shù)中訪問全局變量,需要將這些變量定義為volatile類型。這是因?yàn)橹袛喾?wù)函數(shù)可能會在任何時間被外部中斷所打斷,如果沒有使用volatile類型,就有可能導(dǎo)致變量值不準(zhǔn)確。
4.3 在中斷服務(wù)函數(shù)的結(jié)尾處,需要調(diào)用NVIC_ClearPendingIRQ()函數(shù)來清除中斷掛起位。
4.4 中斷函數(shù)最好別用printf 函數(shù)等耗時、有可能阻塞的一些函數(shù),printf函數(shù)本身就比較耗時,在中斷服務(wù)函數(shù)中調(diào)用的話,可能會導(dǎo)致中斷響應(yīng)時間過長,使系統(tǒng)不穩(wěn)定。如果在中斷服務(wù)函數(shù)中使用了printf函數(shù),可能會導(dǎo)致printf函數(shù)與被打斷的低優(yōu)先級代碼發(fā)生沖突,造成數(shù)據(jù)異常。我這里用 printf 只是為了裝13,我龍傲天誰都不服
4.4 中斷服務(wù)函數(shù)需要快速、簡潔、有效地處理中斷,并且需要小心地處理共享資源和全局變量。
5. 主函數(shù)調(diào)用一下初始化函數(shù)就可以了
int main(void)
{
TIM3_Init();
while (1)
{
printf("劍圣來了,快跑");
}
}
5.1 如果沒有成功輸出pwm波,可能是初始化時序不對,前面已經(jīng)操作過該IO口了,我有很多的例程放在一起,搞混了,需要把原來的操作去掉,屏蔽掉,或者調(diào)整一下 TIM3_Init() 的位置,如果有很多別的初始化函數(shù),就把TIM3_Init() 放到后面一點(diǎn)試試
6. 串口數(shù)據(jù)
7. 拿示波器或者邏分儀去量PB1 引腳,看波形,有毛刺,我沒濾波的,可以處理掉
8. PWM 波頻率、周期計(jì)算
8.1 頻率 F = SYSCLK / ((TIM_Prescaler + 1) / (TIM_Period + 1))
8.2 周期 T = 1 / F
8.3 制造一個頻率是1 Hz的PWM 波,周期 1s, 占空比50%,改下面三個參數(shù)值就行了
TIM_InitStruct.TIM_Prescaler = 7199;
TIM_InitStruct.TIM_Period = 10000;
TIM_OCInitStruct.TIM_Pulse = 5000; // 占空比50% = 5000 / (TIM_Period + 1)
文章來源:http://www.zghlxwxcb.cn/news/detail-478375.html
9. TIM3的四個通道輸出四路PWM,各個通道之間輸出的PWM是獨(dú)立的,頻率,占空比可單獨(dú)設(shè)置
void TIM3_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
TIM_TimeBaseInitTypeDef TIM_InitStruct;
TIM_OCInitTypeDef TIM_OCInitStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;
GPIO_Init(GPIOA, &GPIO_InitStruct);
/*
* Initialize TIM3 for generation PWM
* Set PWM frequency to 72kHz (72 MHz / (999 + 1) / (0 + 1)), TIM3_FRQ = SYSCLK / ((TIM_Period + 1) * (TIM_Prescaler + 1))
* STM32F105RBT6_PB1 - TIM3_Ch4
*/
TIM_InitStruct.TIM_Prescaler = 7199; // 0, 7199
TIM_InitStruct.TIM_Period = 9999; // 999, 9999
TIM_InitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_InitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_InitStruct);
TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStruct.TIM_Pulse = 5000; // 500,5000 Duty cycle = 50%
TIM_OC1Init(TIM3, &TIM_OCInitStruct);
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_OC2Init(TIM3, &TIM_OCInitStruct);
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_Cmd(TIM3, ENABLE);
}
主函數(shù)調(diào)用,使能每個通道輸出
while (1) {
TIM_SetCompare1(TIM3, 5000);
TIM_SetCompare2(TIM3, 5000);
TIM_SetCompare4(TIM3, 5000);
}
文章來源地址http://www.zghlxwxcb.cn/news/detail-478375.html
到了這里,關(guān)于STM32F105RBT6 使用定時器TIM3輸出PWM波的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!