stm32 之 中断按键初始化(注意事项)

stm32 之 中断按键初始化(注意事项)
stm32 之 中断按键初始化(注意事项)

stm32 之中断按键初始化(注意事项)

之前做终端按键的时候都是只做了一个,没有做多个,昨天在把所有按键都设置成中断模式的时候遇到问题,于是乎还跟一个网上的哥们进行了热议,后来还是我发现了问题!最终把问题给解决了!

我的按键的GPIO连接有点奇葩,他不是连续的,这可能就是竞赛板故意设置的难度吧!首先管脚初始化:

[cpp]view plaincopyprint?

1. GPIO_InitTypeDef key;

2.

3. RCC->APB2ENR |= ((1<<0)|(1<<2)|(1<<3));

4.

5. key.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_8;

6. key.GPIO_Mode = GPIO_Mode_IPD;

7. GPIO_Init(GPIOA, &key);

8.

9. key.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2;

10. key.GPIO_Mode = GPIO_Mode_IPD;

11. GPIO_Init(GPIOB, &key);

全部设置成输入模式,AFIO再时钟使能的时候不要忘记了!这里我就不多说了!然后就是中断组设置:NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC初始化:

[cpp]view plaincopyprint?

1. key_nvic.NVIC_IRQChannel = EXTI0_IRQn;

2. key_nvic.NVIC_IRQChannelCmd = ENABLE;

3. key_nvic.NVIC_IRQChannelPreemptionPriority = 0;

4. key_nvic.NVIC_IRQChannelSubPriority = 1;

5. NVIC_Init(&key_nvic);

重点都不在这,值得注意的是下面:

我第一次在配置EXTI Line的时候这样配置!

GPIO_EXTILineConfig(GPIO_PortSourceGPIOA|GPIO_PortSourceGPIOB,\ GPIO_PinSource0|GPIO_PinSource1|GPIO_PinSource2|GPIO_PinSource8); 大致一看,貌似很正常啊!但是问题就出在这!

我们跳转到GPIO_PinSourcex和GPIO_PortSourceGPIOx哪里看看:

[cpp]view plaincopyprint?

1. #define GPIO_PortSourceGPIOA ((uint8_t)0x00)

2. #define GPIO_PortSourceGPIOB ((uint8_t)0x01)

3. #define GPIO_PortSourceGPIOC ((uint8_t)0x02)

4. #define GPIO_PortSourceGPIOD ((uint8_t)0x03)

5. #define GPIO_PortSourceGPIOE ((uint8_t)0x04)

6. #define GPIO_PortSourceGPIOF ((uint8_t)0x05)

7. #define GPIO_PortSourceGPIOG ((uint8_t)0x06)

[cpp]view plaincopyprint?

1. #define GPIO_PinSource0 ((uint8_t)0x00)

2. #define GPIO_PinSource1 ((uint8_t)0x01)

3. #define GPIO_PinSource2 ((uint8_t)0x02)

4. #define GPIO_PinSource3 ((uint8_t)0x03)

5. #define GPIO_PinSource4 ((uint8_t)0x04)

6. #define GPIO_PinSource5 ((uint8_t)0x05)

7. #define GPIO_PinSource6 ((uint8_t)0x06)

8. #define GPIO_PinSource7 ((uint8_t)0x07)

9. #define GPIO_PinSource8 ((uint8_t)0x08)

10. #define GPIO_PinSource9 ((uint8_t)0x09)

11. #define GPIO_PinSource10 ((uint8_t)0x0A)

12. #define GPIO_PinSource11 ((uint8_t)0x0B)

13. #define GPIO_PinSource12 ((uint8_t)0x0C)

14. #define GPIO_PinSource13 ((uint8_t)0x0D)

15. #define GPIO_PinSource14 ((uint8_t)0x0E)

16. #define GPIO_PinSource15 ((uint8_t)0x0F)

我们来计算下:

GPIO_PortSourceGPIOA | GPIO_PortSourceGPIOB = 0x00 | 0x01 = 0x01 =

GPIO_PortSourceGPIOB

GPIO_PinSource0 | GPIO_PinSource1 | GPIO_PinSource2 | GPIO_PinSource8 = 0x00 | 0x01 | 0x02 | 0x08 = 0x0b = GPIO_PinSource11

所以我最后初始化后的中断就成

为:GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource11);

最终让我事与愿违了。发现这个问题后,我仔细研究了一下GPIO_EXTILineConfig函数[cpp]view plaincopyprint?

1. void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSo

urce)

2. {

3. uint32_t tmp = 0x00;

4. /* Check the parameters */

5. assert_param(IS_GPIO_EXTI_PORT_SOURCE(GPIO_PortSource));

6. assert_param(IS_GPIO_PIN_SOURCE(GPIO_PinSource));

7.

8. tmp = ((uint32_t)0x0F) << (0x04 * (GPIO_PinSource & (uint8_t)0x03));

9. AFIO->EXTICR[GPIO_PinSource >> 0x02] &= ~tmp;

10. AFIO->EXTICR[GPIO_PinSource >> 0x02] |= (((uint32_t)GPIO_PortSourc

e) << (0x04 * (GPIO_PinSource & (uint8_t)0x03)));

11. }

明白了,没有什么好纠结的了!

最后,我就感叹,他这个中断函数写的一点都不灵活!我还是喜欢我写的这个,详情看前面中断按键!

[cpp]view plaincopyprint?

1. void init_interrupt(u8 group,u8 inter_id,u8 preempting,u8 subpriority)

2. {

3. u32 aircr;

4. u8 ip;

5.

6. /* Set Group :2 */

7. aircr = SCB->AIRCR; //Get AIRCR register

8. aircr &= 0x0000f8ff; //Clear Password & PriGroup

9. aircr |= 0x05fa0000; //Set Password

10. aircr |= ((~group&0x7)<<8); //Set PriGroup Group:2 0000 0010 => 11

11 1101 [5 = 0101b]<<8

11. SCB->AIRCR = aircr; //Set AIRCR

12.

13. /*

14. * Group 2 2:2

15. * 0~3 : 0~3

16. * Set Preempting = 0 Subpriority = 0

17. * 1001 0000b = 0x00;

18. */

19. if(inter_id<32)

20. NVIC->ISER[0] = 1<< inter_id;

21. else

22. NVIC->ISER[1] = 1<<(inter_id-32); //EXIT15_10 vector:37

23. switch(group)

24. {

25. case 0: ip = 0x0f&subpriority;break;

26. case 1: ip = (0x08&preempting) | (0x07&subpriority);break;

27. case 2: ip = (0x0C&preempting) | (0x03&subpriority);break;

28. case 3: ip = (0x0e&preempting) | (0x01&subpriority);break;

29. case 4: ip = 0x0f&preempting;break;

30. default: ip = 0x00;break;

31. }

32. NVIC->IP[inter_id] = 0xf0&(ip<<4);

33. }

不要看我的一些注释,那些注释是给我自己看的!没有什么参考价值!

这个问题搞清楚了,就没有什么容易出错的了,下面是代码:

[cpp]view plaincopyprint?

1. void ITkey_init(void)

2. {

3. EXTI_InitTypeDef key_exti;

4. NVIC_InitTypeDef key_nvic;

5. GPIO_InitTypeDef key;

6.

7. RCC->APB2ENR |= ((1<<0)|(1<<2)|(1<<3));

8.

9. key.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_8;

10. key.GPIO_Mode = GPIO_Mode_IPD;

11. GPIO_Init(GPIOA, &key);

12.

13. key.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2;

14. key.GPIO_Mode = GPIO_Mode_IPD;

15. GPIO_Init(GPIOB, &key);

16.

17.

18. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

19.

20. key_nvic.NVIC_IRQChannel = EXTI0_IRQn;

21. key_nvic.NVIC_IRQChannelCmd = ENABLE;

22. key_nvic.NVIC_IRQChannelPreemptionPriority = 0;

23. key_nvic.NVIC_IRQChannelSubPriority = 1;

24. NVIC_Init(&key_nvic);

25. GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);

26. key_exti.EXTI_Line = EXTI_Line0;

27. key_exti.EXTI_LineCmd = ENABLE;

28. key_exti.EXTI_Mode = EXTI_Mode_Interrupt;

29. key_exti.EXTI_Trigger = EXTI_Trigger_Rising;

30. EXTI_Init(&key_exti);

31.

32.

33. key_nvic.NVIC_IRQChannel = EXTI9_5_IRQn;

34. NVIC_Init(&key_nvic);

35. GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource8);

36. key_exti.EXTI_Line = EXTI_Line8;

37. EXTI_Init(&key_exti);

38.

39. key_nvic.NVIC_IRQChannel = EXTI1_IRQn;

40. NVIC_Init(&key_nvic);

41. GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource1);

42. key_exti.EXTI_Line = EXTI_Line1;

43. EXTI_Init(&key_exti);

44.

45. key_nvic.NVIC_IRQChannel = EXTI2_IRQn;

46. NVIC_Init(&key_nvic);

47. GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource2);

48. key_exti.EXTI_Line = EXTI_Line2;

49. EXTI_Init(&key_exti);

50.

51. }

相关主题
相关文档
最新文档