MCS-51单片机实验源程序.doc
- -MCS-51单片机实验源程序仅供参考。没有最好,只有更好!希望大家设计出更好的程序来。软件实验一 求一组数据的最大小值/*软件实验的目的:熟悉单片机常用的根本程序算法,调试时观察变量含数组值的变化,从而理解程序的功能,了解变量含数组在单片机存储器中的具体位置。*/int a=-1,2,-30,40,-500,600,-7000,8000,-32750,32765; /任意给出10个int型数围:-32768+32767,放在数组a中void main()unsigned char i;int max,min;max=min=a0; /max,min先取该组数据的第一个for(i=1;i<10;i+) if(ai>max) max=ai; if(ai<min) min=ai; while(1); /没有什么要做了,那么用该语句作为main函数的结尾,无限循环附调试截图:注意:由于是纯软件实验单片机没有进展实际的输入与输出,有些变量要声明为全局变量如上面的数组a,否那么可能会被Keil软件编译时优化掉即:一些语句没有真正生成执行代码,导致无法观察到正确结果。软件实验二 二进制十六进制数转换为BCD数/按流程图,编写程序如下:#define uchar unsigned charvoid main()uchar x=0xA5; /设二进制数为1010 0101,在Keil中只能用十六进制0xA5或十进制165不能直接用二进制形式uchar a3;a2=x/100;x=x%100;a1=x/10;x=x%10;a0=x;while(1);/或者用for循环语句,先取出个位#define uchar unsigned charvoid main()uchar x=0xA5;uchar i,a3;for(i=0;i<3;i+)ai=x%10;x=x/10;while(1);软件实验三 二进制十六进制数转换为ASCII码/将0-9、A-F的ASCII码做成表格数组放到程序存储器ROM中#define uchar unsigned charuchar code ascii="0123456789ABCDEF" /ASCII码表放ROM中/*上句赋值也可写成0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39, 0x41,0x42,0x43,0x44,0x45,0x46 */* 还可写成48,49,50,51,52,53,54,55,56,57,65,66,67,68,69,70 */* 还可写成'0','1','2','3','4','5','6','7','8','9','A','B','C','D', 'E','F' */void main()uchar x=0x5A; /设二进制数为0101 1010,在Keil中只能用十六进制0x5A或十进制90不能直接用二进制形式uchar cc,a2;cc=x & 0x0f; /取x的低4位1010即Aa0=asciicc; /查表,a0存x低4位对应十六进制数即A的ASCII码cc=(x>>4)& 0x0f; /取x的高4位0101即5a1=asciicc; /查表,a1存x高4位对应十六进制数即5的ASCII码while(1);硬件实验一 并行口输入、输出/P2做输出口,接8只LED,编写程序,使LED循环点亮流水灯#include<reg51.h>#include<intrins.h> /部函数_crol_,_cror_等的头文件void Delay(unsigned int x) /延时函数,在12MHz晶振下,延时约x msunsigned char i; while(x-) for(i=0;i<123;i+);void main() char a=0xfe; while(1) P2=a; Delay(500); /在12MHz晶振下,延时约500ms a=_crol_(a,1); /循环左移,_cror_为循环右移 /P3.2和P3.3做输入口,分别接两个拨动开关到GND;P2.7P2.4做输出口,接4只LED,用来指示两个开关的闭合状态组合#include<reg51.h>void main() char a; while(1) a=P3; /读入P3口状态 a=a&0x0C; /a中只保存P3.3、P3.2的值,其余位清零if(a=0x0C) P2=0x7F; /P3.3=1开,P3.2=1开,那么P2.7=0亮 if(a=0x08) P2=0xbF; /P3.3=1开,P3.2=0合,那么P2.6=0亮 if(a=0x04) P2=0xdF; /P3.3=0合,P3.2=1开,那么P2.5=0亮 if(a=0x00) P2=0xEF; /P3.3=0合,P3.2=0合,那么P2.4=0亮 /用一个共阳七段数码管循环显示0-9和A-F,每个数显示0.5s#include<reg51.h>sbit P1_0=P10;char code TABLE=0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8, 0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e; /共阳数码管段码放在程序存储器ROM中void Delay(unsigned int x) /延时函数,在12MHz晶振下,延时约x msunsigned char i; while(x-) for(i=0;i<123;i+);void main() char j; P1_0=0; /位选信号 while(1) for(j=0;j<16;j+) P0=TABLEj; Delay(500); 硬件实验二 外部中断/通过外部中断0(下降沿触发),启动或关闭流水灯,即上电复位时不亮,按一次INT0P3.2引脚的按钮,流水灯开启,再按一次,灯熄灭#include<reg51.h>#include<intrins.h> /部函数_crol_,_cror_等的头文件bit LED=0; /位变量LED用于记录流水灯的状态,0为关闭,1为开启void Delay(unsigned int x) /延时函数,在12MHz晶振下,延时约x msunsigned char i; while(x-) for(i=0;i<123;i+);void INT0_srv(void) interrupt 0 /INT0中断号为0 Delay(10); /延时10ms,去抖动 if(INT0=0) LED=!LED; /每次中断时切换LED开启或关闭void main() char a=0xfe;IT0=1; /下降沿触发 EX0=1; /允许INT0中断 EA=1; while(1) if(LED) /开启 P2=a; Delay(500); /在12MHz晶振下,延时约500ms a=_crol_(a,1); /循环左移,_cror_为循环右移 else /关闭 P2=0xff; /通过外部中断0(低电平触发),启动或关闭流水灯,即上电复位时不亮,按一次INT0P3.2引脚的按钮,流水灯开启,再按一次,灯熄灭#include<reg51.h>#include<intrins.h> /部函数_crol_,_cror_等的头文件bit LED=0; /位变量LED用于记录流水灯的状态,0为关闭,1为开启void Delay(unsigned int x) /延时函数,在12MHz晶振下,延时约x msunsigned char i; while(x-) for(i=0;i<123;i+);void INT0_srv(void) interrupt 0 /INT0中断号为0 Delay(10); /延时10ms,去抖动 if(INT0=0) LED=!LED; /每次中断时切换LED开启或关闭 while(INT0=0); /如P3.2(INT0)还是0,那么等待,变为1后才从中断返回void main() char a=0xfe; IT0=0; /低电平触发 EX0=1; /允许INT0中断 EA=1; while(1) if(LED) /开启 P2=a; Delay(500); /在12MHz晶振下,延时约500ms a=_crol_(a,1); /循环左移,_cror_为循环右移 else /关闭 P2=0xff; 硬件实验三 定时计数器/用单片机部定时器方式计时,实现每一秒钟P2口输出状态发生一次反转。/设置定时器溢出时间为50ms,溢出20次那么为1s/12MHz晶振下,部每个计数脉冲为1ms,50ms那么需要50000个脉冲/在定时器方式1下初值为65536-50000/中断法#include<reg51.h>unsigned char count=20; /定时溢出次数void T0_int(void) interrupt 1 /T0中断号为1 TH0=(65536-50000)/256; /每次溢出重新置初值 TL0=(65536-50000)%256; count-; if(count=0) /溢出20次,即1s count=20; P2=P2; void main() TMOD=0x01; /T0部定时,方式1 TH0=(65536-50000)/256; /置初值 TL0=(65536-50000)%256; ET0=1; /允许T0中断 EA=1; TR0=1; /启动T0 while(1); /循环等待/查询法#include<reg51.h>unsigned char count=20; /定时溢出次数void main() TMOD=0x01; /T0部定时,方式1,由TR0启动 TH0=(65536-50000)/256; /置初值 TL0=(65536-50000)%256; TR0=1; /启动T0 while(1) while(!TF0); /等待定时溢出 TF0=0; /溢出标志清零 TH0=(65536-50000)/256; /溢出重新置初值 TL0=(65536-50000)%256; count-; if(count=0) /溢出20次,即1s count=20; P2=P2; /单片机对从P3.4(T0)输入的脉冲信号计数,T0工作于方式1,将计数结果送至P2口显示二进制形式/由于输出低电平时LED亮,故需反转后输出#include<reg51.h>void main() TMOD=0x05; /T0外部计数,方式1,由TR0启动 TH0=TL0=0; /置初值可省略 TR0=1; /启动T0 while(1) P2=TL0; /将计数值实时送P2口显示,未考虑TH0 /单片机对从P3.4(T0)输入的脉冲信号计数,T0工作于方式1,将计数结果用4位共阳数码管动态扫描显示P0口输出段码,P1.0P1.3分别选择千、百、十、个位,参见实验板原理图#include<reg51.h>char code SEG=0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90; /共阳数码管09的段码放在程序存储器ROM中char code bit_sel=0xf7,0xfb,0xfd,0xfe;/个、十、百、千 位选信号void Delay(unsigned int x) /延时函数,在12MHz晶振下,延时约x msunsigned char i; while(x-) for(i=0;i<123;i+);void main() unsigned int count; unsigned char k; TMOD=0x05; /T0外部计数,方式1,由TR0启动 TH0=TL0=0; /置初值可省略 TR0=1; /启动T0 while(1) count=TH0*256+TL0; /将计数值送countfor(k=0;k<4;k+) /动态扫描显示 P1=bit_selk; /输出位选信号 P0=SEGcount%10; /输出段码 Delay(5); count=count/10; 硬件实验四 串行通信/单片机甲用于串行发送,单片机乙用于接收。甲向乙发送0-9和A-F共16个数。/乙接收这16个数存放到数组,然后依次用一个接在P0口的共阳七段数码管显示出来,每个数显示时间约0.5s/单片机甲发送程序查询方式 Keil中需单独建一个工程#include <reg51.h>#define uchar unsigned charvoid main() uchar i=0; TMOD=0x20; /*设置定时器T1为方式2*/ TH1=TL1=0xfd;/*波特率9600*/ SCON=0x40; /*串口方式1只发送,不接收*/ TR1=1;/*启动T1*/ for(i=0;i<16;i+) /循环16次,依次发送0-F SBUF=i; /*数据送串行口发送缓冲器*/ while(TI=0);/*如果TI=0,未发送完,循环等待*/ TI=0;/*已发送完,再把TI清0*/ while(1);/单片机乙接收程序中断方式 Keil中需单独建一个工程#include <reg51.h>sbit P1_0=P10;#define uchar unsigned charuchar sc=0,a16; /数组a存放接收到的数据,sc为数组下标char code TABLE=0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8, 0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e; /共阳数码管段码void Delay(unsigned int x) /延时函数unsigned char i; while(x-) for(i=0;i<123;i+);void SI_int(void) interrupt 4 /串行口中断号为4 if(RI) /接收到一帧数据 asc=SBUF; RI=0; sc+; void main() uchar i=0; TMOD=0x20; /*设置定时器T1为方式2*/ TH1=TL1=0xfd;/*波特率9600*/ SCON=0x50; /*串口方式1,允许接收*/ TR1=1;/*启动T1*/ ES=EA=1; /*允许串行口中断*/ P1_0=0; /数码管位选信号 while(1) if(sc>=16) /接收到16个数后,循环显示 for(i=0;i<16;i+) /循环16次,依次显示a0-a15 P0= TABLEai; Delay(500); /发生外部中断0下降沿触发时,单片机从串行口输出字符串"Hello";/发生外部中断1下降沿触发时,单片机从串行口输出字符串"SCUT!"。#include <reg51.h>char sa="Hello",sb="SCUT!"void INT0_srv(void) interrupt 0 /INT0中断号为0 char i; for(i=0;i<5;i+) /循环5次,依次发送各字符 SBUF=sai; /*数据送串行口发送缓冲器*/ while(TI=0);/*如果TI=0,未发送完,循环等待*/ TI=0;/*已发送完,再把TI清0*/ void INT1_srv(void) interrupt 2 /INT1中断号为2 char i; for(i=0;i<5;i+) /循环5次,依次发送各字符 SBUF=sbi; /*数据送串行口发送缓冲器*/ while(TI=0);/*如果TI=0,未发送完,循环等待*/ TI=0;/*已发送完,再把TI清0*/ void main() TMOD=0x20; /*设置定时器T1为方式2*/ TH1=TL1=0xfd;/*波特率9600*/ SCON=0x40; /*串口方式1只发送,不接收*/ TR1=1;/*启动T1*/ IT0=IT1=1; /INT0,INT1下降沿触发 EX0=EX1=EA=1; /允许INT0,INT1中断 while(1);- word.zl