ImageVerifierCode 换一换
格式:DOCX , 页数:46 ,大小:350.80KB ,
资源ID:29213107      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/29213107.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(第八章 单片机8051内部资源C语言编程.docx)为本站会员(b****8)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

第八章 单片机8051内部资源C语言编程.docx

1、第八章 单片机8051内部资源C语言编程第八章 8051内部资源C语言编程一、I/O口编程例1:用按键控制发光二极管。并口是用的最多的资源,下面以P1口为例,见电路图,P1口低4位接了4个按钮,高4位接了4个指示灯,要求按下相应的按钮,对应的指示灯亮。P10对应P14,依次类推。指示灯是端口输出高电平亮。源程序如下:#includevoid main() unsigned char data x,i; while(1) P1=P1|0x0f; /给低4位置1,高4位不变 x=P1&0x0f; /读低4位 x=x; /低4位取反 P1=x4; /左移4位 for(i=0;i255;i+); /延

2、时 (端口编程)注意上面几种常见的用法。二、中断的C语言编程编号中 断 源入口地址0外部中断00003H1定时器/计数器0000BH2外部中断10013H3定时器/计数器1001BH4串行口中断0023HC51编译器支持在C源程序中直接开发中断程序。前面已经讲过,中断服务程序是通过按规定语法格式定义的一个函数。(中断有关内容)中断服务程序的函数定义的语法格式如下:Void 函数名(void) interrupt m using n 中断程序代码;m为MCS-51中断源编号,见表using n 选项用于实现工作寄存器组的切换,n是中断服务子程序中选用的工作寄存器组号(0 3)。例2: 设AT89

3、C52 的时钟频率为12MHz,利用定时中断在其P1.0 引脚输出周期为4ms,占空比为1:1的方波。确定定时器工作方式和计算定时器初值。选用定时器T0工作方式1,每个机器周期为1s,翻转一次电平需要2ms,则计数次数n2000/1=2000,初值x65536200063536F830H参考程序如下:#includesbit P10 = P10;/定义位void clock_initial() reentrant using 0/在中断中调用,定义为重入函数TR0=0; TH0=0XF8;/装载计数初值 TL0=0X30;TR0=1;main( )TMOD = 0x01; /定时器T0方式1

4、工作P10 = 0; /初始值为低电平TF0=0;/清除中断标志位clock_initial();ET0=1;EA=1;do while(1); /死循环,等价于汇编语言的SJMP $void clk_int ( void ) interrupt 1 using 0P10= !P10;/逻辑变量clock_initial();(延时中断)例3: 图示是利用优先权解码芯片74LS148,在单片机8031的一个外部中断INT1上扩展多个中断源的原理电路图。图中是以开关闭合来模拟中断请求信号。当有任一中断源产生中断请求,能给8031的INT1引脚送一个有效中断信号,由P1的低3位可得对应中断源的中断

5、号。74LS148是8线3线优先编码器,为输入端,为编码输出端,为扩展端。真值表见右图。只要有输入的中断请求,为低电平,申请中断。同时根据P10,P11,P12的值,可以判断出是那一个中断源提出的中断申请。在中断服务程序中仅设置标志,并保存I/O口输入状态。参考程序如下:# include unsigned char status; bit flag=0; void service_int1( ) interrupt 2 using 2 / INT1中断服务程序,使 用第3组工作寄存器 flag=1; / 设置标志 status=P1&0x07; / 存输入口状态 void main(void

6、) IP=0x04 ; / 置INT1为高优先级中断 IE=0x84 ; / INT1开中断,CPU开中断 for(; ;)/无限循环 if(flag) / 有中断 switch(status) / 根据中断源分支 case 0 :中断1程序; break ; / 处理IN0 case 1 :中断2程序; break ; / 处理IN1 case 2 :中断3程序; break; / 处理IN2 case 3 :中断4程序; break; / 处理IN3 case 4 :中断5程序; break ; / 处理IN4 case 5 :中断6程序; break; / 处理IN5 case 6 :中

7、断7程序; break; / 处理IN6 default :中断8程序; / 处理IN8 flag=0 ; / 处理完成清标志 三、定时器/计数器的c语言编程定时器/计数器的有关内容:定时器的编程,要选择定时器/计数器的工作方式,如果要定时,需要计算初值,溢出时相应中断标志置1。下面用例子就 进行说明。例4:将中断中的例2采用查询的方法实现。采用AT89C51单片机。参考程序如下:#includemain()TMOD=0x01;/置工作方式, for(;)/无限循环 TR0=0; TF0=0; TH0=0xf8; TL0=0x30; TR0=1;/开定时器T0 do while(!TF0);/

8、循环等待,TF0为1时退出 P1_0=!P1_0;/AT89C51的头文件中已经定义 计数器在生产线等场合应用的很多,下面看以下定时器的编程。思路:计数器初始化,如果计数总值小于65535,直接取出TL0、TH0中的数据即可,如果大于65535,则要设置一个存储单元进行软件计数,本程序用软件计数。每中断一次,计数值增加65535。例5、由P3.4输入脉冲信号,用定时器T0进行计数,并不断输出计数值。#includetypedef unsigned char uchar;#define uint unsigned int ;uchar clow,chigh;unsigned long cvalu

9、e=0;/用全局变量传递数据void c_initial() TCON=0x00;/将中断标志和开关全置0 TH0=0x00; TL0=0x00; TR0=1;/开定时器T0uint c_module() /从TL0、TH0中取数据并计数 unsigned long data x; do chigh=TH0;/读取数据 clow=TL0; while(chigh!=TH0);/ (item1) x=cvalue*65536+chigh*256+clow;/计数总值 return x;void main() TMOD=0x05;/设T0为16位(方式1)计数状态, c_initial();/初始

10、化 ET0=1;/开中断 EA=1; doc_module();(显示程序和其他数据处理程序)while(1); void c_int(void) interrupt 1 using 1/中断程序,计溢出中断的次数cvalue=cvalue+1;(定时中断1)item1;在THO、TL0中取数时,有一个时间差,先取TH0,然后在取TL0,在取TL0前,TL0可能进位。因此取完TL0后返回来再取TH0判断是否变化,取值过程中若有进位,则重新取值。四、 串行口的C语言编程(串行通信有关内容)串行口通信,采用T1定时器作为波特率发生器,对不同的工作方式,波特率的设置是不同的,数据的位数也不同。下面举

11、几个例子:例6:在单片机中,printf的默认输出是串行口,用串行口输出字符“hello world”。#include #include void main (void) SCON = 0x50;/串行通信方式1,10位 TMOD = 0x20;/定时器T1方式2 TH1= 243;/置初值 TL1= 243; TR1= 1;/开定时器 TI= 1;/用串行口软件仿真输出时,必须这样设置while (1) printf (Hello Worldn);以上程序很简单,但在keil软件上进行仿真时很有用。注意,和原例有修改,原例是用Monitor51可以在目标硬件上调试程序。例7:要求每按一下按

12、键(P10口),从串行口发出一个字符,该程序主要用于串行通信是否正常工作的调试。和计算机通信时,由于各种原因,有时经常调试不通,可以用最简单的程序进行调试,调好后再调试应用程序。下面是一段调试单片机与微机用VB编程通信的一段调试程序。波特率9600B/S,24MHz的晶振频率,定时器初值的确定,当SMOD1时,舍入误差较小(作业已做过)。 取x2430xf3.#include#define uchar unsigned char;#define uint unsigned int;void main() uchar data x=5;/待发送的数 TMOD=0x20;/定时器T1方式2 TL1

13、=0xf3;/置初值 TH1=0xf3; SCON=0xd8;/串行通信方式3 PCON=0x80;/SMOD=1 TR1=0; while(1) while(P1_0!=0);/当按键未按下时等待 while(P1_0=0);/当按键未放开时等待 TR1=1; SBUF=x; while(TI=0); TI=0; TR1=0; (串行通信)例8: 点对点的串行异步通信1、通信双方的硬件连接 2、程序流程图及编程点对点通信双方基本等同,只是人为规定一个为发送,一个为接收。要求两机串行口的波特率相同,因而发送和接收方串行口的初始化相同。可编制含有初始化函数、发送函数接收函数的程序,在主函数中根据

14、程序的发送、接收设置TR,采用条件判别决定使用发送函数还是接收函数。这样点对点通信的双方都可运行此程序,只需在程序运行之前人为设置选择TR,一个令TR=0,一个令TR=1,然后分别编译,在两机上分别装入,同时运行。A机开始发送时,先送一个AA信号,B机接收到AA信号后,回答一个BB信号,表示准备好可以接受。然后A机发送,B机接收,A机边发送边求校验和,B机边接收边求校验和,发送完后发校验和,B机接收校验和进行校对。不正确要求重发。本例晶振频率为11.0592MHz,波特率为1200。初值为:下面程序是将发送和接收都合在一个程序中,可以分别装入两个单片机系统中,由语句“#define TR 1”

15、确定发送或接收, TR=0发送,TR=1为接收。3、参考源程序#include#define uchar unsigned char#define TR 1 /发送与接收差别值TR=0发送,TR=1为接收uchar idata buf16;uchar pf;/求和void init(void) /串行口初始化 TMOD=0x20; /设T/C1为定时方式2 TH1=0xe8; /设定波特率TL1=0xe8; PCON=0x00; TR1=1; /启动T/C1 SCON=0x50; /串行口工作在方式1void send(uchar idata *d)/发送字符,参数用指针说明 uchar i;

16、/下面是两机联络 do SBUF=0xaa; /发送联络信号 while(TI=0); /等待发送结束 TI=0; for(i=1;i0xff;i+);/注意发送完以后要等待接收,否则出错 while(SBUF0xbb)!=0); /B机未准备好,继续联络 RI=0;/接收后RI=1,软件清0 do /以下为发送数据,每发送一个都要求和。 pf=0; /清校验和 for ( i=0;i16;i+) SBUF=di; /发送一个数据 pf+=di; /求校验和 while(TI=0);TI=0;/等待发送结束 SBUF=pf; /发送校验和while(TI=0);TI=0;/等待发送结束whil

17、e(RI=0);RI=0; /等待B机回答 while(SBUF!=0); /回答出错,则重发 void receive (uchar idata *d)/接收字符 uchar i; do while (RI=0); RI=0; /等待接收 while (SBUF0xaa)! =0)/判A机请求否 SBUF=0xbb; /发应答信号 while (TI= =0); TI=0;/等待发送结束 while (1) pf=0; /清校验和 for ( i=0;i16;i+) while (RI= =0); RI=0; d i =SBUF; /接收一个数据 pf+ =di; /求校验和 while (

18、RI= =0); RI=0; /接收A机校验和 if (SBUF pf) = =0) /接收的校验和与自加得比较 SBUF=0x00; /校验和相同,回答0X00 while(TI= =0); TI=0; break; /校验和相同发00 else SBUF=0xff; /出错发FF,重新接收 while(TI= =0); TI=0; void main (void) init ( ); if(TR= =0) send(buf);/参数为数组名,指针 else receive(buf); (串行通信1)将上面的程序发送与接收分开,接收程序如下:#include#define uchar uns

19、igned charuchar idata buf16;uchar pf;/求和void init(void) /串行口初始化 TMOD=0x20; /设T/C1为定时方式2 TH1=0xe8; /设定波特率TL1=0xe8; PCON=0x00; TR1=1; /启动T/C1 SCON=0x50; /串行口工作在方式1void receive (uchar idata *d)/接收字符 uchar i; do while (RI=0); RI=0; /等待接收 while (SBUF0xaa)! =0)/判A机请求否 SBUF=0xbb; /发应答信号 while (TI= =0); TI=

20、0;/等待发送结束 while (1) pf=0; /清校验和 for ( i=0;i16;i+) while (RI= =0); RI=0; d i =SBUF; /接收一个数据 pf+ =di; /求校验和 while (RI= =0); RI=0; /接收A机校验和 if (SBUF pf) = =0) /接收的校验和与自加得比较 SBUF=0x00; /校验和相同,回答0X00 while(TI= =0); TI=0; break; /校验和相同发00 else SBUF=0xff; /出错发FF,重新接收 while(TI= =0); TI=0; void main (void) i

21、nit ( ); receive(buf); 发送程序如下:#include#define uchar unsigned charuchar idata buf16;uchar pf;/求和void init(void) /串行口初始化 TMOD=0x20; /设T/C1为定时方式2 TH1=0xe8; /设定波特率TL1=0xe8; PCON=0x00; TR1=1; /启动T/C1 SCON=0x50; /串行口工作在方式1void send(uchar idata *d)/发送字符,参数用指针说明 uchar i;/下面是两机联络 do SBUF=0xaa; /发送联络信号 while(

22、TI=0); /等待发送结束 TI=0; for(i=1;i0xff;i+);/注意发送完以后要等待接收,否则出错 while(SBUF0xbb)!=0); /B机未准备好,继续联络 RI=0;/接收后RI=1,软件清0 do /以下为发送数据,每发送一个都要求和。 pf=0; /清校验和 for ( i=0;i16;i+) SBUF=di; /发送一个数据 pf+=di; /求校验和 while(TI=0);TI=0;/等待发送结束 SBUF=pf; /发送校验和while(TI=0);TI=0;/等待发送结束while(RI=0);RI=0; /等待B机回答 while(SBUF!=0);

23、 /回答出错,则重发 void main (void) init ( ); send(buf);/参数为数组名,指针 五、综合编程举例例9、定时器程序,用到定时器、定时器中断、端口按键控制并用串行口输出,是一个片内资源的综合应用实例,程序是由本人编写,并用keil软件仿真通过,但不是所有的功能全部调试过,难免还有错误。从思路上,不是完美的,但通过亲自编程,体会了该程序编写中的难点,以便更好的给大家介绍。晶振按24MHz,用定时器0方式1,计数次数为25000/0.5=50000,初值为65535-50000=15535=3CAFH。该程序有分辨大、小月、2月,2412显示功能,有时间调整功能。

24、参考程序:#include#include #include #define uchar unsigned char#define uint unsigned intsbit an1=P10;/调整时间功能转换sbit an2=P11;/加1sbit an3=P12;/减1sbit an4=P13;/12-24显示转换sbit an5=P14;/显示年月日与时分秒转换sbit an6=P15;/待定uchar data clow,chigh,year=4,month=12,day=31,hour=23,minute=59,second=0,m,x;uint data n=0;void c_in

25、itial() reentrant using 1 TCON=0x00; TH0=0x3c; TL0=0xaf; TR0=1; SCON=0x50; TH1=221; TR1=1; TI=1; add(uchar m) /加1 uchar i; if(an2=0) for(i=0;i0xff;i+); while(an2=0); m+; return m; sub(m)/减1 uchar i; if(an3=0) for(i=0;i0xff;i+); while(an3=0); m-; return m; xianshi(uint s1,uint s2,uint s3)/ 显示 printf

26、(%d ,s1); printf (%d ,s2); printf (%u n,s3); void main() uchar data i,j=0; bit n=0; TMOD=0x21; c_initial(); ET0=1; EA=1; while(1) lab0:while(an1=0); if(an4=0) for(i=1;i12) xianshi(hour-12,minute,second); /12小时制式 else xianshi(hour,minute,second); if(an1=0) while(an1=0);/调整年 while(1) if(an2=0) year=ad

27、d(year); if(year=99) year=0; if(an3=0) year=sub(year); if(year=0) year=99; if(an1=0) goto lab2; lab2:while(an1=0);/调整月 while(1) if(an2=0) month=add(month); if(month=13) month=1; if(an3=0) month=sub(month); if(month=0) month=12; if(an1=0) goto lab3; lab3:while(an1=0);/调整天 while(1) if(an2=0) day=add(day); if(month=1|month=3|month=5|month=7|month=8|month=10|month=12)

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1