




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
单片机的C语言应用程序设计1C51数据类型及在51中的存储方式
2C51数据的存储类型与51存储结构351特殊功能寄存器(SFR)的C51定义451并行接口的C51定义5位变量的C51定义6中断应用的C语言编程7定时器/计数器的应用编程851片外扩展的C语言编程951机串行通信的C语言编程10键盘和数码显示人机交互的C语言编程1.C51数据类型及在51中的存储方式1.1C51的数据类型C51编译器具体支持的数据类型有:位型(bit)、无符号字符(unsignedchar)、有符号字符(singedchar)、无符号整型(unsignedint)、有符号整型(signedint)、无符号长整型(unsignedlong)、有符号长整型(signedlong)、浮点型(float)和指针类型等。C51的数据类型数据类型长度(bit)长度(byte)值域bit110,1unsignedchar810~255signedchar81–128~127unsignedint1620~65535signedint162–32768~32767unsignedlong3240~4294967295signedlong324–2147483648~2147483647float324±1.176E–38~±3.40E+38(6位数字)double648±1.176E–38~±3.40E+38(10位数字)一般指针243存储空间0~655351.2C51数据的存储类型与51存储结构C51存储类型与MCS-51存储空间的对应关系存储类型与存储空间的对应关系data直接寻址片内数据存储区,访问速度快(128字节)bdata可位寻址片内数据存储区,允许位与字节混合访问(16字节)idata间接寻址片内数据存储区,可访问片内全部RAM地址空间(256字节)pdata分页寻址片外数据存储区(256字节)由MOV@Ri访问(i=0,1)xdata片外数据存储区(64KB)由MOVX@DPTR访问code程序存储器64KB空间,由MOVC@DPTR访问C51存储类型及其数据长度和值域存储类型长度(bit)长度(byte)值域范围data810~255idata810~255pdata810~255xdata1620~65535code1620~65535带存储类型的变量的定义的一般格式为数据类型存储类型变量名带存储类型的变量定义举例:chardatavar1;bitbdataflags;floatidatax,y,z;unsignedintpdatavar2;unsignedcharvector[3][4];1.351特殊功能寄存器(SFR)的C51定义MCS-51单片机中,除了程序计数器PC和4组工作寄存器组外,其它所有的寄存器均为特殊功能寄存器(SFR),分散在片内RAM区的高128字节中,地址范围为80H~0FFH。SFR中有11个寄存器具有位寻址能力,它们的字节地址都能被8整除,即字节地址是以8或0为尾数的。为了能直接访问这些SFR,C51提供了一种自主形式的定义方法,这种定义方法与标准C语言不兼容,只适用于对MCS-51系列单片机进行C语言编程。特殊功能寄存器C51定义的一般语法格式如下: sfrsfr-name=intconstant;"sfr"是定义语句的关键字,其后必须跟一个MSC-51单片机真实存在的特殊功能寄存器名,"="后面必须是一个整型常数,不允许带有运算符的表达式,是特殊功能寄存器"sfr-name"的字节地址,这个常数值的范围必须在SFR地址范围内,位于0x80~0xFF。例如:sfrSCON=0x98; /*串口控制寄存器地址98H*/sfrTMOD=0x89; /*定时器/计数器方式控制寄存器地址89H*/对于位寻址的SFR中的位,C51的扩充功能支持特殊位的定义,像SFR一样不与标准C兼容,使用“sbit”来定义位寻址单元。有三种表达方式第一种格式:sbitbit-name=sfr-name^intconstant;"sbit"是定义语句的关键字,后跟一个寻址位符号名(该位符号名必须是MCS-51单片机中规定的位名称),"="后的"sfr-name"必须是已定义过的SFR的名字,"^"后的整常数是寻址位在特殊功能寄存器"sfr-name"中的位号,必须是0~7范围中的数。例如:sfrPSW=0xD0; /*定义PSW寄存器地址为D0H*/sbitOV=PSW^2; /*定义OV位为PSW.2,地址为D2H*/sbitCY=PSW^7; /*定义CY位为PSW.7,地址为D7H*/第二种格式:sbitbit-name=intconstant^intconstant;"="后的intconstant为寻址地址位所在的特殊功能寄存器的字节地址,"^"符号后的intconstant为寻址位在特殊功能寄存器中的位号。例如:sbitOV=0XD0^2; /*定义OV位地址是D0H字节 中的第2位*/sbitCY=0XD0^7; /*定义CY位地址是D0H字节中 的第7位*/第三种格式:sbitbit-name=intconstant;"="后的intconstant为寻址位的绝对位地址。例如:sbitOV=0XD2; /*定义OV位地址为D2H*/sbitCY=0XD7; /*定义CY位地址为D7H*/特殊功能位代表了一个独立的定义类,不能与其它位定义和位域互换。1.451并行接口的C51定义MCS-51系列单片机并行I/O接口除了芯片上的4个I/O口(P0~P3)外,还可以在片外扩展I/O口。MCS-51单片机I/O口与数据存储器统一编址,即把一个I/O口当作数据存储器中的一个单元来看待。对于MCS-51片内I/O口按特殊功能寄存器方法定义。例如:sfrP0=0x80;/*定义P0口,地址为80H*/sfrP1=0x90;/*定义P1口,地址为90H*/对于片外扩展I/O口,则根据硬件译码地址,将其视作为片外数据存储器的一个单元,使用#define语句进行定义。例如#include<absacc.h>#definePORTAXBYTE[0xFFC0]absacc.h是C51中绝对地址访问函数的头文件,将PORTA定义为外部I/O口,地址为FFC0H,长度为8位。一旦在头文件或程序中对这些片外I/O口进行定义后,在程序中就可以自由使用变量名与其实际地址的联系,以便使程序员能用软件模拟51的硬件操作。1.551内部资源使用的C语言编程(1)中断应用的C语言编程C51编译器支持在C源程序中直接开发中断程序。中断服务程序是通过按规定语法格式定义的一个函数。中断服务程序的函数定义的语法格式如下:返回值函数名([参数])interruptm[usingn]{
}…MCS-51中断源编号编号中断源入口地址0外部中断00003H1定时器/计数器0000BH2外部中断10013H3定时器/计数器1001BH4串行口中断0023H
usingn选项用于实现工作寄存器组的切换,n是中断服务子程序中选用的工作寄存器组号(0~3)。在许多情况下,响应中断时需保护有关现场信息,以便中断返回后,能使中断前的源程序从断点处继续正确地执行下去。这在MCS-51单片机中,能很方便地利用工作寄存器组的切换来实现。即在进入中断服务程序前的程序中使用一组工作寄存器,进入中断服务程序后,由"usingn"切换到另一组寄存器,中断返回后又恢复到原寄存器组。这样互相切换的两组寄存器中的内容彼此都没有被破坏。扩展多个中断源例下图示是利用优先权解码芯片,在单片机8031的一个外部中断INT1上扩展多个中断源的原理电路图。图中是以开关闭合来模拟中断请求信号。当有任一中断源产生中断请求,能给8031的INT1引脚送一个有效中断信号,由P1的低3位可得对应中断源的中断号。在中断服务程序中仅设置标志,并保存I/O口输入状态。C51编译器提供定义特定MCS-51系列成员的寄存器头文件。MCS-51头文件为reg51.h。C51程序如下:#include<reg51.h>unsignedcharstatus;bitflag;voidservice_int1()interrupt2using2 /*INT1中断服务程序,使用第2组工 作寄存器*/{flag=1; /*设置标志*/status=p1; /*存输入口状态*/}voidmain(void){IP=0x04; /*置INT1为高优先级中断*/IE=0x84; /*INT1开中断,CPU开中断*/for(;;){if(flag) /*有中断*/{switch(status) /*根据中断源分支*/{case0:break; /*处理IN0*/case1:break; /*处理IN1*/case2:break; /*处理IN2*/case3:break; /*处理IN3*/…default:;}flag=0; /*处理完成清标志*/}}}
1.6定时器/计数器(T/C)应用的C语言编程例设单片机的fosc=12MHz晶振,要求在P1.0脚上输出周期为2ms的方波。周期为2ms的方波要求定时时间隔1ms,每次时间到P1.0取反。机器周期=12/fosc=1μs需计数次数=1000/(12/fosc)=1000/1=1000由于计数器是加1计数,为得到1000个计数之后的定时器溢出,必须给定时器置初值为-1000(即1000的补数)。(1)用定时器0的方式1编程,采用查询方式,程序如下:
#include<reg51.h>sbitP1_0=P1^0;voidmain(void){TMOD=0x01; /*设置定时器1为非门控制方式1*/TR0=1; /*启动T/C0*/for(;;){TH0=-(1000/256); /*装载计数器初值*/TL0=-(1000%256);while(!TF0); /*查询等待TF0置位*/P1_0=!P1_0; /*定时时间到P1.0反相*/TF0=0; /*软件清TF0*/}}(2)用定时器0的方式1编程,采用中断方式。程序如下:#include<reg51.h>sbitP1_0=P1^0;voidtime(void)interrupt1using1/*T/C0中断服务程序入口*/{P1_0=!P1_0; /*P1.0取反*/TH0=-(1000/256);
TL0=-(1000%256); /*重新装载计数初值*/}voidmain(void){TMOD=0x01; /*T/C0工作在定时器非门控制方式1*/P1_0=0;TH0=-(1000/256); /*预置计数初值*/TL0=-(1000%256);EA=1; /*CPU中断开放*/ET0=1; /*T/C0中断开放*/TR0=1; /*启动T/C0开始定时*/do{}while(1); /*等待中断*/}例采用10MHz晶振,在P1.0脚上输出周期为2.5s,占空比20%的脉冲信号。10MHz晶振,使用定时器最大定时几十毫秒。取10ms定时,周期2.5s需250次中断,占空比20%,高电平应为50次中断。10ms定时,晶振fosc=10MHz。#include<reg51.h>#defineucharunsignedcharucharperiod=250;ucharhigh=50;timer0()interrupt1using1 /*T/C0中断服务程序*/{TH0=-8333/256; /*重置计数值*/TL0=-8333%256;if(++time==high)P1=0; /*高电平时间到变低*/elseif(time==period) /*周期时间到变高*/{time=0;P1=1;}}main(){TMOD=0x01; /*定时器0方式1*/TH0=-8333/256; /*预置计数初值*/TL0=-8333%256;EA=1; /*开CPU中断*/ET0=1; /*开T/C0中断*/TR0=1; /*启动T/C0*/P1=1;do{}while(1);}中断服务程序流程图
1.751数据采集的C语言编程例ADC0809与8031接口的数据采集程序举例。程序如下:#include<absacc.h>#include<reg51.h>#defineucharunsignedchar#defineIN0XBYTE[0x7ff8] /*设置AD0809的通道0地址*/sbitad_busy=P3^3; /*即EOC状态*/voidad0809(ucharidata*x) /*采样结果放指针中的A/D采集函数*/{uchari;ucharxdata*ad_adr;ad_adr=&IN0;for(i=0;i<8;i++) /*处理8通道*/{*ad_adr=0; /*启动转换*/ i=i; /*延时等待EOC变低*/i=i;while(ad_busy==0);/*查询等待转换结束*/x[i]=*ad_adr; /*存转换结果*/ad_adr++; /*下一通道*/}}voidmain(void){staticucharidataad[10];ad0809(ad); /*采样AD0809通道的值*/}1.851输出控制的C语言编程例8031与DAC0832双缓冲接口的数据转换程序举例。将data1和data2数据同时转换为模拟量的C51程序如下:#include<absacc.h>#include<reg51.h>#defineINPUTR1XBYTE[0x8fff]#defineINPUTR2XBYTE[0xa7ff]#defineDACRXBYTE[0x2fff]#defineucharunsignedcharvoiddac2b(data1,data2)uchardata1,data2;{INPUTR1=data1; /*送数据到一片0832*/INPUTR2=data2; /*送数据到另一片0832*/DACR=0; /*启动两路D/A同时转换*/}例8031与DAC0832单缓冲区接口的数据转换举例。按片选线确定FFFEH为DAC0832的端口地址。使运行输出端输出一个锯齿波电压信号的C51程序如下:#include<reg51.h>#defineDA0832XBYTE[0xfffe]#defineucharunsignedchar#defineuintunsignedintvoidmain(void){uchari;while(1){for(i=0;i<=255;i++) /*形成锯齿波输出值,最大值为255*/DA0832=i; /*D/A转换输出*/}}1.951机间通信的C语言编程点对点的串行异步通信1.通信双方的硬件连接图7.178031间RS—232C电平信号的传2.通信双方的约定3.点对点通信编程点对点通信双方基本等同,只是人为规定一个为发送,一个为接收。要求两机串行口的波特率相同,因而发送和接收方串行口的初始化相同。可编制含有初始化函数、发送函数接收函数的程序,在主函数中根据程序的发送、接收设置TR,采用条件判别决定使用发送函数还是接收函数。这样点对点通信的双方都可运行此程序,只需在程序运行之前人为设置选择TR,一个令TR=0,一个令TR=1,然后分别编译,在两机上分别装入,同时运行。点对点通信的程序如下:#include<reg51.h>#defineucharunsignedchar#defineTR1 /*发送接收差别值TR=0发送*/ucharidatabuf[10];ucharpf;voidinit(void) /*串行口初始化*/{TMOD=0x20; /*设T/C1为定时方式2*/TH1=0xe8; /*设定波特率*/TL1=0xe8;PCON=0x00;TR1=1; /*启动T/C1*/SCON=0x50; /*串行口工作在方式1*/}voidsend(ucharidata*d){uchari;do{SBUF=0xaa; /*发送联络信号*/while(TI==0); /*等待发送出去*/TI=0;while(RI==0); /*等待B机回答*/RI=0;}while((SBUF^0xbb)!=0); /*B机未准备好,继续联络*/do{pf=0; /*清校验和*/for(i=0;i<16;i++){SBUF=d[i]; /*发送一个数据*/pf+=d[i]; /*求校验和*/while(TI==0);TI=0;}SBUF=pf; /*发送校验和*/while(TI==0);TI=0;while(RI==0);RI=0; /*等待B机回答*/}while(SBUF!=0); /*回答出错,则重发*/}
voidreceive(ucharidata*d){uchari;do{while(RI==0);RI=0;} while((SBUF^0xaa)!=0); /*判A机请求否*/SBUF=0xbb; /*发应答信号*/ while(TI==0);TI=0;while(1){pf=0; /*清校验和*/for(i=0;i<16;i++){while(RI==0);RI=0;d[i]=SBUF; /*接收一个数据*/pf+=d[i]; /*求校验和*/}while(RI==0);RI=0; /*接收A机校验和*/if((SBUF^pf)==0) /*比较校验和*/{SBUF=0x00;break;} /*校验和相同发"00"*/else{SBUF=0xff; /*出错发"FF",重新接收*/ while(TI==0);TI=0;}}}voidmain(void){init();if(TR==0){send(buf);}else{receive(buf);}}1.10键盘和数码显示人机交互的C语言编程1行列式键盘与8031的接口键盘输入信息的主要过程是:(1)单片机判断是否有键按下。(2)确定按下的是哪一个键。(3)把此步骤代表的信息翻译成计算机所能识别的代码,如ASCII或其它特征码。8031与行列式键盘的接口例174×4键盘的扫描程序。扫描程序查询的内容为:(1)查询是否有键按下。首先单片机向行扫描P1.0~P1.3输出全为"0"扫描码F0H,然后从列检查口P1.4~P1.7输入列扫描信号,只要有一列信号不为"1",即P1口不为F0H,则表示有键按下。接着要查出按下键所在的行、列位置。(2)查询按下键所在的行列位置。单片机将得到的信号取反,P1.4~P1.7中的为1的位便是键所在的列。接下来要确定键所在的行,需要进行逐行扫描。单片机首先使P1.0为"0",P1.1~P1.7为"1",即向P1口发送扫描码FEH,接着输入列检查信号,若全为"1",表示不在第一行。接着使P1.1接地,其余为"1",再读入列信号……这样逐行发"0"扫描码,直到找到按下键所在的行,将该行扫描码取反保留。当各行都扫描以后仍没有找到,则放弃扫描,认为是键的误动作。(3)对得到的行号和列号译码,得到键值。(4)键的抖动处理。当用手按下一个键时,往往会出现所按键在闭合位置和断开位置之间跳几下才稳定到闭合状态的情况。在释放一个键时,也会出现类似的情况,这就是键抖动,抖动的持续时间不一,通常不会大于10ms,若抖动问题不解决,就会引起对闭合键的多次读入,对于键抖动最方便的解决方法就是当发现有键按下后,不是立即进行逐行扫描,而是延时10ms后再进行。由于键按下的时间持续上百毫秒,延时后再也不迟。扫描函数的返回值为键特征码,若无键按下,返回值为0。程序如下:#include<reg51.h
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 茶叶对应茶具使用
- DB1308-T 390-2025 麒麟瓜设施栽培技术规程
- 儿童心脏疾病的诊断和治疗进展
- 四川省眉山市仁寿县乡村学校(联考)2024-2025学年七年级下学期6月期末地理试卷(含答案)
- 江西省萍乡市2024-2025学年高一下学期4月期中考试政治试题(含答案)
- 小学科学手工活动方案
- 小熊电器活动方案
- 小班儿童区域活动方案
- 工地诚信宣讲活动方案
- 山东博物馆特色活动方案
- 北京2024年北京市公安局人工智能安全研究中心招聘笔试历年典型考题及考点附答案解析
- 2023-2024学年译林版八年级英语下册期末易错120题(江苏专用)(含答案解析)
- G -B- 17378.7-2007 海洋监测规范 第7部分 近海污染生态调查和生物监测(正式版)
- DZ/T 0430-2023 固体矿产资源储量核实报告编写规范(正式版)
- (高清版)JTST 325-2024 水下深层水泥搅拌桩法施工质量控制与检验标准
- 小学数学研究专题
- HYT 104-2008 陶瓷微孔滤膜组件
- 茂名高州市村(社区)后备干部招聘笔试真题2023
- 2021年电梯检验员理论考试题库
- 西南科技大学-2019级-下-工学类-电路分析A2-毕业生补考-试卷
- 沪教版数学五年级下册小数简便运算练习100题及答案
评论
0/150
提交评论