发 帖  
原厂入驻New

[经验] ARM的外部中断配置

2020-8-31 08:22:53  212 外部中断 ARM
分享
0
很多情况下,要实现一个嵌入式程序,用到某一功能或者某一个硬件资源时,我经常拿厂家或者是其他人给提供的代码,参考其中的配置代码段部分,只去修改实现成我需要的功能就好。相信大家也和我有相似的经历吧!?从工程的角度来说,这没问题。但是理论上总感觉少了点什么,今天以外部中断的寄存器配置为例,进一步讲解中断源是如何进入CPU中,CPU又如何处理中断信号的,这一过程。单纯学术的角度,具体涉及到哪些寄存器、填写什么值,就不细述了。这里用的单片机是FS4412多核ARM芯片
中断的实现过程(程序的角度)
中断发生后,硬件自动跳转到异常向量表中对应异常类型的位置,然后进行处理。处理过程,先进行现场保护(数据进栈操作),然后根据处理中断函数,根据中断号进行特定的中断处理,等中断程序处理完后,还要恢复中断前的现场(数据出栈操作)。
1.png
对中断源的处理过程(硬件的角度)这个过程涉及到我们要讲的中断初始化配置,从图中可以看到,一个外部中断信号需要经过这么多步骤才能到达ARM内核。

首先,外部中断信号需经过GPIO管脚进入CPU内部,然后再内部经使能-->分发-->分发使能-->cpu接口-->接口使能和优先级-->ARM内核  过五关 斩六将 终于到达ARM内核,然后产生中断标志位,再执行之前讲到的中断实现(程序实现)。
2.png
中断初始化配置单片机有内置外设,GPIO属于外围功能模块,中断控制器GIC属于内部外设。由于中断源从IO口进入到中断控制器GIC,才能进入ARM内核。我们需要同时配置这两块资源。
  1. #define  GPX1CON        (*(volatile unsigned int *)0x11000c20)
  2. #define  EXT_INT41CON   (*(volatile  int *)0x11000E04)
  3. #define  EXT_INT41_MASK (*(volatile  int *)0x11000F04)
  4. #define ICDISER1_CPU0  (*(volatile  int *)0x10490104)
  5. #define ICDIPTR14_CPU0 (*(volatile  int *)0x10490838)
  6. #define ICDDCR (*(volatile  int *)0x10490000)
  7. #define ICCICR_CPU0  (*(volatile  int *)0x10480000)
  8. #define ICCPMR_CPU0  (*(volatile  int *)0x10480004)
  9. #define EXT_INT41_PEND (*(volatile  int *)0x11000f44)
  10. #define ICCIAR_CPU0  (*(volatile  int *)0x1048000C)
  11. #define ICCEOIR_CPU0 (*(volatile  int *)0x10480010)
  12. #define ICDICPR1_CPU0 (*(volatile  int *)0x10490284)



  13. void interrupt_init(void)
  14. {
  15.         //-----外: 配置管脚的工作模式
  16.         GPX1CON = (GPX1CON & ~(0xF<<4))|(0xF<<4);  //配置 GPX1_1为中断模式
  17.        
  18.         EXT_INT41CON = (EXT_INT41CON & ~(0x7<<4))|(0x2<<4);  //设置GPX1_1的触发方式为 下降沿触

  19.         EXT_INT41_MASK = EXT_INT41_MASK & (~0x02);                //GPX1_1 中断使能

  20.        
  21.        
  22.         //-----内: 功能块设置
  23.         ICDISER1_CPU0 = ICDISER1_CPU0 | (1<<25);        //EINT9 (GPX1_1)  GIC中断使能
  24.         ICDIPTR14_CPU0 = 0x01010101;   //参考例子背景,用默认设置
  25.         ICDDCR = ICDDCR|1; //GIC 分发总使能
  26.         ICCICR_CPU0 = 1;  // CPU0  中断使能
  27.         ICCPMR_CPU0 = 0XFF;   //设置CPU0的优先级门槛为最低

  28. }
复制代码
注:外部中断配置过程:
  1. 1配置中断

  2. 1、  分配中断向量表:

  3. /* Set the Vector Table base location at 0x20000000 */

  4. NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);

  5. 2、  设置中断优先级:

  6. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);  //设置中断优先级

  7. 3、  初始化外部中断:

  8. /*允许EXTI4中断 */

  9.        NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQChannel; //中断通道

  10.        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = PreemptionPriorityValue;//强占优先级

  11.        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  //次优先级

  12.        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //通道中断使能

  13.        NVIC_Init(&NVIC_InitStructure);       //初始化中断

  14. 注意:如果我们配置的外部针脚为PA4,或PB4,或PC4,PD4等,那么采用的外部中断也必须是EXTI4,同样,如果外部中断针脚是PA1,PB1,PC1,PD1 那么中断就要用EXTI1,其他类推。



  15. 2配置GPIO针脚作为外部中断的触发事件

  16. 1、  选择IO针脚

  17. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;

  18. 注意,如果的针脚是端口的4号针脚,配置的中断一定是EXTI4

  19. 2、  配置针脚为输入

  20. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

  21. 3、  初始化针脚

  22. GPIO_Init(GPIOD,&GPIO_InitStructure);





  23. 3配置EXTI线,使中断线和IO针脚线连接上

  24. 1、  将EXTI线连接到IO端口上

  25. 将EXTI线4连接到端口GPIOD的第4个针脚上

  26.        GPIO_EXTILineConfig(GPIO_PortSourceGPIOD,GPIO_PinSource4);

  27.        注意:如果配置的针脚是4号,那么参数必须是GPIO_PinSource4

  28.               如果配置的针脚是3号,那么参数必须是GPIO_PinSource3

  29. 2、配置中断边沿

  30.        /*配置EXTI线0上出现下降沿,则产生中断*/

  31.        EXTI_InitStructure.EXTI_Line = EXTI_Line4;

  32.        注意:如果配置的4号针脚,那么EXTI_Line4是必须的

  33.        EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;

  34.        EXTI_InitStructure.EXTI_trigger = EXTI_Trigger_Falling;  //下降沿触发

  35.        EXTI_InitStructure.EXTI_LineCmd = ENABLE;     //中断线使能

  36.        EXTI_Init(&EXTI_InitStructure);                 //初始化中断

  37.        EXTI_GenerateSWInterrupt(EXTI_Line4);         //EXTI_Line4中断允许



  38. 到此中断配置完成,可以写中断处理函数。

  39. 举例:

  40. 配置函数

  41. /*************************************************************************

  42. * 函数名      NVIC_Configration

  43. * 描述          配置各个中断寄存器

  44. * 输入           无

  45. * 输出           无

  46. * 返回值       无

  47. ****************************************************************************/

  48. void NVIC_Configration(void)

  49. {

  50.         NVIC_InitTypeDef NVIC_InitStructure;

  51. //#ifdef  VECT_TAB_RAM

  52.       /* Set the Vector Table base location at 0x20000000 */

  53.       NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);

  54. //#else  /* VECT_TAB_FLASH  */

  55.       /* Set the Vector Table base location at 0x08000000 */

  56.       //NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);  

  57. //#endif  

  58.        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);  //设置中断优先级

  59.        /*允许EXTI4中断 */

  60.        NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQChannel;

  61.        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = PreemptionPriorityValue;

  62.        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

  63.        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  64.        NVIC_Init(&NVIC_InitStructure);      

  65.        /*允许EXTI9中断*/

  66.        NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQChannel;

  67.        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

  68.        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

  69.        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  70.        NVIC_Init(&NVIC_InitStructure);      

  71.        /*配置SysTick处理优先级:优先级以及子优先级*/

  72.       

  73. }



  74. /************************************************************************

  75. * 函数名       :GPIO_Configuration(void)

  76. * 描述           :配置TIM2阵脚

  77. * 输入           :无

  78. * 输出      :无

  79. * 返回           :无

  80. ************************************************************************/

  81. void GPIO_Configuration(void){

  82. /*    GPIO_InitTypeDef GPIO_InitStructure;

  83.        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;

  84.        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

  85.        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  86.        GPIO_Init(GPIOA,&GPIO_InitStructure);  */



  87.        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;

  88.        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

  89.        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;

  90.        GPIO_Init(GPIOC,&GPIO_InitStructure);



  91.        /*配置GPIOD的第一个管角为浮动输入*/

  92.        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;

  93.        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

  94.        GPIO_Init(GPIOD,&GPIO_InitStructure);



  95.        /*配置GPIOB的第9个管脚为浮动输入*/

  96.        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;

  97.        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

  98.        GPIO_Init(GPIOB,&GPIO_InitStructure);

  99. }





  100. /**************************************************************

  101. * 函数           SysTick_Configuration

  102. * 描述          设置SysTick

  103. * 输入           无

  104. * 输出          无

  105. * 返回值      无

  106. ***************************************************************/

  107. void SysTick_Configuration(void)

  108. {

  109.       /*配置 HCLK 时钟做为SysTick 时钟源*/

  110.        SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //系统时钟8分频  72MHz



  111.        NVIC_SystemHandlerPriorityConfig(SystemHandler_SysTick, 8,2);

  112.        /*SysTick Interrupt each 1000Hz with HCLK equal to 72MHz*/

  113.        SysTick_SetReload(9000);//中断周期1ms

  114.        /*Enable the SysTick Interrupt */

  115.        SysTick_ITConfig(ENABLE);//打开中断         

  116.        SysTick_CounterCmd(SysTick_Counter_Enable);

  117.        SysTick_CounterCmd(SysTick_Counter_Clear);               

  118. }





  119. /******************************************************************************

  120. * 函数名       EXTI_Configuration

  121. * 描述           配置EXTI线

  122. * 输入           无

  123. * 输出           无

  124. * 返回值       无

  125. ******************************************************************************/

  126. void EXTI_Configuration(void){



  127.        /*将EXTI线0连接到PA0*/

  128.        GPIO_EXTILineConfig(GPIO_PortSourceGPIOD,GPIO_PinSource4);

  129.        /*配置EXTI线0上出现下降沿,则产生中断*/

  130.        EXTI_InitStructure.EXTI_Line = EXTI_Line4;

  131.        EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;

  132.        EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;

  133.        EXTI_InitStructure.EXTI_LineCmd = ENABLE;

  134.        EXTI_Init(&EXTI_InitStructure);

  135.        EXTI_GenerateSWInterrupt(EXTI_Line4);

  136.       

  137.        /*将EXTI线9连接到PB9上*/

  138.        GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource9);

  139.        /*将EXTI线9上出现下降沿产生中断*/

  140.        EXTI_InitStructure.EXTI_Line = EXTI_Line9;

  141.        EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;

  142.        EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;

  143.        EXTI_InitStructure.EXTI_LineCmd = ENABLE;

  144.        EXTI_Init(&EXTI_InitStructure);

  145.        EXTI_GenerateSWInterrupt(EXTI_Line9);      

  146. }



  147. 中断函数:

  148. void EXTI4_IRQHandler(void)

  149. {

  150.        if(EXTI_GetITStatus(EXTI_Line4)!= RESET){

  151.               EXTI_ClearITPendingBit(EXTI_Line4);

  152.               if(LEDflag == 0){

  153.                      Ledflag = 1;

  154.                      GPIOC->ODR |= 0X00000080;

  155.               }

  156.               else{

  157.                      Ledflag = 0;         

  158.                      GPIOC->ODR &= 0XFFFFFF7F;

  159.               }

  160.        }

  161. }

复制代码


相关经验

评论

高级模式
您需要登录后才可以回帖 登录 | 注册

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。 侵权投诉
发经验
关闭

站长推荐 上一条 /8 下一条

快速回复 返回顶部 返回列表