用定時器控制Led燈閃爍

來源:互聯網
上載者:User
實驗目的
閃燈程式在嵌入式學習中猶如“Hello World。”在C/C++語言學習中一樣經典。它以簡單的方式引導了無數的嵌入式愛好者。通過本節的學習你可以基本瞭解STM32的GPIO以及基本定時器的使用。
硬體說明
本常式需要一個定時器和一個LED,其中LED就是擴充板上的紅色LED接在PD3上且正極接在高電平上,定時器選用基本定時器7。
1. STM32 GPIO簡介
GPIO主要特性
輸出狀態可選推挽、開漏、上拉或下拉
可為每個I/O選擇速度
輸入狀態可選則懸空、上拉/下拉、類比
每個I/O引腳都有複用功能
可對每個輸出引腳進行位操作
STM32的每個GPIO都有4個32位配置寄存器:模式選擇寄存器、輸出類型配置寄存器、輸出速度配置寄存器、上拉/下拉電阻配置寄存器;2個32位元據寄存器:資料輸入寄存器、資料輸出寄存器;1個32位鎖定寄存器和2個32位複用功能選擇寄存器。無論你選擇某個I/O作為輸入還是輸出,都可以給根據需求選擇是否使用上拉或下拉電阻。總的來講,每個I/O有8中模式可供選擇:輸入懸空、帶上拉輸入、來下拉輸入、帶上拉或下拉開漏輸出、帶上拉或下拉推挽輸出、類比輸入、推挽且帶上拉或下拉的複用功能、開漏且帶上拉或下拉的複用功能。

1.1 I/O模式選擇
每個I/O引腳都有4種用途模式可供選擇。GPIOx_MODER(x = A..I)是一個32位寄存器,每兩位配置一個引腳,位[1:0]配置引腳0以此類推。其取值及含義如表1.1所示。
表1.1 I/O用途模式設定
MODER[1:0] 描述
B00 輸入模式(初始值)
B01 通用輸出模式
B10 複用功能模式
B11 類比訊號模式

1.2 輸出類型選擇
根據輸出需求你可在GPIOx_OTYPER中設定推挽或開漏輸出。這個寄存器只有低16位有效,取值及定義如表1.2所示。
表1.2 輸出類型設定
OT[0] 描述
B0 推挽輸出(初始值)
B1 開漏輸出

1.3 輸出速度設定
表1.3 連接埠輸出速度設定
OSPEEDER[1:0] 描述
B00 2MHZ低速
B01 25MHZ中速
B10 50MHZ快速
B11 100MHZ高速

1.4 上拉下拉電阻設定
表1.4 上拉下拉電阻設定
PUPDR[1:0] 描述
B00 無上拉或下拉電阻
B01 上拉電阻串連
B10 下拉電阻串連
B11 保留

1.5 資料輸入和輸出
當GPIO設定為通用輸入時,讀取寄存器GPI Ox_IDR)(x = A..I)可得到連接埠的輸入狀態且這個寄存器是唯讀;GPIOx_ODR(x = A..I)是一個可讀寫寄存器,寫資料到這個寄存器可控制連接埠輸出電平,從這個寄存器讀資料可判斷連接埠的輸出狀態。
1.6 複用功能選擇
STM32中有16種複用功能,一個引腳會對應其中幾種。共有兩個寄 
存器GPIOx_AFRL與GPIOx_AFRH 用來設定引腳的複用功能,其中每
4位對應一個引腳。 
表1.6 複用功能配置
AFR[3:0] 描述
0X1 AF1(TIM1/TIM2)
0X2 AF2(TIM3...5)
0X4 AF4(I2C1...3)
0XD AF14(DCMI)

2. STM32基本定時器簡介
STM32的定時器非常強大,根據功能可分為進階控制定時器、通用定時器、基本定時,其中定時器6、7為基本定時器。在這裡我們主要對基本定時器給予簡單介紹。它具有一個16位自動重載加法計數器和一個16位可程式化預分頻器。預分頻器對輸入時鐘進行分頻,然後提供給計數器作為計數時鐘使用。STM32的自動重載寄存器(TIMx_ARR)在物理上對應兩個寄存器,一個是咱們可以隨便讀寫的,另一個則只能被定時器讀取。這個咱們無法操作的寄存器被稱作影子寄存器。當TIMx_CR1中的ARPE位等於0時改變TIMx_ARR的值就可馬上改變影子寄存器裡的值。當ARPE等於1時TIMx_ARR的值被緩衝起來了,只有當更新事件發生後才會將新的值傳送到影子寄存器中。
操作定會器前需要先開啟輸入時鐘,然後可設定重預分頻係數寄存器(TIMx_PSC)和自動載值寄存器。因為我們要讓定時器產生更新中斷,因此必需使能TIMx_DIER中的UIE位以及設定NVIC相關寄存器。初始化完成後設定TIMx_CR1的CEN位即可開啟定時器。

實驗原理及程式結構
實驗設計
利用STM32的基本定時器產生更新中斷,在中斷處理函數中控制LED引腳的電平,帶給大家一個閃燈的效果。本常式會涉及到GPIO_D03以及基本定時器7的初始化和一個定時器7 插斷服務常式等。
來源程式說明
下面讓我們來看看blink.c是如何?的。 
LED初始化
代碼: 全選 /* blink.c */ 
void led_init(void)
{    
    GPIO_InitTypeDef  GPIO_InitStructure;

    /* 使能GPIOD時鐘 */
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

    /* 配置GPIO_LED引腳 */
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;        
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; 
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL; 

    GPIO_Init(GPIOD, &GPIO_InitStructure);
}

LED的初始化比較簡單,選擇好引腳並將引腳用途模式設定為輸出即可。需要注意的是STM32的每個外設的時鐘都可單獨控制,在操作前需要開啟時鐘而且要從STM32使用者手冊中確認清楚,你要用到的外設具體掛載在哪個匯流排上的(AHB1、APB1等)。
LED控制
代碼: 全選 /* blink.c */ 
void led_on(void)
{
    /* 設定PD3為低電平 */
    GPIO_ResetBits(GPIOD, GPIO_Pin_3);
}

void led_off(void)
{
      /* 設定PD3為高電平 */
    GPIO_SetBits(GPIOD, GPIO_Pin_3);
}

void led_toggle(void)
{
      /* 切換PD3電平狀態 */
    GPIO_ToggleBits(GPIOD, GPIO_Pin_3);
}

這三個LED控制函數都使用了位操作,由於LED的正極是接在高電平上的,led_on是讓PD3輸出低電平從而點亮LED。led_toggle將會在定時器的插斷服務常式中調用,它會把引腳在高低電平之間切換達到閃燈的果。
定時器初始化
代碼: 全選 /* blink.c */ 
void TIM7_Configuration(void)
{
    NVIC_InitTypeDef NVIC_InitStructure; 
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseInitStruct;
    
    /* 操作定時器前先使能輸入時鐘 */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE);
    /**** Time base configuration ****/
    
    /* 設定自動重裝載周期,計數到5000為1000ms */
    TIM_TimeBaseInitStruct.TIM_Period = 5000;
    /* 設定預分頻值,即定時器計數頻率為10Khz */
    TIM_TimeBaseInitStruct.TIM_Prescaler =(8400-1);
    TIM_TimeBaseInitStruct.TIM_ClockDivision = 0; 
    /* 向上計數模式 */
    TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; 

    /* 根據TIM_TimeBaseInitStruct中指定的參數初始化TIM7的時基單位 */
    TIM_TimeBaseInit(TIM7, &TIM_TimeBaseInitStruct); 
    /* 使能TIM7更新中斷 */
    TIM_ITConfig(TIM7, TIM_IT_Update, ENABLE);

    /* Configure the NVIC Preemption Priority Bits */
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    /* Enable the TIM7 global Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    /* 啟動定時器 */       
        TIM_Cmd(TIM7, ENABLE);  
}

 

這裡使用的是最簡單的基本定時器,開啟輸入時鐘、設定預分頻器和計數重載值後配置好相關中斷寄存器後就可啟動定時器了。在ST庫代碼的stm32f4xx_it.C中定義了所有中斷入口,我們需要在裡面添加如下代碼:
定時器7插斷服務常式
代碼: 全選 /* stm32f4xx_it.C */ 
void TIM7_IRQHandler(void)    
{
    if (TIM_GetITStatus(TIM7, TIM_IT_Update) != RESET)  
    {   
         /* 清除中斷標誌 */
         TIM_ClearITPendingBit(TIM7, TIM_IT_Update  );   
       /* 切換I/O狀態 */     
         led_toggle();
    }
}

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.