为什么我Systick中断打开之后主程序就跑飞了

为什么我Systick中断打开之后主程序就跑飞了,第1张

第一步,将一个I/O口配置成中断输入模式。

这里需要注意的是,GPIO本身是没有中断功能神马的。如果硬要使他产生中断输入方式,就得将相应的端口映射到相应的外部事件上去。而其他外设是有中断功能的,直接使能/失能其中断即可,比如USART,直接开启其发送/接收中断,那么USART也就相应的采取中断方式进行工作了。

而这一点,是我开始很疑惑的:为啥GPIO口使用中断方式进行工作的时候就必须要映射到外部事件上去,而其他就不呢?百度网友的解惑是:比如USART产生的中断,是没有经过EXTI,而是直接将中断放入了NVIC;但是GPIO它作为中断源,是要经过EXTI的。仔细参看下面两个图,其实就会恍然大悟:

这第一步就是作为输入中断源的I/O口的相关配置,例程库函数如下:

1 void BUTTON_Configuration(void)

2 {

3 GPIO_InitTypeDefGPIO_InitStructure

4 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU

5 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 GPIO_Pin_12

6 GPIO_Init(GPIOD, GPIO_InitStructure)

7

8 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD RCC_APB2Periph_AFIO,ENABLE)

9 GPIO_EXTILineConfig(GPIO_PortSourceGPIOD , GPIO_PinSource11)

10 GPIO_EXTILineConfig(GPIO_PortSourceGPIOD , GPIO_PinSource12)

11 }

因为我板子上的例程是按键输入中断,所以函数名字就写的按键配置吧;

3~5行,就是gpio口的普通配置,学习单片机开天辟地,就先是gpio口,这个没啥稀奇的了,没啥可说的了;我的板子上是PD^11,PD^12两个端口作为中断输入的。

8行,注意这个时候,要使能GPIO口的复用时钟功能。

9~10行,就是将PD^11,PD^12映射到外部事件线上去。在keil中跳转到其函数实现中:

1 void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource)

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_PortSource) (0x04 * (GPIO_PinSource (uint8_t)0x03)))

11 }

5~6行,用库函数的都知道,就是两个宏定义,起到的作用是对相关的数据神马的进行正确性检查。

8行,GPIO_PinSource这个是外面BUTTON_Configuration()调用GPIO_EXTILineConfig()时传的参数。可能都不知道8行这个式子为啥要这么写。先看看我例程中是如何传的参:

GPIO_EXTILineConfig(GPIO_PortSourceGPIOD , GPIO_PinSource11)

也即是GPIO_PinSource ==GPIO_PinSource11;那么GPIO_PinSource11是个什么东西呢:官方库已经这样定义了:

define GPIO_PinSource11 ((uint8_t)0x0B)

如果按照我的例程,8行这个式子中,tmp == 0x0F (0x04 *(0x0B 0x03)==tmp = 0x0F000先不管这个数字是个啥意思,反正它就是个数字,它其实是为了第9行寄存器的值服务的--既然如此,如果用寄存器写的话,我可以直接给寄存器某个值,何必要山路十八弯呢?当然,库函数,是有通用性的,就像一个数学公式的作用。

9行:AFIO_EXTICR:外部事件控制配置寄存器。在数据手册中显示,有4个,它们分别对应的是各个外部事件exit_xx = 0~15。每个寄存器对应4个外部事件,于是4x4 = 16。,注意数据手册中的编号是从1开始的,而不是0开始的;但是,MDK中是0~3的。于是这里把相关值带进来一看,第九行其实就变成了如下式子:

AFIO-EXTICR[GPIO_PinSource 0x02] = ~tmp

AFIO-EXTICR[2] = ~0xF000==AFIO-EXTICR[2] = 0x0FFF

什么意思?不就是将这个寄存器的第12~15清零吗?不就是将数据手册中第AFIO_EXTICR3寄存器的12~15清零么?再次注意:该寄存器在MDK中是0~3的,数据手册中的编号是从1开始的,而不是0开始的;

这个样,9行以前的一切的 *** 作,就是为了给该寄存器的某个位进行清零嘛,至于具体清哪一位,还得看你映射到哪一位。

10行:引脚选择了,现在就选择这个引脚是哪个端口的,我的是D端口,那么按照官方对D端口的定义如下:

define GPIO_PortSourceGPIOD ((uint8_t)0x03)

AFIO-EXTICR[2] = 0x03 12查看数据手册,恰好是设置成了D口的第11号端子上嘛。

于是第一步总结是:

1.配置对应IO口为上(下)拉输入

3 GPIO_InitTypeDefGPIO_InitStructure

4 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU

5 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 GPIO_Pin_12

6 GPIO_Init(GPIOD, GPIO_InitStructure)

2.使能相应IO端口和端口复用时钟

8 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD RCC_APB2Periph_AFIO,ENABLE)

3.外部事件寄存器相关位清零;

8 tmp = ((uint32_t)0x0F) (0x04 * (GPIO_PinSource (uint8_t)0x03))

9 AFIO-EXTICR[GPIO_PinSource 0x02] = ~tmp

4.设置输入端子、端口编号

10 AFIO-EXTICR[GPIO_PinSource 0x02] = (((uint32_t)GPIO_PortSource) (0x04 * (GPIO_PinSource (uint8_t)0x03)))

步骤3-4:(库函数)

9 GPIO_EXTILineConfig(GPIO_PortSourceGPIOD , GPIO_PinSource11)

10 GPIO_EXTILineConfig(GPIO_PortSourceGPIOD , GPIO_PinSource12)

注:一共有A~G个端口嘛,而每个端口上又有N多端子,这个参看GPIo那章数据手册。

悟出:库函数确实方便,具有公式效应,但山路十八弯,在这里,该例程中,要实现该功能,用寄存器,就两条语句嘛:

1 AFIO-EXTICR[2] = 0x0FFF

2 AFIO-EXTICR[2] = 0x03 12

1行:12~15清零

2行:0x03:表示是PD端口 0x03 12:表示在AFIO_EXTICR寄存器中的第12位开始写入0x03这个值,而括号中的2,说明是第三个寄存器,这样一组合,恰好就是PD^11了.描述起来一长串,如果看对照个看数据手册的话,就一目了然了。而这里唯一会让人凌乱的是:这个寄存器在数据手册上的编号和MDK中的编号不一致。自己在细读了stm32不完全手册才发现这个问题,开始可是百思不得其解呀。

单片机程序运行的原理是通过寄存器状态的设置来控制单片机内部以及端口的各个管脚的逻辑状态,来实现预期逻辑功能的目的。

而这所有的功能是通过逻辑单元的0-1电平来实现的,这些逻辑可能被外界的电磁干扰或者内部本身逻辑结构的问题,使得出现了一个不可控的逻辑状态,这是单片机会出现很多预料之外的状态,这是我们就说单片机”跑飞了“。

而防止这种状态的出现就是加入“看门狗”机制,也就是说,单片机在运行中,我使用一个定时器,定时器不断的递增,如果程序运行正常,我会在一段时间内(定时器溢出之前)将其清空,也就是说,只要程序运行正常,这个定时器永远也不会溢出。但,如果程序跑飞了,进入了不可控的状态,则程序不会运行到清空定时器这个命令上来,这是,我强行将单片机重启,使单片机恢复初始状态

对的

void main()

{

初始化

while(1)

{

主循环

}

跑飞会死机,控制错误等。可以开启看门狗,确保程序不跑飞

}


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/11967524.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-20
下一篇 2023-05-20

发表评论

登录后才能评论

评论列表(0条)

保存