匠人浅谈单片机程序设计中的“分层思想”
- 格式:doc
- 大小:30.00 KB
- 文档页数:5
浅谈单片机应用程序架构对于单片机程序来说,大家都不陌生,但是真正使用架构,考虑架构的恐怕并不多,随着程序开发的不断增多,本人觉得架构是非常必要的。
前不就发帖与大家一起讨论了一下《谈谈怎样架构你的单片机程序》,发现真正使用架构的并不都,而且这类书籍基本没有。
本人经过摸索实验,并总结,大致应用程序的架构有三种:1. 简单的前后台顺序执行程序,这类写法是大多数人使用的方法,不需用思考程序的具体架构,直接通过执行顺序编写应用程序即可。
2. 时间片轮询法,此方法是介于顺序执行与操作系统之间的一种方法。
3. 操作系统,此法应该是应用程序编写的最高境界。
下面就分别谈谈这三种方法的利弊和适应范围等。
1. 顺序执行法:这种方法,这应用程序比较简单,实时性,并行性要求不太高的情况下是不错的方法,程序设计简单,思路比较清晰。
但是当应用程序比较复杂的时候,如果没有一个完整的流程图,恐怕别人很难看懂程序的运行状态,而且随着程序功能的增加,编写应用程序的工程师的大脑也开始混乱。
即不利于升级维护,也不利于代码优化。
本人写个几个比较复杂一点的应用程序,刚开始就是使用此法,最终虽然能够实现功能,但是自己的思维一直处于混乱状态。
导致程序一直不能让自己满意。
这种方法大多数人都会采用,而且我们接受的教育也基本都是使用此法。
对于我们这些基本没有学习过数据结构,程序架构的单片机工程师来说,无疑很难在应用程序的设计上有一个很大的提高,也导致了不同工程师编写的应用程序很难相互利于和学习。
本人建议,如果喜欢使用此法的网友,如果编写比较复杂的应用程序,一定要先理清头脑,设计好完整的流程图再编写程序,否则后果很严重。
当然应该程序本身很简单,此法还是一个非常必须的选择。
下面就写一个顺序执行的程序模型,方面和下面两种方法对比:复制内容到剪贴板代码:/****************************************************************************** ********* FunctionName : main()* Description : 主函数* EntryParameter : None* ReturnValue : None******************************************************************************* *******/int main(void){uint8 keyValue;InitSys(); .default: break;}}}2. 时间片轮询法时间片轮询法,在很多书籍中有提到,而且有很多时候都是与操作系统一起出现,也就是说很多时候是操作系统中使用了这一方法。
单片机程序分层单片机程序分层法是一种非常重要的编程方法,这种方法能够帮助程序员将程序的复杂性分解成不同的层级,从而更好地组织和管理代码,并提高程序的可读性、可维护性和可扩展性。
下面我们将详细介绍单片机程序分层的概念和实现方法。
一、概念单片机程序分层,顾名思义就是将一个复杂的程序划分成若干个不同的层级,每个层级都是一个独立的模块,这些模块相互依赖,各司其职,最终完成系统的任务。
通常情况下,单片机程序的分层可以分为三个层次:应用层、驱动层和硬件层。
应用层:应用层主要是负责完成系统的业务逻辑,这一层通常是程序员最主要的工作区域,他们通过编写代码实现算法、处理数据等任务。
这一层的代码通常是高度抽象的,具有很强的可移植性和可读性。
驱动层:驱动层主要是负责控制硬件资源的分配和管理,例如:控制输入输出口、USART串口、SPI等常见的外设接口。
驱动层的代码与具体的硬件相关,通常需要根据不同的硬件平台做出一定的修改。
硬件层:硬件层主要是与硬件相关的代码,例如:控制LED灯、蜂鸣器等设备的开和关等功能。
这一层代码通常较为底层,可移植性较差,但执行效率要高于其他两个层次。
二、实现方法单片机程序分层方法的核心就是将系统的功能进行分解,然后将分解得到的功能组织成不同层级的模块。
下面我们以一个LED闪烁程序为例,来看看如何实现单片机程序的分层。
1.硬件层首先,我们需要配置GPIO口,选择一个可控制的IO口,然后实现LED的闪烁。
通常情况下,硬件层代码相对简单,下面是一个基本的LED闪烁程序:#include "stm32f10x.h" //包含STM32的头文件#define LED GPIO_Pin_5 //LED控制IO口void LED_Init(void) //初始化GPIO口{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //GPIOA口时钟使能GPIO_InitStructure.GPIO_Pin = LED;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_SetBits(GPIOA, LED); //LED关闭(高电平)}2.驱动层在驱动层,我们需要编写与硬件设备相关的代码,这应该是单片机程序的最核心部分。
单片机程序设计有十层功力,你现在在哪一层?
第一层: 我来了
处在这一层的典型是可以用C语言写简单的逻辑控制,如闪烁LED,简单数码管显示,简单外围模块驱动实验。
一般对单片机感兴趣,经常动手实践的人,半年左右,可以练到此地步(针对没有接触过单片机的人而言)。
此层最典型的示例就是,扫描按键时候,检测按下------延时20ms --再次检测按下----返回键值或等待释放。
如果你是这样做的,或者正在这样做,毫无悬念,应该处于这个级别。
对于95%的电类专业学生来说,毕业时候,远远低于这个级别,剩下的5%则依次分布在各层上。
这也是为什幺学单片机的人成千上万,而会用的人寥寥无几的原因。
第二层真的打呀
步入这一层的典型标志就是开始思考自己所写的程序是否能够有一点实用价值。
譬如应用在实际工程项目中。
在这一层,应该开始思考如何让程序结构简单模块化,如何合理的利用CPU的时间。
我曾经写过这一层的一点简单教程。
对付这一层应该是绰绰有余了。
第三层并肩作战,时间,说爱你不容易
这一层是建立在第二层的基础上面。
从第二层跨越到这一层,需要很多代码行的积累。
在这一层,你对系统中的各个模块应该能够很好的区分。
同时对于时间的应用安排更加合理。
在这一层,同时也应该考虑时间驱动的设计模式。
如何让CPU更有效率的利用起来,需要长时间的积累,并非看,想就可以弄明白,而是不断的实践。
第四层状态,你在哪里
这一层同样建立在第三层基础之上。
掌握了以上三层,只要基本不涉及复。
单片机程序架构通常采用分层设计,以增强程序的可移植性、可维护性和模块化。
以下是一些常见的分层方式:
1.管理层:这一层负责整个系统的协调和管理,包括系统初始化、任务调度、资源管理等。
它通常是与硬件无关的部分,负责决策和策略的实施。
2.具体设备层:这一层包含与特定硬件设备直接交互的代码,例如按键、屏幕、传感器等。
这些代码通常包含了设备驱动程序,负责具体的硬件操作。
3.内核抽象层(KAL):这一层提供了对操作系统或内核功能的抽象,使得上层应用不需要关心底层的具体实现细节。
这样可以在不同的操作系统或内核之间移植应用程序。
4.芯片抽象层(CAL):这一层是对微控制器特定功能(如定时器、串口、ADC等)的抽象,它封装了与芯片相关的操作,为上层提供统一的接口。
5.应用层:这是最接近用户的一层,包含了用户界面、业务逻辑等。
它使用下层提供的服务来完成具体的功能。
6.驱动层:这一层包含设备的驱动程序,负责直接与硬件通信,如SPI、I2C等通信协议的实现。
7.固件层:这是最底层,通常是由官方提供的库函数,直接对寄存器进行操作,是与硬件最接近的软件层次。
总的来说,在设计单片机程序时,采用分层思想可以提高程序的可读性和可维护性,同时也便于团队协作开发。
每一层都有其特
定的职责,上层依赖于下层提供的服务,而不需要关心服务的实现细节。
这种分层屏蔽的思想不仅存在于单片机程序设计中,也是许多复杂系统设计中的常见做法,如操作系统、网络协议等都是基于分层架构设计的。
单片机程序架构详解一、前言单片机,也称为微控制器(Microcontroller),是将计算机的体系结构集成到一个芯片上的微型计算机。
由于其体积小、成本低、可靠性高等特点,单片机在工业控制、智能仪表、家用电器等领域得到了广泛应用。
了解单片机的程序架构是编写和优化单片机程序的关键。
二、单片机程序架构概述单片机的程序架构主要由以下几个部分组成:1. 硬件抽象层(HAL):这一层为上层软件提供了一个与硬件无关的接口,使得软件可以独立于硬件进行开发和运行。
HAL层通常包括对单片机各种外设(如GPIO、UART、SPI、PWM等)的操作函数。
2. 系统服务层:这一层提供了系统级的各种服务,如任务调度、内存管理、时间管理等。
这些服务使得上层应用程序可以更加专注于业务逻辑的实现。
3. 应用层:这是最上层,直接面向用户,包含了各种应用程序的逻辑代码。
三、各层详解1. 硬件抽象层(HAL)硬件抽象层(HAL)是单片机程序架构中非常重要的一层,其主要目标是使得硬件相关的操作与具体的硬件实现无关。
这样,当硬件平台发生变化时,只要HAL层设计得当,上层代码就不需要改变。
HAL层通常包括以下内容:* 各种外设寄存器的操作函数:例如,GPIO的输入输出函数、UART的发送接收函数等。
这些函数隐藏了具体的寄存器操作细节,使得开发者只需要关注功能实现而不需要关心底层寄存器的操作。
* 硬件初始化函数:用于在系统启动时对单片机进行初始化,如配置时钟、启动看门狗等。
* 中断处理函数:用于处理单片机的各种中断事件,如定时器溢出、串口接收等。
2. 系统服务层系统服务层提供了单片机操作系统所需的各种服务,如任务调度、内存管理、时间管理等。
这些服务使得上层应用程序可以更加专注于业务逻辑的实现。
以下是一些常见的系统服务:* 任务调度:多任务环境下,任务调度器负责分配CPU时间给各个任务,使得各个任务能够按需运行。
* 内存管理:负责动态内存的分配和释放,如堆和栈的管理。
单片机程序架构设计
1.程序结构设计
程序结构是指整个单片机程序的组织框架,它需要清晰明确、层次分明。
一个常用的程序结构是主循环结构,即程序在无限
循环中执行各种任务。
在主循环内,可以根据需要调用各个模
块的函数来实现不同的任务。
2.任务划分设计
将任务划分为不同的模块有助于程序的模块化设计和维护。
每个模块可以负责一个特定的功能,如控制输入输出、数据处理、通信等。
每个模块应该有清晰的接口和功能,使得模块之
间的协作和交互更加方便。
3.模块化设计
模块化设计是指将程序分成多个模块,每个模块负责一个特
定的功能。
每个模块应该具有独立性,可重用性和可测试性。
模块之间可以通过接口和消息传递来实现数据的交换和协作。
模块化设计有助于程序的可维护性和扩展性。
在设计过程中,可以根据具体功能将程序划分成多个模块,并定义各个模块之
间的接口和功能。
4.时序管理设计
时序管理是指对程序中各个任务的调度和执行进行管理。
在单片机系统中,由于计算能力和资源有限,需要合理规划任务的执行顺序和时序。
可以使用定时器或中断等方式来实现任务的调度和切换。
通过合理设置任务的优先级和时间片,可以确保各个任务按照预定的顺序和时间执行,从而提高系统的响应速度和效率。
单片机程序分层一、引言单片机是嵌入式系统中常用的核心部件,负责控制和处理各种硬件设备。
在设计单片机程序时,分层的思想非常重要,可以提高代码的可读性、可维护性和可扩展性。
本文将介绍单片机程序分层的概念、优势以及具体的分层方式。
单片机程序分层是指将程序按照功能划分为不同的层次,每个层次负责不同的任务。
这样可以将复杂的问题分解为简单的模块,使程序结构清晰,易于理解和调试。
常用的分层方式包括硬件层、驱动层、逻辑层和应用层。
三、单片机程序分层的优势1. 提高代码的可读性:通过将程序划分为不同的层次,每个层次只关注自己的功能,代码更加简洁清晰,易于阅读和理解。
2. 提高代码的可维护性:当需要修改某个功能时,只需修改对应的层次,不会影响其他层次的代码,减少了修改的风险。
3. 提高代码的可扩展性:当需要添加新的功能时,只需新增对应的层次,不会对其他层次的代码造成影响,方便扩展和维护。
4. 降低程序的耦合性:各个层次之间通过接口进行通信,层与层之间的依赖关系清晰明确,降低了代码的耦合度。
5. 方便调试和排错:分层的结构使得问题定位更加精确,可以快速定位到具体的层次进行调试。
四、硬件层硬件层是单片机程序的最底层,负责与硬件设备进行交互。
在这一层,程序需要与外部设备进行通信,包括读取传感器的数据、控制执行器等。
硬件层的代码通常是直接操作寄存器或引脚,需要对硬件的特性有一定的了解。
五、驱动层驱动层是建立在硬件层之上的,负责对硬件进行抽象和封装。
驱动层提供了一系列的函数接口,用于控制和访问硬件设备。
通过驱动层,上层的逻辑层和应用层可以方便地调用硬件功能,而不需要关心具体的硬件细节。
六、逻辑层逻辑层是单片机程序的核心,负责处理各种逻辑运算和算法。
在这一层,程序需要根据输入的数据进行一系列的计算和判断,并产生相应的输出。
逻辑层的代码通常涉及到数值运算、逻辑判断、状态机等。
七、应用层应用层是单片机程序的最高层,负责实现具体的功能和业务逻辑。
单片机分层设计架构单片机分层设计架构是一种将程序按照不同层次划分的设计方法,它有助于提高程序的可维护性和可扩展性。
本文将以人类的视角,详细介绍单片机分层设计架构的概念、原理和应用。
一、概述单片机分层设计架构是一种将程序按照不同层次划分的设计方法。
这种设计方法将整个程序分解为若干个层次,每个层次都有特定的功能和职责。
各个层次之间通过接口进行通信和协作,从而实现了模块化的设计。
二、分层设计的原理单片机分层设计的原理是将程序按照功能和职责进行划分,每个层次都有自己的任务和功能。
各个层次之间通过接口进行通信和协作,实现了模块化的设计。
这种设计方法可以提高程序的可维护性和可扩展性。
三、分层设计的应用单片机分层设计架构广泛应用于各种嵌入式系统和物联网设备中。
它可以将程序按照功能划分为若干个层次,使得程序的各个功能模块之间松耦合,便于维护和扩展。
同时,分层设计还可以提高代码的重用性,降低开发成本。
四、分层设计的具体实现单片机分层设计的具体实现包括以下几个步骤:1.确定程序的功能和职责,将其分解为若干个层次。
2.定义各个层次之间的接口,明确数据的输入和输出。
3.实现各个层次的功能模块,确保其功能正确和稳定。
4.测试各个层次的功能模块,验证其正确性和可靠性。
5.将各个功能模块组合在一起,形成完整的程序。
五、分层设计的优势和挑战单片机分层设计架构具有以下优势:1.提高程序的可维护性和可扩展性。
2.降低代码的耦合度,提高代码的重用性。
3.简化程序的调试和测试过程,提高开发效率。
然而,单片机分层设计也面临一些挑战:1.需要合理划分层次,避免层次之间的功能重叠。
2.需要定义清晰的接口,确保各个层次之间的数据传输正确和稳定。
3.需要进行全面的测试和验证,保证整个程序的正确性和可靠性。
六、结论单片机分层设计架构是一种提高程序可维护性和可扩展性的有效方法。
通过将程序按照不同层次划分,并定义清晰的接口,可以实现模块化的设计。
然而,分层设计也需要合理划分层次和定义接口,同时进行全面的测试和验证。
模块化编程的分层设计经验(转载)电脑技术2011-01-04 16:48:54 阅读12 评论0 字号:大中小订阅模块化编程的分层设计经验操作要点:1、每一层直接对下一层操作,尽量避免交叉调用或越级调用2、某些器件会把硬件驱动层合并成一个文件时,则归于较高的层3、相同功能的外部函数尽量一致,尽量保证通用性4、对于初次编程的模块,要严格保证中间各层的正确性好处:1、对于后期维护扩展,只需修改应用层和物理层,根据需要扩展功能层2、一个新项目只需把要用到的文件加入工程,简单修改调试就出来了3、随着模块的不断积累,新的项目将越来越容易完成,后期的维护扩展也变得非常简单了4、对于C语言编程,只需简单修改物理层就可完成不同单片机间的移植呵呵,一些经验,大家有好的想法可以继续补充指正一般分为以下几层:---应用层--面向用户软| ↓件|---协议层--现成的协议栈、软件包、标准库,大多是移植,不自己写,如FAT、TCPIP、OS、GAME等相| ↓关| ↓---功能层--实现器件无关性,实现器件的各种功能扩展和器件通用性处理,如LCD的线、圆、矩形等功能,如EEPROM的块写,自己的print硬| ↓件|---器件层--实现硬件无关性,保证IO无关性,只提供器件的基本功能,如字节读写、点驱| ↓动---物理层--IO相关,直接操作硬件,实现硬件连接的多种方案对应文件举例1:---应用层--面向用户的主程序软| ↓件|---协议层--如FAT、TCPIP、OS等现成的协议栈、算法、游戏等相| ↓关| ↓---功能层--如文件lcd.c;led.c;eeprom.c;time.c;ir.c;keybord.c;harddisk.c;引出LCD的线、圆、矩形、填充等功能硬| ↓↓件|--- 器件层--文件lcd61202.c;lcd1520.c;lcd6963.c;lcd133x.c;lcd44780.c;lcd1 62x.c;lcd856x.c或者lcd1602.c;lcd12864.c;lcd320240.c 等,引出基本的初始化、定位、写点、写字节函数驱| ↓↓动---物理层--文件lcd61202_io.c;lcd61202_bus.c;引出器件的基本读写函数对应文件应用举例2:---应用层--面向用户的主程序软| ↓件|---协议层--如FAT、TCPIP、OS等现成的协议栈、算法、游戏等相| ↓关| ↓---功能层--如文件lcd.c;led.c;eeprom.c;time.c;ir.c;keybord.c;harddisk.c;如EEPROM的块写统一化硬| ↓↓件|---器件层--文件ee24xx.c;ee93xx.c;ee_sdcard.c;ee29xx.c;ee28f.c;ee39xx.c;等驱| ↓↓动---物理层--文件bus_i2c.c;bus_spi.c等一个大的单片机程序往往包含很多模块,我是这样组织的1。
单片机程度架构
单片机是一种集成电路芯片,其程度架构可以分为以下几个层次:
1. 物理层:单片机物理层包括芯片、引脚、外设等硬件部分。
物理层的设计决定了单片机的性能和功能扩展的可能性。
2. 核心层:核心层是单片机的核心处理单元,通常由一个或多个处理器核心组成。
该层负责执行程序指令、进行算术和逻辑运算以及处理各种中断和异常。
3. 存储层:存储层包括程序存储器(程序存储ROM)和数据存储器(数据存储RAM)。
程序存储器存储了单片机的程序代码,数据存储器用于存储程序运行时的临时数据。
4. 总线层:总线层主要用于各个部件之间的数据传输和通信。
它包括地址总线、数据总线和控制总线。
5. 外设层:外设层是单片机与外部设备进行物理接口的部分,包括各种输入输出端口、AD转换器、定时器等。
外设层实现了单片机与外部环境的连接和数据交换。
6. 系统层:系统层是单片机的软件和操作系统部分,主要包括编译器、调试工具、操作系统和驱动程序等。
系统层通过提供高级编程接口和软件库,简化了单片机开发过程。
以上是单片机的典型程度架构,具体的架构会根据不同的单片机型号和品牌有所差异。
浅谈单片机程序设计中的“分层思想”
随便写下的一点东西,本来打算去发表,不过想想还是算了,不是什么重要的东西,不过这个东西确实很有用。
文章烂的去组织和修改了,随便看看吧。
分层的思想,并不是什么神秘的东西,事实上很多做项目的工程师本身自己也会在用。
看了不少帖子都发现没有提及这个东西,然而分层结构确是很有用的东西,参透后会有一种恍然大悟的感觉。
如果说我不懂LCD怎么驱动,那好办,看一下datasheet,参考一下阿别人的程序,很快就可以做出来。
但是如果不懂程序设计的思想的话,会给你做项目的过程中带来很多很多的困惑。
参考了市面上各种各样的嵌入式书籍,MCS-51,AVR ,ARM 等都有看过,但是没有发现有哪本是介绍设计思想的,就算有也是凤毛麟角。
写程序不难,但是程序怎么样才能写的好,写的快,那是需要点经验积累的。
结构化模块化的程序设计的思想,使最基本的要求。
然而这么将这个抽象的概念运用到工程实践当中恩?那需要在做项目的过程中经历磨难,将一些东西总结出来,抽象升华为理论,对经验的积累和技术的传播都大有裨益。
所以在下出来献丑一下,总结一些东西。
就我个人的经验而谈,有两个设计思想是非常重要的。
一个就是“时间片轮的设计思想”,这个对实际中解决多任务问题非常有用,通常可以用这个东西来判断一个人是单片机学习者,还是一个单片机工程师。
这个必须掌握。
由于网上介绍这个的帖子也不少,所以这里就不多说了。
第二个就是我今天想说的主题“分层屏蔽的设计思想”。
下面用扫描键盘程序例子作为引子,引出今天说的东西。
问题的提出
单片机学习板一般为了简单起见,将按键分配的很好,例如整个 4*4 的键盘矩阵分配到 P1 口上面,8条控制线,刚好。
这样的话程序也非常好写。
只需要简单的
KEY_DAT = P1;
端口的数据就读进来了。
诚然,现实中没有这么好的事情。
在实际的项目应用当中,单片机引脚的复用相当厉害,这跟那些所谓的单片机学习板就有很大的差别了。
另外一个原因,一般设计来说,是“软件配合硬件”的设计流程,简单点说就是,先确定好硬件原理图,硬件布线,最后才是软件的开发,因为硬件修改起来比较麻烦,相对来说软件修改的时候比较好改。
这个就是中国传统的阴阳平衡哲学原理。
硬件设计和软件设计本来就是鱼和熊掌的关系,两者不可兼得。
方便了硬件设计,很可能给写软件带来很大的麻烦。
反过来说,方便了软件设计,硬件设计也会相当的麻烦。
如果硬件设计和软件设计同时方便了,那只有两种可能,一是这个设计方案非常简单,二是设计师已经达到了一个非常高的境界。
我们不考虑那么多情况,单纯从常用的实际应用的角度来看问题。
硬件为了布线的方便,很多时候会可能将IO口分配到不同的端口上面,例如上面说的4*4键盘,8根线分别分配到 P0 P1 P2 P3 上面去了。
那么,开发板的那些扫描键盘程序可以去见鬼了。
怎么扫按键?我想起了我刚开始学习的时候,分成3段非常相似的程序,一个一个按键的扫描的经历......
或许有人不甘心,“那些东西我花了很长时间学习的,也用的好好的,怎么能说一句不用就不用?”虽然有点残忍,但是我还是想说“兄弟,接受现实吧,现实是残酷的......”
不过,人区别于低等动物的差别,是人会创造,在碰到困难的时候会想办法解决,于是我们开始了沉思......
最后我们引入初中数学学的“映射”的概念来解决问题。
基本思想就是,将不同端口的按键映射到相同端口上面。
这样按键扫描程序就分成3个层次了。
1)最底层的是硬件层,完成端口扫描,20ms延时消抖,将端口的数据映射到一个KEY_DAT寄存器上面,K EY_DAT作为对上层驱动层的一个接口。
2)中间的一层是驱动层,驱动层只对 KEY_DAT 寄存器的数值进行操作。
简单点说,我们无论底层的硬件是怎么接线的,在驱动层都不需要关心,只需要关心 KEY_DAT 这个寄存器的数值是什么就可以了。
这样出来的间接效果就是“屏蔽了底层硬件的差异”,所以驱动层写的程序就可以通用了。
驱动层的另外一个功能是为了上层提供消息接口。
我们用了类似window程序的消息的概念。
这里可以提供一些按键消息,例如:按下消息,松开消息,长按键消息,长按键的时候的步进消息,等等。
3)应用层。
这里就是根据项目的不同分别写按键功能程序,属于最上层的程序。
它使用的是驱动层提供的消息接口。
在应用层写程序的思想就是,我不管下层是怎么工作的,我只关心按键消息。
有按键消息来的时候我就执行功能,没有消息来的时候,我就什么也不做。
下面用一个简单的常用的例子,说明我们这个设计思想的用法。
秒表调整时间的时候,要求按着某个按键不放,时间能连续的向上增加。
这个东西很实用,实际的家电中用途很广泛。
在看下面的东西之前,大家可以想一下,这东西难吗?相信大家都会很响亮的回答,“不难!!”,然而我再问:“这东西麻烦吗?”我相信很多人肯定会说“很麻烦!!” 这不禁让我想起开始学单片机的时候写这种按键的那程序,乱七八糟的结构。
如果不相信的话,可以自己用51写一下哦,那样就更加能体会本文说的分层结构的优越性。
项目要求:
两个按键,分别分配在P10 和P20,分别是“加”“减”按键,要求长按键的时候实现连续加和连续减的功能。
实战:
假设:
按键上拉,没有按键的时候高电平,有按键的时候低电平,另外,为了突出问题,这里没有将延时消抖的程序写上去,在实际项目中应该加上。
C语言函数参数的传递多种多样,这里作为例子,用了最简单的全局变量来传递参数,当然你也可以用 unsigned char ReadPort(void) 返回一个读键结果,甚至还可以 v oid ReadPort(unsigned char *pt) 用一个指针变量传递地址而达到直接修改变量的目的。
方法是多种多样的,这个决定于每个人的程序风格。
1)开始写硬件层程序,完成映射
#define KYE_MIN 0X01
#define KEY_PLUS 0X01
unsigned char KeyDat;
void ReadPort(void)
{
if (P1 & KEY_PLUS == 0 ){
KeyDat |= 0x01 ;
}
if (P2 & KEY_MIN == 0 ){
KeyDat |= 0x02 ;
}
}
C语言应该很容易看懂吧?如果 KEY_PLUS 按下,P10口读到低电平,则 P1 & KEY_PLUS 的结果为 0 ,满足if 的条件,进入KeyDat |= 0x01 是将 KeyDat 的bit0 置一,也就是说,将 KEY_PLUS 映射到 KeyD at 的 bit0
KEY_MIN 是同样的道理映射到 KeyDat 的 bit1
如果 KeyDat 的 bit0 为 1 ,则说明 KEY_PLUS 按下,反则亦然。
不需要想的很神秘,映射就是这么一回事。
如果还有其他按键的话,用同样办法,将他们全部映射到 Key Dat 上面。
2)驱动层程序编写
如果将 KeyDat想象成 P1 口,那么这个跟学习板那标准的扫描程序不就是一样了吗?对的,这个就是底层映射的目的了。
3)应用层程序编写
根据消息
硬件层是必须分离出来,然而驱动层和应用层的要求就不那么严格了,事实上一些简单的项目没有必要将这两层分离开来,根据实际应用灵活应对就可以了。
其实这样写程序是很方便移植的,根据板子的不同而适当的修改一下硬件层那个 ReadPort 函数就完成了,驱动层和应用层很多代码可以不经过修改直接用,很能提高开发效率的。
当然这个按键程序会存在一定的问题,特别是遇到常闭按键和点触按键的混合使用的场合。
这个留给大家自己去想了,反正问题总是能找到解决办法的,尽管方法有好有坏。
结束语
以按键为媒介,介绍了程序设计当中的“分层屏蔽”的思想的原理和应用,按键只是一个例子,其实分层的思想普遍存在着程序设计当中。
细心留意一下的话发现其实window,linux,网络的tcp/ip 结构全部都是分层的。
这东西不是绣花枕头,而是实际用在工程上面的,只是平时不多见帖子介绍,或者没有人特意这样来总结,又或者是有经验的工程师作为藏在心中的法宝吧,这个就不得而知。
不过好东西应该共享,菜鸟应该共勉,一起来学飞吧。