源码下载:https://download.csdn.net/download/Sure_gengjia/125628
内容关注公众号:激活未来
1 overview
1.1 目的
本文档用于起点开发板的PORT模块软件编写说明。
不局限于硬件功能的实现,着眼于实现高质量、优美的软件。
2 软件分层架构
软件分为底层驱动层——driver层,中间件层(本软件中称之为modules)和应用层——application。
2.1 driver层
与MCU寄存器打交道的软件放在driver层。
diver层分为两部分,一部分是MCU芯片内部寄存器中需要配置的参数,每一个module里面有一个xxx_cfg.c,把MCU在本module中尽量多的寄存器都放在指针数组中,给上层的中间件层和driver层中的服务函数访问。
如在drio_cfg.c中定义drio_dir_reg[]
在drio.c中的drio_set_pin_input()函数会访问该数组以设置某个具体的port和pin的为输入属性。
2.2 中间件层
中间件中放每个模块的相关功能。中间件层分为两部分,一部分为服务函数,包括如每个模块的初始化(IO初始化,ADC初始化)、每个模块处理任务、每个模块数据采集任务。另外一部分为配置部分,需要根据硬件原理图填入对应的配置。
如在中间件层的mdio.c中,包括了IO的初始化部分和输入的IO的电平采集任务;
在mdio_cfg.c中,则是具体的IO输出输入配置;
3 LED分析
3.1 原理图
起点开发板共计8个LED。
LED | MCU PIN |
LED1 | PP2 |
LED2 | PP3 |
LED3 | PP4 |
LED4 | PP5 |
LED5 | PP6 |
LED6 | PP7 |
LED7 | PT7 |
LED8 | PT6 |
3.2 PORT和PIN的处理
以PORTT为例:
从《MC9S12G128模块化分层化软件架构之二——IO驱动》中可知,方向寄存器DDR可以存储在drio_cfg.c的drio_dir_reg数组中,
PP2~PP7、PT6和PT7引脚设置为输出:
BYTEOP_BIT_CLEAR_AT(*drio_dir_reg[port],pin);
4 软件实现
4.1 CodingRule
具体可在源码的 .\MC9S12G128_LED\Sources\code_rules.txt中可见。
4.2 driver层
4.2.1 drio.c
该文件中主要有以下功能:
① 引脚输出设置;
② 引脚输入设置;
③ 引脚上拉下拉使能设置;
④ 引脚下拉下拉选择;
4.2.1.1 引脚输出设置修改
形参:
port: drio_cfg.h中所有的枚举的port;
pin:drio_cfg.h中所有枚举的PIN;
-
使用位操作
4.2.1.2 引脚输入设置
形参:
port: drio_cfg.h中所有的枚举的port;
pin:drio_cfg.h中所有枚举的PIN;
-
使用位操作
4.2.1.3 设置引脚输出值
形参:
port: drio_cfg.h中所有的枚举的port;
pin:drio_cfg.h中所有枚举的PIN;
bit_val:引脚要输出的电平值;
4.2.2 drio.h
函数声明
4.3 中间件module层
4.3.1 mdio_cfg.c
该文件与MCU原理图紧密关联,根据原理图,文件中应当定义有哪些port的哪些PIN是输出的,哪些port的哪些PIN是输入的,输入的引脚是否需要上拉还是下拉,是否需要debounce,debounce的时长是多少,debounce方式是什么?
考虑的问题可以在文件的log中看到:
4.3.1.1 引脚输出配置
输出的引脚具有以下属性:
* port
* pin
* open drain(可省略)
* 初始化引脚电平
* 进入睡眠模式的引脚电平(在实际应用中,MCU进入睡眠模式后需要明确输出脚的电平。)
增加输出port和pin:
数组化配置,更有利于实现平台化配置,方便产品的迭代和多样化。
4.3.1.2 引脚输入配置
输出的引脚具有以下属性:
* port
* pin
* deb_type(debounce type)
* deb_ctr(debounce counter)
4.3.1.3 输出输入数组大小定义
设置数组中配置元素大小的意义在于可以在mdio_init初始化中确定需要初始化的个数,在input IO采样的任务中,可以明确采样的个数。
4.3.2 mdio_cfg.h
4.3.2.1 输出数组类型结构体定义
4.3.2.2 输入数组类型结构体定义
4.3.2.3 debounce方式枚举定义
4.3.2.4 无效值定义
4.3.3 mdio.c
4.3.3.1 io初始化函数
codeing rule:
① 使用指针指向mdio_output_cfg和mdio_input_cfg,不直接操作全局数组;
② 对port和pin的范围有效性判断;
4.3.4 mdio.h
函数声明:
4.3.5 apl_led.h
在应用层中,应该只调用中间层——module层。
① 首先要确定的是每个LED的在mdio_cfg.c中的mdio_output_cfg[]中的index是多少;
② 使用宏给应用层提供LED_ON和LED_OFF的接口,然后宏替换为中间层的接口;
代码如下:
4.3.6 apl_led.c
暂时使用apl_led.h中的宏提供LED_ON和LED_OFF,后期需要在apl_led.c中添加LED闪烁和PWM调节LED光亮。
4.3.7 main.c
4.3.7.1 时间片基准
在main函数中使用delay_1ms模拟1毫秒时间片,为main提供时间片基准。
4.3.7.2 LED500ms周期闪烁
LED闪烁周期LED_TASK_PERIOD为500,tick_ctr当做计时器,计满清零。
注意:tick_ctr最大为65536,但是不能让tick_ctr自动的加满至65536后溢出归零。
5 软件测试及调试
5.1 MCU register
5.1.1 DDR数据方向寄存器
从图中可以看出,我们需要PP2~PP7的DDR为1,即output,PPT6和PPT7的DDR为1,即output,正确无误。
5.1.2 Data Register数据寄存器
5.1.2.1 LEDOFF
在LED_OFF出打断点,LED OFF需要输出高电平,即数据寄存器为1,从图中可见,当程序运行出LED_OFF的代码后,PTT的PTT6和PTT7,PTP的PTP2~PTP7数据寄存器都为1。
5.1.2.2 LED ON
在LED_ON处打断点,LED ON需要输出高电平,即数据寄存器为0,从图中可见,当程序运行到LED_ON的代码后,PTT的PTT6和PTT7,PTP的PTP2~PTP7数据寄存器都为0。(注LED8对应的PIN为PTT6,还未运行完APL_LED8_ON,所以PTT6还是1.)
5.2 tick_ctr循环周期
从图中可以见看出,当进入LED_ON时,tick_ctr为7000,可以整除LED_TASK_PERIOD(500)。
5.3 tick_ctr归零
在tick_ctr归零处打断点,当tick_ctr大于等于(65535 – 65535 % 500)时,tick_ctr归零,开始新的循环。
5.4 实物展示