关于stm32的MY_NVIC_Init()中断管理函数的使用心得!

46 篇文章 1 订阅
38 篇文章 1 订阅

        有次在使用stm32做项目时,遇到要用2个定时器及其中断服务程序的情况。这样就需要使用函数MY_NVIC_Init(NVIC_PreemptioPriority,NVIC_SubPriority,NVIC_Channel,NVIC_Group)对两个中断服务的优先级进行设定了。最开始,这个函数看得我是一头雾水,无从着手,仔细研究了一会才明白该如何使用了。相信很多新手同学会和我有类似的经历吧,为了方便大家的学习和工作,特将此函数在此讲述一番,希望对大家有帮助(注:本文章的作用仅在于使新手学会使用stm32的中断管理函数,不能达到深入理解目的)!

        1、对各个参数的解释:

(1)NVIC_PreemptionPriority:这个参数是用来设定抢占优先级的

(2)NVIC_SubPriority:这个参数是用来设定响应优先级的      

(3)NVIC_Channel:这个参数是用来设定中断编号的(范围是0~59)

(4)NVIC_Group:这个参数是用来设定中断分组的(范围是0~4)

        2、关于NVIC_PreemptionPriority和NVIC_SubPriority的设定范围的说明,参下表:

        看了此图,大概就能明白一个问题,就是NVIC_PreemptionPriority和NVIC_SubPriority的设定是和NVIC_Group

这个参数的值有关的,这也是上文没有给出它们的取值范围的原因。

        举例:若选取组2(即参数NVIC_Group的值为2),那么NVIC_PreemptionPriority和NVIC_SubPriority的范围是多少呢?

        答:从上表横向第4栏可以看出,分配结果为:2 位抢占优先级,2 位响应优先级,故抢占优先级和响应优先级

的范围均为0~3(即二进制的00~11).同理若选取组3,则抢占优先级的范围为0~7(即二进制的000~111),响应优先级的范围为0~1(因为此时响应优先级只占一位,故非0即1).

        3、关于各参数选取的原则及作用:

        看了1和2的叙述后,大家只能知晓各参数的选取范围,从而能有效避免取值时的“越界”现象。下面再讲下取

        值的原则和作用。以中断服务A和中断服务B同时出现在项目里为例:

(1)对于NVIC_Group要注意:在一个工程代码里,所有的中断分组都要一致!即若在A中NVIC_Group

         的值为2,那么在B中NVIC_Group的值也应为2,否则可能发生错误!具体关于NVIC_Group的值的选取也要

         参照上表,由抢占优先级和响应优先级的取值范围要求来定。

(2)对于抢占优先级和响应优先级是值越小则优先级越高!

(3)如果A、B两个中断的抢占优先级和响应优先级取值均一样的话,则看哪个中断先发生就先执行哪个中断服务。

         举例:A_INTERRUPT为MY_NVIC_Init(1, 2, 0, 2);

                    B_INTERRUPT为MY_NVIC_Init(1, 2, 1, 2);

         那么A和B谁先发生,就先执行哪个中断服务。

(4)抢占优先级较高的中断可以打断正在进行的抢占优先级较低的中断服务,但对于抢占优先级相同的中断,较

         高的响应优先级不可以打断正在进行的较低的响应优先级中断。

               举例:A_INTERRUPT为MY_NVIC_Init(1, 2, 0, 2);

                     B_INTERRUPT为MY_NVIC_Init(1, 3, 1, 2);

         若中断服务B正在进行中时,中断服务A也发生了,那么B不会被A打断,因为它们的抢占优先级相同(尽管A的

         响应优先级要比B高)。

       4、结束语:

        到此,关于void MY_NVIC_Init(u8 NVIC_PreemptionPriority,u8 NVIC_SubPriority,u8 NVIC_Channel,u8
NVIC_Group) 函数的使用讲解就结束了。相信你也应该明白该怎么使用该函数了吧!  

 

    

  • 8
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32 中,可以通过 DMA 直接将串口接收到的数据存储到内存中,从而减轻 CPU 的负担。在使用 DMA 接收串口数据时,可以通过 `HAL_UARTEx_RxEventCallback` 函数来处理 DMA 接收数据完成后的回调。 `HAL_UARTEx_RxEventCallback` 的函数原型为: ```c void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart); ``` 其中,`huart` 是串口的句柄指针。 在使用 DMA 接收串口数据时,需要先开启 DMA,然后在回调函数中处理接收到的数据。下面是一个使用 DMA 接收串口数据的例子: ```c #include "stm32f4xx_hal.h" #define UART_RX_BUFFER_SIZE 256 UART_HandleTypeDef huart2; DMA_HandleTypeDef hdma_usart2_rx; uint8_t uart_rx_buffer[UART_RX_BUFFER_SIZE]; void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(uartHandle->Instance==USART2) { /* USART2 clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /**USART2 GPIO Configuration PA2 ------> USART2_TX PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART2; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USART2 DMA Init */ /* USART2_RX Init */ hdma_usart2_rx.Instance = DMA1_Stream5; hdma_usart2_rx.Init.Channel = DMA_CHANNEL_4; hdma_usart2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_usart2_rx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_usart2_rx.Init.MemInc = DMA_MINC_ENABLE; hdma_usart2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_usart2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_usart2_rx.Init.Mode = DMA_CIRCULAR; hdma_usart2_rx.Init.Priority = DMA_PRIORITY_LOW; hdma_usart2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; if (HAL_DMA_Init(&hdma_usart2_rx) != HAL_OK) { Error_Handler(); } __HAL_LINKDMA(uartHandle,hdmarx,hdma_usart2_rx); /* USART2 interrupt Init */ HAL_NVIC_SetPriority(USART2_IRQn, 0, 0); HAL_NVIC_EnableIRQ(USART2_IRQn); } } void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if (huart->Instance == USART2) { // 处理接收到的数据 // ... } } int main(void) { HAL_Init(); __HAL_RCC_GPIOA_CLK_ENABLE(); // 配置串口 huart2.Instance = USART2; huart2.Init.BaudRate = 115200; huart2.Init.WordLength = UART_WORDLENGTH_8B; huart2.Init.StopBits = UART_STOPBITS_1; huart2.Init.Parity = UART_PARITY_NONE; huart2.Init.Mode = UART_MODE_RX; huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart2.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart2) != HAL_OK) { Error_Handler(); } // 配置 DMA 接收 HAL_UART_Receive_DMA(&huart2, uart_rx_buffer, UART_RX_BUFFER_SIZE); while (1); } ``` 在上面的代码中,我们在 `HAL_UART_MspInit` 函数中初始化了 DMA,并将 DMA 和串口绑定起来。在 `main` 函数中,我们使用 `HAL_UART_Receive_DMA` 开启了 DMA 接收并指定了接收缓冲区的地址和大小。当 DMA 接收完成后,会自动触发 `HAL_UART_RxCpltCallback` 回调函数,我们可以在该函数中处理接收到的数据。 需要注意的是,在使用 DMA 接收串口数据时,需要确保接收缓冲区的大小大于等于最大接收数据长度,否则可能会出现数据溢出的情况。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值