STM32實驗1:定時器中斷同時產生兩路不同頻率的信號
一、實驗目的
使用STM32同時產生兩路不同頻率的信號,並通過觀察開發板兩個LED閃爍快慢的現象,以及在MDK5中軟件仿真邏輯分析中查看波形,體現兩路信號頻率的不同。
二、實驗原理
通過定時器中斷配置,定時器3每600ms中斷一次,然後中斷服務函數中控制LED實現LED1狀態取反(閃爍);定時器4每200ms中斷一次,然後中斷服務函數中控制LED實現LED0狀態取反(閃爍)。
本實驗用到的硬件資源有:
1) 指示燈 LED0 和 LED1
2) 定時器 TIM3,TIM4
TIM3,TIM4屬於 STM32 的內部資源,只需要軟件設置即可正常工作。
1、通用定時器電路框圖
2、計數器模式
採用向上計數
向上計數模式:計數器從0計數到自動加載值(TIMx_ARR),然後重新從0開始計數並且產生一個計數器溢出事件。
3、信號週期計算(定時器溢出時間)
TIM3 的時鐘爲 72 M,再根據我們設計的 arr 和 psc的值, 就可以計算中斷時間了。公式如下:
Tout= ((arr +1)*(psc+1)) /Tclk;
其中:
Tclk :TIM3 的輸入時鐘頻率 (單位爲 Mhz)。
Tout :TIM3 溢出時間(單位爲 us)。
4、定時器中斷實現步驟
(1) 能定時器時鐘。
RCC_APB1PeriphClockCmd();
(2) 初始化定時器,配置ARR,PSC。
TIM_TimeBaseInit();
(3) 開啓定時器中斷,配置NVIC。
void TIM_ITConfig();
NVIC_Init();
(4) 使能定時器。
TIM_Cmd();
(5) 編寫中斷服務函數。
TIMx_IRQHandler();
三、實驗代碼
timer.c
#include "timer.h"
#include "led.h"
//通用定時器3中斷初始化
//這裏時鐘選擇爲APB1的2倍,而APB1爲36M
//arr:自動重裝值。
//psc:時鐘預分頻數
//這裏使用的是定時器3!
void TIM3_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //時鐘使能
//定時器TIM3初始化
TIM_TimeBaseStructure.TIM_Period = arr; //設置在下一個更新事件裝入活動的自動重裝載寄存器週期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //設置用來作爲TIMx時鐘頻率除數的預分頻值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設置時鐘分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計數模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根據指定的參數初始化TIMx的時間基數單位
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中斷,允許更新中斷
//中斷優先級NVIC設置
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先佔優先級0級
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //從優先級3級
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器
TIM_Cmd(TIM3, ENABLE); //使能TIMx
}
//定時器3中斷服務程序
void TIM3_IRQHandler(void) //TIM3中斷
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //檢查TIM3更新中斷髮生與否
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIMx更新中斷標誌
LED1=!LED1;
}
}
//這裏使用的是定時器4!
void TIM4_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //時鐘使能
//定時器TIM4初始化
TIM_TimeBaseStructure.TIM_Period = arr; //設置在下一個更新事件裝入活動的自動重裝載寄存器週期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //設置用來作爲TIMx時鐘頻率除數的預分頻值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設置時鐘分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計數模式
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根據指定的參數初始化TIMx的時間基數單位
TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE ); //使能指定的TIM4中斷,允許更新中斷
//中斷優先級NVIC設置
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; //TIM4中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先佔優先級0級
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //從優先級3級
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器
TIM_Cmd(TIM4, ENABLE); //使能TIMx
}
//定時器4中斷服務程序
void TIM4_IRQHandler(void) //TIM4中斷
{
if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) //檢查TIM4更新中斷髮生與否
{
TIM_ClearITPendingBit(TIM4, TIM_IT_Update ); //清除TIMx更新中斷標誌
LED0=!LED0;
}
}
main.c
#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include "timer.h"
int main(void)
{
delay_init(); //延時函數初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //設置NVIC中斷分組2:2位搶佔優先級,2位響應優先級
uart_init(115200); //串口初始化爲115200
LED_Init(); //LED端口初始化
TIM3_Int_Init(5999,7199);//10Khz的計數頻率,計數到6000爲600ms
TIM4_Int_Init(1999,7199);//10Khz的計數頻率,計數到2000爲200ms
while(1)
{
}
}
四、結果分析
1、MDK5的軟件仿真中的邏輯分析
波形對應LED說明如下
定時器 | 亮燈 | 引腳 | 週期 | 波形顏色 |
---|---|---|---|---|
TIM3 | LED1(綠色燈) | PE5 | 600ms | 綠色波 |
TIM4 | LED0(紅色燈) | PB5 | 200ms | 紅色波 |
2、開發板現象
如圖
LED0紅色燈閃的更快,差不多是紅色燈閃3次,綠色燈閃1次。
這與軟件仿真相符。
3、注意事項
要確認外部晶振頻率爲8.0Mhz,不然會計時不準。