历史上的今天
返回首页

历史上的今天

今天是:2025年03月03日(星期一)

正在发生

2020年03月03日 | 【STM库应用】stm32 之 中断按键初始化(注意事项)

2020-03-03 来源:eefocus

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

我的按键的GPIO连接有点奇葩,他不是连续的,这可能就是竞赛板故意设置的难度吧!


首先管脚初始化:


GPIO_InitTypeDef key;

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

key.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_8;       

  key.GPIO_Mode = GPIO_Mode_IPD;

  GPIO_Init(GPIOA, &key);

key.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2;

  key.GPIO_Mode = GPIO_Mode_IPD;

  GPIO_Init(GPIOB, &key);


全部设置成输入模式,AFIO再时钟使能的时候不要忘记了!这里我就不多说了!

然后就是中断组设置: NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);


NVIC初始化:


key_nvic.NVIC_IRQChannel = EXTI0_IRQn;

key_nvic.NVIC_IRQChannelCmd = ENABLE;

key_nvic.NVIC_IRQChannelPreemptionPriority = 0;

key_nvic.NVIC_IRQChannelSubPriority = 1;

NVIC_Init(&key_nvic);


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

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


GPIO_EXTILineConfig(GPIO_PortSourceGPIOA|GPIO_PortSourceGPIOB,


GPIO_PinSource0|GPIO_PinSource1|GPIO_PinSource2|GPIO_PinSource8);


大致一看,貌似很正常啊!但是问题就出在这!


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


#define GPIO_PortSourceGPIOA       ((uint8_t)0x00)

#define GPIO_PortSourceGPIOB       ((uint8_t)0x01)

#define GPIO_PortSourceGPIOC       ((uint8_t)0x02)

#define GPIO_PortSourceGPIOD       ((uint8_t)0x03)

#define GPIO_PortSourceGPIOE       ((uint8_t)0x04)

#define GPIO_PortSourceGPIOF       ((uint8_t)0x05)

#define GPIO_PortSourceGPIOG       ((uint8_t)0x06)


#define GPIO_PinSource0            ((uint8_t)0x00)

#define GPIO_PinSource1            ((uint8_t)0x01)

#define GPIO_PinSource2            ((uint8_t)0x02)

#define GPIO_PinSource3            ((uint8_t)0x03)

#define GPIO_PinSource4            ((uint8_t)0x04)

#define GPIO_PinSource5            ((uint8_t)0x05)

#define GPIO_PinSource6            ((uint8_t)0x06)

#define GPIO_PinSource7            ((uint8_t)0x07)

#define GPIO_PinSource8            ((uint8_t)0x08)

#define GPIO_PinSource9            ((uint8_t)0x09)

#define GPIO_PinSource10           ((uint8_t)0x0A)

#define GPIO_PinSource11           ((uint8_t)0x0B)

#define GPIO_PinSource12           ((uint8_t)0x0C)

#define GPIO_PinSource13           ((uint8_t)0x0D)

#define GPIO_PinSource14           ((uint8_t)0x0E)

#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函数


void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource)

{

  uint32_t tmp = 0x00;

  /* Check the parameters */

  assert_param(IS_GPIO_EXTI_PORT_SOURCE(GPIO_PortSource));

  assert_param(IS_GPIO_PIN_SOURCE(GPIO_PinSource));

  

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

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

  AFIO->EXTICR[GPIO_PinSource >> 0x02] |= (((uint32_t)GPIO_PortSource) << (0x04 * (GPIO_PinSource & (uint8_t)0x03)));

}


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

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


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

{

u32 aircr;

u8  ip;

/* Set Group :2 */

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

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

aircr |= 0x05fa0000; //Set Password

aircr |= ((~group&0x7)<<8); //Set PriGroup Group:2 0000 0010 => 1111 1101 [5 = 0101b]<<8

SCB->AIRCR = aircr; //Set AIRCR

/* 

* Group 2  2:2

* 0~3 : 0~3

* Set Preempting = 0  Subpriority = 0

* 1001 0000b = 0x00;

*/

if(inter_id<32)

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

else

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

switch(group)

{

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

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

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

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

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

default: ip = 0x00;break;

}

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

}

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

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


void ITkey_init(void)

{

EXTI_InitTypeDef key_exti;

NVIC_InitTypeDef key_nvic;

GPIO_InitTypeDef key;

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

key.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_8;       

  key.GPIO_Mode = GPIO_Mode_IPD;

  GPIO_Init(GPIOA, &key);

key.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2;

  key.GPIO_Mode = GPIO_Mode_IPD;

  GPIO_Init(GPIOB, &key);

 

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

 

key_nvic.NVIC_IRQChannel = EXTI0_IRQn;

key_nvic.NVIC_IRQChannelCmd = ENABLE;

key_nvic.NVIC_IRQChannelPreemptionPriority = 0;

key_nvic.NVIC_IRQChannelSubPriority = 1;

NVIC_Init(&key_nvic);

GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);

key_exti.EXTI_Line = EXTI_Line0;

key_exti.EXTI_LineCmd = ENABLE;

key_exti.EXTI_Mode = EXTI_Mode_Interrupt;

key_exti.EXTI_Trigger = EXTI_Trigger_Rising;

EXTI_Init(&key_exti);

key_nvic.NVIC_IRQChannel = EXTI9_5_IRQn;

NVIC_Init(&key_nvic);

GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource8);

key_exti.EXTI_Line = EXTI_Line8;

EXTI_Init(&key_exti);

 

key_nvic.NVIC_IRQChannel = EXTI1_IRQn;

NVIC_Init(&key_nvic);

GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource1);

key_exti.EXTI_Line = EXTI_Line1;

EXTI_Init(&key_exti);

key_nvic.NVIC_IRQChannel = EXTI2_IRQn;

NVIC_Init(&key_nvic);

GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource2);

key_exti.EXTI_Line = EXTI_Line2;

EXTI_Init(&key_exti);

 

}

推荐阅读

史海拾趣

Cal Test Electronics公司的发展小趣事

随着客户需求的多样化,Cal Test Electronics开始关注小批量定制型测试电缆组件的市场。公司利用自身的技术优势和生产能力,为客户提供个性化的定制服务。这些定制产品不仅满足了客户的特殊需求,也提高了公司的市场竞争力。通过这一策略,Cal Test Electronics成功打开了一个全新的市场领域,为公司的发展注入了新的动力。

Bel Power Solutions公司的发展小趣事

随着全球环保意识的日益增强,Bel Power Solutions积极响应号召,将环保理念融入产品设计和生产中。公司推出了多款环保型电源产品,如高效能、低能耗的DC-DC转换器和电源供应器,帮助客户降低能耗、减少碳排放。同时,公司还致力于研发和推广可再生能源应用技术,为可持续发展做出贡献。

Greenconn Corp公司的发展小趣事
避免将过多食物一次性放入冰箱,以减少冰箱电机的负荷。
德丰(DEFOND)公司的发展小趣事

德丰金属材料有限公司(简称“德丰金属”)是一家专业从事铝合金建筑型材加工的企业。随着市场竞争的加剧和环保要求的提高,公司意识到必须加快转型升级的步伐。为此,德丰金属加大了研发投入和技术改造力度,成功开发出了一系列符合绿色环保标准的新型铝合金型材产品。同时,公司还积极拓展国际市场,与多家国外知名企业建立了长期稳定的合作关系。通过不断的努力和创新,德丰金属成功实现了从传统制造业向绿色环保型制造业的转型升级。

AdaptivEnergy公司的发展小趣事

德丰电创科技股份有限公司(简称“德丰电创”)自1984年成立以来,从一个东莞的洪梅电器厂逐步发展为一家专业从事开关制造到电子电路模块、机电一体化集成模组等多元化产品的大型港资实业公司。公司凭借多年的产品研发和高端制造经验,以及完善的供应链管理体系,成功在家用电器、电动工具、汽车等多个市场领域占据一席之地。德丰电创的发展历程充满了不断的技术创新和市场扩张,其产品质量和服务得到了全球客户的广泛认可。

安国国际(ALCOR)公司的发展小趣事

随着公司规模的扩大和业绩的增长,安国国际的产品线逐渐从计算机外设产品拓展至消费型电子产品和手持便携装置。为满足市场需求,公司不断推出创新产品,如输出入装置暨多媒体图像处理装置应用控制芯片、网桥控制芯片、网络安全保护装置等。同时,为提升运营效率和灵活性,安国在2015年进行了组织调整和专业分工,将不同业务线分割为多家子公司,使得各业务领域能够更加专注和高效地发展。

问答坊 | AI 解惑

想了解海尔单片机的请进

海尔单片机海尔单片机在华南区代理商,专门为客户开发设计各种单片机应用程序和电路板,目前拥有多种家电、工控、仪表成熟方案,欢迎广大用户合作。    开发过的大小家电类产品:电热水器、蒸汽清洁机、空调机控制板、洗衣机控制板、汽车 ...…

查看全部问答>

怎样写testbench(xilinx的)文章共享

怎样写testbench的资料贡献给大家!…

查看全部问答>

剖析切換式電源供應器的原理及常用元件規格

由於大部分電子器材(如電視機、音響、電腦…等)其內部元件所使用的電源均為直流電,故必須有電源供應器(或整流器)來把交流市電轉換成各種不同的直流電壓以使電器發揮功能。依其電路結構的不同,電源供應器可分為線性式和切換式電源供應器兩種, ...…

查看全部问答>

求助:一道Intel笔试题

题目:给出至少两种方法实现存储器管理,比如虚存。 题目中提到了虚存,那么答案应该不能再列举它。…

查看全部问答>

MSP430 的IO端口详细介绍。新手学习贴

       MSP430的端口有P1、P2、P3、P4、P5、P6、S和COM(型号不同,包含的端口也不仅相同,如MSP430X11X系列只有P1,P2端口,而MSP430X4XX系列则包含全部上述端口),它们都可以直接用于输入/输出。MSP430系统中没 ...…

查看全部问答>

有谁用过r8c/38a? (瑞萨单片机)

有谁用过r8c/38a?(瑞萨单片机)…

查看全部问答>