内容
1 overview
1.1 目的
2 优化内容
2.1 软件功能
2.2 编程健壮性
3 软件实现
3.1 Coding Rule
3.2 中断基础知识
3.2.1 mc9s12g128的中断向量号
3.2.2 mc9s12g128中断向量表
3.3 driver层
3.3.1 drio_cfg.c
3.3.2 drio_cfg.h
3.3.3 drio.c
3.3.4 drio.h
3.3.5 新建drint.c
3.3.6 新建drint.h
3.4 中间件module层优化
3.4.1 mdio_cfg.h
3.4.2 mdio_cfg.c
3.4.3 mdio.c
3.4.4 mdio.h
3.5 应用层
3.5.1 apl_key.h
3.5.2 apl_key.c
3.6 main.c
3.6.1 main
4 软件测试及调试
4.1 PORTJ验证代码
4.2 MCU register
4.2.1 中断使能寄存器PIEJ
4.2.2 极性选择寄存器PPSJ
4.2.3 中断标志位寄存器PIFJ
5 实物展示
上一期的
MC9S12G128模块化分层化软件架构之六——KEY代码下载地址:
https://download.csdn.net/download/Sure_gengjia/12801323
实物展示:
更多内容,请持续关注公众号:激活未来。
本文档用于起点开发板的外部中断模块软件说明。
不局限于硬件功能的实现,着眼于实现高质量、优美的软件。
① 增加PORTA、PORTB、PORTC、PORTD和PORTAD引脚的相关配置;
② driver层和module层针对新增的PORT进行调整;
① 常量前增加const修饰;
② 仅用于本文件调用的变量和函数前增加static;
具体可在源码的\Sources\code_rules.txt中可见。
见mc9s12g128.h文件的第51行,如下:
每一个中断处理函数都要有一个中断向量号,中断处理函数格式如下:
每个中断发生后,PC都会跳转到对应的地址去取值,然后进入不同的中断处理函数中。
change log:
3.3.1.1 新增drio_enable_interrupt_reg[]中断使能使能寄存器
如下:
在mc9s12g128数据手册中提到:
只有PORTP、PORTJ和PORTAD支持外部中断功能,如下:
注意:由于不是所有的PORT都支持中断,所有在使能中断时不能像其他寄存器一样在drio_enable_interrupt_reg[]中直接用PORT的枚举索引,需要在PORTP的基础上索引中断使能寄存器,如使能PORTJ的PIN3,应写成:
BYTEOP_BIT_SET_AT(*drio_interrupt_flag_reg[DRIO_PORTJ - DRIO_PORTP], DRIO_PIN3);
3.3.1.1.1 PIEP
在MC9S12G128.h中的定义:
在芯片手册中的定义:
3.3.1.1.2 PIEJ
在mc9s12g128.h中的定义:
在datasheet中的定义:
3.3.1.1.3 PIE1AD
在mc9s12g128.h中的定义:
在datasheet中的定义:
3.3.1.1.4 PIE0AD
在mc9s12g128.h中的定义:
在datasheet中的定义:
3.3.1.2 新增drio_interrupt_flag_reg[]中断标志位寄存器
如下:
在mc9s12g128数据手册中提到:
只有PORTP、PORTJ和PORTAD支持外部中断功能。
注意:由于不是所有的PORT都支持中断,所有在查询使能中断时不能像其他寄存器一样在drio_interrupt_flag_reg[]中直接用PORT的枚举索引,需要在PORTP的基础上索引中断使能寄存器,如查询PORTJ的PIN3中断标志位,应写成:
BYTEOP_BIT_READ_AT(*drio_interrupt_flag_reg[DRIO_PORTJ - DRIO_PORTP], DRIO_PIN3);
3.3.1.2.1 PIFP
在mc9s12g128.h中的定义:
在datasheet中的定义:
3.3.1.2.2 PIFJ
在mc9s12g128.h中的定义:
在datasheet中的定义:
3.3.1.2.3 PIF1AD
在mc9s12g128.h中的定义:
在datasheet中的定义:
3.3.1.2.4 PIF0AD
在mc9s12g128.h中的定义:
在datasheet中的定义:
3.3.1.3 新增drio_pins_in_port[]
用于确定每个port有多少个引脚PIN。
3.3.2.1 声明extern
3.3.3.1 修改drio_set_pin_pull()
只有PORTT、PORTS、PORTM、PORTP、PORTJ和PORTAD有上下拉极性选择,所以drio_polarity_select_reg[]中是以PPST开始的寄存器。
3.3.3.2 增加drio_enable_interrupt()
使能中断使能前先清中断标志位。
3.3.3.3 增加drio_set_pin_int_type()
设置中断类型:上升沿中断还是下降沿中断,由于中断方式选择和上下拉极性选择是同一个寄存器,但是支持中断的只有PORTP、PORTJ、PORTAD,所以要从PORTP开始,增加有效port范围检查。
change log:
3.3.5.1 新增drint_portj_isr()
PORTJ中断处理函数:
说明:
1. 所有的中断处理函数都要在非分页区,因为16位芯片的MC9S12寻址范围0~2^16,十六进制范围(0, 0xFFFF),这个地址范围内是非分页区;
2. 中断处理函数需要有中断向量号,VectorNumber_Vportj为PORTJ中断向量号,具体的中断向量号可以在mc9s12g128.h的第51找到;
3. PIFJ是PORTJ中断标志位寄存器,应在处理完任务之后写1清中断标志位;清中断标志位是为了下次中断能正常进入;在处理完之后再清中断标志位是防止在没有处理完中断处理任务时PORTJ再次触发中断,造成中断嵌套,造成处理错乱。
3.3.5.2 新增drint_portp_isr()
PORTP外部中断处理函数:
3.3.5.3 新增drint_portad_isr()
PORTAD中断处理函数:
在中断处理函数接收后,需要声明代码段恢复到默认代码段。
代码段定义在Project.prm中可见:
中断处理函数自下而上调用callback函数,driver层调用module中间层,使用宏替换实现。
change history:
3.4.1.1 增加中断类型枚举
枚举数值需要和极性选择对应,在数据手册中可见,对于支持中断的PORT,极性选择寄存器1代表pulldown,同时代表上升沿中断选择;0代表pullup,同时代表下降沿中断选择。输入和中断不能同时选择,可以共用这个寄存器。
3.4.1.2 修改MdIoInputCfgStruct
增加中断类型选择
change log:
3.4.2.1 修改mdio_input_cfg[]
增加int_type选择,KEY1设置为下降沿触发中断,KEY2设置为上升沿触发中断。
根据原理图可知,对应的按键
key |
SW丝印标号 |
PIN |
key1 |
SW4 |
PJ4 |
key2 |
SW5 |
PJ5 |
key3 |
SW6 |
PJ6 |
key4 |
SW3 |
PJ7 |
change log:
3.4.3.1 io初始化函数mdio_init优化
1. 增加中断类型判断;
2. 如果配置了中断,设置中断触发方式,并使能中断;
3.4.3.2 增加静态函数uint8 mdio_find_in_input_cfg(uint8port, uint8 pin)
根据port和pin找到在mdio_input_cfg[]数组中排第几个,返回给mdio_portj_isr_callback(),便于应用层查询。
3.4.3.3 增加mdio_portj_isr_callback()
中间层中断处理函数callback函数,根据产生中断的PORT和pin查找到配置的index,然后传递给应用层,便于应用层处理。
新增函数声明:
有原理图知:按键按下,PIN脚电平为0,松开为1。
3.5.2.1 新增void apl_key_int_handler(uint8 keyx)
用于按键中断处理。第一个按键触发中断,LED1~LED4开,LED5~LED8关,第二个按键触发中断,LED1~LED4关,LED5~LED8开。
1. 调用初始化函数;
2. 调用周期任务;
PORTJ的中断使能寄存器PIEJ,从图中可以看出,我们需要PIEJ位4到位5都为1,即使能中断。
根据mdio_cfg.c中的配置,在KEY1对应的PJ4设置为下降沿触发中断,KEY2对应的PJ5设置为上升沿触发中断,所以PPSJ极性寄存器bit4应为0,bit5应为1, debug可以看到如下:
4.2.3.1 没有按键触发中断时
在没有外部中断触发时,中断标志位寄存器都为0:
4.2.3.2 按键KEY1触发中断时
在drint.c中的drint_portj_isr()打断点,当按键KEY1按下时(下降沿):
此时的中断标志位寄存器PIFJ的位4为1:
在中断处理函数接收后清中断标志位后,中断标志位重新恢复到0x00。
4.2.3.3 按键KEY2触发中断时
在drint..c中的drint_portj_isr()打断点,当按键KEY2按下并松开时(上升沿):
此时的中断标志位寄存器PIFJ的位4为1:
在中断处理函数接收后清中断标志位后,中断标志位重新恢复到0x00。