【示例1:高優先級中斷屏蔽並清除低優先級中斷】
#include <stm32f10x.h>
#define _BV(n) (1 << (n))
uint16_t status = 0;
uint8_t seg8[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e};
void delay(void)
{
uint16_t i;
for (i = 0; i < 20000; i++);
}
void ser_in(uint8_t data)
{
uint8_t i;
for (i = 0; i < 8; i++)
{
GPIOB->BRR = GPIO_BRR_BR9; // SCLK=PB9
if (data & 0x80)
GPIOB->BSRR = GPIO_BSRR_BS7; // DIO=PB7
else
GPIOB->BRR = GPIO_BRR_BR7;
data <<= 1;
GPIOB->BSRR = GPIO_BSRR_BS9;
}
}
void par_out(void)
{
GPIOB->BRR = GPIO_BRR_BR8; // RCLK=PB8
GPIOB->BSRR = GPIO_BSRR_BS8;
}
// 單步數碼管掃描
void seg_scan(void)
{
static uint8_t i = 0;
static uint16_t num;
__disable_irq(); // 關總中斷, 防止74HC595晶片時序錯亂導致數碼管閃爍
if (i == 0)
num = TIM1->CNT / 100;
if (i == 5)
num = status;
ser_in(seg8[num % 10]);
ser_in(_BV(i));
par_out();
delay();
num /= 10;
// 數碼管0~2顯示定時器1計數值的百~萬位, 數碼管5~7顯示status的個~百位
// 從低位向高位掃描
if (i == 2)
i = 5;
else if (i == 7)
i = 0;
else
i++;
__enable_irq(); // 開總中斷, 並立即處理剛才中斷關閉時已經置位的中斷請求
}
/*
// 這個數碼管掃描函數影響中斷處理的程度要高一些
// 功能和上面那個一樣
void seg_scan(void)
{
uint8_t i;
uint16_t num = TIM1->CNT / 100;
__disable_irq();
for (i = 0; i <= 2; i++)
{
ser_in(seg8[num % 10]);
ser_in(_BV(i));
par_out();
delay();
num /= 10;
}
num = status;
for (i = 5; i <= 7; i++)
{
ser_in(seg8[num % 10]);
ser_in(_BV(i));
par_out();
delay();
num /= 10;
}
__enable_irq();
}
*/
int main(void)
{
RCC->APB2ENR |= RCC_APB2ENR_IOPBEN | RCC_APB2ENR_TIM1EN | RCC_APB2ENR_AFIOEN;
GPIOB->CRH = 0x00000033;
GPIOB->CRL = 0x30000008;
GPIOB->BSRR = GPIO_BSRR_BS0;
AFIO->EXTICR[0] = 0x01; // Px0 = PB0
EXTI->IMR |= EXTI_IMR_MR0; // 開Px0外中斷
EXTI->FTSR |= EXTI_FTSR_TR0; // Px0下降沿觸發
//EXTI->RTSR |= EXTI_RTSR_TR0; // Px0上升沿觸發
TIM1->ARR = 12099;
TIM1->PSC = 48000;
TIM1->DIER |= TIM_DIER_UIE;
NVIC->ISER[0] = NVIC_ISER_SETENA_6 | NVIC_ISER_SETENA_25;
TIM1->CR1 |= TIM_CR1_CMS | TIM_CR1_URS;
TIM1->EGR |= TIM_EGR_UG;
TIM1->CR1 &= ~TIM_CR1_URS;
TIM1->CR1 |= TIM_CR1_CEN;
while (1)
{
seg_scan();
}
}
// 高優先級中斷(外部中斷)
void EXTI0_IRQHandler(void)
{
status++;
while ((GPIOB->IDR & GPIO_IDR_IDR0) == 0) // 等待按鍵釋放
{
seg_scan();
if (NVIC->ICPR[0] & NVIC_ICPR_CLRPEND_25)
{
// 高優先級中斷清除低優先級中斷
// 只要按鍵沒有鬆開, 定時器中斷就無法觸發
TIM1->SR &= ~TIM_SR_UIF;
NVIC->ICPR[0] |= NVIC_ICPR_CLRPEND_25;
}
}
EXTI->PR |= EXTI_PR_PR0;
}
// 低優先級中斷(定時器溢出中斷)
void TIM1_UP_IRQHandler(void)
{
TIM1->SR &= ~TIM_SR_UIF;
status += 10;
}