RT1052之NVIC中断系统

RT1052之NVIC中断系统

一、简介

The Nested Vectored Interrupt Controller (NVIC) collects up to 240 interrupt request, sources and provides an interface to the Cortex-M7 core.

NVIC中文名称为可嵌套向量中断控制器:

  1. 可嵌套:当处理器在处理一个中断时,若此时有另外一个优先级更高的中断到来,这个优先级更高的中断可以打断优先级低的中断。当处理器处理完优先级高的中断后,回重新回来处理刚刚没处理完的低优先级中断。

  2. 向量:向量和非向量的区别在于:

    • 向量中断的情况下,每个中断源会有特定地址的函数入口,当一个中断触发了,硬件会自动跳转到相应的中断函数。
    • 非向量中断的情况下,CPU要在收到中断信号后,自己去读取所有的中断标志位,自己去判断当前是哪个中断源发出的中断后,再去做相应的处理。

    可见,中断向量的效率要高很多。

二、相关概念

  • 中断请求,相当于一个信号,比如串口收到数据了,要发送一个中断请求信号告诉CPU,要去中断函数进行相关处理了。
  • 中断号,CPU 通过中断号来区分不同的中断,有点类似于中断的学号,一个号对应一个中断,RT1052 拥有151个中断号。
  • 中断优先级,在RT1052 中每个中断号拥有一个优先级,这个就类似于你在看电视,突然你刚刚烧的水烧开了,本来你想去关煤气,结果女朋友来电话了,先去关煤气,还是先接女朋友电话?这就由优先级去决定了。在Cortex-M里面,中断优先级越小,优先级越高。
  • 中断优先级分组,用来分配抢占优先级和子优先级的位数。
  • 中断服务函数,最终我们要把我们处理这个中断信号的过程写进这个函数内。

三、中断库

1、库函数中断操作的库函数

2、中断号

在MIMXRT1052.h文件中有详细定义。在这里插入图片描述

3、中断服务函数名称

在startup_MIMXRT1052.s启动文件内有详细定义。

/* eg: void SysTick_Handler(void) */
void xxx_Handler(void)
{
	/* add your code here */
}

在这里插入图片描述

4、中断优先级分组

在这里插入图片描述

三、中断系统初始化实例

/* 步骤一:设置中断优先级分组*/
Set_NVIC_PriorityGroup(Group_4);  // 只有Group_4 - Gruop_7

/* 步骤二:设置中断优先级*/
/* 获取在Group4的情况下,主优先级为0,子优先级
为0的32位编码保存到priority_code,下一步要使用  */
uint32_t priority_code = NVIC_EncodePriority (Group_4, 0, 0);  

/* 传入中断号和上一步的priority_code */
NVIC_SetPriority(GPIO5_Combined_0_15_IRQn, priority_code);

/* 步骤三:使能中断 */
NVIC_EnableIRQ(GPIO5_Combined_0_15_IRQn);

/* 步骤四:撰写中断函数 */
void GPIO5_Combined_0_15_IRQHandler(void)
{
	/* 注意,在中断函数内,还需要将中断标志位
	清除,否则中断会一直产生,导致CPU卡死 */
	/* your code here */
}

注意,我们上面一番折腾只是打开了CPU的中断处理,但是触发中断的信号有可能还有另外在去打开,比如GPIO的上升沿触发中断或者下降沿触发中断,这就需要再去配置GPIO,以使GPIO在恰当的时候发出信号告诉CPU该去中断里面处理了。

四、参考文献

1、[野火]《i.MX RT库开发实战指南》.pdf
2、IMXRT1052RM.pdf

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以按照以下步骤实现STM32F103利用rt-thread外部中断接收nrf24l01的数据: 1. 首先,需要配置nrf24l01的SPI接口,并初始化nrf24l01的寄存器。 2. 配置外部中断,使其对应nrf24l01的IRQ引脚。在中断服务函数中,读取nrf24l01的状态寄存器,判断是否有数据接收完成。 3. 如果有数据接收完成,从nrf24l01的接收缓冲区中读取数据,并将数据传递给rt-thread的消息队列。 4. 在rt-thread的线程中,从消息队列中读取数据,并进行处理。 以下是一个简单的示例代码: ``` #include "rtthread.h" #include "drv_spi.h" #include "drv_nrf24l01.h" #define NRF24L01_IRQ_PIN GPIO_PIN_0 #define NRF24L01_IRQ_PORT GPIOA static rt_mq_t nrf24l01_mq; void nrf24l01_irq_handler(void) { if (nrf24l01_rx_data_ready()) { uint8_t data[32]; nrf24l01_read_rx_payload(data, sizeof(data)); rt_mq_send(&nrf24l01_mq, data, sizeof(data)); } } void nrf24l01_thread_entry(void* parameter) { rt_uint8_t data[32]; while (1) { rt_err_t result = rt_mq_recv(&nrf24l01_mq, data, sizeof(data), RT_WAITING_FOREVER); if (result == RT_EOK) { // 处理接收到的数据 } } } static void nrf24l01_init(void) { // 配置SPI接口 spi_init(); // 初始化nrf24l01寄存器 nrf24l01_init(); // 配置外部中断 GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Pin = NRF24L01_IRQ_PIN; GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(NRF24L01_IRQ_PORT, &GPIO_InitStruct); // 配置中断服务函数 HAL_NVIC_SetPriority(EXTI0_IRQn, 5, 0); HAL_NVIC_EnableIRQ(EXTI0_IRQn); // 创建消息队列 rt_mq_init(&nrf24l01_mq, "nrf24l01_mq", data, sizeof(data), 32, RT_IPC_FLAG_FIFO); } int rt_application_init(void) { // 创建nrf24l01线程 rt_thread_t nrf24l01_thread = rt_thread_create("nrf24l01", nrf24l01_thread_entry, RT_NULL, 1024, 25, 10); if (nrf24l01_thread != RT_NULL) { rt_thread_startup(nrf24l01_thread); } // 初始化nrf24l01 nrf24l01_init(); return 0; } ``` 在上面的代码中,nrf24l01_irq_handler()函数是中断服务函数,会在nrf24l01的IRQ引脚触发外部中断时被调用。在该函数中,读取nrf24l01的状态寄存器,判断是否有数据接收完成,如果有,则从nrf24l01的接收缓冲区中读取数据,并将数据传递给rt-thread的消息队列。 nrf24l01_thread_entry()函数是rt-thread的线程函数,会从消息队列中读取数据,并进行处理。在该函数中,调用rt_mq_recv()函数从消息队列中读取数据。如果读取成功,则可以对接收到的数据进行处理。 在rt_application_init()函数中,创建nrf24l01线程,并初始化nrf24l01。在初始化nrf24l01时,会配置nrf24l01的SPI接口,并初始化nrf24l01的寄存器。同时,会配置外部中断,使其对应nrf24l01的IRQ引脚。创建消息队列时,需要指定消息队列的名称、消息缓冲区、消息长度和消息数量等参数。 如果需要发送数据,可以调用nrf24l01_write_tx_payload()函数将数据写入nrf24l01的发送缓冲区,然后调用nrf24l01_transmit()函数启动发送过程。发送完成后,会触发中断,可以在中断服务函数中处理发送完成的事件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值