51单片机模块化编程设计与实例要点分析

合集下载

51单片机C语言程序设计经典案例

51单片机C语言程序设计经典案例

项目三C51程序设计语言基础任务1 C51程序的识读1.C51程序结构例3-1 P_test/********************* //注释,还可用//注释掉一行File name:P_test.cChip name:STC89C51RCClock frequency:1.20MHz***********************/#include “reg52.h” //预处理命令,文件包含预处理命令,后缀名都是.h,标准的MCS-51单片机头文件为”reg51.h”,STC89系列单片机头文件为”reg52.h”#define unit unsigned int //宏定义预处理命令sbit BZ=P3`7 ;sbit key=P1`0;void delay(unit ms){unit i;while( ms --){for(i=0;i<120;i++);}}void main(void){while(1){if(key==0){BZ=0x0;delayms(10);BZ=0x1;delayms(50);P0=0xFF;}else{P0=~P0;delayms(500);}}}2.C51的数据类型位变量型 bit字符型无符号字符型 unsigned char有符号字符型 signed charC51的数据类型整数型无符号整数型 unsigned int基本类型有符号整数型 signed int长整数型无符号长整数型 unsigned long int有符号长整数型signed long int实数型(浮点型)单精度浮点型float双精度浮点型double数组类型array结构体类型struct构造类型共用体union枚举enum指针类型空类型(void)表3-1 C51基本数据类型的长度和值域3.C51的标识符和关键字标识符是由字母、数字和下划线组成的字符串,第一个字符必须是字母或下划线,不超过32个字符。

C51模块化编程

C51模块化编程

7.5.2

模块设计原则
若我们把复杂的问题分解成许多容易解决的小问题,复杂 的问题也就容易解决了。但是如果只是简单地分解任务,不 注意对一些子任务的归纳与抽象,不注意模块之间的关系, 往往会使模块数太多,模块之间的关系变得复杂,从而使程 序的调试、修改变得更加复杂。一般说来,模块设计应该遵 从以下几条原则: (1)模块独立 模块的独立性原则应保证模块完成独立的功能,模块与模 块之间关系简单,修改某一模块,不会造成整个程序的混乱。 保证模块的独立性应注意以下几点: ①每个模块完成一个相对独立的特定功能。在对任务分解 时,要注意对问题的综合。 ②模块之间的关系力求简单。例如:模块之间最好只通过 数据传递发生联系,而不发生控制关系。C语言中禁止goto 语句作用到另一函数,就是为了保证函数的独立性。
关于流程图,图7.12给出了我国国家标准GB1526—89中 推荐的一套流程图标准化符号的一部分。常用的符号含义如 下: · 数据 平行四边形表示数据,其中可注明数据名称、来源 或用途,也可以用其他文字说明。 · 特定处理 带有双竖边线的矩形。矩形内可注明特定处理 名称或简要功能,表示已命名的处理。 · 判断 菱形表示判断。菱形内可注明判断的条件。它只有 一个入口,但有多个出口。 · 循环界限 循环界限表示循环的上界和下界,中间是要循 环执行的处理内容,称为循环体。循环界限由去上角的矩形 (表示上界限)和去下角的矩形(表示下界限)构成。 · 端点 扁圆形表示从外部环境转入或转向外部环境的端点 符。 · 注解 注解是程序的编写者向阅读者提供的说明。它用虚 线连接到被注解的符号或符号组上。
C51模块化编程
7.5
模块化程序设计
• 7.5.1 基本概念
设计程序的一般过程是:在拿到一个需要解决的 问题后,首先对问题进行分析,把问题分成几个部分。 然后分别分析几个部分,进一步求精细化。每一部分 又可再分成更细的若干部分,直至分解成容易求解的 小问题。原问题的求解可以用这些小问题的求解来实 现。 求解小问题的算法和程序称为“功能模块”,各功能 模块可以单独设计,然后将求解的所有子问题的模块 组合成求解原问题的程序。一个解决大问题的程序, 可以分解成多个解决小问题的模块,这是“自顶由下” 的程序设计方法。由功能模块组成程序的结构如图 7.11所示。

51单片机讲解 第四章

51单片机讲解 第四章

例5、拆字。将片内RAM20H单元内容拆成两段,每段4位, 并将它们分别存入21H与22H单元中。即把压缩的BCD 码变成非压缩的BCD码存储。 ORG 2000H START:MOV R0,#21H ;21H→(R0) MOV A,20H ;(20H)→A ANL A,#0FH ;A∧#0FH→A MOV @R0,A ;A→((R0)) INC R0 MOV A,20H SWAP A ;A0~3←→A4~7 ANL A,#0FH MOV @R0,A
例2、8位数据交换,R3与R5内容互换,R4与35H单元内 容互换。 XCHR: XCH A,R3 ;XCH目的操作数一定为A XCH A,R5 XCH A,R3 XCH A,R4 XCH A,35H XCH A,R4 例3、双字节加法程序,设被加数存放于片内RAM的 addr1(低位)和addr2(高位),加数存放于addr3 (低位)和addr4(高位),结果存放于addr1和 addr2中。
例7、BCD码化二进制数。将片内RAM21H和20H单元中的3 位压缩存放的8421BCD码,转换成二进制数,结果仍 存放于21H和20H。 转换方法:
二进制数=百位数字×64H(100)+ 十位数字×0AH(10)+个位数字
ORG MOV START: PUSH PUSH MOV ANL MOV要入栈保护
例4、编双字节乘法(16bit×8bit)子程序,并写出主 程序。 思路:被乘数放在(R4)(R3)中,乘数放(R2),结果放 (R7)(R6)(R5)中, (R7)(R6)(R5)=[(R4)×28+(R3)]×(R2) =(R4)×(R2)×28+(R3)×(R2) 子程序: NFA: MOV A,R2 ;乘数→A MOV B,R3 ;被乘数低位→B MUL AB MOV R5,A MOV R6,B ;(R3)×(R2)积存于(R6)(R5) MOV A,R2 MOV B,R4 ;被乘数高位→B MUL AB

单片机89C51汇编模块化编程

单片机89C51汇编模块化编程

单片机89C51汇编模块化编程
高手从菜鸟忽略作起之(七)一,汇编模块类别
1.1子过程:无参数,无返回值的一段功能代码。

1.2函数:参数,返回值至少有一项的功能代码。

1.3中断处理:中断发生时的处理代码。

二,子过程框架
2.1 标签+LJMP:
2.2 函数框架:
详见函数框架。

三,函数框架:
3.1 函数传递参数:调用前,将参数从右到左压入栈,函数中从左到右弹出栈。

3.2 函数返回值:用Acc寄存器保存返回值。

3.3 函数传址参数:将地址作为参数,传递。

3.4 代码框架:
四,中断处理:
3.1 定入中断入口及跳转。

3.2 中断处理设定:保护现场+中断处理+恢复现场3.2 代码框架。

51单片机典型开发实例大全

51单片机典型开发实例大全
提供电子技术最新最实用设计方案
——单片机 C51 编程规范
typedef unsigned char INT8U; // 无符号 8 位整型变量 //
typedef signed char INT8S; // 有符号 8 位整型变量 //
1 单片机 C51 编程规范- 前言
typedef unsigned int INT16U; // 无符号 16 位整型变量 //
uCOSII 工作核心原理是:近似地让最高优先级的就绪任务处于运行状态。
——uCOS-II 在 51 单片机上的移 植
引言:随着各种应用电子系统的复杂化和系统实时性需求的提高,并伴 随应用软件朝着系统化方向发展的加速,在 16 位/32 位单片机中广泛使用了 嵌入式实时操作系统。然而实际使用中却存在着大量 8 位单片机,从经济性 考虑,对某些应用场合,在 8 位 MCU 上使用操作系统是可行的。从学习操作 系统角度,uC/OS- II for 51 即简单又全面,学习成本低廉,值得推广。
********************************************************** */
6.3 函数注释
6.3.1 函数头部注释
一般情况源程序有效注释量在 30%左右。 注释语言必须准确、易懂、简洁。

函数头部注释应包括函数名称、函数功能、入口参数、出口参 数等内容。如有必要还可增加作者、创建日期、修改记录(备注) 等相关项目。
7.2 函数定义
*函数若没有入口参数或者出口参数,应用 void 明确申明。 *函数名称与出口参数类型定义间应该空一格且只空一格。 *函数名称与括号()之间无空格。
uCOSII 包括任务调度、时间管理、内存管理、资源管理(信号量、邮箱、 消息队列)四大部分,没有文件系统、网络接口、输入输出界面。它的移植 只与 4 个文件相关:汇编文件(OS_CPU_A.ASM)、处理器相关 C 文件(OS_CPU.H、

谈谈8051模块化编程的技巧

谈谈8051模块化编程的技巧
mov
se97:调用转按子程序.取目示断码
p2

r3#60h;是SBl.键值“60H“送寄存器R3
a.+位敬段码送P2口
b,取个位数
slmp
ksr是,不进行任何操作逅目
mov
acall
k2check acall dell0:谰月毫种延时,去抖
se97.调用转换子程序.取显示断码
曲kb begin ksr.干扰,返目

fnb k。-beg,n k2check.SB2拄下转移
s』mp ksr
人口参数存放在寄存器R2中
display:mov
r2,取被显示值
klcheck
aca!l
dell0.调用毫秒延时.去抖
mov
b#10,取被Ⅱ示值的十位数
归kbinit
ks r.干扰.返回
div ab 808]1 mov
Jnb№init¥等待拄键释放
psw3:切换至第1组寄存器
r7加bh:
r6月0fIl’.
d11…v
该子程序有一个八口参数和一个出1:3参数。人1:3参数就
是被显示的数.出口参数就是该数的段码(相应位=O 表示亮}.都存放在累加器A中。
d12 djnz r6,d12 dnz r7 dll
clr re[
psw3.切抉至第0组寄存器
按照图5的流程图和51单片机的指令系统编制的
s.寄存器R3中的内窖减1.不为零转移到当
dell寄存器R2中的内窖减1-不为零转移到
db
8eh:cd盱
djnz
rl
del0:寄存器R1中的内窖减1.不为零转移到
“)延时子程序 延时子程序完成一定的延时时间任务。这里有两个 延时时间不同的子程序(也可以调用100发10mS做 1s延迟).其流程如图6所示。延时子程序没有^口和 出13参数。 按照图6的流程围和51单片机的指令系统编制的 子程序如下

单片机汇编语言的模块化编程方法举例

单片机汇编语言的模块化编程方法举例

(上接 16 页)
二、元件选择
液体水平检测开关采用透明硬塑材料(如光 盘盒)粘合而成,具体尺寸由电子水准仪的长度、 宽度和高度决定,以刚好放入不松动和不影响顶 盖与底盒切合为宜 ;四根电极采用不易被水侵蚀 的 金 属 丝( 如 镀 镍、 镀 铬 的 导 线 ), 用 微 型 钻 头 打孔后用防水胶(如市售普通 AB 胶)粘固密封。 为了提高灵敏度,液体检测开关长度尽可能大一 点,上面两根电极要尽可能接近水面,注好水密 封后一定要检察是否漏水。为使效果明显,液体
制作天地
HANDS ON PROJECTS
编者按 :单片机的汇编语言是学习单片机的基础,而汇编语言的最大不足就是程序的结构不清晰和易读 性差,而模块化编程能在一定程序上弥补这一缺陷。作者结合其教学经验,提出的汇编语言的模块化编程的 理念,值得从事单片机编程的技术员借鉴,特别是对初学单片机的人,更是有必要。
把已有的功能子程序简单地堆放在一起就可以实 现的,而是要把这些子程序进行有机的整合才行。 那么,在整合的过程中会遇到哪些问题?要注意 哪些问题?下面我们以一个交通灯项目为例,运 用子程序化、模块化的编程方法进行编程,并把 编程的过程做一个完整的讲述,希望读者对这种 编程方法有一个具体的认识。
一、交通灯项目的任务分析
在进行项目教学时我们发现,同学们也知道 这个项目需要哪几个任务来完成,他们也知道每 个任务应该怎样实现,然而如何把这些任务弄到 一起去完成项目所要求的设计目标,成了一个教 学难点。当然方法可以多种多样,聪明的学生可 以想出一些奇特的方法实现,但那些毕竟不是正 途,不是一般的方法。有没有一种有章可循的方 法呢?有,这就是子程序化、模块化的编程方法。
这就是交通灯项目程序的整体结构,而原程序 与这个结构则是一致的。

51单片机实例(含详细代码说明)

51单片机实例(含详细代码说明)

1.闪烁灯1.实验任务如图4.1.1所示:在P1.0端口上接一个发光二极管L1,使L1在不停地一亮一灭,一亮一灭的时间间隔为0.2秒。

2.电路原理图图4.1.13.系统板上硬件连线把“单片机系统”区域中的P1.0端口用导线连接到“八路发光二极管指示模块”区域中的L1端口上。

4.程序设计内容(1).延时程序的设计方法作为单片机的指令的执行的时间是很短,数量大微秒级,因此,我们要求的闪烁时间间隔为0.2秒,相对于微秒来说,相差太大,所以我们在执行某一指令时,插入延时程序,来达到我们的要求,但这样的延时程序是如何设计呢?下面具体介绍其原理:如图4.1.1所示的石英晶体为12MHz,因此,1个机器周期为1微秒机器周期微秒MOV R6,#20 2个 2D1: MOV R7,#248 2个 2 2+2×248=498 20× DJNZ R7,$ 2个2×248 (498DJNZ R6,D1 2个2×20=4010002因此,上面的延时程序时间为10.002ms。

由以上可知,当R6=10、R7=248时,延时5ms,R6=20、R7=248时,延时10ms,以此为基本的计时单位。

如本实验要求0.2秒=200ms,10ms×R5=200ms,则R5=20,延时子程序如下:DELAY: MOV R5,#20D1: MOV R6,#20D2: MOV R7,#248DJNZ R7,$DJNZ R6,D2DJNZ R5,D1RET(2).输出控制如图1所示,当P1.0端口输出高电平,即P1.0=1时,根据发光二极管的单向导电性可知,这时发光二极管L1熄灭;当P1.0端口输出低电平,即P1.0=0时,发光二极管L1亮;我们可以使用SETB P1.0指令使P1.0端口输出高电平,使用CLR P1.0指令使P1.0端口输出低电平。

5.程序框图如图4.1.2所示图4.1.26.汇编源程序ORG 0START: CLR P1.0LCALL DELAYSETB P1.0LCALL DELAYLJMP STARTDELAY: MOV R5,#20 ;延时子程序,延时0.2秒D1: MOV R6,#20D2: MOV R7,#248DJNZ R7,$DJNZ R6,D2DJNZ R5,D1RETEND7. C语言源程序#include <AT89X51.H>sbit L1=P1^0;void delay02s(void) //延时0.2秒子程序{unsigned char i,j,k;for(i=20;i>0;i--)for(j=20;j>0;j--)for(k=248;k>0;k--);}void main(void) {while(1){L1=0;delay02s();L1=1;delay02s();}2.模拟开关灯1.实验任务如图4.2.1所示,监视开关K1(接在P3.0端口上),用发光二极管L1(接在单片机P1.0端口上)显示开关状态,如果开关合上,L1亮,开关打开,L1熄灭。

CH14(单片机C51模块化编程)

CH14(单片机C51模块化编程)

新语新知—建立头文件的步骤
第二步 防重复包含处理
例如对于delay.h文件,其内容如下: #ifndef __DELAY_H__ #define __DELAY_H__ ... //此处添加代码 #endif
新语新知—建立头文件的步骤
第二步 防重复包含处理 因为在同一个工程内,文件名都是唯一 的,因此这种命名规则可以保证XXX不会重 复。之后要添加到.h文件的代码都放在第3行 的位置。
新语新知—模块化编程的三种手段
函数、宏定义与头文件
实现模块化编程的三个主要手段是函数、 宏定义与头文件,对于函数与宏定义之前我 们有所讲解,通过几个例子使大家进一步加 深对其的理解。下面讲解一下头文件操作的 详细步骤。
新语新知—建立头文件的步骤
第一步 创建头文件 建立一个.c文件(源文件)和一个.h文 件 (头文件)。原则上文件名可以任意 命名,但强烈推荐如下原则: .c 文件与 .h 文件同名 ;文件名要有意义,最好能 够体现该文件代码的功能。例如延时函 数相关的源文件与头文件命名为delay.c 与delay.h。
设置中间过程产生的文件的放置位置
编写主函数,编译 编译之后,可以发现编译器编译出错,说找不到led.h 于是,我们还必须进行一项设置(编译路径)
编译路径我们添加进去了,再重新编译,
可以看到没有报错,(一个警告是因为我们编写的另 外一个函数LED_OFF()函数没有调用),如果想不要 这个警告可以这样设置
延时相关函数的头文件
流程简介:在之前的几讲当中,我们定义过几种延时函
数,现在我们将延时函数统一为两种形式:微秒级延时函数 _delay_us(unsigned int n)与毫秒级延时函数 _delay_ms(unsigned int n)。注意对于单片机C语言,进出 一个函数所消耗的时间都是几个微秒级的,因此微秒级的延 时函数不可能做的非常精确,尤其是延时长度小于10uS时 基本已经无法使用。此处我们采用带参数的宏定义代替函数 形式来实现微秒级延时,可以适当提高定时精度。

51单片机应用设计与实例

51单片机应用设计与实例



显示缓冲区,小时、分、秒(高位在前)
3CH~3FH 计时缓冲区,时、分、秒、100 ms
40H~42H 闹钟值寄存区,时、分、秒
50H~7FH
PSW.5 PSW.1
堆栈区 计时显示允许位(1:禁止,0:允许) 闹钟标志位(1:正在闹响,0:未闹响)
名称
DISP0~DISP5
HOUR,MIN, SEC,MSEC
片内部还带有非易失性RAM,可用来存放需长期保存但有 时也需变更的数据。由于功能完善,精度高,软件程序设计 相对简单,且计时不占用CPU时间,因此,这一类专用芯片 在工业实时测控系统中多被采用。
方案二:软件控制。 利用MCS-51内部的定时/计数器进行中断定时,配合软 件延时实现时、分、秒的计时。该方案节省硬件成本,且能 够使读者在定时/计数器的使用、中断及程序设计方面得到 锻炼与提高,因此本系统将采用软件方法实现计时。
方案一:串口扩展,LED静态显示。 如图10.1(a)所示,该方案占用口资源少,利用串口扩展 并口,实现静态显示,显示亮度有保证,但硬件开销大,电 路复杂,信息刷新速度慢,比较适用于并行口资源较少的场 合。 方案二:直接接口,LED动态显示。 如图10.1(b)所示,直接使用单片机的并行口作为显示接 口,无需外扩接口芯片,但占用口资源较多,且动态扫描的 显示方式需占用CPU较多的时间,在单片机没有太多外围接 口及实时测控任务的情况下可以采用。
间。 (3) 具备定时启闹功能。 (4) 一天时差不超过1 s。
10.1.2 总体方案 1. 计时方案 方案一:采用实时时钟芯片。 针对计算机系统对实时时钟功能的普遍需求,各大芯片生
产厂家陆续推出了一系列的实时时钟集成电路,如DS1287、 DS12887、DS1302、PCF8563等。这些实时时钟芯片具备年、 月、日、时、分、秒计时功能和多点定时功能,计时数据的更 新每秒自动进行一次,不需程序干预。计算机可通过中断或查 询方式读取计时数据并进行显示,因此计时功能的实现无需占 用CPU的时间,程序简单。此外,实时时钟芯片多数带有锂电 池作后备电源,具备永不停止的计时功能;具有可编程方波输 出功能,可用作实时测控系统的采样信号等;有的实时时钟芯

51单片机C语言编程基础及实例

51单片机C语言编程基础及实例

51单片机C语言编程基础及实例C语言是一门通用计算机编程语言,应用广泛。

下面是小编整理的51单片机C语言编程基础及实例,希望对大家有帮助!单片机的外部结构:DIP40双列直*;P0,P1,P2,P3四个8位准双向I/O引脚;(作为I/O输入时,要先输出高电平)电源VCC(PIN40)和地线GND(PIN20);高电平复位RESET(PIN9);(10uF电容接VCC与RESET,即可实现上电复位)内置振荡电路,外部只要接晶体至X1(PIN18)和X0(PIN19);(频率为主频的12倍)程序配置EA(PIN31)接高电平VCC;(运行单片机内部ROM中的程序)P3支持第二功能:RXD、TXD、INT0、INT1、T0、T1单片机内部I/O部件:(所为学习单片机,实际上就是编程控制以下I/O部件,完成指定任务)四个8位通用I/O端口,对应引脚P0、P1、P2和P3;两个16位定时计数器;(TMOD,TCON,TL0,TH0,TL1,TH1) 一个串行通信接口;(SCON,SBUF)一个中断控制器;(IE,IP)针对AT89C52单片机,头文件AT89x52.h给出了SFR特殊功能寄存器所有端口的定义。

C语言编程基础:十六进制表示字节0x5a:二进制为01011010B;0x6E为01101110。

如果将一个16位二进数赋给一个8位的字节变量,则自动截断为低8位,而丢掉高8位。

++var表示对变量var先增一;var—表示对变量后减一。

x|=0x0f;表示为x=x|0x0f;TMOD=(TMOD&0xf0)|0x05;表示给变量TMOD的低四位赋值0x5,而不改变TMOD的高四位。

While(1);表示无限执行该语句,即死循环。

语句后的分号表示空循环体,也就是{;}在某引脚输出高电平的编程方法:(比如P1.3(PIN4)引脚)代码#include//该头文档中有单片机内部资源的符号化定义,其中包含P1.3voidmain(void)//void表示没有输入参数,也没有函数返值,这入单片机运行的复位入口{P1_3=1;//给P1_3赋值1,引脚P1.3就能输出高电平VCCWhile(1);//死循环,相当LOOP:gotoLOOP;}注意:P0的每个引脚要输出高电平时,必须外接上拉电阻(如4K7)至VCC电源。

单片机模块化编程方法

单片机模块化编程方法

{ TMOD |= 0x01; TH0 = 0x3C; TL0 = 0xB0; ET0 = 1; TR0 = 1; } void timer0(void) interrupt 1 //定时器 0 中断函数 { TH0 = 0x3C; TL0 = 0xB0; //定时器 0 重赋初值 if (TimeCounter != 0) { TimeCounter--; } } 其对应的头文要向 led.c 文件提供 TimeCounter 变量,向 main.c 提 Timer0Config 函数, 因此要在头文件中进行声明,具体内容如下: #ifndef TIMR0_H #define TIMR0_H extern unsigned char TimeCounter; extern void Timer0Config(void); #endif 3.3 串口通信文件 串口配置及中断服务程序 uart.c 文件,该文件的代码如下: #include <reg52.h> #include "uart.h" unsigned char tem = 0; void UartConfig(void) { SCON = 0x50; //串口工作在方式 1,即 10 位收发器模式 PCON = 0x00; //波特率不增倍 TMOD |= 0x20; //定时器 1 做波特率发生器,工作在方式 2 即 8 位自动重装初值模式 TH1 = 0xFD; //定器 1 赋初值 TL1 = TH1; //定时器 0 工作在方式 2,即 16 位计数器 //定时器 0 重赋初值 //使能定时器 0 中断 //开启定时器 0
单片机模块化编程方法
目前我们在学习和开发单片机时广泛采用 c 语言进行编程, 当我们开发的单片机项目较 小时, 或者我们所写的练习程序很小时, 我们总是习惯于将所有代码编写在同一个 c 文件下, 由于程序代码量较少,通常为几十行或者上百行,此时这种操作是可行方便的,也没有什么 问题。但如果要开发的项目较大,代码量上千行或者上万行甚至更大,如果你还继续将所有 代码全部编写在仅有的一个 c 文件下,这种方式的弊病会凸显出来,它会给代码调试、更改 及后期维护都会带来极大的不便。 试想一下, 当你尝试着从几千几万行代码中定位到某一位 置或者去寻找某一错误点,上下拉动巨长的滚动条慢慢地、一点点地浏览整个 c 文件,是件 多么令人眼花缭乱,头昏脑胀的事。模块化编程可解决这个问题,我们只要根据实际需要使 用模块化编程的思维将具有不同功能的程序封装在不同模块中, 将各个不同模块存放在不同 的 c 文件中。模块化编程后的程序不但使整体的程序功能结构清晰明了,同时也提高程序代 码的利用率, 有些模块代码我们可以直接进行移植或者经简单修改就可另作他用, 好比封装 好的函数。 那么什么是模块化呢?首先我们来简单来聊聊模块概念, 我们可能听说过电源模块, 通 信模块,这些是硬件模块,它们都提供一些接口,譬如电源模块会有输出额定电压电流的接 口,通信模块可能提供了 RS232、USB 等接口。那么对软件来说模块是怎样的呢?软件里 的模块跟硬件模块类似,抽象地说就像一个黑盒子,盒子内部细节我们可以不予理会,我们 只关心盒子给我们提供什么东西,即提供了什么接口,利用这些接口我们能实现什么功能。 我们把相对独立, 具有独立功能用代码编写在一个 c 文件下, 把需要对外的函数或变量进行 声明供外部使用,把不需要的细节尽可能对外部屏蔽起来,这就是软件模块化编程的思维。 这样不同的模块占用不同 c 文件,一个个 c 文件将整个项目串接起来实现所有的功能。

51单片机模块化编程设计与实例要点分析

51单片机模块化编程设计与实例要点分析

模块化编程设计题一、简述模块化编程的必要性(模块化的优点)参考答案:大多数的编程学习者一开始接触和学习到的程序很小,代码量很少,甚至只有几十行。

对于这样短小的程序进行模块化设计不是完全必要的。

很多情况下程序模块化设计需要“浪费”很多时间,例如增加了代码的数量,增加了构思的时间。

把所有的程序代码都写在一个main()函数中程序完全可以运行。

但是随着学习的深入,代码量的增加,将所有的代码都放在同一个.C文件中的做法越发使得程序结构混乱,虽然可以运行,但是可读性、可移植性变差。

即使是自己写的程序,时间长以后对程序的阅读和修改也要花一些时间。

模块化编程使得程序的组织结构更加富有层次感,立体感和降低程序的耦合度。

在大规模程序开发中,一个程序由很多个模块组成,很可能,这些模块的编写任务被分配到不同的人。

几乎所有商用程序都必须使用模块化程序设计理念。

在程序的设计过程中各个开发者分工合作,分别完成某一模块特定的功能,减少开发时间等。

二、模块化编程设计步骤(1)、创建头文件在模块化编程中,往往会有多个C文件,而且每个C文件的作用不尽相同。

在我们的C 文件中,由于需要对外提供接口,因此还必须有一些函数或者是变量提供给外部其它文件进行调用。

对于每一个模块都有相应的.c文件和.h文件,为了阅读调试方便,原则上.c文件和.h文件同名,如delay.c和delay.h。

(2)防重复包含例如delay.h文件#ifndef__DELAY_H__#define__DELAY_H__void delay(uint t);#endif假如有两个不同源文件需要调用delay(uint t)这个函数,他们分别都通过#include “delay.h”把这个头文件包含了进去。

在第一个源文件进行编译时候,由于没有定义过delay.h_ 因此#ifndef__DELAY_H__条件成立,于是定义_DELAY_H_ 并将下面的声明包含进去。

在第二个文件编译时候,由于第一个文件包含时候,已经将_DELAY_H_定义过了。

C51的模块化设计方法

C51的模块化设计方法

C51的模块化设计方法C51的模块化设计方法C51的模块化设计方法一个大的单片机程序往往包含很多模块,我是这样组织的:1、每一个C源文件都要建立一个与之名字一样的H文件(头文件),里面仅仅包括该C文件的函数的声明,其他的什么也不会有,比如变量的定义啊等等不应该有。

2、建立一个所有的文件都要共同使用的头文件,里面当然就是单片机的管脚使用的定义,还有里面放那些需要的KEIL系统的头文件,比如#i nclude,#i nclude等等,把这个文件命名为common.h,或者干脆就叫main.h3、每个C源文件应该包含自己的头文件以及那个共同的使用的头文件,里面还放自己本文件内部使用的全局变量或者以extern定义的全局变量4、主文件main.c里面包含所有的头文件包括那个共同使用的文件,main.c里面的函数可以再做一个头文件,也可以直接放在文件的开头部分声明就可以了,里面一般还有中断服务程序也放在main.c里面5、对于那些贯穿整个工程的变量,可以放在那个共同的使用的头文件里面,也可以用extern关键字在某个C源文件里面定义,哪个文件要使用就重复定义一下6、建立工程的时候,只要把C源文件加到工程中,把H文件直接放到相应的目录下面就可以了,不需要加到工程里面。

第一章概述本手册介绍ASM51宏汇编器及用汇编语言开发MCS-51系列单片机软件的过程。

本章概述ASM51宏汇编器及用法。

1.1 模块化程序设计ASM51宏汇编器允许用户以模块方式编程,以适应用户模块化的程序设计。

模块是具有相对独立功能的程序,它能独立进行汇编或编译。

模块化程序设计是将一个大的或复杂的程序分成小的功能模块,每个模块程序单独编写、汇编和调试,最后再将这些模块连接起来,形成一个完整的用户程序。

这样做比单块程序更易编写、调试和修改。

模块程序的开发只需根据模块的输入及输出定义,按其所需的输入并检查其输出以校核模块的正确性。

由于程序具有良好的模块接口,可以把问题限定在模块内,一旦识别出有毛病的模块,解决这个问题就相当简单了。

C51单片机模块化编程万年历设计

C51单片机模块化编程万年历设计

C51单片机模块化编程万年历设计程序如下:main.h#ifndef __MAIN_H__#define __MAIN_H__#include<regx52.h>#include<intrins.h>#include<absacc.h>#define uchar unsigned char #define uint unsigned int#define DQ P3_7#endifds18b20.h#include "main.h"uint sec;uint min=41;uint hour=18;uint day=20;uint month=4;uint yearl=11;uint yearh=20;uint tcnt;uint cursor=0;uchar a=0xff;uchar code Seg[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};void delay(uint t){uint i;while(t--){for (i=0;i<125;i++);}}void Tdelay(unsigned int i){while(i--);}void Kdelay(unsigned int z){uchar i,j;for(i=0;i<z;i++)for(j=248;j>0;j--);}Init_DS18B20(void){unsigned char x = 0;DQ = 1;Tdelay(200);DQ=0;Tdelay(80);DQ=1;Tdelay(200);Tdelay(200);}//读一个字节ReadOneChar(void){unsigned char i=0;unsigned char dat = 0;for (i=8;i>0;i--){DQ = 0;dat>>=1;DQ = 1;if(DQ)dat|=0x80;Tdelay(4);}return(dat);}//写一个字节WriteOneChar(unsigned char dat) {unsigned char i=0;for (i=8; i>0; i--){DQ = 0;DQ = dat&0x01;Tdelay(5);DQ = 1;dat>>=1;}}//读取温度ReadTemperature(void){unsigned char a=0;unsigned char b=0;unsigned int t=0;float tt=0;Init_DS18B20();WriteOneChar(0xCC); WriteOneChar(0x44);Init_DS18B20();WriteOneChar(0xCC); WriteOneChar(0xBE);a=ReadOneChar();b=ReadOneChar();t=b;t<<=8;t=t|a;tt=t*0.0625;t= tt*10+0.5;return(t);}void display(uchar L1,uchar L2,uchar L3,uchar L4,uchar L5,uchar L6,uchar L7,ucharL8,uchar L9,uchar L10,uchar L11,uchar L12,uchar L13,uchar L14,uchar L15,uchar L16) {P2=0x7F;P0=L1;delay(1); //yearhP2=0xBF;P0=L2;delay(1); //yearhif(cursor==6){P2=0xDF;P0=L3;delay(1);}else{P2=0xDF;P0=L3;delay(1);} //yearl if(cursor==6){P2=0xEF;P0=L4;delay(1);}else{P2=0xEF;P0=L4;delay(1);} //yearl if(cursor==5){P2=0xF7;P0=L5;delay(1);}else{P2=0xF7;P0=L5;delay(1);} //month if(cursor==5){P2=0xFB;P0=L6;delay(1);}else{P2=0xFB;P0=L6;delay(1);} //month if(cursor==4){P2=0xFD;P0=L7;delay(1);}else{P2=0xFD;P0=L7;delay(1);} //dayif(cursor==4){P2=0xFE;P0=L8;delay(1);}else{P2=0xFE;P0=L8;delay(1);} //dayP2=0xFF;if(cursor==3){P1=0x7F;P0=L9;delay(1);}else{P1=0x7F;P0=L9;delay(1);} //hourif(cursor==3){P1=0xBF;P0=L10;delay(1);}else{P1=0xBF;P0=L10;delay(1);} //hour if(cursor==2){P1=0xDF;P0=L11;delay(1);}else{P1=0xDF;P0=L11;delay(1);} //minif(cursor==2){P1=0xEF;P0=L12;delay(1);}else{P1=0xEF;P0=L12;delay(1);} //minif(cursor==1){P1=0xF7;P0=L13;delay(1);}else{P1=0xF7;P0=L13;delay(1);} //secif(cursor==1){P1=0xFB;P0=L14;delay(1);}else{P1=0xFB;P0=L14;delay(1);} //secP1=0xFD;P0=L15;delay(1); //tempP1=0xFE;P0=L16;delay(1); //tempP1=0xFF;}main.c#include "main.h"#include "ds18B20.h"void delay(uint t);void Tdelay(unsigned int i);void Kdelay(unsigned int z);Init_DS18B20(void);ReadOneChar(void);WriteOneChar(unsigned char dat);ReadTemperature(void);void display(uchar L1,uchar L2,uchar L3,uchar L4,uchar L5,uchar L6,uchar L7,ucharL8,uchar L9,uchar L10,uchar L11,uchar L12,uchar L13,uchar L14,uchar L15,uchar L16); main(){uint i;TMOD=0x02; //设置模式为定时器T0的模式2 (8位自动重装计数初值的计数TH0=0x06; //设置计数器初值,靠TH0存储重装的计数值X0=256-250=6 TL0=0x06;TR0=1; //启动T0ET0=1; //开启定时器T0中断允许EA=1; //开启中断总控制while(1){if(P3_0==0){Kdelay(200);if(P3_0==0){cursor++;if(cursor>=7){cursor=0;}}}if(P3_1==0){Kdelay(200);if(P3_1==0){if(cursor==1){sec++;if(sec==60)sec=0;}if(cursor==2){min++;if(min==60)min=0;}if(cursor==3){hour++;if(hour==24)hour=0;}if(cursor==4){day++;if(day==31)day=0;}if(cursor==5){month++;if(month==12)month=0;}if(cursor==6){yearl++;if(yearl==100)yearl=0;}if(cursor==7){yearh++;if(yearh==30)yearh=20;}}}if(P3_2==0){Kdelay(200);if(P3_2==0){if(cursor==1){sec--;}if(cursor==2){min--;}if(cursor==3){hour--;}if(cursor==4){day--;}if(cursor==5){month--;}if(cursor==6){yearl--;}if(cursor==7){yearh--;}}i=ReadTemperature();display(Seg[yearh/10],Seg[yearh],Seg[yearl/10],Seg[yearl],Seg[month/10],Seg [month],Seg[day/10],Seg[day],Seg[hour/10],Seg[hour],Seg[min/10],Seg[min],Seg[sec/10 ],Seg[sec],Seg[i/100],Seg[i/10]);}}void t0(void)interrupt 1 using 0 //t0的中断程序{tcnt++;if(tcnt==4000)//定时器的定时计数,4000次250us为1秒{tcnt=0;P3_3=~P3_3;a=~a;sec++;if(sec==60){sec=0;min++;if(min==60){min=0;hour++;if(hour==24){hour=0;day++;if(month==2&&((yearl==0&&yearh%4==0)||(yearl!=0&&yearl%4==0))&& day==30)day=1;else if(month==2&&day==29)day=1;elseif((month==4||month==6||month==9||month==11)&&day==31)day=1;else if(day==32)day=1;if(day==1){month++;if(month==13){month=1;yearl++;if(yearl==100){yearl=0;yearh++;if(yearh==100) {yearh=20; }}}}}}}}}。

51单片机课程设计实例

51单片机课程设计实例

51单片机设计实例二、总原理图及元器件清单2.1、总原理图:2.3、声音部分2.5、继电器三、模块电路分析3.1、硬件模块本系统主要有单片机控制系统、按键模块、串口通信模块、LED 显示模块、交通灯显示模块等组成,如图1所示。

其中,单片机系统为系统的主控制器,用以控制其他模块协调工作;按键模块采用外部中断INTO的方式;串口通信模块采用RS-485接口;LED显示模块用以显示交通灯控制参数;交通灯显示模块用以显示各车道的通行情况。

3.2、单片机控制系统及基本电路本系统采用AT89C52芯片作为核心控制器件。

他的P0、P2口用于数码管显示控制,P1口用于交通灯显示控制,按键处理主要用中断的方式进行,保证该系统的稳定性。

单片机基本外围电路如图2所示3.3、按键控制模块按键控制模块由AT89C52芯片的P3口控制,电路如图2所示。

当某个键按下时产生的负脉冲通过编码器74LS148的GS致使INTO中断,单片机响应这个中断,并读入74LS148的编码信息,从而根据按下不同键进行相应处理。

按键中断程序:按键采用中断的工作方式,当按下某个键时,单片机响应中断,进行相应的处理。

其程序流程如下所示:说明:按键程序调节数码管绿灯的显示时间,按下K1键申请中断,判断是否有K1或者K2键按下,按下K2键执行初始值减一工作,按下K3键执行初始值加一操作,如果K2和K3见都未按下,则判断是否按下K1键,是则中断返回,否则继续重复上面的工作。

3.4、LED显示模块LED显示模块包括控制参数调整显示模块和交叉口倒计时显示模块两部分,此两部分的8位LED均采用动态显示方式,即将所有数码管的段码线相应段并联在一起,接到P0口,用P2口的各位对各个LED进行控制从而实现对LED的定时选通。

3.5、交通灯显示模块整个系统设计如图所示,该系统主要由计数模块、控制模块、分频模块、分位模块以及显示电路构成。

其中分频模块主要将系统输入的基准时钟信号转换为1 Hz的激励信号,驱动计数模块和控制模块工作。

AT89C51单片机编程

AT89C51单片机编程

{ while ((p34&&p35) ! = 0); delay( ); if ((p34&p35) != 0 ) continue; else break; }
/* 下列语句分析被按下的键所在的列号 */ mask = 0xfe; while (1)
{ TI = 0; SBUF = mask; while(TI = = 0); if((p34&&p35) ! = 0)
7.5.2

模块设计原则
若我们把复杂的问题分解成许多容易解决的小问题,复 杂的问题也就容易解决了。但是如果只是简单地分解任务, 不注意对一些子任务的归纳与抽象,不注意模块之间的关系, 往往会使模块数太多,模块之间的关系变得复杂,从而使程 序的调试、修改变得更加复杂。一般说来,模块设计应该遵 从以下几条原则: (1)模块独立 模块的独立性原则应保证模块完成独立的功能,模块与 模块之间关系简单,修改某一模块,不会造成整个程序的混 乱。保证模块的独立性应注意以下几点: ①每个模块完成一个相对独立的特定功能。在对任务分 解时,要注意对问题的综合。 ②模块之间的关系力求简单。例如:模块之间最好只通 过数据传递发生联系,而不发生控制关系。 C 语言中禁止 goto语句作用到另一函数,就是为了保证函数的独立性。
带寄存器参数的函数名加入“ _” 字符前缀,表明这类 函数包含寄存器的参数传递 对于重入函数加上“_?”字符串前缀,表明这类函数包 含栈内的参数传递
void func(void)
_FUNC
void func(void) reentrant
_?FUNC
例2 用汇编语言编写函数"toupper",参数传递发生在寄存器R7中。

8051单片机c语言程序设计与实例解析

8051单片机c语言程序设计与实例解析

8051单片机C语言程序设计与实例解析在现代电子技术领域,单片机是一种应用十分广泛的微处理器,而在单片机的应用中,8051单片机是一种非常经典的代表。

与此C语言作为一种高级编程语言,在单片机的程序开发中也有着广泛的应用。

本文将从8051单片机C语言程序设计的角度,对其进行深度和广度兼具的解析,通过实例来帮助读者更好地理解和掌握这一技术。

1. 8051单片机概述8051单片机是由Intel公司于上世纪80年代推出的一款经典单片机,至今仍然广泛应用于各种领域。

它的特点是体积小、功能强大、接口丰富,以及使用方便等。

在实际应用中,我们可以根据不同的需求选择不同型号的8051单片机,比如常见的AT89S52、AT89C52等。

2. C语言在8051单片机中的应用C语言作为一种高级编程语言,具有结构化、模块化和可移植性等优点,因此在单片机的程序设计中有着广泛的应用。

通过C语言编程,我们可以更轻松地实现对单片机的控制和管理,而且代码的可读性也更好,易于维护和修改。

3. 程序设计与实例解析接下来,我们将结合具体的实例来说明8051单片机C语言程序设计的方法和技巧。

我们可以以LED灯的控制、数码管的显示、蜂鸣器的驱动等为例,详细讲解如何使用C语言编写程序,通过8051单片机实现相应的功能。

我们也可以讲解一些常用的库函数和编程技巧,让读者能够更好地理解和应用这些知识。

4. 个人观点与理解在我看来,8051单片机C语言程序设计是一项非常有趣和有挑战性的工作。

通过编写程序,我们可以将自己的想法转化为现实,实现各种各样的功能,这种成就感是非常有价值的。

掌握了这项技能之后,我们也能够更好地应对各种实际问题,为自己的学习和职业发展打下良好的基础。

总结回顾通过本文的阐述,我们对8051单片机C语言程序设计进行了全面的评估和解析,从基本概念到具体实例,再到个人观点和理解,希望读者能够从中受益。

通过不断地实践和学习,我们相信大家一定能够掌握这一领域的知识,成为优秀的单片机程序设计工程师。

keil C51模块化编程经验总结

keil C51模块化编程经验总结

模块化编程(keil)前言:看过小编前段时间上传的那份有关C51程序书写,介绍#include指令两种写法的区别和使用typedef声明新类型名等方面知识的文档,可能会对#include 指令的两种写法不是很明白。

比如,什么时候适合用“#include<>”,什么时候又适合用“#include""”。

本次小编将通过介绍如何在keil软件里面进行模块化编程来详细说明。

为什么要进行模块化编程:一般而言,一个小程序只包含一个源程序文件,在这个源程序文件中又包含若干个函数(其中有一个是main函数)。

刚开始写程序,很多读者在keil里面编程,几乎都是一个程序一个源程序文件(小编刚开始写程序也是一样滴)。

当然,刚开始写的程序都是些小程序,所以进行模块化编程也没这个必要。

不过随着编程者知识的积累,当尝试着去写大程序时就会发现,当程序规模较大时,所包含的函数的数量较多,如果把所有的函数都放在同一个源程序文件中,则此文件显得太大,不便于编译和调试。

而且有时连自己都会被弄得稀里糊涂的,那就更不用说把程序拿个别人看了。

所以为了便于调试和管理,可以使一个程序包含若干个源程序文件,每个源程序文件又包含若干个函数。

(一个源程序文件就是一个程序模块,即将一个程序分成若干个程序模块。

)接下来小编将通过介绍“数码管模拟时钟”这个程序来给大家详细的介绍三种模块化编程方法:(提示:此次小编介绍的这三种模块化编程方法相互之间是存在着一定的联系的,所以读者最好按照从前及后的顺序浏览,免得看到后面的内容时会很模糊。

另外,虽然文章篇幅很长,但信息量不多,需要注意的知识点可能“藏在了”某些不起眼的地方。

这点小编今后会逐渐完善。

此外,keil版本为UV4,与UV5的不同文中会具体细节具体说明。

)方法一:一个“.c”文件对应一个“.h”文件。

步骤一:(建立源程序文件)新建一个工程后,我们新建一个源程序文件,保存时我们不能像往常那样直接保存在之前建的那个文件夹里面,而是在之前建的那个文件夹里再建一个文件夹。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

模块化编程设计题
一、简述模块化编程的必要性(模块化的优点)
参考答案:
大多数的编程学习者一开始接触和学习到的程序很小,代码量很少,甚至只有几十行。

对于这样短小的程序进行模块化设计不是完全必要的。

很多情况下程序模块化设计需要“浪费”很多时间,例如增加了代码的数量,增加了构思的时间。

把所有的程序代码都写在一个main()函数中程序完全可以运行。

但是随着学习的深入,代码量的增加,将所有的代码都放在同一个.C文件中的做法越发使得程序结构混乱,虽然可以运行,但是可读性、可移植性变差。

即使是自己写的程序,时间长以后对程序的阅读和修改也要花一些时间。

模块化编程使得程序的组织结构更加富有层次感,立体感和降低程序的耦合度。

在大规模程序开发中,一个程序由很多个模块组成,很可能,这些模块的编写任务被分配到不同的人。

几乎所有商用程序都必须使用模块化程序设计理念。

在程序的设计过程中各个开发者分工合作,分别完成某一模块特定的功能,减少开发时间等。

二、模块化编程设计步骤
(1)、创建头文件
在模块化编程中,往往会有多个C文件,而且每个C文件的作用不尽相同。

在我们的C 文件中,由于需要对外提供接口,因此还必须有一些函数或者是变量提供给外部其它文件进行调用。

对于每一个模块都有相应的.c文件和.h文件,为了阅读调试方便,原则上.c文件和.h文件同名,如和。

(2)防重复包含
例如文件
#ifndef__DELAY_H__
#define__DELAY_H__
void delay(uint t);
#endif
假如有两个不同源文件需要调用delay(uint t)这个函数,他们分别都通过#include “”把这个头文件包含了进去。

在第一个源文件进行编译时候,由于没有定义过因此#ifndef__DELAY_H__条件成立,于是定义_DELAY_H_ 并将下面的声明包含进去。

在第二个文件编译时候,由于第一个文件包含时候,已经将_DELAY_H_定义过了。

因此#ifndef__DELAY_H__不成立,整个头文件内容就没有被包含。

假设没有这样的条件编译语句,那么两个文件都包含了delay(uint t);就会引起重复包含的错误。

所以在.h文件中,为了防止出现错误都进行防重复包含。

(3)代码封装
将需要模块化的进行代码封装
头文件的作用可以称其为一份接口描述文件。

其文件内部不应该包含任何实质性的函数代码。

我们可以把这个头文件理解成为一份说明书,说明的内容就是我们的模块对外提供的接口函数或者是接口变量。

同时该文件也包含了一些很重要的宏定义以及一些结构体的信息,离开了这些信息,很可能就无法正常使用接口函数或者是接口变量。

但是总的原则是:不该让外界知道的信息就不应该出现在头文件里(不需要外部调用的函数不在头文件中申明),而外界调用模块内接口函数或者是接口变量所必须的信息就一定要出现在头文件里(需要被外部调用的函数一定要在头文件中申明),否则,外界就无法正确的调用我们提供的接口功能。

(4)使用源文件(将文件加到工程之中)
将.c文件添加到工程之中,同时在需要调用.h文件中的宏或函数的.c文件中将.h文件包含进去(.h文件中的宏和函数可以在.c文件中自由调用)。

三、程序实例
以简单的52单片机LCD例程为例,将下面的程序模块化。

将延时函数独立成一个模块,为了使程序简化,将所有的和LCD相关的函数(包括LCD初始化函数、写命令函数、写数据函数、显示函数等)独立成一个模块。

#include <>
#include <>
#define uchar unsigned char
#define uint unsigned int
sbit rs = P2^5;
sbit rw = P2^6;
sbit e = P2^7;
uint i;
/*********************************************/
void delay1ms(uint z)
{ 文件加入到工程之中编译即可,在工程中可以清楚地看到各个.c文件包含的.h文件,以及各个模块包含的子函数,层次分明,很方便进行调试修改。

相关文档
最新文档