51单片机模块化编程设计与实例要点分析
- 格式:doc
- 大小:17.00 KB
- 文档页数:2
项目三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个字符。
单片机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 代码框架。
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熄灭。
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电源。
模块化编程设计题一、简述模块化编程的必要性(模块化的优点)参考答案:大多数的编程学习者一开始接触和学习到的程序很小,代码量很少,甚至只有几十行。
对于这样短小的程序进行模块化设计不是完全必要的。
很多情况下程序模块化设计需要“浪费”很多时间,例如增加了代码的数量,增加了构思的时间。
把所有的程序代码都写在一个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的模块化设计方法一个大的单片机程序往往包含很多模块,我是这样组织的: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单片机模块化编程万年历设计程序如下: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单片机设计实例二、总原理图及元器件清单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的激励信号,驱动计数模块和控制模块工作。
模块化编程设计题
一、简述模块化编程的必要性(模块化的优点)
参考答案:
大多数的编程学习者一开始接触和学习到的程序很小,代码量很少,甚至只有几十行。
对于这样短小的程序进行模块化设计不是完全必要的。
很多情况下程序模块化设计需要“浪费”很多时间,例如增加了代码的数量,增加了构思的时间。
把所有的程序代码都写在一个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文件,以及各个模块包含的子函数,层次分明,很方便进行调试修改。