【示例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;
}