收藏 分销(赏)

51单片机实验程序.doc

上传人:二*** 文档编号:4509756 上传时间:2024-09-26 格式:DOC 页数:16 大小:65KB 下载积分:5 金币
下载 相关 举报
51单片机实验程序.doc_第1页
第1页 / 共16页
本文档共16页,全文阅读请下载到手机保存,查看更方便
资源描述
. . 用查表方式编写y=x13+x23+x33。〔x为0~9的整数〕 #include<reg51.h> void main() { int code a[10]={0,1,8,27,64,125,216,343,512,729};//将0~9对应的每位数字的三次方的值存入code中,code为程序存储器,当所存的值在0~255或-128~+127之间的话就用char,而现在的值明显超过这个围,用int较适宜。int的围是0~65535或-32768~32767。 int y,x1,x2,x3;//此处定义根据习惯,也可写成char x1,x2,x3但是变量y一定要用int 来定义。 x1=2; x2=4; x3=9;//x1,x2,x3三个的值是自定的,只要是0~9当中的数值皆可,也可重复。 y=a[x1]+a[x2]+a[x3]; while(1);//单片机的程序不能停,这步就相当于无限循环的指令,循环的容为空白。 } //结果的查询在Keilvision软件部,在仿真界面点击右下角〔一般初始位置是右下角〕的watch的框架双击“double-click or F2 to add〞文字输入y后按回车,右侧会显示其16进制数值如0x34,鼠标右键该十六进制,选择第一行的decimal,可查看对应的10进制数。 1、 有10个8位二进制数据,要求对这些数据进展奇偶校验,但凡满足偶校验的数据〔1的个数为偶数〕都要存到RAM50H开场的数据区中。试编写有关程序。 #include<reg51.h> void main() { int a[10]={0,1,5,20,24,54,64,88,101,105};//将所要处理的值存入RAM中,这些可以根据个人随意设定,但建议不要超过0~255的围。 char i; //定义一个变量 char *q=0x50; //定义一个指针*q指向部0x50这个地址。 for(i=9;i>=0;i--)//9~0循环,共十次,也可以用for(i=0;i<10;i++) { ACC=a[i];//将a[i]的值赋给累加器ACC if (P==0)//PSW0位上的奇偶校验位,如果累加器ACC数值1的个数为偶数那么P为0,假设为奇数,P为1。这里的P是大写的。 { *q=a[i]; q++;//每赋一个值,指针挪一个位置指向下一个。 } } while(1);//同实验一,程序不能停。 } 3.有10个8位带符号二进制数,请将10个数按从小到大的顺序排列,并存到RAM50H开场的单元中。 #include<reg51.h> void main() { char data a[10]={-50,-36,0,-128,1,99,127,89,-89,40} ;//将所有值存入RAM中,因为有负数,所以不能用unsigned char。因为是char所以假设的数值不要超过-128~+127之外 unsigned char *q=0x50; //定义指针*q指向0x50 unsigned char i,j; char t; //定义三个变量,用于循环及换位。在换位时有赋值,所以t要用char不能用unsigned char。 for(i=0;i<10;i++) for(j=0;j<10-i;j++)//冒泡法,具体可以参考C语言程序设计的书。 { if(a[j]>a[j+1]) { t=a[j]; a[j]=a[j+1]; a[j+1]=t; } } for(i=0;i<10;i++) //将已经排好序的数组存入*q指向的地址。 { *q=a[i]; q++; } while(1); } 1、根本局部: 〔1〕P1口做输出口,接八只发光二极管,编写程序,使发光二极管循环点亮。 #include<reg51.h> void delay(unsigned char x) //定义延迟函数,用于后面LED灯亮的持续时间。 { unsigned char i,j,k; do { for(i=10;i>0;i--) for(j=100;j>0;j--) for(k=249;k>0;k--); } while(--x);} main() { P1=0xfe;//11111110第一个灯亮 while(1) { delay(1);//延时500ms P1=P1<<1|1;//P1左移一个位即11111101 具体crol跟<<的区别与具体细节可联系我与你讲解 if(P1==0XFF) { P1=0XFE; } } } 〔2〕P1.0、P1.1作输入口接两个拨动开关,P1.2、P1.3作输出口,接两个发光二极管,编写程序读取开关状态,将此状态,在发光二极管上显示出来。编程时应注意P1.0、P1.1作为输入口时应先置1,才能正确读入值。 #include<reg51.h> sbit p1_0=P1^0; sbit p1_1=P1^1; sbit p1_2=P1^2; sbit p1_3=P1^3;//程序不能对单个引脚进展编程,需要用sbit定义才可用。 main() { p1_0=1;p1_1=1;p1_2=1;p1_3=1;//前两个引脚置一是为了让其能获取输入信号,后两个引脚是赋初值,方便后面取反工作。 while(1) { if(!p1_0)//判断P1.0的引脚是否有变化。 { p1_2=!p1_2; //如果P1.0引脚变化,P1.2引脚也跟随变化。 } if(!p1_1)//判断P1.1的引脚是否有变化。 { p1_3=!p1_3;//如果P1.1引脚变化,P1.3引脚也跟随变化。 } } } 2、扩展局部: 〔1〕 利用P1口控制发光二极管LED灯按照下面方式工作: a) LED灯从左到右依次点亮; b) LED灯从右到左依次点亮; c) 按照以上步骤重复运行,其中要求灯亮的时间为500ms。 #include <reg51.h> void delay(unsigned char x) { unsigned char i,j,k; do { for(i=10;i>0;i--) for(j=100;j>0;j--) for(k=249;k>0;k--); }while(--x); } main() { while(1) //无限循环里面的容 { P1=0XFE;//右移完毕后赋初值,为左移做准备 delay(1); while(1) { P1=P1<<1;//如果左移右移是单个灯移动的话,那么这句改为LED=LED<<1|1;就可以了。 delay(1); if(P1==0x00) //判断左移是否完毕,完毕break跳出此次的while break; } P1=0x7f; //左移完毕后给P1赋初值,准备右移 delay(1); while(1) { P1=P1>>1;//如果左移右移是单个灯移动的话,那么这句改为LED=LED>>1|0x80;就可以了。 delay(1); if(P1==0x00)//判断右移是否完毕,完毕后break跳出 break; } } } 〔2〕 利用P1口控制发光二极管LED灯按照下面方式工作: a〕从左到右奇数LED灯依次点亮; b〕从右到左偶数LED灯依次点亮; c〕按照以上步骤重复运行,其中要求灯亮的时间为500ms。 #include<reg51.h> //此程序也可以用<<和>>来实现,具体细节可以来问我 #include<intrins.h>//当程序中有涉及到_crol_或者_nop_等库函数时,必须添加此头文件。 void delay(unsigned char x) { unsigned char i,j,k; do { for(i=10;i>0;i--) for(j=100;j>0;j--) for(k=249;k>0;k--); }while(--x); } main() { while(1) //无限循环括号里的容 { P1=0xfe; //第一个灯亮, while(1) { delay(1); P1=_crol_(P1,2); //P1左移两个位置 if(P1==0xfe) //判断左移完毕 break; } P1=0X7f; while(1) { delay(1); P1=_cror_(P1,2); //P1右移两个位置 if(P1==0x7f) //判断右移完毕 break; } } } #include<reg51.h> void delay(unsigned char x)//延时函数500ms { unsigned char i,j,k; do { for(i=10;i>0;i--) for(j=100;j>0;j--) for(k=249;k>0;k--); }while(--x); } main() { while(1) //无限循环括号里的容 { P1=0xfe;//赋值,为左移做准备 delay(1); while(1) { P1=(P1<<1)|0x01;//P1左移一个位置,补位补的是1。此处不明白可以找我。 P1=P1<<1; //P1左移一个位置,补位补的是0。 delay(1); if(P1==0xaa) //左移完毕,跳出循环 break; } P1=0X7f; //P1赋值,为右移做准备 delay(1); while(1) { P1=(P1>>1)|0x80; //P1右移一个位,补位补的是1,同样的,不明白来找我 P1=P1>>1; //P1右移一个位 delay(1); if(P1==0x55) //判断右移是否完毕,退出此次循环。 break; } } } 本实验模拟交通信号灯控制,一般情况下正常显示,有急救车到达时,两个方向交通信号灯全红,以便让急救车通过。设急救车通过路口时间为5秒,急救车通过后,交通恢复正常,本实验用单次脉冲申请外部中断,表示有急救车通过。 #include<reg51.h> unsigned char x,y,i,j,k; //设置 unsigned char d0,d1,d2,d3; //定义四个变量用于记录中断时的现场,以便恢复现场。 void delay(x)//延时函数 { do { for(i=10;i>0;i--) for(j=100;j>0;j--) for(k=249;k>0;k--); } while(--x); } zd() interrupt 0 //定义中断函数,无需声明。interrupt 0表示外部中断0的中断函数 { y=P1; d0=x; d1=i; d2=j; d3=k; //记录中断时P1的值,延时函数的x,i,j,k也要记录。 P1=0xf6; //P1应为东西红南北红,所以设为F6。 delay(5); x=d0; i=d1; j=d2; k=d3; P1=y; //现场恢复,包括延时函数中的x,i,j,k。 } main() { P1=0xf6; //P1设定初始状态,两路皆为红灯,此步骤可以忽略。 delay(1); EA=1; //开总中断 EX0=1; //开外部中断0中断。 IT0=1; //设置外部中断0为下降沿触发有效方式。IT0=0为低电平有效 while(1) //以下四种灯亮的状态循环。 { P1=0xf3;//东西绿,南北红 delay(10); P1=0xf5; //东西黄,南北红 delay(3); P1=0xde;//东西红,南北绿 delay(10); P1=0xee;//东西红,南北黄 delay(3); } } 1、根本局部: 用CPU部定时器中断方式计时,实现每一秒钟输出状态发生一次反转. #include<reg51.h> sbit p1_0=P1^0; //要使用单个引脚应先定义 unsigned char i; void main() { TMOD=0X01;//t0工作在定时器,工作方式1 TL0=0XB0; TH0=0X3C;//设定定时器初值,初值的计算可查看书本P143,此处定时器定时时间为100ms IE=0X82; //开EA总中断,开t0中断 TR0=1; //定时器工作开关开启 i=10; //设定i作为后面定时一秒的使用 while(1); } t_0() interrupt 1//T0定时/计数器的中断 { i--; //进入一次中断,i的值减一 if(i==0) //当进入10次中断,即i=0的时候,定时时间为1S。 { i=10; //重新让i=10,使得后面继续定时1S。 p1_0=~p1_0; //P1.0取反。 } TL0=0XB0; TH0=0X3C;//赋定时初值,定时器或计数器必要步骤,除工作方式2外。 } 2、扩展局部: 利用P1口控制发光二极管LED灯按照下面方式工作: 1〕从左到右奇数LED灯依次点亮; 2〕从右到左偶数LED灯依次点亮; 3〕按照以上步骤重复运行,其中要求灯亮的时间为500ms,由定时器T1实现。 #include<reg51.h> #include<intrins.h> unsigned char i,j,k; void main() { TMOD=0X10; //设定T1工作在定时器T1,方式1。同时也会设定T0工作在定时器T0,方式0,但是我们后面没有interrupt 1的子函数,所以T0没发挥作用。 IE=0X88; //开总中断,开T1中断 TL1=0XB0; TH1=0X3C;//定时器初值,时间为100ms TR1=1; //开定时器T1的开关 i=5; j=0; k=0; //用三个变量来判断时长,循环阶段。 P1=0xfe; //赋P1初值,第一个灯亮 while(1); //等待定时工作完成 } t_1() interrupt 3 //T1的中断子函数 { i--; //进入一次,i就减1 TL1=0xB0; TH1=0x3C; //每次进入中断定时器的初值就为0,所以需要重装 if(i==0) //500ms后 { i=5; //让i=5,继续定时500ms。 j++; //j一开场为0,j加一 if(j==4)//如果j等于4,代表P1口左移了四次 { j=0; k=!k; //k取反,用于后面左移右移的执行 } if(k==0) //P1口左移 { if(P1==0xfd) //左移到头了,要右移需要把灯亮的位置变化下 { P1=0xbf; } P1=_crol_(P1,2); } if(k!=0)//P1口右移 { if(P1==0xbf)//右移到头了,要右移需要把灯亮的位置变化下 { P1=0xfd; } P1=_cror_(P1,2); } } } #include<reg51.h> unsigned char i,j; void main() { i=5; j=0; P1=0xfe;//只亮第一个灯 TMOD=0X10; //设置T1的工作方式为1,定时器工作 IE=0X88; //中断EA开,ET1开 TL1=0XB0; TH1=0X3C; //初值设定为100ms TR1=1; //开启工作开关 while(1); //等待定时工作完成 } t_1() interrupt 3 //T1中断子函数 { i--; TL1=0XB0; TH1=0X3C; //赋初值 if(i==0)//时间为500ms { i=5; j++; //利用j来判断左移或右移是否完毕 if(j<4) { P1=P1<<1|0x01; P1=P1<<1|0x01; //P1口左移两位,且补位是补1。也可以用P1=P1<<2|0X03代替 } if(j==4) //左移完毕,赋P1值准备右移 { P1=0x7f; } if(j>4) //右移阶段 { P1=P1>>1|0X80; P1=P1>>1|0X80;//P1口右移两位,且补位是补1。也可以用P1=P1>>2|0XC0代替 } if(j==8) //右移完毕,赋P1值准备左移 { P1=0xfe; j=0; //最后还要将J恢复为0以便下次循环。 } } } 1、根本局部: 8031部定时计数器T0,按计数器模式和方式1工作,对P3.4〔T0〕引脚进展计数。将其数值按二进制数在P1口驱动LED灯上显示出来。 #include<reg51.h> void main() { TMOD=0X05; //T0工作方式1,计数器工作 TL0=0X00; TH0=0Xff;//初值设置方法可以参考P143页 IE=0X82; //中断EA=1,ET0中断开启 TR0=1; //开启中断开关 while(1) { P1=~TL0; //计数器的值存在TL0里面。每加一个值,所得的值就是以八位二进制形式存在TL0里面的。 } } t_0() interrupt 1 //T0的计数器中断 { TL0=0X00; TH0=0Xff; } 2、扩展局部: 利用T0作为定时器,T1作为计数器,将试验箱上的脉冲信号源接到T1引脚,测量出脉冲信号源的频率。 #include<reg51.h> unsigned char i,a; void main() { a=0; i=10; TMOD=0X51; //设置T0为工作方式1,定时器工作。T1为工作方式1,计数器工作 EA=1; ET0=1; ET1=0;//这里也可以设置为IE=0x82。关闭了T1的中断 TL0=0XB0; TH0=0X3C;//时间设定为100ms TL1=0X00; TH1=0X00; //计数器开启最大围计数 TR0=1; TR1=1; //皆开启开关 while(1)//等待计数定时工作完成 { if(TF1==1)//查询溢出标志位。 { a++; //溢出一次a的值加1 TF1=0; //将溢出标志位清零 TH1=0x00; TL1=0X00;//重新装上计数器初值 } } } t_0() interrupt 1 //定时器T0的中断子程序 { TL0=0XB0; TH0=0X3C; //赋初值 i--; if(i==0) { i=10; P1=TL1;//将低位记录的次数赋给P1显示出来。 P2=TH1;//将高位记录的次数赋给P2显示出来,即一秒的计数次数,即为频率。 TR0=0; TR1=0;//频率读出后关闭T0和T1 } } //一般情况下,所测频率不能超过500kHz,否那么此程序结果有错。程序频率计算为:P1和P2的读数转为十进制数字,加上〔a*65536〕得出频率总和。 1、根本局部: 利用74ls165读入拨盘开关的状态,利用单片机串行口将状态读入并通过P1口输出到LED,从而实现拨盘开关对LED灯的控制。 #include<reg51.h> sbit P1_6=P1^6; //实验箱部已经将P1.6引脚与165的S/L引脚相连,也把P3.6与165的CLK引脚相连 void main() { SM0=0; SM1=0; REN=1; //串行口工作方式0,也可用SCON=0x10 EA=1; ES=1; //开总中断和串行口中断 while(1); } I_0() interrupt 4 //串行口中断子程序 { P1_6=0; //让74LS165将按键的状态读入 P1_6=1; //让74LS165将读入的8位按键码用串行方式输出,从低位到高位; P2=SBUF; //将SBUF缓冲器里的数据读给P2 RI=0;//RI要由软件置0 } 2、扩展局部: 利用74ls165读入拨盘开关的状态,利用单片机P3口将状态读入并通过P1口输出到LED,从而实现拨盘开关对LED灯的控制。 #include<reg51.h> sbit p1_6=P1^6;//与165的部S/L相连 sbit p3_6=P3^6; //与165的部CLK相连 sbit p1_7=P1^7; //P1.7短路帽扣上时,P1.7与165的QH相连 unsigned char i,x; main() { while(1) { p1_6=0; //数据移入165芯片 p1_6=1; //数据从165芯片输出 x=p1_7; //防止第一位丧失 for(i=0;i<7;i++) { p3_6=0; p3_6=1; //部制造一个上升沿,从而到达数据传输,一个上升沿一个数据。 x=x<<1|p1_7;//每次左移一个位,空出来的位补P1_7的值 } P2=x; //将移位完的X赋给P2,那么P2上显示的就是按键的二进制状态 } } 1、根本局部: 利用单片机串行口,实现两个实验台之间的串行通讯。其中一个实验台作为发送方,另一侧为接收方。利用发送方的拨盘控制接收方的LED。 甲方: #include<reg51.h> void main() { SM0=0; SM1=1; SM2=0;//设定串行口工作方式1,单对单通信,可用SCON=0X40代替 EA=0; ES=0; ET1=0; //关串行口中断,关总中断,关定时/计数器T1中断 PCON=0; //设置SMOD=0,波特率不加倍 TMOD=0X20; //设置定时/计数器T1为工作方式2,定时器工作 TH1=0XFE; TL1=0XFE; //赋初值,此处赋值与定时或计数赋初值不同,此处初值用于波特率,可参考P168 TR1=1; //开定时器T1 while(1) { SBUF=P2; //把P2口接收到的值赋给发送SBUF,准备发送 while(TI==0); //等待发送完毕 TI=0; //将发送标志位TI置0,此步一定要软件操作 } } 乙方: #include<reg51.h> void main() { SM0=0; SM1=1; SM2=0; REN=1; //串行口工作方式1,单对单通信,可用SCON=0x50代替 EA=0; ET1=0; ES=0; //关所有中断 TMOD=0X20; //T1工作方式2,定时器工作 PCON=0; //SMOD=0,波特率不加倍 TH1=0XFE; TL1=0XFE; //与发送端一样的波特率,那么初值也应当一样 TR1=1; while(1) { while(RI==0); //等待接收完毕 P1=SBUF; //将接收到的值赋给P1 RI=0; //将接收标志位置0 } } 2、扩展局部: 利用单片机的串行口完成数据的自发自收,发送数据在部RAM30H为首的8个单元中,数据分别是:55H,AAH,33H,CCH,0FH,F0H,66H,99H;接收后能在LED显示出接收的数据值〔二进制形式〕。 #include<reg51.h> unsigned char x,i,*p,*q; void delay(x) { unsigned char j,k,l; do { for(j=10;j>0;j--) for(k=100;k>0;k--) for(l=249;l>0;l--); } while(--x); } main() { unsigned char data a[8]={0x55,0xAA,0x33,0xCC,0x0F,0xF0,0x66,0x99}; p=0x30; for(i=0;i<8;i++) { *p=a[i]; p++; } SM0=0; SM1=1; REN=1;//串行口工作方式1,可用SCON=0X50代替 TMOD=0X20; //T1工作在方式2,定时器工作 PCON=0; //SMOD=0,波特率不加倍 TH1=0Xe8; TL1=0Xe8; //设定初值,用于设定波特率,换算公式参考P168 EA=1; //开总中断 ET1=0; //关定时器T1中断,此处一定要关中断,因为我们不是用该定时器来做定时工作的 ES=1; //开串行口中断 q=0x30; //指针指向0x30地址 TR1=1; //开T1工作开关 SBUF=*q; //将指针指向的值赋给发送SBUF等待发送 while(1); } T_1() interrupt 4 //串行口中断程序 { q++; //传输完一个数据后,指针加1,指向下一个位置 P1=SBUF;//将接收到的数据在P1口显示出来 delay(1);//延时500MS〔晶振在12MHz的前提下〕 SBUF=*q; //将指针指向的值赋给发送SBUF,准备发送 TI=0; RI=0;//置TI和RI为0 } . .word.zl.
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 学术论文 > 其他

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2025 宁波自信网络信息技术有限公司  版权所有

客服电话:4009-655-100  投诉/维权电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服