設置 | 登錄 | 註冊

目前共有7篇帖子。

【程序】STM32外部中斷的使用(以PB4為例)

1樓 巨大八爪鱼 2016-12-19 19:26

#include <stm32f10x.h>
#define _BV(n) (1 << (n))
uint8_t num = 0;
uint8_t seg8[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90};
void delay(void)
{
    uint32_t i;
    for (i = 0; i < 2000; i++);
}
// 數碼管顯示部分
void SerIn(uint8_t data)
{
    uint8_t i;
    for (i = 0; i < 8; i++)
    {
        GPIOC->BRR = _BV(15);
        if (data & 0x80)
            GPIOC->BSRR = _BV(13);
        else
            GPIOC->BRR = _BV(13);
        GPIOC->BSRR = _BV(15);
        data <<= 1;
    }
}
void ParOut(void)
{
    GPIOC->BRR = _BV(14);
    GPIOC->BSRR = _BV(14);
}
int main(void)
{
    RCC->APB2ENR = 0x19; // 開啟PB和PC以及AFIO的時鐘
    GPIOB->CRL = 0x00280000; // PB4設為帶上下拉的輸入, PB5設為2MHz推輓輸出
    GPIOB->ODR = 0x10; // PB4選擇上拉模式, PB5輸出0
    GPIOC->CRH = 0x33300000; // PC13~15設為50MHz推輓輸出
   
    // External interrupt/event controller
    EXTI->IMR = _BV(4); // 開啟PX4中斷 (Interrupt mask register)
    EXTI->FTSR = _BV(4); // PX4在下降沿觸發中斷 (Falling trigger selection register)
   
    AFIO->EXTICR[1] = 0x01; // 指定PX4中的PX為PB
   
    SerIn(seg8[num]); // 段選
    SerIn(_BV(0)); // 位選
    ParOut();
   
    while (1)
    {
        if (EXTI->PR & _BV(4)) // 檢測中斷標誌位 (Pending register)
        {
            num++;
            if (num > 9)
                num = 0;
               
            SerIn(seg8[num]);
            SerIn(_BV(0));
            ParOut();
               
            // 等待按鍵PB4釋放
            while ((GPIOB->IDR & _BV(4)) == 0)
                delay();
           
            EXTI->PR |= _BV(4); // 通過寫1來清除中斷標誌位
        }
    }
}

2樓 巨大八爪鱼 2016-12-19 19:29

【步驟】
1.開啟AFIO的時鐘,也就是將RCC->APB2ENR寄存器的最低位設為1
2.把相應端口設為輸入
3.通過EXTI->IMR寄存器開中斷
4.通過EXTI->FTSR寄存器設置中斷觸發方式
5.通過AFIO->EXTICR[n]寄存器決定PX中X的值。PX0~3在該[0]號寄存器中設置,PX4~7在[1]號寄存器中設置,以此類推

3樓 巨大八爪鱼 2016-12-19 19:33
對於第4步,EXTI_RTSR寄存器設置的觸發方式為上升沿觸發,EXTI_FTSR為下降沿觸發
4樓 巨大八爪鱼 2016-12-19 20:19
1樓的程序是通過查詢的方式來處理中斷。下面的程序則是通過中斷服務函數來處理:
#include <stm32f10x.h>
#define _BV(n) (1 << (n))
uint8_t num = 0;
uint8_t seg8[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90};
void delay(void)
{
    uint32_t i;
    for (i = 0; i < 2000; i++);
}
// 數碼管顯示部分
void SerIn(uint8_t data)
{
    uint8_t i;
    for (i = 0; i < 8; i++)
    {
        GPIOC->BRR = _BV(15);
        if (data & 0x80)
            GPIOC->BSRR = _BV(13);
        else
            GPIOC->BRR = _BV(13);
        GPIOC->BSRR = _BV(15);
        data <<= 1;
    }
}
void ParOut(void)
{
    GPIOC->BRR = _BV(14);
    GPIOC->BSRR = _BV(14);
}
// 中斷服務函數
void EXTI4_IRQHandler(void)
{
    num++;
    if (num > 9)
        num = 0;
               
    SerIn(seg8[num]);
    SerIn(_BV(0));
    ParOut();
               
    // 等待按鍵PB4釋放
    while ((GPIOB->IDR & _BV(4)) == 0)
        delay();
    // 清除中斷標誌
    //NVIC->ICPR[0] = _BV(10); // 無效, 因為該中斷正在執行
    EXTI->PR |= _BV(4); // 只能通過這種方式清除中斷
}
int main(void)
{
    RCC->APB2ENR = 0x19; // 開啟PB和PC以及AFIO的時鐘
    GPIOB->CRL = 0x00280000; // PB4設為帶上下拉的輸入, PB5設為2MHz推輓輸出
    GPIOB->ODR = 0x10; // PB4選擇上拉模式, PB5輸出0
    GPIOC->CRH = 0x33300000; // PC13~15設為50MHz推輓輸出
   
    // External interrupt/event controller
    EXTI->IMR = _BV(4); // 開啟PX4中斷 (Interrupt mask register)
    EXTI->FTSR = _BV(4); // PX4在下降沿觸發中斷 (Falling trigger selection register)
   
    AFIO->EXTICR[1] = 0x01; // 指定PX4中的PX為PB
    NVIC->ISER[0] = _BV(10); // 允許執行中斷函數
   
    SerIn(seg8[num]); // 段選
    SerIn(_BV(0)); // 位選
    ParOut();
   
    while (1);
}
5樓 巨大八爪鱼 2016-12-19 20:21
首先,對於PX4中斷,所使用的線路是EXTI4,也就是EXTI Line4 interrupt。該線路的位置(Position)是10。這在用戶手冊中是可以查到的:

6樓 巨大八爪鱼 2016-12-19 20:29
要想中斷函數得到執行,就必須配置NVIC->ISER[n]寄存器(Interrupt set-enable registers)。
表中的Position的值的範圍是0~59,而每個ISER寄存器只有32位,所以分了好幾個寄存器來設置:

[0]號寄存器專門設置0~31號中斷
[1]號寄存器專門設置32~63號中斷

因此配置第10號中斷的代碼就是:
NVIC->ISER[0] = _BV(10);
寫1是開啟,寫0無效。要想關閉只有對NVIC->ICER[n]寄存器(Interrupt clear-enable registers)寫1才行。

中斷服務函數的名稱必須為EXTI4_IRQHandler,不能自行修改。在該函數中必須通過對EXTI->PR寄存器(Pending register)寫1來清除中斷標誌,防止該函數反覆執行。
7樓 巨大八爪鱼 2016-12-19 20:35
IRQHandler的全稱是Interrupt Request Handler,也就是中斷請求處理器。

內容轉換:

回覆帖子
內容:
用戶名: 您目前是匿名發表。
驗證碼:
看不清?換一張
©2010-2025 Purasbar Ver3.0 [手機版] [桌面版]
除非另有聲明,本站採用知識共享署名-相同方式共享 3.0 Unported許可協議進行許可。