单片机程序的设计

合集下载

MCS-51单片机程序设计

MCS-51单片机程序设计

+1
,当X>0
Y= 0
,当X=0
开始
-1
,当X<0
X=0
N
程序流程框图如图4.1所示。 Y
Y←0
X>0 Y
Y←1
N Y←-1
结束
程序如下: ORG
MOV CJNE MOV AJMP MP1: JB MOV LJMP MP2: MOV HERE: SJMP
1000H A,R0 A,#00H,MP1 R1,#00H HERE ACC.7 MP2 R1,#01H HERE R1,#0FFH HERE
1000H DPTR,#2000H DPL DPH DPTR,#3000H R2,DPL R3,DPH
;源数据区首地址 ;源首址暂存堆栈
;目的数据区首地址 ;目的首址暂存寄存器
LOOP:
POP POP MOVX INC PUSH PUSH MOV MOV MOVX MOV MOV DJNZ SJMP
;源数据区首地址 ;目的数据区首地址 ;循环次数 ;取数据 ;数据传送 ;源地址加1 ;目的地址加1 ;循环控制 ;结束
例4.8 外部RAM之间的数据传送程序。
把外部RAM 2000H开始单元中的数据传送到外部RAM 3000H开始的单 元中,数据个数在内部RAM的35H单元中。
START:
ORG MOV PUSH PUSH MOV MOV MOV
K=?
K=0
K=1
转向 0 分支 转向 1 分支
K= n-1
K=n
转向 n-1 分支 转向 n 分支
例4.5 设内部RAM的30H单元有一个数,根据该数值的不同 转移到不同的程序段进行处理,设数值的范围为0~10的 无符号数。

单片机按键程序设计

单片机按键程序设计

单片机按键程序设计单片机按键的基本原理其实并不复杂。

通常,按键就是一个简单的开关,当按键按下时,电路接通,对应的引脚电平发生变化;当按键松开时,电路断开,引脚电平恢复到初始状态。

在程序设计中,我们需要不断检测引脚的电平变化,从而判断按键是否被按下。

在实际的按键程序设计中,有多种方式可以实现按键检测。

其中一种常见的方法是查询法。

这种方法是通过不断地读取按键对应的引脚状态来判断按键是否被按下。

以下是一个简单的查询法示例代码:```cinclude <reg51h> //包含 51 单片机的头文件sbit key = P1^0; //定义按键连接的引脚void main(){while(1) //无限循环{if(key == 0) //如果按键按下,引脚为低电平{//执行按键按下的操作//比如点亮一个 LED 灯P2 = 0xfe;while(key == 0);//等待按键松开}}}```上述代码中,我们首先定义了按键连接的引脚`key`,然后在主函数的无限循环中不断检测按键引脚的状态。

当检测到按键按下时,执行相应的操作,并通过`while(key == 0)`等待按键松开。

除了查询法,还有中断法可以用于按键检测。

中断法的优点是能够及时响应按键动作,不会因为程序的其他操作而导致按键响应延迟。

```cinclude <reg51h> //包含 51 单片机的头文件sbit key = P1^0; //定义按键连接的引脚void int0_init()//中断初始化函数{IT0 = 1; //下降沿触发中断EX0 = 1; //使能外部中断 0EA = 1; //开总中断}void int0() interrupt 0 //外部中断 0 服务函数{//执行按键按下的操作//比如点亮一个 LED 灯P2 = 0xfe;}void main(){int0_init();//初始化中断while(1);//无限循环,保持程序运行}```在上述代码中,我们首先在`int0_init` 函数中对中断进行了初始化设置,然后在`int0` 函数中编写了按键按下时的处理代码。

单片机c语言程序设计

单片机c语言程序设计

单片机c语言程序设计
单片机C语言程序设计是指使用C语言编写单片机控制程序,实现各种功能和任务。

具体步骤如下:
1. 确定程序功能:首先明确单片机的控制目标和需求,确定要实现的功能。

2. 编写主函数:使用C语言编写一个主函数,作为程序的入
口点。

在主函数中,可以定义变量、调用函数、编写主要的程序逻辑。

3. 初始化设置:在主函数中,进行单片机的初始化设置,包括引脚初始化、时钟设置、模块初始化等。

4. 编写中断服务函数:根据需要,编写中断服务函数。

在中断服务函数中,处理特定的中断事件,例如定时器中断、外部中断等。

5. 编写任务函数:根据程序的需求,编写各个任务函数。

任务函数可以是循环执行的函数,或者是根据事件触发执行的函数。

6. 实现控制逻辑:在任务函数中编写具体的控制逻辑代码,根据需要使用控制语句(如if、switch)和循环语句(如for、while)。

7. 进行调试和测试:完成编写后,进行程序的调试和测试,通过仿真器或者实际连接到单片机的硬件进行测试。

8. 优化和修改:根据测试结果进行程序的优化和修改,改善程序的性能和功能。

9. 生成可执行文件:将C源文件编译成可执行文件,可以直接下载到单片机中运行。

10. 下载和运行:将生成的可执行文件通过下载器下载到目标单片机中,并进行运行测试。

以上是单片机C程序设计的一般步骤,具体的实现方法和内容会根据不同的单片机型号和功能需求而有所不同。

51单片机C程序设计100例

51单片机C程序设计100例

《单片机 C 语言程序设计实训 100 例---基于 8051 和 PROTEUS 仿真》案例
//延时 void DelayMS(uint x) { uchar i; while(x--) { for(i=0;i<120;i++); } } //主程序 void main() { P0=0xfe; while(1) { P0=_crol_(P0,1); //P0 的值向左循环移动 DelayMS(150); } } 03 /* 8 只 LED 左右来回点亮 名称:8 只 LED 左右来回点亮 说明:程序利用循环移位函数_crol_和_cror_形成来回滚动的效果
名称:LED 模拟交通灯 说明:东西向绿灯亮若干秒,黄 灯闪烁 5 次后红灯亮, 红灯亮后,南 北向由红灯变为绿灯,若干秒后南北 向黄灯闪烁 5 此后变红灯,东西向变 绿灯,如此重复。 */ #include<reg51.h> #define uchar unsigned char #define uint unsigned int sbit RED_A=P0^0; //东西向灯 sbit YELLOW_A=P0^1; sbit GREEN_A=P0^2; sbit RED_B=P0^3; //南北向灯 sbit YELLOW_B=P0^4; sbit GREEN_B=P0^5; uchar Flash_Count=0,Operation_Type=1; //闪烁次数,操作类型变量
2 上海师范大学信息与机电工程学院—倪继锋
《单片机 C 语言程序设计实训 100 例---基于 8051 和 PROTEUS 仿真》案例
for(i=0;i<7;i++) { P2=_crol_(P2,1); //P2 的值向左循环移动 DelayMS(150); } for(i=0;i<7;i++) { P2=_cror_(P2,1); //P2 的值向右循环移动 DelayMS(150); } } } 04 /* 花样流水灯

100例单片机程序设计范例汇总

100例单片机程序设计范例汇总

100例程序设计范例汇总第一章 (4)【实例1】使用累加器进行简单加法运算: (4)【实例2】使用B寄存器进行简单乘法运算: (4)【实例3】通过设置RS1,RS0选择工作寄存器区1: (4)【实例4】使用数据指针DPTR访问外部数据数据存储器: (4)【实例5】使用程序计数器PC查表: (4)【实例6】IF语句实例: (4)【实例7】SWITCH-CASE语句实例: (4)【实例8】FOR语句实例: (4)【实例9】WHILE语句实例: (5)【实例10】DO...WHILE语句实例: . (5)【实例11】语句形式调用实例: (5)【实例12】表达式形式调用实例: (5)【实例13】以函数的参数形式调用实例: (5)【实例14】函数的声明实例: (5)【实例15】函数递归调用的简单实例: (5)【实例16】数组的实例: (6)【实例17】指针的实例: (6)【实例18】数组与指针实例: (6)【实例19】P1口控制直流电动机实例 (6)第二章 (8)【实例20】用74LS165实现串口扩展并行输入口 (8)【实例21】用74LS164实现串口扩展并行输出口 (10)【实例22】P0I/O扩展并行输入口 (12)【实例23】P0I/O扩展并行输出口 (12)【实例24】用8243扩展I/O端口 (12)【实例25】用8255A扩展I/O口 (14)【实例26】用8155扩展I/O口 (19)第三章 (26)【实例29】与AT24系列EEPROM接口及驱动程序 (26)【实例30】EEPROM(X5045)接口及驱动程序 (30)【实例31】与铁电存储器接口及驱动程序 (33)【实例32】与双口RAM存储器接口及应用实例 (35)【实例33】与NANDFLASH(K9F5608)接口及驱动程序 (35)第四章 (43)【实例34】独立键盘控制 (43)【实例35】矩阵式键盘控制 (44)【实例36】改进型I/O端口键盘 (46)【实例37】PS/2键盘的控制 (49)【实例39】段数码管(HD7929)显示实例 (54)【实例40】16×2字符型液晶显示实例 (55)【实例41】点阵型液晶显示实例 (61)【实例42】LCD显示图片实例 (63)第五章 (70)【实例43】简易电子琴的设计 (70)【实例44】基于MCS-51单片机的四路抢答器 (71)【实例45】电子调光灯的制作 (76)【实例46】数码管时钟的制作 (81)【实例47】LCD时钟的制作 (96)【实例48】数字化语音存储与回放 (103)【实例49】电子标签设计 (112)第六章 (120)【实例50】指纹识别模块 (121)【实例51】数字温度传感器 (121)第七章 (124)【实例53】超声波测距 (124)【实例54】数字气压计 (125)【实例55】基于单片机的电压表设计 (132)【实例56】基于单片机的称重显示仪表设计 (133)【实例57】基于单片机的车轮测速系统 (136)第八章 (138)【实例58】电源切换控制 (138)【实例59】步进电机控制 (140)【实例60】单片机控制自动门系统 (141)【实例61】控制微型打印机 (144)【实例62】单片机控制的EPSON微型打印头 (144)【实例63】简易智能电动车 (145)【实例64】洗衣机控制器 (149)第九章 (152)【实例65】串行A/D转换 (152)【实例66】并行A/D转换 (153)【实例67】模拟比较器实现A/D转换 (154)【实例68】串行D/A转换 (155)【实例69】并行电压型D/A转换 (156)【实例70】并行电流型D/A转换 (156)【实例71】2I C接口的A/D转换 (157)【实例72】2I C接口的D/A转换 (161)【实例73】单片机间双机通信 (164)【实例74】单片机间多机通信方法之一 (166)【实例75】单片机间多机通信方法之二 (171)【实例76】PC与单片机通信 (176)【实例77】红外通信接口 (178)第十一章 (180)【实例79】单片机实现PWM信号输出 (180)【实例80】实现基于单片机的低频信号发生器 (182)【实例81】软件滤波方法 (183)【实例82】FSK信号解码接收 (186)【实例83】单片机浮点数运算实现 (187)【实例84】神经网络在单片机中的实现 (192)【实例85】信号数据的FFT变换 (194)第十二章 (198)【实例86】2I C总线接口的软件实现 (198)【实例87】SPI总线接口的软件实现 (200)【实例88】1-WIRE总线接口的软件实现 (205)【实例89】单片机外挂CAN总线接口 (207)【实例90】单片机外挂USB总线接口 (210)【实例91】单片机实现以太网接口 (214)【实例92】单片机控制GPRS传输 (221)【实例93】单片机实现TCP/IP协议 (223)第十三章 (229)【实例94】读写U盘 (229)【实例95】非接触IC卡读写 (234)【实例96】SD卡读写 (238)【实例97】高精度实时时钟芯片的应用 (242)第十四章 (247)【实例98】智能手机充电器设计 (247)【实例99】单片机控制门禁系统 (248)第一章【实例1】使用累加器进行简单加法运算:MOV A,#02H ;A←2ADD A,#06H ;A←A+06H【实例2】使用B寄存器进行简单乘法运算:MOV A,#02H ; A←2MOV B,#06H ; B←6MUL AB ; BA←A*B=6*2【实例3】通过设置RS1,RS0选择工作寄存器区1:CLR PSW.4 ; PSW.4←0SETB PSW.5 ; PSW.5←1【实例4】使用数据指针DPTR访问外部数据数据存储器:MOV DPTR, #data16 ; DPTR←data16MOVX A, @ DPTR ; A←((DPTR))MOVX @ DPTR, A ; (DPTR)←A【实例5】使用程序计数器PC查表:MOV A, #data ;A←dataMOVC A, @ A+DPTR ; PC←(PC)+1 ,A←((A)+(PC)) 【实例6】if语句实例:void main(){ int a,b,c,min;printf("\n please input three number:");scanf("%d%d%d ",&a,&b,&c);if(a<b&&a<c) printf("min=%d\n",a );else if(b<a&&b<c) printf("min=%d\n",b);else if(c<a&&c<c) printf("min=%d\n",c);else printf("There at least two numbers are equal\n");}【实例7】switch-case语句实例:void main(){ int num; printf("input one number:");scanf("%d",& num);switch(num){ case 1: printf("num =%d\n", num);break;case 2: printf("num =%d\n", num);break;case 3: printf("num =%d\n", num);break;case 4: printf("num =%d\n", num);break;default: printf("The number is out of the range\n", num);}}【实例8】for语句实例:void main(){ for(int a=10;n>0;a --)printf("%d",a);}【实例9】while语句实例:void main(){ int i=0;while(i<=10) i++;}【实例10】do…while语句实例:void main(){ int i=0;do{ i++;}while(i<=10);}【实例11】语句形式调用实例:void main(){ int i=0; while(i<=10) i++; ……Sum(); /*函数调用*/}【实例12】表达式形式调用实例:void main(){ int a,b,i=0; while(i<=10) i++; ……i=4*Sum(a,b); /*函数调用*/}【实例13】以函数的参数形式调用实例:void main(){ int a,b,c,i=0; while(i<=10) i++; ……i= max(c,Sum(a,b)); /*函数调用*/ }【实例14】函数的声明实例:void main(){ int max(int x,int y); /*函数的声明*/ int a,b,c,i=0; while(i<=10) i++; ……i= max(c,Sum(a,b)); /*函数调用*/ }【实例15】函数递归调用的简单实例:void fun(){ int a=1, result,i;for(i=0;i<10;){ i=a+I;result = fun(); /*函数调用*/}return result;}【实例16】数组的实例:void main(){ char num[3] [3]={{ '','#',''},{'#','','#'},{'','#',''}}; /*定义多维数组*/ int i=0,j=0;for(;i<3;i++){ for(;j<3;j++) printf(“%c”,num[i][j]);printf(“/n”);}【实例17】指针的实例:void main(){ int a=3,*p;p=&a; /*将变量a的地址赋值给指针变量p*/printf(“%d,%d”,a,*p); /*输出二者的数值进行对比*/}【实例18】数组与指针实例:void main(){ int i=3,num[3]={1,2,3},*p;p=num; /*将数组num[]的地址赋值给指针变量p*/result =max(p,3); /*函数调用,计算数组的最大值*/}【实例19】P1口控制直流电动机实例sfr p1=0x90;sbit p10=p1^0;sbit p11=p1^1;void main (){int i, m;int j=100;int k=20;// 正快转for (i=0; i<100; i++){P10=1;for (j=0; j<50; j++){m=0;}}P10=0;for (j=0; j<10; j++){m=0}//正慢转for (i=0; i<100; i++) {P10=1;for (j=0; j<10; j++) {m=0}}p10=0;for (j=0; j<50; j++) {m=0}// 负快转for (i=0; i<100; i++) {p11=1;for (j=0; j<50; j++) {m=0;}}p11=0;for (j=0; j<10; j++) {m=0;}// 负慢转for (i=0; i<100; i++) {p11=1;for (j=0;j<10;j++) {m=0;}}p11=0for (j=0; j<50; j++) {m=0;}}第二章【实例20】用74LS165实现串口扩展并行输入口(1)函数声明管脚定义//---------------------------------------库函数声明,管脚定义------------------------------------------ #include<reg52.h>sbit LOAD=P1^7;//用P1^7控制SH/ 管脚(2)串口初始化函数UART_init()//-------------------------------------------------------------------------------------------------------------- // 函数名称:UART_init()// 功能说明:串口初始化,设定串口工作在方式0//-------------------------------------------------------------------------------------------------------------- void UART_init(void){SCON=0x10;//设串行口方式0,允许接收,启动接收过程ES=0;//禁止串口中断}(3)数据接收函数PA()//-------------------------------------------------------------------------------------------------------------- // 函数名称:PA()// 输入参数:无// 输出参数:返回由并口输入的数据// 功能说明:接收八位串行数据//-------------------------------------------------------------------------------------------------------------- unsigned char PA(void){unsigned char PA_data;LOAD=0;//当P1.7输出低电平,74LS165将并行数据装入寄存器//当中LOAD=1;//当P1.7输出高电平,74LS165在时钟信号下进行移位UART_init();//74LS165工作在时钟控制下的串行移位状态while(RI==0);//循环等待RI=0;PA_data=SBUF;return PA_data;//返回并行输入的数据}(1)函数声明管脚定义//---------------------------------------库函数声明,管脚定义------------------------------------------ #include<reg52.h>sbit a7=ACC^7;sbit simuseri_CLK=P1^6;//用P1^6模拟串口时钟sbit simuseri_DATA=P1^5;//用P1^5模拟串口数据sbit drive74165_LD=P1^7;//用P1^7控制SH/ 管脚(2)数据输入函数in_simuseri()//-------------------------------------------------------------------------------------------------------------- // 函数名称:in_simuseri()// 输入参数:无// 输出参数:data_buf// 功能说明:8位同位移位寄存器,将simuseri_DATA串行输入的数据按从低位到// 高位// 保存到data_buf//-------------------------------------------------------------------------------------------------------------- unsigned char in_simuseri(void){unsigned char i;unsigned char data_buf;i=8;do{ACC=ACC>>1;for(;simuseri_CLK==0;);a7= simuseri_DA TA;for(;simuseri_CLK==1;);}while(--i!=0);simuseri_CLK=0;data_buf=ACC;return(data_buf);}(3)数据输出函数PAs()//-------------------------------------------------------------------------------------------------------------- // 函数名称:PAs()// 输入参数:无// 输出参数:PAs _buf,返回并行输入74LS165的数据// 功能说明:直接调用,即可读取并行输入74LS165的数据,不需要考虑74LS165的// 工作原理//--------------------------------------------------------------------------------------------------------------unsigned char PAs(void){unsigned char PAs_buf;drive74165_LD=0;drive74165_LD=1;PAs_buf= in_simuseri();return(PAs_buf);}【实例21】用74LS164实现串口扩展并行输出口单片机串口驱动74LS164的程序主要包括函数声明管脚定义部分、串口初始化函数以及数据发送函数。

第3章51系列单片机程序设计(C语言部分)

第3章51系列单片机程序设计(C语言部分)

idata
间接寻址片内数据存储区,可访问片内全部RAM地址空间(256字节)
pdata
分页寻址片外数据存储区(256字节)由MOV @Ri访问(i=0,1)
xdata
片外数据存储区(64 KB)由MOVX @DPTR访问
code
程序存储器64 KB空间,由MOVC @DPTR访问
第3章 51系列单片机程序设计(C部分)
/* Ary37定义为abry[3]的第7位 */
第3章 51系列单片机程序设计(C部分)
3.5 数 组
数组:数组是一组类型相同 有序数据的集合。用数组名 和下标来唯一确定数组中的 元素。
第3章 51系列单片机程序设计(C部分)
3.5.1 一维数组
一、一维数组的定义 形式:类型说明符 数组名 [常量表达式]
使用C51进行编程时,MCS-51片内的I/O口与片外扩展的I/O可以统一在一个头文 件中定义,也可以在程序中(一般在开始的位置)进行定义。
对于MCS-51片内I/O口按特殊功能寄存器方法定义。 例如:
sfr P0=0x80 ; /* 定义P0口,地址为80H */ sfr P1=0x90 ; /* 定义P1口,地址为90H */
第3章 51系列单片机程序设计(C部分)
3.4.3 C51数据的存储类型与MCS-51存储结构
表 3.4.2 C51存储类型与MCS-51存储空间的对应关系
存储类型 与存储空间的对应关系
data
直接寻址片内数据存储区,访问速度快(128字节)
bdata
可位寻址片内数据存储区,允许位与字节混合访问(16字节)
据 浮点型(float) 类
型 指针类型
详细见表3.4.1

单片机程序设计规范与技巧

单片机程序设计规范与技巧

单片机程序设计规范与技巧单片机程序设计规范与技巧本文档旨在提供单片机程序设计的规范和技巧,帮助开发人员编写高质量的单片机程序。

以下为详细的内容。

一、程序设计规范1.1 命名规范1.1.1 使用有意义的变量、函数和文件名1.1.2 采用驼峰命名法或下划线命名法1.1.3 避免使用保留关键字作为命名1.1.4 使用全大写字母表示常量1.1.5 使用规定的前缀表示不同类型的变量或函数1.2 注释规范1.2.1 在代码中添加适当的注释解释功能或算法1.2.2 使用清晰明了的语言和常见的注释格式1.2.3 避免添加与代码功能不符的注释1.3 代码编写规范1.3.1 模块化设计,实现功能相对独立的代码模块1.3.2 使用合适的数据结构和算法1.3.3 避免使用全局变量,使用局部变量和函数传参来保持代码的可读性和可维护性1.3.4 严格遵守禁止使用硬编码的原则,使用宏定义或常量来定义硬编码的值1.3.5 通过代码缩进和空格来提高代码的可读性二、技巧2.1 变量的初始化2.1.1 所有变量都应该被初始化,避免使用随机值2.1.2 在适当的时机进行变量的重置,保证代码的可靠性2.2 代码复用2.2.1 提取公共代码作为函数或宏定义,避免重复编写代码2.2.2 将通用的功能模块封装成库,方便多个项目的复用2.3 资源优化2.3.1 合理使用闲置资源,如定时器、中断等2.3.2 避免使用过多的全局变量和动态内存分配,减小内存占用2.3.3 优化算法和数据结构,提高代码的执行效率和响应速度3、附件本文档涉及的附件包括示例代码、库文件和文档。

请参考附件中的相关内容。

4、法律名词及注释4.1 法律名词:本文档中涉及的法律名词包括但不限于版权、专利和商标等。

这些名词在不同国家和地区可能有不同的定义和适用法规。

5、全文结束。

单片机程序设计编程规范

单片机程序设计编程规范

单片机程序设计编程规范单片机程序设计编程规范1.文件结构与命名规范1.1 源码文件- 所有源码文件统一使用英文小写字母命名。

- 文件名应简洁明了,能够清晰表达文件的功能。

- 文件名中可以使用下划线 (_) 连接多个单词。

1.2 头文件- 头文件名与源码文件名相同,但使用大写字母命名。

- 头文件应包含必要的宏定义、类型定义、函数声明等。

1.3 项目结构- 源码文件应按功能模块进行组织和管理,每个模块应放在独立的文件夹中。

- 在项目的根目录下添加一个README文件,对项目进行简要说明。

2.编码规范2.1 缩进与空格- 使用4个空格进行缩进,不使用Tab字符。

- 在操作符前后添加空格,增加可读性。

2.2 函数命名- 函数名使用小写字母命名,单词之间使用下划线 (_) 连接。

- 函数名应能够清晰表达函数的功能。

2.3 变量命名- 变量名使用小写字母命名,单词之间使用下划线 (_) 连接。

- 变量名应简洁明了,能够清晰表达变量的用途和含义。

- 全局变量命名应以g_开头。

2.4 常量命名- 常量名使用全大写字母命名,单词之间使用下划线(_) 连接。

2.5 注释规范- 使用注释来解释代码的意图、功能和实现细节。

- 在关键代码处添加注释,并保持注释与代码的同步更新。

- 注释应写在被注释代码的上方,并使用// 或 / /注释符号。

3.函数设计3.1 函数长度- 函数应尽量保持简短,避免超过一页纸的长度。

- 如果函数过长,应考虑将其拆分为多个较小的函数。

3.2 函数参数- 函数参数应尽量少,并且要考虑参数的顺序和类型。

- 不要在函数参数中使用全局变量,尽量使用局部变量。

3.3 函数返回值- 函数的返回值应具有明确的含义,并清晰地传达函数的执行结果。

4.异常处理与错误消息4.1 异常处理- 对可能发生异常的代码块进行适当的异常处理。

- 使用try-catch块捕获异常,并进行相应的处理或记录。

4.2 错误消息- 提供清晰、准确的错误消息,以便于调试和修复问题。

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

单片机程序的设计程序设计是单片机开发最重要的工作,程序设计就是利用单片机的指令系统,根据应用系统(即目标产品)的要求编写单片机的应用程序,其实我们前面已经开始这样做过了,这一课我们不是讲如何来设计具体的程序,而是教您设计单片机程序的基本方法。

不过在讲解之前还是有必要先了解一下单片机的程序设计语言。

一.程序设计语言这里的语言与我们通常理解的语言是有区别的,它指的是为开发单片机而设计的程序语言,如果您没有学过程序设计可能不太明白,我给大家简单解释一下,您知道微软的VB,VC吗?VB,VC就是为某些工程应用而设计的计算机程序语言,通俗地讲,它是一种设计工具,只不过这种工具是用来设计计算机程序的。

要想设计单片机的程序当然也要有这样一种工具(说设计语言更确切些)单片机的设计语言基本上有三类:1.完全面向机器的机器语言机器语言就是能被单片机直接识别和执行的语言,计算机能识别什么?以前我们讲过--是数字"0"或"1",所以机器语言就是用一连串的"0"或"1"来表示的数字。

比如:MOV A,40H;用机器语言来表示就是11100101 0100000,很显然,用机器语言来编写单片机的程序不太方便,也不好记忆,我们必须想办法用更好的语言来编写单片机的程序,于是就有了专门为单片机开发而设计的语言:2.汇编语言汇编语言也叫符号化语言,它使用助记符来代替二进制的"0"和"1",比如:刚才的MOV A,40H就是汇编语言指令,显然用汇编语言写成的程序比机器语言好学也好记,所以单片机的指令普遍采用汇编指令来编写,用汇编语言写成的程序我们就叫它源程序或源代码。

可是计算机不能识别和执行用汇编语言写成的程序啊?怎么办?当然有办法,我们可以通过"翻译"把源代码译成机器语言,这个过程就叫做汇编,汇编工作现在都是由计算机借助汇编程序自动完成的,不过在以前,都是靠手工来做的。

值得注意的是,汇编语言也是面向机器的,它仍是一种低级语言。

每一类计算机都有它自己的汇编语言,比如:51系列有它的汇编语言,PIC系列也有它的汇编语言,微机也有它自己的汇编语言,它们的指令系统是各不相同的,也就是说,不同的单片机有不同的指令系统,它们之间是不通用的,这就是为什么世界上有很多单片机类型的缘故。

为了解决这个问题,人们想了很多的办法,设计了许多的高级计算机语言,而其中最适合单片机编程的要数C语言。

3.C语言-高级单片机语言C语言是一种通用的计算机程序设计语言,它既可以用来编写通用计算机的系统程序,也可以用来编写一般的应用程序,由于它具有直接操作计算机硬件的功能,所以非常适合用来编写单片机程序,与其他的计算机高级程序设计语言相比,它具有以下的特点:(1)。

语言规模小,使用简单在现有的计算机设计程序中,C语言的规模是最小的,ANSIC标准的C语言一共只有32个关键字,9种控制语句,然而它的书写形式却比较灵活,表达方式简洁,使用简单的方法就可以构造出相当复杂的数据类型和程序结构。

(2)。

可以直接操作计算机硬件C语言能够直接访问单片机的物理空间地址(KEIL C51软件中的C51编译器更具有直接操作51单片机内部存储器和I/O口的能力),亦可直接访问片内或片外存储器,还可以进行各种位操作。

(3)。

表达能力强,表达方式灵活C语言有丰富的数据结构类型,可以采用整型、实型、字符型、数组类型、指针类型、结构类型、联合类型、枚举类型等多种数据类型来实现各种复杂数据结构的运算。

利用C语言提供的多种运算符,我们可以组成各种表达式,还可以采用多种方法来获得表达式的值,从而使程序设计具有更大的灵活性。

(4)。

可进行结构化设计单片机教程(MCS-51系列)结构化程序是单片机程序设计的组成部分,C语言中的函数相当于汇编语言中的子程序,KEIL C51的编译器提供了一个函数库,其中包含有许多标准函数,如各种数学函数、标准输入输出函数等,此外还可以根据用户需要编制满足某种特殊需要的自定义函数。

C语言程序就是由许多个函数组成的,一个函数即相当于一个程序模块,所以C语言可以很容易地进行结构化程序设计。

(5)。

可移植性前面我们讲过,由于单片机的结构不同,所以不同类型的单片机就要用不同的汇编语言来编写程序,而C语言则不同,它是通过汇编来得到可执行代码的,所以不同的机器上有80%的代码是公用的,一般只要对程序稍加修改,甚至不加修改就可以方便地把代码移植到另一种单片机中。

这对于已经掌握了一种单片机的编程原理,又想用另一种单片机的人来说,可以大大地缩短学习周期,我们将在教程的下册中专门来讲解C语言的应用及其编程原理。

不过作为单片机初学者想要学会C语言并不是一件容易的事,因此对于大多数人来说,汇编语言仍是编写单片机程序的主要语言。

我们上册的教程将全部以汇编语言来编写单片机的程序。

了解了单片机编程的设计语言,下面我们来看单片机编程的基本过程和步骤。

二.单片机程序设计的步骤单片机的程序设计通常包括根据任务建立数学模型、绘制程序流程图、编写程序及汇编三个步骤。

1.建立数学模型数学实在是太有用了,在单片机的程序设计领域,根据任务建立数学模型是程序设计的关键工作。

比如,在一个测量系统中,从模拟通道输入的温度、压力、流量等信息与该信号的实际值是非线性关系,这就需要我们对其进行线性化处理,此时就要用到指数和函数等数学变量来进行计算;再比如,在直接数字化控制的系统中,常采用PID控制算法来进行系统的运算,此时又要用到数学中的微分和积分运算等等。

因此,数学模型对于单片机的程序设计是非常重要的。

只不过作为初学者,我们还没有复杂到如此程度,因此,详细的内容就不讲解了。

下面的绘制程序流程图可是初学者的基本功,请大家务必仔细看一下。

2.绘制流程图所谓流程图,就是用各种符号、图形、箭头把程序的流向及过程用图形表示出来。

绘制流程图是单片机程序编写前最重要的工作,通常我们的程序就是根据流程图的指向采用适当的指令来编写的,下面的图形和箭头就是我们绘制流程图用的工具(图中左边所示)。

绘制流程图时,首先画出简单的功能流程图(粗框图),再对功能流程图进行扩充和具体化,即对存储器、标志位等单元做具体的分配和说明,把功能图上的每一个粗框图转化为具体的存储器或单元,从而绘制出详细的程序流程图,即细框图。

下面举个例子给大家演示一下,请看下面的程序:主程序:LOOP:SETB P1.0;LCALL DELAY;CLR P1.0;LCALL DELAY;LJMP LOOP;子程序:DELAY:MOV R7,#250;D1:MOV R6,#250;D2:DJNZ R6,D2;DJNZ R7,D1;RET;END。

还记得吗,这是我们第四课中做过的LED灯闪烁的实验,以前我们曾对程序进行过分析,现在让我们用流程图来把这段程序的主程序部分画出来,看上图的右边部分。

这就是程序的流程图,在单片机的编程过程中,绘制流程图能看清楚程序执行的步骤以及程序的流向,事实上,程序的编写就是根据流程图的功能完成的。

下面我们来把第十五课中的那个程序也用流程图画出来。

程序如下:ORG 0000H;LJMP START;ORG 30H;START:MOV SP,#5FH;MOV P1,#0FFH;MOV P3,#0FFH;L1:JNB P3.5,L2;P3.5上接有一只按键,它按下时,P3.5=0 JNB P3.6,L3;P3.6上接有一只按键,它按下时,P3.6=0 LJMP L1;L2:CLR P1.0;亮LED1 LJMP L1;L3:SETB P1.0;暗LED1 LJMP L1;END。

先不看图,自己画一下,看是不是同我画的一样。

在实际的程序设计中,根据框图,采用适当的指令编写出实现流程图的源程序就是我们编写程序的最后工作。

3.编写程序和汇编程序编写完之后,我们要把它汇编成机器语言,这种机器语言就是十六进制文件,后缀名为*.HEX文件,以前还要把它转换成二进制文件,后缀名为*.BIN文件,不过现在的编程器都能直接读入十六进制文件,就不需要转换了,最后用编程器把程序写入单片机。

这些以前都讲过了,这里就不重复了。

下面来讲本课的主题-程序设计的方法。

单片机程序设计的方法要想搞清楚程序设计的方法,我们首先要知道单片机到底有哪几类程序?单片机的程序分为结构化程序、子程序和综合程序三个大类,先来看结构化程序。

1.结构化程序的设计方法在单片机的程序中,既有复杂的程序,也有简单的程序,但不论哪种程序,它们都是由一个个基本的程序结构组成的,这些基本结构有顺序结构、分支结构和循环结构。

(1)。

顺序结构程序的设计顺序结构的程序一般用来处理比较简单的算术或逻辑问题,它的执行过程是按照程序存储器PC自动加1的顺序执行的,主要用数据传递类指令和数据运算类指令来实现。

比如我们前面第六课中的I/O口输入实验就是典型的顺序结构的程序。

试试看,把这个程序的流程图写出来。

下面再看一个例子:将内部RAM中20H单元和30H单元的无符号数相加,存入R0(高位)和R1(低位)中。

先画出流程图:根据流程图编写源代码如下:MOV A,20H;ADD A,30H;MOV R0,A;CLR A;ADDC A,#00H;MOV R0,A;MOV A,30H;ADD A,R1;MOV R1,A;CLR A;ADDC A,R0;MOV R0,A;这就是顺序结构程序,程序的原理我就不分析了,我们接着讲分支结构的程序设计。

这里说明一点,最近有朋友提出这一课的有些程序看不懂,的确如此,这一课的有几个程序实例我们从来没有学过,之所以放在这里,原本是为了让大家理解程序设计的方法,举几个示例证明一下,没想到反而增加了大家的难度。

其实这些示例你不需要刻意的去理解它,只要明白它的设计方法就可以了,因为这一张的主要内容是程序设计的方法,而不是程序执行的原理和结果。

如果以后有更好的示例我会修改一下。

(2)。

分支结构程序的设计所谓分支结构就是利用条件转移指令,使程序执行某一指令后,根据所给的条件是否满足来改变程序执行的顺序,也就是本条指令执行完后,并不是象顺序结构那样执行下一条指令,而是看本条指令所给的条件是否满足,如果满足条件就跳转到其他的指令,如果不满足就顺序执行;当然也可以是满足条件顺序执行,而不满足条件跳转执行,看十五课实验程序中的下面两条:L1:JNB P3.5,L2;P3.5上接有一只按键,它按下时,P3.5=0 JNB P3.6,L3;P3.6上接有一只按键,它按下时,P3.6=0这就是分支结构的程序,如果P3.5为"0",就转移;反之就顺序执行。

相关文档
最新文档