历史上的今天
今天是:2025年07月16日(星期三)
2021年07月16日 | MC9S12G128模块化分层化软件架构之四——LED
2021-07-16 来源:eefocus
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。

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_LEDSourcescode_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 实物展示
史海拾趣
|
我是一只菜鸟。遇到一个问题,烦请大侠帮忙解决。有一个喷墨墨盒,上有一芯片,记录打印次数,如果超过限制,就不让使用,想解开此芯片,把新墨盒的数据写到老墨盒上,在灌上代用墨汁,就不用买原装的了。本菜鸟在很偏僻的树林(沈阳)没有找到办法 ...… 查看全部问答> |
|
产品设计的可测试性(De sign For Testability. OFT) 也是产品可制造性的主要内容从生产角度考虑也是设计的工艺性之一.它是指在设计时考虑产品性能能够检测的难易程度,也就是说设计产品时应考虑如何以最简单的方法对产品的性能和加工质量进行检测, ...… 查看全部问答> |
|
DEBUGMSG(ZONE_TRACE, (TEXT("XXXX\r\n")));这样的语句在驱动里面怎么打印到调试串口? DEBUGMSG(ZONE_TRACE, (TEXT(\"XXXX\\r\\n\")));这样的语句在驱动里面怎么打印到调试串口? … 查看全部问答> |
|
近期对嵌入式系统开发很有兴趣,像微软的WM,谷歌的android,苹果的iphone OS 本身我学习计算机语言就是想涉足计算机系统开发,但是开始学了C#,被微软的VS小黑盒子式编程给洗脑了...感觉编程好像比画图还简单!好想学了C#跟没学似地, 所以现在觉 ...… 查看全部问答> |
|
程序的目的是把采集的温度通过串口显示,现在做的程度是我把硬件连接好后,用MSP430仿真器查看温湿度的数值不正确,比如humi_val.i用quick watch查看value为62850这样的数据,单片机的txd用示波器观察没有波形,可能程序存在很大问题,现在比 ...… 查看全部问答> |
|
我把所有的程序都只注释掉了,只留IO初始化,SD16_A初始化,和一些延时子程序。 一运行到SD16_A初始化完成 中断允许后 单片机就复位了。这是什么情况 坐等高人解惑~~~~… 查看全部问答> |
|
BB Black 入门基础之Eclipse C++ 控制LED灯(中) 本帖最后由 lonerzf 于 2014-1-13 10:57 编辑 接着上一篇。之前的地方设置是有问题的,先不讲可能是哪,大家帮忙给查个错呗。谢谢啦{:soso_e100:} 补充下,如果用 SSH Only方式进行远程部署,则在某些情况下方便得多。 还是在编译好之后选择绿 ...… 查看全部问答> |




