stm32寄存器编程--AFIO、EXTI、NVIC
·
先讲讲AFIO,其实这个不难,主要功能就是复用重映射引脚和链接外部中断引脚。
1、先讲讲复用引脚重映射,我们的板子上有许多引脚,也有许多外设,也有对应的外设引脚,未免会有一些引脚拥有多种功能,比如说定时器的引脚和uart的引脚共用,如果我们需要同时用到,可以使用AFIO将某一个引脚映射到其他引脚使用,举个例子:

我们此时可以通过AFIO去将PA9,PA10映射到PB6,PB7,这就是AFIO的其中一个作用。寄存器的话,我建议自己去翻数据手册。记得先使能AFIO时钟。

优先级这一块要了解
NVIC:管理中断,选择中断源,设置优先级组,中断仲裁(多个中断就绪的时候,按照优先级来选择)

一个demo,NVIC的寄存器配置比较抽象一些,要先配置SCB->AIRCR设置优先级组
这边是一个极简写法,详细在NVIC_Init函数实现里面,其他寄存器对着手册配就好。
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
void gpio_init(){
//开启GPIOA的时钟
RCC->APB2ENR |= (1ul << 2);
//PA0浮空输入0100
GPIOA->CRL &= ~(0x0F << (4 * 0));
GPIOA->CRL |= (0x04 << (4 * 0));
//PA5推挽输出0011
GPIOA->CRL &= ~(0x0F << (4 * 5));
GPIOA->CRL |= (0x03 << (4 * 5));
}
void afio_exti_init(){
//开启AFIO时钟
RCC->APB2ENR |= (1ul << 0);
//AFIO_EXTICR1,操作低四位EXTI0[3:0],然后选择PA0
AFIO->EXTICR[0] &= ~(0x0F << (4 * 0));
//开放来自线0上的中断请求
EXTI->IMR |= (1ul << 0);
//允许输入线0上的下降沿触发
EXTI->FTSR |= (1ul << 0);
}
void nvic_init(){
//优先级组,2位抢占优先级,2位子优先级
SCB->AIRCR |= (0x5FA << 16) | (1ul << 10) | (1ul << 8);
SCB->AIRCR &= ~(1ul << 9);
//NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/*设置优先级,抢占优先级2,子优先级1,这里是我本人知道优先级组2,2的情况,如果是其他优先级组的话,参考官方写法。
如果是3,1的话:NVIC->IP[6] = ((2 << 1) | 1) << 4;抢占只左移一位,4个位置占三个,就有0~7可选,子优先级只有1位,只有0~1可选
*/
NVIC->IP[6] = ((1 << 2) | 1) << 4;
//开启EXTI0_IRQn中断,注意查看中断号,数组下标为中断号/32,后面为中断号对32取余,以此类推
NVIC->ISER[0] |= (1ul << 6);
// NVIC_InitTypeDef NVIC_InitStruct;
// NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn; //中断响应函数
// NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级
// NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1; //子优先级
// NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; //使能中断
//
// NVIC_Init(&NVIC_InitStruct);
}
void led_toggle(){
if(GPIOA->ODR & (1ul << 5)){
GPIOA->BSRR = (1ul << 21);
}
else{
GPIOA->BSRR = (1ul << 5);
}
}
void EXTI0_IRQHandler(){
if(EXTI->PR & (1ul << 0)){
led_toggle();
//清除中断标志位
EXTI->PR |= (1ul << 0);
}
}
int main(void)
{
gpio_init();
afio_exti_init();
nvic_init();
while (1)
{
}
}
更多推荐
所有评论(0)