目录git
目录................................................................................................................................1数组
函数的使用和熟悉********************************/.......................................4函数
实例3:用单片机控制第一个灯亮.............................................................................4ui
实例4:用单片机控制一个灯闪烁:认识单片机的工做频率.................................4spa
实例5:将P1口状态分别送入P0、P2、P3口:认识I/O口的引脚功能............5设计
实例6:使用P3口流水点亮8位LED.......................................................................5指针
实例7:经过对P3口地址的操做流水点亮8位LED...............................................6code
实例8:用不一样数据类型控制灯闪烁时间.................................................................7接口
实例9:用P0口、P1口分别显示加法和减法运算结果.........................................8字符串
实例10:用P0、P1口显示乘法运算结果................................................................9
实例11:用P1、P0口显示除法运算结果................................................................9
实例12:用自增运算控制P0口8位LED流水花样..............................................10
实例13:用P0口显示逻辑"与"运算结果...............................................................10
实例14:用P0口显示条件运算结果.......................................................................11
实例15:用P0口显示按位"异或"运算结果...........................................................11
实例16:用P0显示左移运算结果...........................................................................11
实例17:"万能逻辑电路"实验.................................................................................11
实例18:用右移运算流水点亮P1口8位LED.......................................................12
实例19:用if语句控制P0口8位LED的流水方向..............................................13
实例20:用swtich语句的控制P0口8位LED的点亮状态..................................13
实例21:用for语句控制蜂鸣器鸣笛次数..............................................................14
实例22:用while语句控制LED...............................................................................16
实例23:用do-while语句控制P0口8位LED流水点亮......................................16
实例24:用字符型数组控制P0口8位LED流水点亮..........................................17
实例25:用P0口显示字符串常量.........................................................................18
实例26:用P0口显示指针运算结果......................................................................19
实例27:用指针数组控制P0口8位LED流水点亮..............................................19
实例28:用数组的指针控制P0口8位LED流水点亮........................................20
实例29:用P0、P1口显示整型函数返回值........................................................21
实例30:用有参函数控制P0口8位LED流水速度..............................................22
实例31:用数组做函数参数控制流水花样.............................................................23
实例32:用指针做函数参数控制P0口8位LED流水点亮..................................23
实例33:用函数型指针控制P1口灯花样...............................................................25
实例34:用指针数组做为函数的参数显示多个字符串.........................................26
实例35:字符函数ctype.h应用举例.......................................................................27
实例36:内部函数intrins.h应用举例.....................................................................27
实例37:标准函数stdlib.h应用举例.......................................................................28
实例38:字符串函数string.h应用举例..................................................................29
实例39:宏定义应用举例2......................................................................................29
1/192
实例40:宏定义应用举例2......................................................................................30
实例41:宏定义应用举例3......................................................................................30
中断、定时器************************************************ .........31
实例42:用定时器T0查询方式P2口8位控制LED闪烁....................................31
实例43:用定时器T1查询方式控制单片机发出1KHz音频.................................31
实例44:将计数器T0计数的结果送P1口8位LED显示....................................32
实例45:用定时器T0的中断控制1位LED闪烁...................................................33
实例46:用定时器T0的中断实现长时间定时.......................................................34
实例47:用定时器T1中断控制两个LED以不一样周期闪烁...................................34
实例48:用计数器T1的中断控制蜂鸣器发出1KHz音频.....................................36
实例49:用定时器T0的中断实现"渴望"主题曲的播放.......................................36
实例50-1:输出50个矩形脉冲...............................................................................39
实例50-2:计数器T0统计外部脉冲数...................................................................40
实例51-2:定时器T0的模式2测量正脉冲宽度...................................................40
实例52:用定时器T0控制输出高低宽度不一样的矩形波.......................................41
实例53:用外中断0的中断方式进行数据采集.....................................................42
实例54-1:输出负脉宽为200微秒的方波.............................................................43
实例54-2:测量负脉冲宽度.....................................................................................43
实例55:方式0控制流水灯循环点亮.....................................................................44
实例56-1:数据发送程序.........................................................................................45
实例56-2:数据接收程序.........................................................................................47
实例57-1:数据发送程序.........................................................................................47
实例57-2:数据接收程序.........................................................................................49
实例58:单片机向PC发送数据..............................................................................50
实例59:单片机接收PC发出的数据......................................................................51
*********************************数码管显示 ...............................52
实例60:用LED数码显示数字5..............................................................................52
实例61:用LED数码显示器循环显示数字0~9......................................................52
实例62:用数码管慢速动态扫描显示数字"1234".................................................53
实例63:用LED数码显示器伪静态显示数字1234...............................................54
实例64:用数码管显示动态检测结果.....................................................................54
实例65:数码秒表设计.............................................................................................56
实例66:数码时钟设计.............................................................................................58
实例67:用LED数码管显示计数器T0的计数值...................................................62
实例68:静态显示数字“59”...................................................................................63
*****************************键盘控制
2
/
192
*****************************************************/...........................63
实例69:无软件消抖的独立式键盘输入实验.........................................................64
实例70:软件消抖的独立式键盘输入实验.............................................................64
实例71:CPU控制的独立式键盘扫描实验.............................................................65
实例72:定时器中断控制的独立式键盘扫描实验.................................................68
实例73:独立式键盘控制的4级变速流水灯.........................................................71
实例74:独立式键盘的按键功能扩展:"以一当四".............................................73
实例75:独立式键盘调时的数码时钟实验.............................................................75
实例76:独立式键盘控制步进电机实验.................................................................79
实例77:矩阵式键盘按键值的数码管显示实验.....................................................82
//实例78:矩阵式键盘按键音..................................................................................85
实例79:简易电子琴.................................................................................................86
实例80:矩阵式键盘实现的电子密码锁.................................................................92
*********************************************************************
*****液晶显示LCD*********液晶显示LCD*****液晶显示LCD*************
***********************************************************/...............95
实例81:用LCD显示字符'A'....................................................................................96
实例82:用LCD循环右移显示"WelcometoChina"...............................................99
实例83:用LCD显示适时检测结果......................................................................102
实例84:液晶时钟设计...........................................................................................106
******************************************一些芯片的使用*****24c02 ........DS18B20 X5045 ADC0832 DAC0832 DS1302
红外遥控**********************************************/......................112
实例85:将数据"0x0f"写入AT24C02再读出送P1口显示..................................112
实例86:将按键次数写入AT24C02,再读出并用1602LCD显示.......................117
实例87:对I2C总线上挂接多个AT24C02的读写操做.......................................124
实例88:基于AT24C02的多机通讯 读取程序..................................................129
实例88:基于AT24C02的多机通讯写入程序....................................................133
实例90:DS18B20温度检测及其液晶显示...........................................................144
实例91:将数据"0xaa"写入X5045再读出送P1口显示......................................153
实例92:将流水灯控制码写入X5045并读出送P1口显示................................157
实例93:对SPI总线上挂接多个X5045的读写操做............................................161
实例94:基于ADC0832的数字电压表..................................................................165
实例95:用DAC0832产生锯齿波电压..................................................................171
实例96:用P1口显示红外遥控器的按键值.........................................................171
实例97:用红外遥控器控制继电器.......................................................................174
实例98:基于DS1302的日历时钟........................................................................177
实例99:单片机数据发送程序...............................................................................185
实例100:电机转速表设计.....................................................................................186
模拟霍尔脉冲............................................................................................................192
3
/
192
/************************************************************
函数的使用和熟悉***************
************************************************/
//实例3:用单片机控制第一个灯亮
#include<reg51.h> //包含51单片机寄存器定义的头文件
voidmain(void)
{
P1=0xfe;//P1=11111110B,即P1.0输出低电平
}
//
4
//实例4:用单片机控制一个灯闪烁:认识单片机的工做频率
#include<reg51.h> //包含单片机寄存器的头文件
/****************************************
函数功能:延时一段时间
*****************************************/
voiddelay(void) //两个void意思分别为无需返回值,没有参数传递
{
unsignedinti; //定义无符号整数,最大取值范围65535
for(i=0;i<20000;i++) //作20000次空循环
; //什么也不作,等待一个机器周期
}
/*******************************************************
函数功能:主函数(C语言规定必须有也只能有1个主函数)
********************************************************/
voidmain(void)
{
while(1) //无限循环
{
P1=0xfe; //P1=11111110B,P1.0输出低电平
delay(); //延时一段时间
P1=0xff; //P1=11111111B,P1.0输出高电平
delay(); //延时一段时间
}
}
4/192
//
5
P1
P0
P2
P3
I/O
//实例5:将
#include<reg51.h>
P1口状态分别送入P0、P2、P3口:认识I/O口
的引脚功能
//包含单片机寄存器的头文件
/*******************************************************
函数功能:主函数(C语言规定必须有也只能有1个主函数)
********************************************************/
voidmain(void)
{
while(1) //无限循环
{
P1=0xff; //P1=11111111B,熄灭LED
P0=P1; // 将P1口状态送入P0口
P2=P1; // 将P1口状态送入P2口
P3=P1; // 将P1口状态送入P3口
}
}
//实例6:使用P3口流水点亮8位LED
#include<reg51.h> //包含单片机寄存器的头文件
/****************************************
函数功能:延时一段时间
*****************************************/
voiddelay(void)
{
unsignedchari,j;
for(i=0;i<250;i++)
for(j=0;j<250;j++)
;
}
/*******************************************************
函数功能:主函数
********************************************************/
voidmain(void)
{
5/192
while(1)
{
P3=0xfe;
delay();
P3=0xfd;
delay();
P3=0xfb;
delay();
P3=0xf7;
delay();
P3=0xef;
//第一个灯亮
//调用延时函数
//第二个灯亮
//调用延时函数
//第三个灯亮
//调用延时函数
//第四个灯亮
//调用延时函数
//第五个灯亮
delay();
//调用延时函数
P3=0xdf;
delay();
P3=0xbf;
//第六个灯亮
//调用延时函数
//第七个灯亮
delay();
//调用延时函数
P3=0x7f;
//第八个灯亮
}
}
delay();
//调用延时函数
//实例7:经过对P3口地址的操做流水点亮8位LED
#include<reg51.h> //包含单片机寄存器的头文件
sfrx=0xb0; //P3口在存储器中的地址是b0H,经过sfr可定义8051内核单片
机
//的全部内部8位特殊功能寄存器,对地址x的操做也就是对P1口的
操做
/****************************************
函数功能:延时一段时间
*****************************************/
voiddelay(void)
{
unsignedchari,j;
for(i=0;i<250;i++)
for(j=0;j<250;j++)
; //利用循环等待若干机器周期,从而延时一段时间
}
/*****************************************
函数功能:主函数
6/192
******************************************/
voidmain(void)
{
while(1)
{
x=0xfe; //第一个灯亮
delay(); //调用延时函数
x=0xfd; //第二个灯亮
delay(); //调用延时函数
x=0xfb; //第三个灯亮
delay(); //调用延时函数
x=0xf7; //第四个灯亮
delay(); //调用延时函数
x=0xef; //第五个灯亮
delay(); //调用延时函数
x=0xdf; //第六个灯亮
delay(); //调用延时函数
x=0xbf; //第七个灯亮
delay(); //调用延时函数
x=0x7f; //第八个灯亮
delay(); //调用延时函数
}
}
//实例8:用不一样数据类型控制灯闪烁时间
#include<reg51.h> //包含单片机寄存器的头文件
/******************************************************
函数功能:用整形数据延时一段时间
******************************************************/
voidint_delay(void)//延时一段较长的时间
{
unsignedintm; //定义无符号整形变量,双字节数据,值域为0~65535
for(m=0;m<36000;m++)
; //空操做
}
/******************************************************
函数功能:用字符型数据延时一段时间
******************************************************/
7/192
voidchar_delay(void)//延时一段较短的时间
{
unsignedchari,j; //定义无符号字符型变量,单字节数据,值域0~255
for(i=0;i<200;i++)
for(j=0;j<180;j++)
; //空操做
}
/******************************************************
函数功能:主函数
******************************************************/
voidmain(void)
{
unsignedchari;
while(1)
{
for(i=0;i<3;i++)
{
P1=0xfe; //P1.0口的灯点亮
int_delay();//延时一段较长的时间
P1=0xff; //熄灭
int_delay();//延时一段较长的时间
}
for(i=0;i<3;i++)
{
P1=0xef; //P1.4口的灯点亮
char_delay();//延时一段较长的时间
P1=0xff; //熄灭
char_delay();//延时一段较长的时间
}
}
}
//实例9:用P0口、P1
#include<reg51.h>
voidmain(void)
{
unsignedcharm,n;
口分别显示加法和减法运算结果
m=43;
//即十进制数2x16+11=43
8/
192
n=60;
P1=m+n;
//即十进制数3x16+12=60
//P1=103=01100111B,结果P1.3、P1.4、P1.7
口的灯被点亮
}
P0=n-m;
//P0=17=00010001B,结果P0.0、P0.4的灯被熄灭
//实例10:用P0、P1口显示乘法运算结果
#include<reg51.h>//包含单片机寄存器的头文件
voidmain(void)
{
unsignedcharm,n;
unsignedints;
m=64;
n=71;
s=m*n; //s=64*71=4544,须要16位二进制数表示,高8位送P1口,低
8位送P0口
//因为4544=17*256+192=H3*16*16*16+H2*16*16+H1*16+H0
//两边同除以256,可得17+192/256=H3*16+H2+ H1*16+H0)
/256
//所以,高8位16进制数H3*16+H2必然等于17,即4544
除以256的商
//低8位16进制数H1*16+H0必然等于192,即4544除以
256的余数
P1=s/256; //高8位送P1口,P1=17=11H=00010001B,P1.0和P1.4口灭,
其他亮
P0=s%256; //低8位送P0口,P3=192=c0H=11000000B,P3.1,P3.6,P3.7口
灭,其他亮
}
//实例11:用P1、P0口显示除法运算结果
#include<reg51.h> //包含单片机寄存器的头文件
voidmain(void)
{
P1=36/5; //求整数
P0=((36%5)*10)/5;//求小数
while(1)
9/192
}
;
//无限循环防止程序“跑飞”
//实例12:用自增运算控制P0口8位LED流水花样
#include<reg51.h> //包含单片机寄存器的头文件
/******************************************************
函数功能:延时一段时间
******************************************************/
voiddelay(void)
{
unsignedinti;
for(i=0;i<20000;i++)
;
}
/******************************************************
函数功能 :主函数
******************************************************/
voidmain(void)
{
unsignedchari;
for(i=0;i<255;i++) //注意i的值不能超过255
{
P0=i; //将i的值送P0口
delay();//调用延时函数
}
}
//实例13:用P0口显示逻辑"与"运算结果
#include<reg51.h> //包含单片机寄存器的头文件
voidmain(void)
{
P0=(4>0)&&(9>0xab);//将逻辑运算结果送P0口
while(1)
; //设置无限循环,防止程序“跑飞”
}
110/192
//
14
P0
//实例14:用P0口显示条件运算结果
#include<reg51.h> //包含单片机寄存器的头文件
voidmain(void)
{
P0=(8>4)?8:4;//将条件运算结果送P0口,P0=8=00001000B
while(1)
; //设置无限循环,防止程序“跑飞”
}
//实例15:用P0口显示按位"异或"运算结果
#include<reg51.h> //包含单片机寄存器的头文件
voidmain(void)
{
P0=0xa2^0x3c;//将条件运算结果送P0口,P0=8=00001000B
while(1)
; //设置无限循环,防止程序“跑飞”
}
//
16
P0
//实例16:用P0显示左移运算结果
#include<reg51.h> //包含单片机寄存器的头文件
voidmain(void)
{
P0=0x3b<<2;//将左移运算结果送P0口,P0=11101100B=0xec
while(1)
; //无限循环,防止程序“跑飞”
}
#include<reg51.h>
sbitF=P1^4;
//实例17:"万能逻辑电路"实验
//包含单片机寄存器的头文件
//将F位定义为P1.4
111/192
sbitX=P1^5;
sbitY=P1^6;
sbitZ=P1^7;
voidmain(void)
{
while(1)
{
//将X位定义为
//将Y位定义为
//将Z位定义为
P1.5
P1.6
P1.7
}
}
F=((~X)&Y)|Z;//将逻辑运算结果赋给F
;
//实例18:用右移运算流水点亮P1口8位LED
#include<reg51.h> //包含单片机寄存器的头文件
/*****************************
函数功能:延时一段时间
*****************************/
voiddelay(void)
{
unsignedintn;
for(n=0;n<30000;n++)
;
}
/*****************************
函数功能:主函数
*****************************/
voidmain(void)
{
unsignedchari;
while(1)
{
P1=0xff;
delay();
for(i=0;i<8;i++)//设置循环次数为8
{
P1=P1>>1; //每次循环P1的各二进位右移1位,高位补0
delay(); //调用延时函数
}
}
}
112/192
//
19
iff
P0
8
LED
//实例19:用iff语句控制P0口8位LED的流水方向
#include<reg51.h> //包含单片机寄存器的头文件
sbitS1=P1^4; //将S1位定义为P1.4
sbitS2=P1^5; //将S2位定义为P1.5
/*****************************
函数功能:主函数
*****************************/
voidmain(void)
{
while(1)
{
if(S1==0) //若是按键S1按下
P0=0x0f; //P0口高四位LED点亮
if(S2==0) //若是按键S2按下
P0=0xf0; //P0口低四位LED点亮
}
}
//实例20:用swtich语句的控制P0口8位LED的点亮状态
#include<reg51.h> //包含单片机寄存器的头文件
sbitS1=P1^4; //将S1位定义为P1.4
/*****************************
函数功能:延时一段时间
*****************************/
voiddelay(void)
{
unsignedintn;
for(n=0;n<10000;n++)
;
}
/*****************************
函数功能:主函数
*****************************/
voidmain(void)
{
unsignedchari;
113/192
i=0;
while(1)
{
//将i初始化为0
if(S1==0)
{
delay();
//若是S1键按下
//延时一段时间
}
if(S1==0)//若是再次检测到S1键按下
i++; //i自增1
if(i==9) //若是i=9,从新将其置为1
i=1;
}
switch(i)
}
{
}
//使用多分支选择语句
case1:P0=0xfe; //第一个LED亮
break;
case2:P0=0xfd; //第二个LED亮
break;
case3:P0=0xfb; //第三个LED亮
break;
case4:P0=0xf7; //第四个LED亮
break;
case5:P0=0xef; //第五个LED亮
break;
case6:P0=0xdf; //第六个LED亮
break;
case7:P0=0xbf; //第七个LED亮
break;
case8:P0=0x7f; //第八个LED亮
break;
default: //缺省值,关闭全部LED
P0=0xff;
//
21
for
//实例21:用for语句控制蜂鸣器鸣笛次数
#include<reg51.h> //包含单片机寄存器的头文件
sbitsound=P3^7; //将sound位定义为P3.7
/****************************************
函数功能:延时造成1600Hz音频
114/192
****************************************/
voiddelay1600(void)
{
unsignedcharn;
for(n=0;n<100;n++)
;
}
/****************************************
函数功能:延时造成800Hz音频
****************************************/
voiddelay800(void)
{
unsignedcharn;
for(n=0;n<200;n++)
;
}
/****************************************
函数功能:主函数
****************************************/
voidmain(void)
{
unsignedinti;
while(1)
{
for(i=0;i<830;i++)
{
sound=0; //P3.7输出低电平
delay1600();
sound=1; //P3.7输出高电平
delay1600();
}
for(i=0;i<200;i++)
{
sound=0; //P3.7输出低电平
delay800();
sound=1; //P3.7输出高电平
delay800();
}
}
}
115
/
192
//实例22:用whille语句控制LED
#include<reg51.h>
//包含单片机寄存器的头文件
/****************************************
函数功能:延时约60ms(3*100*200=60000μs)
****************************************/
voiddelay60ms(void)
{
unsignedcharm,n;
for(m=0;m<100;m++)
for(n=0;n<200;n++)
;
}
/****************************************
函数功能:主函数
****************************************/
voidmain(void)
{
unsignedchari;
while(1) //无限循环
{
i=0; //将i初始化为0
while(i<0xff) //当i小于0xff(255)时执行循环体
{
P0=i; //将i送P0口显示
delay60ms();//延时
i++; //i自增1
}
}
}
//实例23:用do-whiile语句控制P0口8位LED流水点亮
#include<reg51.h> //包含单片机寄存器的头文件
/****************************************
函数功能:延时约60ms(3*100*200=60000μs)
****************************************/
voiddelay60ms(void)
{
116/192
}
unsignedcharm,n;
for(m=0;m<100;m++)
for(n=0;n<200;n++)
;
/****************************************
函数功能:主函数
****************************************/
voidmain(void)
{
do
{
P0=0xfe; //第一个LED亮
delay60ms();
P0=0xfd; //第二个LED亮
delay60ms();
P0=0xfb; //第三个LED亮
delay60ms();
P0=0xf7; //第四个LED亮
delay60ms();
P0=0xef; //第五个LED亮
delay60ms();
P0=0xdf; //第六个LED亮
delay60ms();
delay60ms();
P0=0xbf; //第七个LED亮
delay60ms();
P0=0x7f; //第八个LED亮
delay60ms();
}while(1); //无限循环,使8位LED循环流水点亮
}
//实例24:用字符型数组控制P0口8位LED流水点亮
#include<reg51.h> //包含单片机寄存器的头文件
/****************************************
函数功能:延时约60ms(3*100*200=60000μs)
****************************************/
voiddelay60ms(void)
{
unsignedcharm,n;
for(m=0;m<100;m++)
117/192
}
for(n=0;n<200;n++)
;
/****************************************
函数功能:主函数
****************************************/
voidmain(void)
{
unsignedchari;
unsignedcharcodeTab[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//定义无符
号字符型数组
while(1)
{
for(i=0;i<8;i++)
{
P0=Tab[i];//依次引用数组元素,并将其送P0口显示
delay60ms();//调用延时函数
}
}
}
//
25
P0
//实例25:
用P0口显示字符串常量
#include<reg51.h>
//包含单片机寄存器的头文件
/*************************************************
函数功能:延时约150ms(3*200*250=150000μs=150ms
*************************************************/
voiddelay150ms(void)
{
unsignedcharm,n;
for(m=0;m<200;m++)
for(n=0;n<250;n++)
;
}
/*************************************************
函数功能:主函数
*************************************************/
voidmain(void)
{
unsignedcharstr[]={"Now,Temperatureis:"}; //将字符串赋给字符型所有元素
赋值
unsignedchari;
118/192
while(1)
{
i=0;
//将i初始化为0,从第一个元素开始显示
}
}
while(str[i]!='\0')//只要没有显示到结束标志'\0'
{
P0=str[i]; //将第i个字符送到P0口显示
delay150ms(); //调用150ms延时函数
i++; //指向下一个待显字符
}
//实例26:用P0
#include<reg51.h>
voidmain(void)
{
口显示指针运算结果
unsignedchar*p1,*p2;
//定义无符号字符型指针变量p1,p2
unsignedchari,j;
//定义无符号字符型数据
i=25;
j=15;
p1=&i;
p2=&j;
//给i赋初值25
//使指针变量指向i
//使指针变量指向j
,对指针初始化
,对指针初始化
P0=*p1+*p2;
//*p1+*p2至关于i+j,因此P0=25+15=40=0x28
}
//则P0=00101000B,结果P0.3、P0.5引脚LED熄灭,其他点亮
while(1)
; //无限循环,防止程序“跑飞”
//
27
P0
8
LED
//实例27:用指针数组控制P0口8位LED流水点亮
#include<reg51.h>
/*************************************************
函数功能:延时约150ms(3*200*250=150000μs=150ms
*************************************************/
voiddelay150ms(void)
{
unsignedcharm,n;
for(m=0;m<200;m++)
119/192
}
for(n=0;n<250;n++)
;
/*************************************************
函数功能:主函数
*************************************************/
voidmain(void)
{
unsignedcharcodeTab[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
unsignedchar*p[]={&Tab[0],&Tab[1],&Tab[2],&Tab[3],&Tab[4],&Tab[5],
&Tab[6],&Tab[7]};
unsignedchari; //定义无符号字符型数据
while(1)
{
for(i=0;i<8;i++)
{
P0=*p[i];
delay150ms();
}
}
}
//
28
P0
8
LED
//实例28:用数组的指针控制P0
#include<reg51.h>
口8
位LED流水点亮
/*************************************************
函数功能:延时约150ms(3*200*250=150000μs=150ms
*************************************************/
voiddelay150ms(void)
{
unsignedcharm,n;
for(m=0;m<200;m++)
for(n=0;n<250;n++)
;
}
/*************************************************
函数功能:主函数
*************************************************/
voidmain(void)
{
220/192
}
unsignedchari;
unsignedcharTab[]={0xFF,0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,
0x7F,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0xFE,
0xFE,0xFC,0xFB,0xF0,0xE0,0xC0,0x80,0x00,
0xE7,0xDB,0xBD,0x7E,0x3C,0x18,0x00,0x81,
0xC3,0xE7,0x7E,0xBD,0xDB,0xE7,0xBD,0xDB};
//流水灯控制码
unsignedchar*p; //定义无符号字符型指针
p=Tab; //将数组首地址存入指针p
while(1)
{
for(i=0;i<32;i++)//共32个流水灯控制码
{
P0=*(p+i); //*(p+i)的值等于a[i]
delay150ms(); //调用150ms延时函数
}
}
//
29
P0
P1
//实例29:用P0
#include<reg51.h>
、P1口显示整型函数返回值
/*************************************************
函数功能:计算两个无符号整数的和
*************************************************/
unsignedintsum(inta,intb)
{
unsignedints;
s=a+b;
return(s);
}
/*************************************************
函数功能:主函数
*************************************************/
voidmain(void)
{
unsignedz;
z=sum(2008,2009);
P1=z/256; //取得z的高8位
P0=z%256; //取得z的低8位
while(1)
;
221/192
}
//实例30:用有参函数控制P0口8位LED流水速度
#include<reg51.h>
/*************************************************
函数功能:延时一段时间
*************************************************/
voiddelay(unsignedcharx)
{
unsignedcharm,n;
for(m=0;m<x;m++)
for(n=0;n<200;n++)
;
}
/*************************************************
函数功能:主函数
*************************************************/
voidmain(void)
{
unsignedchari;
unsigned charcodeTab[]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};
//流水灯控制码
while(1)
{
//快速流水点亮LED
for(i=0;i<8;i++)//共8个流水灯控制码
{
P0=Tab[i];
delay(100); //延时约60ms,(3*100*200=60000μs)
}
//慢速流水点亮LED
for(i=0;i<8;i++)//共8个流水灯控制码
{
P0=Tab[i];
delay(250); //延时约150ms,(3*250*200=150000μs)
}
}
}
222
/
192
//
31
//实例31:用数组做函数参数控制流水花样
#include<reg51.h>
/*************************************************
函数功能:延时约150ms
*************************************************/
voiddelay(void)
{
unsignedcharm,n;
for(m=0;m<200;m++)
for(n=0;n<250;n++)
;
}
/*************************************************
函数功能:流水点亮P0口8位LED
*************************************************/
voidled_flow(unsignedchara[8])
{
unsignedchari;
for(i=0;i<8;i++)
{
P0=a[i];
delay();
}
}
/*************************************************
函数功能:主函数
*************************************************/
voidmain(void)
{
unsigned charcodeTab[]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};
//流水灯控制码
led_flow(Tab);
}
//
32
P0
8
LED
//实例32:用指针做函数参数控制P0口8位LED流水点亮
#include<reg51.h>
223/192
/*************************************************
函数功能:延时约150ms
*************************************************/
voiddelay(void)
{
unsignedcharm,n;
for(m=0;m<200;m++)
for(n=0;n<250;n++)
;
}
/*************************************************
函数功能:流水点亮P0口8位LED
*************************************************/
voidled_flow(unsignedchar*p)//形参为无符号字符型指针
{
unsignedchari;
while(1)
{
i=0; //将i置为0,指向数组第一个元素
while(*(p+i)!='\0')//只要没有指向数组的结束标志
{
P0=*(p+i);// 取的指针所指变量(数组元素)的值,送P0口
delay(); //调用延时函数
i++; //指向下一个数组元素
}
}
}
/*************************************************
函数功能:主函数
*************************************************/
voidmain(void)
{
unsigned charcodeTab[]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F,
0x7F,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0xFE,
0xFF,0xFE,0xFC,0xFB,0xF0,0xE0,0xC0,0x80,
0x00,0xE7,0xDB,0xBD,0x7E,0xFF,0xFF,0x3C,
0x18,0x0,0x81,0xC3,0xE7,0xFF,
0xFF,0x7E};
//流水灯控制码
unsignedchar*pointer;
224/192
}
pointer=Tab;
led_flow(pointer);
//
33
P1
//实例33:用函数型指针控制P1口灯花样
#include<reg51.h> //包含51单片机寄存器定义的头文件
unsignedcharcodeTab[]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};
//流水灯控制码,该数组被定义为全局变量
/**************************************************************
函数功能:延时约150ms
**************************************************************/
voiddelay(void)
{
unsignedcharm,n;
for(m=0;m<200;m++)
for(n=0;n<250;n++)
;
}
/**************************************************************
函数功能:流水灯左移
**************************************************************/
voidled_flow(void)
{
unsignedchari;
for(i=0;i<8;i++) //8位控制码
{
P0=Tab[i];
delay();
}
}
/**************************************************************
函数功能:主函数
**************************************************************/
voidmain(void)
{
void(*p)(void);//定义函数型指针,所指函数无参数,无返回值
p=led_flow; //将函数的入口地址赋给函数型指针p
while(1)
225/192
}
(*p)();
//经过函数的指针p调用函数led_flow()
//
34
//实例34:用指针数组做为函数的参数显示多个字符串
#include<reg51.h> //包含51单片机寄存器定义的头文件
unsignedcharcodestr1[]="TemperatureistestedbyDS18B20";//C语言中,字符串
是做为字符数组来处理的
unsignedcharcodestr2[]="Nowtemperatureis:"; //因此,字符串的名字就是
字符串的首地址
unsignedcharcodestr3[]="TheSystermisdesignedbyZhangSan";
unsignedcharcodestr4[]="Thedateis2008-9-30";
unsignedchar*p[]={str1,str2,str3,str4};//定义p[4]为指向4个字符串的字符型指
针数组
/**************************************************************
函数功能:延时约150ms
**************************************************************/
voiddelay(void)
{
unsignedcharm,n;
for(m=0;m<200;m++)
for(n=0;n<250;n++)
;
}
/**************************************************************
函数功能:流水点亮P0口8位LED
**************************************************************/
voidled_display(unsignedchar*x[]) //形参必须为指针数组
{
unsignedchari,j;
for(i=0;i<4;i++)//有4个字符串要显示
{
j=0; //指向待显字符串的第0号元素
while(*(x[i]+j)!='\0')//只要第i个字符串的第j号元素不是结束标志
{
P0=*(x[i]+j);//取得该元素值送到P0口显示
delay(); //调用延时函数
j++; //指向下一个元素
}
}
}
226/192
/**************************************************************
函数功能:主函数
**************************************************************/
voidmain(void)
{
unsignedchari;
while(1)
{
for(i=0;i<4;i++)
led_display(p);//将指针数组名做实际参数传递
}
}
//实例35:字符函数ctype.h应用举例
#include<reg51.h> //包含51单片机寄存器定义的头文件
#include<ctype.h>
voidmain(void)
{
while(1)
{
P3=isalpha('_')?0xf0:0x0f;//条件运算,若'_'是英文字母,P3=0xf0
}
}
//实例36:内部函数intrins..h应用举例
#include<reg51.h> //包含51单片机寄存器定义的头文件
#include<intrins.h> //包含函数isalpha()声明的头文件
/*************************************************
函数功能:延时约150ms
*************************************************/
voiddelay(void)
{
unsignedcharm,n;
for(m=0;m<200;m++)
for(n=0;n<250;n++)
;
}
227/192
/*************************************************
函数功能:主函数
*************************************************/
voidmain(void)
{
P3=0xfe; //P3=11111110B
while(1)
{
P3=_crol_(P3,1);//将P3的二进制位循环左移1位后再赋给P3
delay(); //调用延时函数
}
}
//
37
stdlib.h
//实例37:标准函数stdliib.h应用举例
#include<reg51.h> //包含51单片机寄存器定义的头文件
#include<stdlib.h> //包含函数isalpha()声明的头文件
/*************************************************
函数功能:延时约150ms
*************************************************/
voiddelay(void)
{
unsignedcharm,n;
for(m=0;m<200;m++)
for(n=0;n<250;n++)
;
}
/*************************************************
函数功能:主函数
*************************************************/
voidmain(void)
{
unsignedchari;
while(1)
{
for(i=0;i<10;i++)//产生10个随机数
{
P3=rand()/160;//将产生的随机数缩小160倍后送P3显示
delay();
}
}
228/192
}
//实例38:字符串函数striing.h应用举例
#include<reg51.h> //包含51单片机寄存器定义的头文件
#include<string.h> //包含函数isalpha()声明的头文件
voidmain(void)
{
unsignedcharstr1[]="Now,Thetemperatureis:";
unsignedcharstr2[]="Now,Thetemperatureis36Centgrade:";
unsignedchari;
i=strcmp(str1,str2);//比较两个字符串,并将结果存入i
if(i==0)//str1=str2
P3=0x00;
else
if(i<0) //str1<str2
P3=0xf0;
else //str1>str2
P3=0x0f;
while(1)
; //防止程序“跑飞”
}
//
39
2
#include<reg51.h>
//实例39:宏定义应用举例2
//包含51单片机寄存器定义的头文件
#defineF(a,b)(a)+(a)*(b)/256+(b)
voidmain(void)
{
unsignedchari,j,k;
i=40;
j=30;
k=20;
//带参数的宏定义,a和b为形参
参
}
P3=F(i,j+k);
while(1)
;
//i和j+k分别为实参,宏展开时,实参将替代宏定义中的形
229/192
//实例40:宏定义应用举例2
#include<AT89X51.h>
#include<ctype.h>
voidmain(void)
{
P3_0=0; //将P3.0引脚置低电平,LED点亮
P3_1=0; //将P3.0引脚置低电平,LED点亮
P3_2=0; //将P3.0引脚置低电平,LED点亮
P3_3=0; //将P3.0引脚置低电平,LED点亮
P3_4=1; //将P3.4引脚置高电平,LED熄灭
P3_5=1; //将P3.5引脚置高电平,LED熄灭
P3_6=1; //将P3.7引脚置高电平,LED熄灭
P3_7=1; //将P3.7引脚置高电平,LED熄灭
while(1)
;
}
//实例41:宏定义应用举例3
#include<reg51.h>
#defineMAX100
voidmain(void)
{
#ifMAX>80
P3=0xf0;
#else
P3=0x0f;
#endif
}
//包含51单片机寄存器定义的头文件
//将MAX宏定义为字符串100
//若是字符串100大于80
//P3口低四位LED点亮
//不然,P3口高四位LED点亮
//结束本次编译
330
/
192
/********************************************************
*********中断、定时器********中断、定时器************
*********中断、定时器*********中断、定时器************
********************************************************/
//实例42:用定时器T0查询方式P2口8位控制LED闪烁
#include<reg51.h> // 包含51单片机寄存器定义的头文件
/**************************************************************
函数功能:主函数
**************************************************************/
voidmain(void)
{
//EA=1; //开总中断
// ET0=1; //定时器T0中断容许
TMOD=0x01; //使用定时器T0的模式1
TH0=(65536-46083)/256; //定时器T0的高8位赋初值
TL0=(65536-46083)%256; //定时器T0的高8位赋初值
TR0=1; //启动定时器T0
TF0=0;
P2=0xff;
while(1)//无限循环等待查询
{
while(TF0==0)
;
TF0=0;
P2=~P2;
TH0=(65536-46083)/256; //定时器T0的高8位赋初值
TL0=(65536-46083)%256; //定时器T0的高8位赋初值
}
}
//实例43:用定时器T1查询方式控制单片机发出1KHz音频
#include<reg51.h> // 包含51单片机寄存器定义的头文件
sbitsound=P3^7; //将sound位定义为P3.7引脚
331/192
/**************************************************************
函数功能:主函数
**************************************************************/
voidmain(void)
{
//EA=1; //开总中断
// ET0=1; //定时器T0中断容许
TMOD=0x10; //使用定时器T1的模式1
TH1=(65536-921)/256; //定时器T1的高8位赋初值
TL1=(65536-921)%256; //定时器T1的高8位赋初值
TR1=1; //启动定时器T1
TF1=0;
while(1)//无限循环等待查询
{
while(TF1==0)
;
TF1=0;
sound=~sound; //将P3.7引脚输出电平取反
TH1=(65536-921)/256; //定时器T0的高8位赋初值
TL1=(65536-921)%256; //定时器T0的高8位赋初值
}
}
//
44
T0
P1
8
LED
//实例44:将计数器T0计数的结果送P1口8位LED显示
#include<reg51.h> // 包含51单片机寄存器定义的头文件
sbitS=P3^4; //将S位定义为P3.4引脚
/**************************************************************
函数功能:主函数
**************************************************************/
voidmain(void)
{
//EA=1; //开总中断
// ET0=1; //定时器T0中断容许
TMOD=0x02; //使用定时器T0的模式2
TH0=256-156; //定时器T0的高8位赋初值
TL0=256-156; //定时器T0的高8位赋初值
TR0=1; //启动定时器T0
while(1)//无限循环等待查询
{
while(TF0==0) //若是未计满就等待
332/192
{
if(S==0)
//按键S按下接地,电平为0
}
}
}
TF0=0;
P1=TL0;//计数器TL0加1后送P1口显示
//计数器溢出后,将TF0清0
//实例45:用定时器T0的中断控制1位LED闪烁
#include<reg51.h> // 包含51单片机寄存器定义的头文件
sbitD1=P2^0; //将D1位定义为P2.0引脚
/**************************************************************
函数功能:主函数
**************************************************************/
voidmain(void)
{
EA=1; //开总中断
ET0=1; //定时器T0中断容许
TMOD=0x01; //使用定时器T0的模式2
TH0=(65536-46083)/256;//定时器T0的高8位赋初值
TL0=(65536-46083)%256;//定时器T0的高8位赋初值
TR0=1; //启动定时器T0
while(1)//无限循环等待中断
;
}
/**************************************************************
函数功能:定时器T0的中断服务程序
**************************************************************/
voidTime0(void)interrupt1using0//“interrupt”声明函数为中断服务函数
//其后的1为定时器T0的中断编号;0表示使用第0组工做
寄存器
{
D1=~D1; //按位取反操做,将P2.0引脚输出电平取反
TH0=(65536-46083)/256;//定时器T0的高8位从新赋初值
TL0=(65536-46083)%256;//定时器T0的高8位从新赋初值
}
333
/
192
//
46
T0
//实例46:用定时器T0的中断实现长时间定时
#include<reg51.h> // 包含51单片机寄存器定义的头文件
sbitD1=P2^0; //将D1位定义为P2.0引脚
unsignedcharCountor;//设置全局变量,储存定时器T0中断次数
/**************************************************************
函数功能:主函数
**************************************************************/
voidmain(void)
{
EA=1; //开总中断
ET0=1; //定时器T0中断容许
TMOD=0x01; //使用定时器T0的模式2
TH0=(65536-46083)/256;//定时器T0的高8位赋初值
TL0=(65536-46083)%256;//定时器T0的高8位赋初值
TR0=1; //启动定时器T0
Countor=0; //从0开始累计中断次数
while(1)//无限循环等待中断
;
}
/**************************************************************
函数功能:定时器T0的中断服务程序
**************************************************************/
voidTime0(void)interrupt1using0//“interrupt”声明函数为中断服务函数
//其后的1为定时器T0的中断编号;0表示使用第0组工做
寄存器
{
Countor++; //中断次数自加1
if(Countor==20) //若累计满20次,即计时满1s
{
D1=~D1; //按位取反操做,将P2.0引脚输出电平取反
Countor=0; //将Countor清0,从新从0开始计数
}
TH0=(65536-46083)/256;//定时器T0的高8位从新赋初值
TL0=(65536-46083)%256;//定时器T0的高8位从新赋初值
}
//实例47:用定时器T1中断控制两个LED以不一样周期闪烁
#include<reg51.h> // 包含51单片机寄存器定义的头文件
sbitD1=P2^0; //将D1位定义为P2.0引脚
334/192
sbitD2=P2^1;
//将D2位定义为P2.1引脚
unsignedcharCountor1;//设置全局变量,储存定时器T1中断次数
unsignedcharCountor2;//设置全局变量,储存定时器T1中断次数
/**************************************************************
函数功能:主函数
**************************************************************/
voidmain(void)
{
EA=1; //开总中断
ET1=1; //定时器T1中断容许
TMOD=0x10; //使用定时器T1的模式1
TH1=(65536-46083)/256;//定时器T1的高8位赋初值
TL1=(65536-46083)%256;//定时器T1的高8位赋初值
TR1=1; //启动定时器T1
Countor1=0; //从0开始累计中断次数
Countor2=0; //从0开始累计中断次数
while(1)//无限循环等待中断
;
}
/**************************************************************
函数功能:定时器T1的中断服务程序
**************************************************************/
voidTime1(void)interrupt3using0//“interrupt”声明函数为中断服务函数
//其后的3为定时器T1的中断编号;0表示使用第0组工做
寄存器
{
Countor1++; //Countor1自加1
Countor2++; //Countor2自加1
if(Countor1==2) //若累计满2次,即计时满100ms
{
D1=~D1; //按位取反操做,将P2.0引脚输出电平取反
Countor1=0; //将Countor1清0,从新从0开始计数
}
if(Countor2==8) //若累计满8次,即计时满400ms
{
D2=~D2; //按位取反操做,将P2.1引脚输出电平取反
Countor2=0; //将Countor1清0,从新从0开始计数
}
TH1=(65536-46083)/256;//定时器T1的高8位从新赋初值
TL1=(65536-46083)%256;//定时器T1的高8位从新赋初值
}
335
/
192
//
48
T1
1KHz
//实例48:用计数器T1的中断控制蜂鸣器发出1KHz音频
#include<reg51.h> // 包含51单片机寄存器定义的头文件
sbitsound=P3^7; //将sound位定义为P3.7引脚
/**************************************************************
函数功能:主函数
**************************************************************/
voidmain(void)
{
EA=1; //开总中断
ET1=1; //定时器T1中断容许
TMOD=0x10; //TMOD=0001000B,使用定时器T1的模式1
TH1=(65536-921)/256; //定时器T1的高8位赋初值
TL1=(65536-921)%256; //定时器T1的高8位赋初值
TR1=1; //启动定时器T1
while(1)//无限循环等待中断
;
}
/**************************************************************
函数功能:定时器T1的中断服务程序
**************************************************************/
voidTime1(void)interrupt3using0//“interrupt”声明函数为中断服务函数
{
sound=~sound;
TH1=(65536-921)/256; //定时器T1的高8位从新赋初值
TL1=(65536-921)%256; //定时器T1的高8位从新赋初值
}
//
49
T0
"
"
//实例49:用定时器T0的中断实现"渴望"主题曲的播放
#include<reg51.h> //包含51单片机寄存器定义的头文件
sbitsound=P3^7; //将sound位定义为P3.7
unsignedintC; //储存定时器的定时常数
//如下是C调低音的音频宏定义
#definel_dao262 //将“l_dao”宏定义为低音“1”的频率262Hz
#definel_re286 //将“l_re”宏定义为低音“2”的频率286Hz
#definel_mi311 //将“l_mi”宏定义为低音“3”的频率311Hz
#definel_fa349 //将“l_fa”宏定义为低音“4”的频率349Hz
#definel_sao392 //将“l_sao”宏定义为低音“5”的频率392Hz
#definel_la440 //将“l_a”宏定义为低音“6”的频率440Hz
#definel_xi494 //将“l_xi”宏定义为低音“7”的频率494Hz
336/192
//如下是C调中音的音频宏定义
#definedao523 //将“dao”宏定义为中音“1”的频率523Hz
#definere587 //将“re”宏定义为中音“2”的频率587Hz
#definemi659 //将“mi”宏定义为中音“3”的频率659Hz
#definefa698 //将“fa”宏定义为中音“4”的频率698Hz
#definesao784 //将“sao”宏定义为中音“5”的频率784Hz
#definela880 //将“la”宏定义为中音“6”的频率880Hz
#definexi987 //将“xi”宏定义为中音“7”的频率523H
//如下是C调高音的音频宏定义
#defineh_dao1046 //将“h_dao”宏定义为高音“1”的频率1046Hz
#defineh_re1174 //将“h_re”宏定义为高音“2”的频率1174Hz
#defineh_mi1318 //将“h_mi”宏定义为高音“3”的频率1318Hz
#defineh_fa1396 //将“h_fa”宏定义为高音“4”的频率1396Hz
#defineh_sao1567 //将“h_sao”宏定义为高音“5”的频率1567Hz
#defineh_la1760 //将“h_la”宏定义为高音“6”的频率1760Hz
#defineh_xi1975 //将“h_xi”宏定义为高音“7”的频率1975Hz
/*******************************************
函数功能:1个延时单位,延时200ms
******************************************/
voiddelay()
{
unsignedchari,j;
for(i=0;i<250;i++)
for(j=0;j<250;j++)
;
}
/*******************************************
函数功能:主函数
******************************************/
voidmain(void)
{
unsignedchari,j;
//如下是《渴望》片头曲的一段简谱
unsigned intcodef[]={re,mi,re,dao,l_la,dao,l_la, //每行对应一小节音符
l_sao,l_mi,l_sao,l_la,dao,
l_la,dao,sao,la,mi,sao,
re,
mi,re,mi,sao,mi,
l_sao,l_mi,l_sao,l_la,dao,
l_la,l_la,dao,l_la,l_sao,l_re,l_mi,
l_sao,
re,re,sao,la,sao,
fa,mi,sao,mi,
la,sao,mi,re,mi,l_la,dao,
337/192
//如下是简谱中每一个音符的节拍
re,
mi,re,mi,sao,mi,
l_sao,l_mi,l_sao,l_la,dao,
l_la,dao,re,l_la,dao,re,mi,
re,
l_la,dao,re,l_la,dao,re,mi,
re,
0xff};//以0xff做为音符的结束标志
//"4"对应4个延时单位,"2"对应2个延时单位,"1"对应1个延时单位
unsignedcharcodeJP[]={4,1,1,4,1,1,2,
2,2,2,2,8,
4,2,3,1,2,2,
10,
4,2,2,4,4,
2,2,2,2,4,
2,2,2,2,2,2,2,
10,
4,4,4,2,2,
4,2,4,4,
4,2,2,2,2,2,2,
10,
4,2,2,4,4,
2,2,2,2,6,
4,2,2,4,1,1,4,
10,
4,2,2,4,1,1,4,
10
};
EA=1; //开总中断
ET0=1; //定时器T0中断容许
TMOD=0x00; // 使用定时器T0的模式1(13位计数器)
while(1) //无限循环
{
i=0; //从第1个音符f[0]开始播放
while(f[i]!=0xff) //只要没有读到结束标志就继续播放
{
C=460830/f[i];
TH0=(8192-C)/32; //可证实这是13位计数器TH0高8位的赋
初值方法
TL0=(8192-C)%32; //可证实这是13位计数器TL0低5位的赋初
值方法
TR0=1; //启动定时器T0
338/192
}
}
}
for(j=0;j<JP[i];j++)
delay();
TR0=0;
i++;
//控制节拍数
//延时1个节拍单位
//关闭定时器T0
//播放下一个音符
/***********************************************************
函数功能:定时器T0的中断服务子程序,使P3.7引脚输出音频的方波
************************************************************/
voidTime0(void)interrupt1using1
{
sound=!sound; //将P3.7引脚输出电平取反,造成方波
TH0=(8192-C)/32; //可证实这是13位计数器TH0高8位的赋初值方法
TL0=(8192-C)%32; //可证实这是13位计数器TL0低5位的赋初值方法
}
//
50-1
50
#include<reg51.h>
//实例50-1:输出50个矩形脉冲
//包含51单片机寄存器定义的头文件
sbitu=P1^4;
//将u位定义为P1.4
/*************************************************
函数功能:延时约30ms(3*100*100=30000μs=30m
*************************************************/
voiddelay30ms(void)
{
unsignedcharm,n;
for(m=0;m<100;m++)
for(n=0;n<100;n++)
;
}
/*******************************************
函数功能:主函数
******************************************/
voidmain(void)
{
unsignedchari;
u=1; //初始化输出高电平
for(i=0;i<50;i++)//输出50个矩形脉冲
{
339/192
}
}
u=1;
delay30ms();
u=0;
delay30ms();
while(1)
;//无限循环,防止程序“跑飞”
//实例50-2:计数器T0统计外部脉冲数
#include<reg51.h> //包含51单片机寄存器定义的头文件
/*******************************************
函数功能:主函数
******************************************/
voidmain(void)
{
TMOD=0x06; //TMOD=00000110B,使用计数器T0的模式2
EA=1; //开总中断
ET0=0; //不使用定时器T0的中断
TR0=1; //启动T0
TH0=0; //计数器T0高8位赋初值
TL0=0; //计数器T0低8位赋初值
while(1) //无限循环,不停地将TL0计数结果送P1口
P1=TL0;
}
//实例51-2:定时器T0的模式2测量正脉冲宽度
#include<reg51.h> //包含51单片机寄存器定义的头文件
sbitui=P3^2; //将ui位定义为P3.0(INT0)引脚,表示输入电压
/*******************************************
函数功能:主函数
******************************************/
voidmain(void)
{
TMOD=0x0a; //TMOD=00001010B,使用定时器T0的模式2,GATE置1
EA=1; //开总中断
440/192
ET0=0;
TR0=1;
TH0=0;
TL0=0;
while(1)
{
while(ui==0)
;
TL0=0;
//不使用定时器T0的中断
//启动T0
//计数器T0高8位赋初值
//计数器T0低8位赋初值
//无限循环,不停地将TL0计数结果送P1口
//INT0为低电平,T0不能启动
//INT0为高电平,启动T0计时,因此将TL0清0
}
}
while(ui==1)//在INT0高电平期间,等待,计时
;
P1=TL0; //将计时结果送P1口显示
//
52
T0
//实例52:用定时器T0控制输出高低宽度不一样的矩形波
#include<reg51.h> //包含51单片机寄存器定义的头文件
sbitu=P3^0; //将u位定义为P3.0,从该引脚输出矩形脉冲
unsignedcharCountor; //设置全局变量,储存负跳变累计数
/*************************************************
函数功能:延时约30ms(3*100*100=30000μs=30ms)
*************************************************/
voiddelay30ms(void)
{
unsignedcharm,n;
for(m=0;m<100;m++)
for(n=0;n<100;n++)
;
}
/*******************************************
函数功能:主函数
******************************************/
voidmain(void)
{
unsignedchari;
EA=1; //开放总中断
EX0=1; //容许使用外中断
IT0=1; //选择负跳变来触发外中断
Countor=0;
441/192
for(i=0;i<100;i++)
{
u=1;
delay30ms();
u=0;
delay30ms();
}
while(1)
//输出100个负跳变
}
;//无限循环,
防止程序跑飞
/**************************************************************
函数功能:外中断T0的中断服务程序
**************************************************************/
voidint0(void)interrupt0using0//外中断0的中断编号为0
{
Countor++;
P1=Countor;
}
//
53
0
//实例53:用外中断0的中断方式进行数据采集
#include<reg51.h> //包含51单片机寄存器定义的头文件
sbitS=P3^2; //将S位定义为P3.2,
/*******************************************
函数功能:主函数
******************************************/
voidmain(void)
{
EA=1; //开放总中断
EX0=1; //容许使用外中断
IT0=1; //选择负跳变来触发外中断
P1=0xff;
while(1)
;//无限循环,防止程序跑飞
}
/**************************************************************
函数功能:外中断T0的中断服务程序
**************************************************************/
voidint0(void)interrupt0using0//外中断0的中断编号为0
{
442/192
}
P1=~P1;
//每产生一次中断请求,P1取反一次。
//实例54-1:输出负脉宽为200微秒的方波
#include<reg51.h> //包含51单片机寄存器定义的头文件
sbitu=P1^4; //将u位定义为P1.4
/*******************************************
函数功能:主函数
******************************************/
voidmain(void)
{
TMOD=0x02; //TMOD=00000010B,使用定时器T0的模式2
EA=1; //开总中断
ET0=1; //定时器T0中断容许
TH0=256-200; //定时器T0的高8位赋初值
TL0=256-200; //定时器T0的高8位赋初值
TR0=1; //启动定时器T0
while(1) //无限循环,等待中断
;
}
/**************************************************************
函数功能:定时器T0的中断服务程序
**************************************************************/
voidTime0(void)interrupt1using0//"interrupt"声明函数为中断服务函数
{
u=~u; //将P1.4引脚输出电平取反,产生方波
}
//
54-2
#include<reg51.h>
//实例54-2:测量负脉冲宽度
//包含51单片机寄存器定义的头文件
sbitu=P3^2;
//将u位定义为P3.2
/*******************************************
函数功能:主函数
******************************************/
443/192
voidmain(void)
{
TMOD=0x02;
//TMOD=00000010B,使用定时器T0的模式2
EA=1;
EX0=1;
IT0=1;
ET0=1;
TH0=0;
TL0=0;
TR0=0;
//开放总中断
//容许使用外中断
//选择负跳变来触发外中断
//容许定时器T0中断
//定时器T0赋初值0
//定时器T0赋初值0
//先关闭T0
}
while(1)
;//无限循环,
不停检测输入负脉冲宽度
/**************************************************************
函数功能:外中断0的中断服务程序
**************************************************************/
voidint0(void)interrupt0using0//外中断0的中断编号为0
{
TR0=1; //外中断一到来,即启动T0计时
TL0=0; //从0开始计时
while(u==0) //低电平时,等待T0计时
;
P1=TL0;//将结果送P1口显示
TR0=0; //关闭T0
}
//实例55:方式0控制流水灯循环点亮
#include<reg51.h> //包含51单片机寄存器定义的头文件
#include<intrins.h>//包含函数_nop_()定义的头文件
unsignedcharcodeTab[]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};//流水灯控
制码,该数组被定义为全局变量
sbitP17=P1^7;
/**************************************************************
函数功能:延时约150ms
**************************************************************/
voiddelay(void)
{
unsignedcharm,n;
for(m=0;m<200;m++)
444/192
}
for(n=0;n<250;n++)
;
/**************************************************************
函数功能:发送一个字节的数据
**************************************************************/
voidSend(unsignedchardat)
{
P17=0; //P1.7引脚输出清0信号,对74LS164清0
_nop_(); //延时一个机器周期
_nop_(); //延时一个机器周期,保证清0完成
P17=1; //结束对74LS164的清0
SBUF=dat; //将数据写入发送缓冲器,启动发送
while(TI==0) //若没有发送完毕,等待
;
TI=0; //发送完毕,TI被置“1”,需将其清0
}
/*******************************************
函数功能:主函数
******************************************/
voidmain(void)
{
unsignedchari;
SCON=0x00; //SCON=00000000B,使串行口工做于方式0
while(1)
{
for(i=0;i<8;i++)
{
Send(Tab[i]); //发送数据
delay(); //延时
}
}
}
#include<reg51.h>
//实例56-1:数据发送程序
//包含单片机寄存器的头文件
unsignedcharcodeTab[]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};
//流水灯控制码,该数组被定义为全局变量
/*****************************************************
445/192
函数功能:向PC发送一个字节数据
***************************************************/
voidSend(unsignedchardat)
{
SBUF=dat;
while(TI==0)
;
TI=0;
}
/**************************************************************
函数功能:延时约150ms
**************************************************************/
voiddelay(void)
{
unsignedcharm,n;
for(m=0;m<200;m++)
for(n=0;n<250;n++)
;
}
/*****************************************************
函数功能:主函数
***************************************************/
voidmain(void)
{
unsignedchari;
TMOD=0x20; //TMOD=00100000B,定时器T1工做于方式2
SCON=0x40; //SCON=01000000B,串口工做方式1
PCON=0x00; //PCON=00000000B,波特率9600
TH1=0xfd; //根据规定给定时器T1赋初值
TL1=0xfd; //根据规定给定时器T1赋初值
TR1=1; //启动定时器T1
while(1)
{
for(i=0;i<8;i++) //模拟检测数据
{
Send(Tab[i]); //发送数据i
delay(); //50ms发送一次检测数据
}
}
}
446
/
192
//
56-2
#include<reg51.h>
//实例56-2:数据接收程序
//包含单片机寄存器的头文件
/*****************************************************
函数功能:接收一个字节数据
***************************************************/
unsignedcharReceive(void)
{
unsignedchardat;
while(RI==0) //只要接收中断标志位RI没有被置“1”
; //等待,直至接收完毕(RI=1)
RI=0; //为了接收下一帧数据,需将RI清0
dat=SBUF; //将接收缓冲器中的数据存于dat
returndat;
}
/*****************************************************
函数功能:主函数
***************************************************/
voidmain(void)
{
TMOD=0x20; //定时器T1工做于方式2
SCON=0x50; //SCON=01010000B,串口工做方式1,容许接收(REN=1)
PCON=0x00; //PCON=00000000B,波特率9600
TH1=0xfd; //根据规定给定时器T1赋初值
TL1=0xfd; //根据规定给定时器T1赋初值
TR1=1; //启动定时器T1
REN=1; //容许接收
while(1)
{
P1=Receive();//将接收到的数据送P1口显示
}
}
//
57-1
#include<reg51.h>
sbitp=PSW^0;
//实例57-1:数据发送程序
//包含单片机寄存器的头文件
unsignedcharcodeTab[]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};
//流水灯控制码,该数组被定义为全局变量
/*****************************************************
447/192
函数功能:向PC发送一个字节数据
***************************************************/
voidSend(unsignedchardat)
{
ACC=dat;
TB8=p;
SBUF=dat;
while(TI==0)
;
TI=0;
}
/**************************************************************
函数功能:延时约150ms
**************************************************************/
voiddelay(void)
{
unsignedcharm,n;
for(m=0;m<200;m++)
for(n=0;n<250;n++)
;
}
/*****************************************************
函数功能:主函数
***************************************************/
voidmain(void)
{
unsignedchari;
TMOD=0x20; //TMOD=00100000B,定时器T1工做于方式2
SCON=0xc0; //SCON=11000000B,串口工做方式3,
//SM2置0,不使用多机通讯,TB8置0
PCON=0x00; //PCON=00000000B,波特率9600
TH1=0xfd; //根据规定给定时器T1赋初值
TL1=0xfd; //根据规定给定时器T1赋初值
TR1=1; //启动定时器T1
while(1)
{
for(i=0;i<8;i++) //模拟检测数据
{
Send(Tab[i]); //发送数据i
delay(); //50ms发送一次检测数据
}
}
}
448
/
192
//
57-2
#include<reg51.h>
sbitp=PSW^0;
//实例57-2:数据接收程序
//包含单片机寄存器的头文件
/*****************************************************
函数功能:接收一个字节数据
***************************************************/
unsignedcharReceive(void)
{
unsignedchardat;
while(RI==0) //只要接收中断标志位RI没有被置"1"
; //等待,直至接收完毕(RI=1)
RI=0; //为了接收下一帧数据,需将RI清0
ACC=SBUF; //将接收缓冲器中的数据存于dat
if(RB8==p)
{
dat=ACC;
returndat;
}
}
/*****************************************************
函数功能:主函数
***************************************************/
voidmain(void)
{
TMOD=0x20; //定时器T1工做于方式2
SCON=0xd0; //SCON=11010000B,串口工做方式1,容许接收(REN=1)
PCON=0x00; //PCON=00000000B,波特率9600
TH1=0xfd; //根据规定给定时器T1赋初值
TL1=0xfd; //根据规定给定时器T1赋初值
TR1=1; //启动定时器T1
REN=1; //容许接收
while(1)
{
P1=Receive();//将接收到的数据送P1口显示
}
}
449
/
192
//
58
PC
#include<reg51.h>
//实例58:单片机向PC发送数据
//包含单片机寄存器的头文件
unsignedcharcodeTab[]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};
//流水灯控制码,该数组被定义为全局变量
/*****************************************************
函数功能:向PC发送一个字节数据
***************************************************/
voidSend(unsignedchardat)
{
SBUF=dat;
while(TI==0)
;
TI=0;
}
/**************************************************************
函数功能:延时约150ms
**************************************************************/
voiddelay(void)
{
unsignedcharm,n;
for(m=0;m<200;m++)
for(n=0;n<250;n++)
;
}
/*****************************************************
函数功能:主函数
***************************************************/
voidmain(void)
{
unsignedchari;
TMOD=0x20; //TMOD=00100000B,定时器T1工做于方式2
SCON=0x40; //SCON=01000000B,串口工做方式1
PCON=0x00; //PCON=00000000B,波特率9600
TH1=0xfd; //根据规定给定时器T1赋初值
TL1=0xfd; //根据规定给定时器T1赋初值
TR1=1; //启动定时器T1
while(1)
{
for(i=0;i<8;i++) //模拟检测数据
{
Send(Tab[i]); //发送数据i
delay(); //150ms发送一次数据
}
550/192
}
}
//
59
PC
//实例59:单片机接收PC发出的数据
#include<reg51.h> //包含单片机寄存器的头文件
/*****************************************************
函数功能:接收一个字节数据
***************************************************/
unsignedcharReceive(void)
{
unsignedchardat;
while(RI==0) //只要接收中断标志位RI没有被置“1”
; //等待,直至接收完毕(RI=1)
RI=0; //为了接收下一帧数据,需将RI清0
dat=SBUF; //将接收缓冲器中的数据存于dat
returndat;
}
/*****************************************************
函数功能:主函数
***************************************************/
voidmain(void)
{
TMOD=0x20; //定时器T1工做于方式2
SCON=0x50; //SCON=01010000B,串口工做方式1,容许接收(REN=1)
PCON=0x00; //PCON=00000000B,波特率9600
TH1=0xfd; //根据规定给定时器T1赋初值
TL1=0xfd; //根据规定给定时器T1赋初值
TR1=1; //启动定时器T1
REN=1; //容许接收
while(1)
{
P1=Receive();//将接收到的数据送P1口显示
}
}
551
/
192
/********************************************************
*********数码管显示*****数码管显示********************
数码管显示****************数码管显示
***************************************************/
#include<reg51.h>
voidmain(void)
{
//实例60:用LED数码显示数字5
// 包含51单片机寄存器定义的头文件
}
P2=0xfe;
P0=0x92;
//P2.0引脚输出低电平,数码显示器接通电源准备点亮
//让P0口输出数字"5"的段码92H
//
61
LED
0~9
//实例61:用LED数码显示器循环显示数字0~9
#include<reg51.h> // 包含51单片机寄存器定义的头文件
/**************************************************
函数功能:延时函数,延时一段时间
***************************************************/
voiddelay(void)
{
unsignedchari,j;
for(i=0;i<255;i++)
for(j=0;j<255;j++)
;
}
/**************************************************
函数功能:主函数
***************************************************/
voidmain(void)
{
unsignedchari;
552
/
192
unsignedcharcode
Tab[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
//数码管显示0~9的段码表,程序运行中当数组值不发生变化
时,
//前面加关键字code,能够大大节约单片机的存储空间
P2=0xfe; //P2.0引脚输出低电平,数码显示器DS0接通电源工做
while(1) //无限循环
{
for(i=0;i<10;i++)
{
P0=Tab[i]; //让P0口输出数字的段码92H
delay(); //调用延时函数
}
}
}
//实例62:用数码管慢速动态扫描显示数字"1234"
#include<reg51.h> // 包含51单片机寄存器定义的头文件
voiddelay(void) //延时函数,延时一段时间
{
unsignedchari,j;
for(i=0;i<250;i++)
for(j=0;j<250;j++)
;
}
voidmain(void)
{
while(1) //无限循环
{
P2=0xfe; //P2.0引脚输出低电平,DS0点亮
P0=0xf9; //数字1的段码
delay();
P2=0xfd; //P2.1引脚输出低电平,DS1点亮
P0=0xa4; //数字2的段码
delay();
P2=0xfb; //P2.2引脚输出低电平,DS2点亮
P0=0xb0; //数字3的段码
delay();
P2=0xf7; //P2.3引脚输出低电平,DS3点亮
P0=0x99; //数字4的段码
553/192
}
}
delay();
P2=0xff;
//
63
LED
1234
//实例63:用LED数码显示器伪静态显示数字1234
#include<reg51.h> // 包含51单片机寄存器定义的头文件
voiddelay(void) //延时函数,延时约0.6毫秒
{
unsignedchari;
for(i=0;i<200;i++)
;
}
voidmain(void)
{
while(1) //无限循环
{
P2=0xfe; //P2.0引脚输出低电平,DS0点亮
P0=0xf9; //数字1的段码
delay();
P2=0xfd; //P2.1引脚输出低电平,DS1点亮
P0=0xa4; //数字2的段码
delay();
P2=0xfb; //P2.2引脚输出低电平,DS2点亮
P0=0xb0; //数字3的段码
delay();
P2=0xf7; //P2.3引脚输出低电平,DS3点亮
P0=0x99; //数字4的段码
delay();
P2=0xff;
}
}
//实例64:用数码管显示动态检测结果
#include<reg51.h> // 包含51单片机寄存器定义的头文件
554/192
#include<stdlib.h>
unsignedchari;
unsignedintx;
//包含随机函数rand()的定义文件
//记录中断次数
//随机检测的数据
unsignedcharcodeTab[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
//数码管显示0~9的段码表
/********************************************************************
***
函数功能:快速动态扫描延时,延时约0.9毫秒
*********************************************************************
***/
voiddelay(void)
{
unsignedinti;
for(i=0;i<300;i++)
;
}
/********************************************************************
***
函数功能:4位数的数码显示器显示
入口参数:k
出口参数:无
*********************************************************************
***/
voiddisplay(unsignedintk)
{
P2=0xfe; //即P2=11111110B,P2.0引脚输出低电平,数码显示器DS0接
通电源
P0=Tab[k/1000]; //显示千位
delay();
P2=0xfd; //即P2=11111101B,P2.1引脚输出低电平,数码显示器DS1接通
电源
P0=Tab[(k%1000)/100]; //显示百位
delay();
P2=0xfb; //即P2=11111011B,P2.2引脚输出低电平,数码显示器DS2接通
电源
P0=Tab[(k%100)/10]; //显示十位
delay();
P2=0xf7; //即P2=11110111B,P2.3引脚输出低电平,数码显示器DS3接
通电源
P0=Tab[k%10];//显示个位
delay();
P2=0xff; //关闭全部显示器
555/192
}
voidmain(void)
{
//主函数
TMOD=0x01;
TH0=(65536-46083)/256;
1.085微秒=50000微秒=50毫秒
TL0=(65536-46083)%256;
EA=1;
ET0=1;
TR0=1;
while(1)
{
//使用定时器T0
//将定时器计时时间设定为46083×
//开启总中断
//定时器T0中断容许
//启动定时器T0开始运行
}
}
display(x);
//调用检测结果的显示程序
/********************************************************
函数功能:定时器T0的中断服务程序
*******************************************************/
voidTime0(void)interrupt1using1
{
TR0=0; //关闭定时器T0
i++; //每来一次中断,i自加1
if(i==20) //够20次中断,即1秒钟进行一次检测结果采样
{
x=rand()/10; //随机产生一个从0到32767的整数,再将其除以10,
得到一个随机4位数,模拟检测结果
i=0; //将i清0,从新统计中断次数
}
TH0=(65536-46083)/256; //从新给计数器T0赋初值
TL0=(65536-46083)%256;
TR0=1; //启动定时器T0
}
//
65
#include<reg51.h>
//
//实例65:数码秒表设计
包含51单片机寄存器定义的头文件
556/192
unsignedcharcodeTab[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
//数码管显示0~9的段码表
unsignedcharint_time; //记录中断次数
unsignedcharsecond; //储存秒
/********************************************************************
***
函数功能:快速动态扫描延时,延时约0.6毫秒
*********************************************************************
***/
voiddelay(void)
{
unsignedchari;
for(i=0;i<200;i++)
;
}
/********************************************************************
***
函数功能:显示秒
入口参数:k
出口参数:无
*********************************************************************
***/
voidDisplaySecond(unsignedchark)
{
P2=0xfb; //P2.6引脚输出低电平,DS6点亮
P0=Tab[k/10]; //显示十位
delay();
P2=0xf7; //P2.7引脚输出低电平,DS7点亮
P0=Tab[k%10]; //显示个位
delay();
P2=0xff; //关闭全部数码管
}
voidmain(void)
{
TMOD=0x01;
//主函数
//使用定时器T0
秒
TH0=(65536-46083)/256;
//将定时器计时时间设定为46083×1.085微
//=50000微秒=50毫秒
TL0=(65536-46083)%256;
557
/
192
EA=1;
ET0=1;
TR0=1;
int_time=0;
second=0;
while(1)
{
//开启总中断
//定时器T0中断容许
//启动定时器T0开始运行
//中断次数初始化
//秒初始化
}
}
DisplaySecond(second);
//调用秒的显示子程序
//********************************************************
//函数功能:定时器T0的中断服务程序
//*******************************************************
voidinterserve(void)interrupt1using1
{
TR0=0; //关闭定时器T0
int_time++; //每来一次中断,中断次数int_time自加1
if(int_time==20) //够20次中断,即1秒钟进行一次检测结果采样
{
int_time=0; //中断次数清0
second++; //秒加1
if(second==60)
second=0;//秒等于60就返回0
}
TH0=(65536-46083)/256; //从新给计数器T0赋初值
TL0=(65536-46083)%256;
TR0=1; //启动定时器T0
}
#include<reg51.h>
//实例66:数码时钟设计
// 包含51单片机寄存器定义的头文件
unsignedcharTab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
//control shape
unsignedcharport[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
unsignedcharint_time;//中断次数计数变量
unsignedcharsecond; //秒计数变量
unsignedcharminute; //分钟计数变量
unsignedcharhour; //小时计数变量
/////////////////////////////////////////////////////
558/192
voiddelay(void)
{
unsignedcharj;
for(j=0;j<200;j++)
;
}
//延时函数,延时约0.6ms
/******************************************************************
函数功能:显示秒的子程序
入口参数:s
********************************************************************/
voidDisplaySecond(unsignedchars)
{
P2=0xbf; //P2.6引脚输出低电平,DS6点亮
P0=Tab[s/10]; //显示十位
delay();
P2=0x7f; //P2.7引脚输出低电平,DS7点亮
P0=Tab[s%10]; //显示个位
delay();
P2=0xff; //关闭全部数码管
}
/******************************************************************
函数功能:显示分钟的子程序
入口参数:m
********************************************************************/
voidDisplayMinute(unsignedcharm)
{
P2=0xf7; //P2.3引脚输出低电平,DS3点亮
P0=Tab[m/10];//显示个位
delay();
P2=0xef; //P2.4引脚输出低电平,DS4点亮
P0=Tab[m%10];
delay();
P2=0xdf; //P2.5引脚输出低电平,DS5点亮
P0=0xbf; //分隔符“-”的段码
delay();
P2=0xff; //关闭全部数码管
559
/
192
}
/******************************************************************
函数功能:显示小时的子程序
入口参数:h
********************************************************************/
voidDisplayHour(unsignedcharh)
{
P2=0xfe; //P2.0引脚输出低电平,DS0点亮
P0=Tab[h/10]; //显示十位
delay();
P2=0xfd; //P2.1引脚输出低电平,DS1点亮
P0=Tab[h%10]; //显示个位
delay();
P2=0xfb; //P2.2引脚输出低电平,DS2点亮
P0=0xbf; //分隔符“-”的段码
delay();
P2=0xff; //关闭全部数码管
}
/******************************************************************
函数功能:主函数
********************************************************************/
voidmain(void)
{
TMOD=0x01; //使用定时器T0
EA=1; //开中断总容许
ET0=1; //容许T0中断
TH0=(65536-46083)/256; //定时器高八位赋初值
TL0=(65536-46083)%256; //定时器低八位赋初值
TR0=1;
int_time=0; //中断计数变量初始化
second=0; //秒计数变量初始化
minute=0; //分钟计数变量初始化
hour=0; //小时计数变量初始化
while(1)
{
DisplaySecond(second); //调用秒显示子程序
delay();
DisplayMinute(minute); //调用分钟显示子程序
660/192
}
}
delay();
DisplayHour(hour);
delay();
/******************************************************************
函数功能:定时器T0的中断服务子程序
********************************************************************/
voidinterserve(void)interrupt1using1 //usingTime0
{
int_time++;
if(int_time==20)
{
int_time=0; //中断计数变量清0
second++; //秒计数变量加1
}
if(second==60)
{
second=0; //若是秒计满60,将秒计数变量清0
minute++; //分钟计数变量加1
}
if(minute==60)
{
minute=0; //若是分钟计满60,将分钟计数变量
清0
hour++; //小时计数变量加1
}
if(hour==24)
{
hour=0; //若是小时计满24,将小时计数变量
清0
}
TH0=(65536-46083)/256; //定时器从新赋初值
TL0=(65536-46083)%256;
}
661
/
192
//
67
LED
T0
//实例67:用LED数码管显示计数器T0的计数值
#include<reg51.h> //包含51单片机寄存器定义的头文件
sbitS=P3^2; //将S位定义为P3.2引脚
unsignedcharTab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
码表
unsignedcharx;
//段
/******************************************************************
函数功能:延时约0.6ms
********************************************************************/
voiddelay(void)
{
unsignedcharj;
for(j=0;j<200;j++)
;
}
/******************************************************************
函数功能:显示计数次数的子程序
入口参数:x
********************************************************************/
voidDisplay(unsignedcharx)
{
P2=0xf7; //P2.6引脚输出低电平,DS6点亮
P0=Tab[x/10]; //显示十位
delay();
P2=0xfb; //P2.7引脚输出低电平,DS7点亮
P0=Tab[x%10]; //显示个位
delay();
}
/*******************************************
函数功能:主函数
******************************************/
voidmain(void)
{
EA=1; //开放总中断
EX0=1; //容许使用外中断
IT0=1; //选择负跳变来触发外中断
x=0;
while(1)
Display(x);
662/192
}
/**************************************************************
函数功能:外中断T0的中断服务程序
**************************************************************/
voidint0(void)interrupt0using0//外中断0的中断编号为0
{
x++;
if(x==100)
x=0;
}
//
68
59
#include<reg51.h>
//实例68:静态显示数字“59”
//包含51单片机寄存器定义的头文件
/*******************************************
函数功能:主函数
******************************************/
voidmain(void)
{
P0=0x92; //将数字5的段码送P0口
P1=0x90; //将数字9的段码送P1口
while(1) //无限循环,防止程序跑飞
;
}
/********************************************************
**************键盘控制*********键盘控制***************
***************键盘控制*********键盘控制******************* **********
*****************************************************/
663
/
192
//
69
//实例69:无软件消抖的独立式键盘输入实验
#include<reg51.h> // 包含51单片机寄存器定义的头文件
sbitS1=P1^4; //将S1位定义为P1.4引脚
sbitLED0=P3^0; //将LED0位定义为P3.0引脚
voidmain(void) //主函数
{
LED0=0; //P3.0引脚输出低电平
while(1)
{
if(S1==0) //P1.4引脚输出低电平,按键S1被按下
LED0=!LED0; //P3.0引脚取反
}
}
//实例70:软件消抖的独立式键盘输入实验
#include<reg51.h> // 包含51单片机寄存器定义的头文件
sbitS1=P1^4; //将S1位定义为P1.4引脚
sbitLED0=P3^0; //将LED0位定义为P3.0引脚
/*************************************************
函数功能:延时约30ms
**************************************************/
voiddelay(void)
{
unsignedchari,j;
for(i=0;i<100;i++)
for(j=0;j<100;j++)
;
}
/*************************************************
函数功能:主函数
**************************************************/
voidmain(void) //主函数
{
LED0=0; //P3.0引脚输出低电平
while(1)
{
if(S1==0) //P1.4引脚输出低电平,按键S1被按下
{
664/192
}
}
}
delay();//延时一段时间再次检测
if(S1==0) //按键S1的确被按下
LED0=!LED0; //P3.0引脚取反
//实例71:CPU控制的独立式键盘扫描实验
#include<reg51.h> //包含51单片机寄存器定义的头文件
sbitS1=P1^4; //将S1位定义为P1.4引脚
sbitS2=P1^5; //将S2位定义为P1.5引脚
sbitS3=P1^6; //将S3位定义为P1.6引脚
sbitS4=P1^7; //将S4位定义为P1.7引脚
unsignedcharkeyval; //储存按键值
/*************************************************
函数功能:流水灯延时
**************************************************/
voidled_delay(void)
{
unsignedchari,j;
for(i=0;i<250;i++)
for(j=0;j<250;j++)
;
}
/*************************************************
函数功能:软件消抖延时
**************************************************/
voiddelay30ms(void)
{
unsignedchari,j;
for(i=0;i<100;i++)
for(j=0;j<100;j++)
;
}
/*************************************************
函数功能:正向流水点亮LED
**************************************************/
voidforward(void)
{
665/192
}
P3=0xfe;
led_delay();
P3=0xfd;
led_delay();
P3=0xfb;
led_delay();
P3=0xf7;
led_delay();
P3=0xef;
led_delay();
P3=0xdf;
led_delay();
P3=0xbf;
led_delay();
P3=0x7f;
led_delay();
P3=0xff;
P3=0xfe;
led_delay();
//第一个灯亮
//第二个灯亮
//第三个灯亮
//第四个灯亮
//第五个灯亮
//第六个灯亮
//第七个灯亮
//第八个灯亮
//第一个灯亮
/*************************************************
函数功能:反向流水点亮LED
**************************************************/
voidbackward(void)
{
P3=0x7f; //第八个灯亮
led_delay();
P3=0xbf; //第七个灯亮
led_delay();
P3=0xdf; //第六个灯亮
led_delay();
P3=0xef; //第五个灯亮
led_delay();
P3=0xf7; //第四个灯亮
led_delay();
P3=0xfb; //第三个灯亮
led_delay();
P3=0xfd; //第二个灯亮
led_delay();
P3=0xfe; //第一个灯亮
led_delay();
}
/*************************************************
666/192
函数功能:关闭全部LED
**************************************************/
voidstop(void)
{
P3=0xff;
}
/*************************************************
函数功能:闪烁点亮LED
**************************************************/
voidflash(void)
{
P3=0xff;
led_delay();
P3=0x00;
led_delay();
}
/*************************************************
函数功能:键盘扫描子程序
**************************************************/
voidkey_scan(void)
{
if((P1&0xf0)!=0xf0) //第一次检测到有键按下
{
delay30ms(); //延时20ms再去检测
if(S1==0) //按键S1被按下
keyval=1;
if(S2==0) //按键S2被按下
keyval=2;
if(S3==0) //按键S3被按下
keyval=3;
if(S4==0) //按键S4被按下
keyval=4;
}
}
/*************************************************
函数功能:主函数
**************************************************/
voidmain(void) //主函数
{
keyval=0; //按键值初始化为0,什么也不作
while(1)
{
key_scan();
667/192
}
}
switch(keyval)
{
case1:forward();
break;
case2:backward();
break;
case3:stop();
break;
case4:flash();
break;
}
//
72
//实例72:定时器中断控制的独立式键盘扫描实验
#include<reg51.h> //包含51单片机寄存器定义的头文件
sbitS1=P1^4; //将S1位定义为P1.4引脚
sbitS2=P1^5; //将S2位定义为P1.5引脚
sbitS3=P1^6; //将S3位定义为P1.6引脚
sbitS4=P1^7; //将S4位定义为P1.7引脚
unsignedcharkeyval; //储存按键值
/*************************************************
函数功能:流水灯延时
**************************************************/
voidled_delay(void)
{
unsignedchari,j;
for(i=0;i<250;i++)
for(j=0;j<250;j++)
;
}
/*************************************************
函数功能:软件消抖延时
**************************************************/
voiddelay20ms(void)
{
unsignedchari,j;
for(i=0;i<100;i++)
668/192
}
for(j=0;j<60;j++)
;
/*************************************************
函数功能:正向流水点亮LED
**************************************************/
voidforward(void)
{
P3=0xfe; //第一个灯亮
led_delay();
P3=0xfd; //第二个灯亮
led_delay();
P3=0xfb; //第三个灯亮
led_delay();
P3=0xf7; //第四个灯亮
led_delay();
P3=0xef; //第五个灯亮
led_delay();
P3=0xdf; //第六个灯亮
led_delay();
P3=0xbf; //第七个灯亮
led_delay();
P3=0x7f; //第八个灯亮
led_delay();
P3=0xff;
P3=0xfe; //第一个灯亮
led_delay();
}
/*************************************************
函数功能:反向流水点亮LED
**************************************************/
voidbackward(void)
{
P3=0x7f; //第八个灯亮
led_delay();
P3=0xbf; //第七个灯亮
led_delay();
P3=0xdf; //第六个灯亮
led_delay();
P3=0xef; //第五个灯亮
led_delay();
P3=0xf7; //第四个灯亮
led_delay();
P3=0xfb; //第三个灯亮
669/192
}
led_delay();
P3=0xfd;
led_delay();
P3=0xfe;
led_delay();
//第二个灯亮
//第一个灯亮
/*************************************************
函数功能:关闭全部LED
**************************************************/
voidstop(void)
{
P3=0xff; //关闭8个LED
}
/*************************************************
函数功能:闪烁点亮LED
**************************************************/
voidflash(void)
{
P3=0xff; //关闭8个LED
led_delay();
P3=0x00; //点亮8个LED
led_delay();
}
/*************************************************
函数功能:主函数
**************************************************/
voidmain(void) //主函数
{
TMOD=0x01; //使用定时器T0的模式1
EA=1; //开总中断
ET0=1; //定时器T0中断容许
TR0=1; //启动定时器T0
TH0=(65536-1000)/256; //定时器T0赋初值,每计数200次(217微秒)发
送一次中断请求
TL0=(65536-1000)%256; //定时器T0赋初值
keyval=0; //按键值初始化为0,什么也不作
while(1)
{
switch(keyval)
{
case1:forward();
770/192
}
}
}
break;
case2:backward();
break;
case3:stop();
break;
case4:flash();
break;
/*************************************************
函数功能:定时器T0的中断服务子程序
**************************************************/
voidTime0_serve(void)interrupt1using1
{
if((P1&0xf0)!=0xf0) //第一次检测到有键按下
{
delay20ms(); //延时20ms再去检测
if(S1==0) //按键S1被按下
keyval=1;
if(S2==0) //按键S2被按下
keyval=2;
if(S3==0) //按键S3被按下
keyval=3;
if(S4==0) //按键S4被按下
keyval=4;
}
TH0=(65536-1000)/256;
TL0=(65536-1000)%256;
}
//
73
4
//实例73:独立式键盘控制的4级变速流水灯
#include<reg51.h> // 包含51单片机寄存器定义的头文件
unsignedcharspeed; //储存流水灯的流动速度
sbitS1=P1^4; //位定义S1为P1.4
sbitS2=P1^5; //位定义S2为P1.5
sbitS3=P1^6; //位定义S3为P1.6
sbitS4=P1^7; //位定义S4为P1.7
771/192
/**************************************************************
函数功能:延时20ms的子程序
**************************************************************/
voiddelay20ms(void) //3*i*j+2*i=3*100*60+2*100=20000μs=20ms;
{
unsignedchari,j;
for(i=0;i<100;i++)
for(j=0;j<60;j++)
;
}
/**************************************************************
函数功能:延时可调子程序
入口参数:x
**************************************************************/
voiddelay(unsignedcharx)
{
unsignedchark;
for(k=0;k<x;k++)
delay20ms();
}
/**************************************************************
函数功能:主函数
**************************************************************/
voidmain(void)
{
TMOD=0x02; //使用定时器T0的模式2
EA=1; //开总中断
ET0=1; //定时器T0中断容许
TR0=1; //定时器T0开始运行
TH0=256-200; //定时器T0赋初值,每200微妙来1次中断请求
TL0=256-200;
speed=3; //默认流水灯流水点亮延时20ms×3=60ms
while(1)
{
P3=0xfe; //第一个灯亮
delay(speed); //调用延时可调子程序
P3=0xfd; //第二个灯亮
delay(speed);
P3=0xfb; //第三个灯亮
delay(speed);
P3=0xf7; //第四个灯亮
delay(speed);
P3=0xef; //第五个灯亮
delay(speed);
772/192
}
}
P3=0xdf;
delay(speed);
P3=0xbf;
delay(speed);
P3=0x7f;
delay(speed);
P3=0xff;
//第六个灯亮
//第七个灯亮
//第八个灯亮
/**************************************************************
函数功能:定时器T0的中断服务子程序,进行键盘扫描
**************************************************************/
voidintersev(void)interrupt1using1
{
TR0=0; //关闭定时器T0/
P1=0xff; //将P1口的均置高电平"1"
if((P1&0xf0)!=0xf0) //若是有键按下
{
delay20ms(); //延时20ms,软件消抖
if((P1&0xf0)!=0xf0) //确实有键按下
{
if(S1==0) //若是是按键S1按下
speed=5; //流水灯流水点亮延时20ms×5=100ms
if(S2==0) //若是是按键S2按下
speed=10; //流水灯流水点亮延时20ms×10=200ms
if(S3==0) //若是是按键S3按下
speed=25; //流水灯流水点亮延时20ms×25=500ms
if(S4==0) //若是是按键S4按下
speed=50; //流水灯流水点亮延时20ms×50=1000ms
}
}
TR0=1; //启动定时器T0
}
//实例74:独立式键盘的按键功能扩展:"以一当四"
#include<reg51.h> // 包含51单片机寄存器定义的头文件
unsignedcharID; //储存流水灯的流动速度
sbitS1=P1^4; //位定义S1为P1.4
/**************************************************************
773/192
函数功能:延时子程序
**************************************************************/
voiddelay(void) //由于仅对一个按键扫描,因此延时时间较长约200ms
{
unsignedchari,j;
for(i=0;i<200;i++)
for(j=0;j<100;j++)
;
}
/**************************************************************
函数功能:主函数
**************************************************************/
voidmain(void)
{
TMOD=0x02; //使用定时器T0的模式2
EA=1; //开总中断
ET0=1; //定时器T0中断容许
TR0=1; //定时器T0开始运行
TH0=256-200; //定时器T0赋初值,每200微妙来1次中断请求
TL0=256-200;
ID=0;
while(1)
{
switch(ID)
{
case0:P3=0xfe;
break;
case1:P3=0xfd;
break;
case2:P3=0xfb;
break;
case3:P3=0xf7;
break;
}
}
}
/**************************************************************
函数功能:定时器T0的中断服务子程序,进行键盘扫描
**************************************************************/
voidintersev(void)interrupt1using1
{
774/192
TR0=0;
P1=0xff;
if(S1==0)
{
//关闭定时器T0
//若是是按键S1按下
}
delay();
if(S1==0)
ID=ID+1;
//延时20ms,软件消抖
//若是是按键S1按下
}
if(ID==4)
ID=0;
TR0=1;
//启动定时器T0
//
75
//实例75:独立式键盘调时的数码时钟实验
#include<reg51.h> // 包含51单片机寄存器定义的头文件
unsignedcharcodeTab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
//数字0~9的段码
unsignedcharint_time;//中断次数计数变量
unsignedcharsecond; //秒计数变量
unsignedcharminute; //分钟计数变量
unsignedcharhour; //小时计数变量
sbitS1=P1^4; //将S1位定义为P1.4
sbitS2=P1^5; //将S2位定义为P1.5
sbitS3=P1^6; //将S3位定义为P1.6
sbitS4=P1^7; //将S4位定义为P1.7
/******************************************************************
函数功能:数码管扫描延时
********************************************************************/
voiddelay(void)
{
unsignedcharj;
for(j=0;j<200;j++)
;
}
/******************************************************************
函数功能:键盘扫描延时
775/192
********************************************************************/
voiddelay60ms(void)
{
unsignedchari,j;
for(i=0;i<200;i++)
for(j=0;j<100;j++)
;
}
/******************************************************************
函数功能:显示秒
入口参数:s
********************************************************************/
voidDisplaySecond(unsignedchars)
{
P2=0xbf; //P2.6引脚输出低电平,DS6点亮
P0=Tab[s/10]; //显示十位
delay();
P2=0x7f; //P2.7引脚输出低电平,DS7点亮
P0=Tab[s%10]; //显示个位
delay();
P2=0xff; //关闭全部数码管
}
/******************************************************************
函数功能:显示分钟
入口参数:m
********************************************************************/
voidDisplayMinute(unsignedcharm)
{
P2=0xf7; //P2.3引脚输出低电平,DS3点亮
P0=Tab[m/10];//显示个位
delay();
P2=0xef; //P2.4引脚输出低电平,DS4点亮
P0=Tab[m%10];
delay();
P2=0xdf; //P2.5引脚输出低电平,DS5点亮
P0=0xbf; //分隔符“-”的段码
delay();
P2=0xff; //关闭全部数码管
}
/******************************************************************
776/192
函数功能:显示小时的子程序
入口参数:h
********************************************************************/
voidDisplayHour(unsignedcharh)
{
P2=0xfe; //P2.0引脚输出低电平,DS0点亮
P0=Tab[h/10]; //显示十位
delay();
P2=0xfd; //P2.1引脚输出低电平,DS1点亮
P0=Tab[h%10]; //显示个位
delay();
P2=0xfb; //P2.2引脚输出低电平,DS2点亮
P0=0xbf; //分隔符“-”的段码
delay();
P2=0xff; //关闭全部数码管
}
/******************************************************************
函数功能:键盘扫描
********************************************************************/
voidkey_scan(void)
{
P1=0xf0; //将P1口高4位置高电平“1”
if((P1&0xf0)!=0xf0) //有键按下
{
delay60ms(); //延时60ms再检测
if((P1&0xf0)!=0xf0) //确实有键按下
{
if(S1==0) //若是是S1键按下
second++; //秒加1
if(S2==0) //若是是S2键按下
minute++; //分钟加1
if(S3==0) //若是是S3键按下
hour++; //小时加1
if(S4==0) //若是是S4键按下
{
second=0; //秒清0
minute=0; //分钟清0
hour=0; //小时清0
}
}
}
777/192
}
/******************************************************************
函数功能:主函数
********************************************************************/
voidmain(void)
{
TMOD=0x01; //使用定时器T0
EA=1; //开中断总容许
ET0=1; //容许T0中断
TH0=(65536-46083)/256; //定时器高八位赋初值
TL0=(65536-46083)%256; //定时器低八位赋初值
TR0=1; //启动定时器T0
int_time=0; //中断计数变量初始化
second=0; //秒计数变量初始化
minute=0; //分钟计数变量初始化
hour=0; //小时计数变量初始化
while(1)
{
DisplaySecond(second); //调用秒显示子程序
DisplayMinute(minute); //调用分钟显示子程序
DisplayHour(hour); //调用小时显示子程序
}
}
/******************************************************************
函数功能:定时器T0的中断服务子程序
********************************************************************/
voidinterserve(void)interrupt1using1 //usingTime0
{
TR0=0; //关闭定时器T0
int_time++; //中断次数加1
if(int_time==20) //若是中断次数满20
{
int_time=0; //中断计数变量清0
second++; //秒计数变量加1
}
if(second==60) //若是秒计满60
{
second=0; //若是秒计满60,将秒计数变量清0
778/192
}
minute++;
//分钟计数变量加1
if(minute==60)
{
minute=0;
hour++;
}
if(hour==24)
{
hour=0;
}
key_scan();
//若是分钟计满60
//若是分钟计满60,将分钟计数变量清0
//小时计数变量加1
//若是小时计满24
//若是小时计满24,将小时计数变量清0
//执行键盘扫描
}
TH0=(65536-46083)/256;
TL0=(65536-46083)%256;
TR0=1;
//定时器T0高四位赋值
//定时器T0低四位赋值
//启动定时器T0
//
76
//实例76:独立式键盘控制步进电机实验
#include<reg51.h> //包含51单片机寄存器定义的头文件
sbitS1=P1^4; //将S1位定义为P1.4引脚
sbitS2=P1^5; //将S2位定义为P1.5引脚
sbitS3=P1^6; //将S3位定义为P1.6引脚
unsignedcharkeyval; //储存按键值
unsignedcharID; //储存功能标号
/*************************************************
函数功能:软件消抖延时(约50ms)
**************************************************/
voiddelay(void)
{
unsignedchari,j;
for(i=0;i<150;i++)
for(j=0;j<100;j++)
;
}
/************************************************
函数功能:步进电机转动延时,延时越长,转速越慢
*************************************************/
voidmotor_delay(void)
{
779/192
}
unsignedinti;
for(i=0;i<2000;i++)
;
/************************************************
函数功能:步进电机正转
*************************************************/
voidforward()
{
P0=0xfc; //P0口低四位脉冲1100
motor_delay();
P0=0xf6; //P0口低四位脉冲0110
motor_delay();
P0=0xf3; //P0口低四位脉冲0011
motor_delay();
P0=0xf9; //P0口低四位脉冲1001
motor_delay();
}
/************************************************
函数功能:步进电机反转
*************************************************/
voidbackward()
{
P0=0xfc; //P0口低四位脉冲1100
motor_delay();
P0=0xf9; //P0口低四位脉冲1001
motor_delay();
P0=0xf3; //P0口低四位脉冲0011
motor_delay();
P0=0xf6; //P0口低四位脉冲0110
motor_delay();
}
/************************************************
函数功能:步进电机停转
*************************************************/
voidstop(void)
{
P0=0xff; //中止输出脉冲
}
/*************************************************
函数功能:主函数
**************************************************/
voidmain(void)
{
880/192
TMOD=0x01;
EA=1;
ET0=1;
TR0=1;
TH0=(65536-500)/256;
送一次中断请求
TL0=(65536-500)%256;
keyval=0;
ID=0;
while(1)
{
switch(keyval)
{
//使用定时器T0的模式1
//开总中断
//定时器T0中断容许
//启动定时器T0
//定时器T0赋初值,每计数200次(217微秒)发
//定时器T0赋初值
//按键值初始化为0,什么也不作
//根据按键值keyval选择待执行的功能
}
}
}
case1:forward();
break;
case2:backward();
break;
case3:stop();
break;
//按键S1按下,正转
//按键S2按下,反转
//按键S3按下,停转
/*************************************************
函数功能:定时器T0的中断服务子程序
**************************************************/
voidTime0_serve(void)interrupt1using1
{
TR0=0; //关闭定时器T0
if((P1&0xf0)!=0xf0) //第一次检测到有键按下
{
delay(); //延时一段时间再去检测
if((P1&0xf0)!=0xf0) //确实有键按下
{
if(S1==0) //按键S1被按下
keyval=1;
if(S2==0) //按键S2被按下
keyval=2;
if(S3==0) //按键S3被按下
keyval=3;
}
}
TH0=(65536-200)/256; //定时器T0的高8位赋初值
TL0=(65536-200)%256; //定时器T0的低8位赋初值
TR0=1; //启动定时器T0
881/192
}
//实例77:矩阵式键盘按键值的数码管显示实验
#include<reg51.h> //包含51单片机寄存器定义的头文件
sbitP14=P1^4; //将P14位定义为P1.4引脚
sbitP15=P1^5; //将P15位定义为P1.5引脚
sbitP16=P1^6; //将P16位定义为P1.6引脚
sbitP17=P1^7; //将P17位定义为P1.7引脚
unsignedcharcodeTab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
//数字0~9的段码
unsignedcharkeyval; //定义变量储存按键值
/**************************************************************
函数功能:数码管动态扫描延时
**************************************************************/
voidled_delay(void)
{
unsignedcharj;
for(j=0;j<200;j++)
;
}
/**************************************************************
函数功能:按键值的数码管显示子程序
**************************************************************/
voiddisplay(unsignedchark)
{
P2=0xbf; //点亮数码管DS6
P0=Tab[k/10]; //显示十位
led_delay(); //动态扫描延时
P2=0x7f; //点亮数码管DS7
P0=Tab[k%10]; //显示个位
led_delay(); //动态扫描延时
}
/**************************************************************
函数功能:软件延时子程序
**************************************************************/
voiddelay20ms(void)
{
unsignedchari,j;
for(i=0;i<100;i++)
for(j=0;j<60;j++)
882/192
}
;
/**************************************************************
函数功能:主函数
**************************************************************/
voidmain(void)
{
EA=1; //开总中断
ET0=1; //定时器T0中断容许
TMOD=0x01; //使用定时器T0的模式1
TH0=(65536-500)/256; //定时器T0的高8位赋初值
TL0=(65536-500)%256; //定时器T0的高8位赋初值
TR0=1; //启动定时器T0
keyval=0x00; //按键值初始化为0
while(1) //无限循环
{
display(keyval); //调用按键值的数码管显示子程序
}
}
/**************************************************************
函数功能:定时器0的中断服务子程序,进行键盘扫描,判断键位
**************************************************************/
voidtime0_interserve(void)interrupt1using1 //定时器T0的中断编号为1,
使用第一组寄存器
{
TR0=0; //关闭定时器T0
P1=0xf0; //全部行线置为低电平“0”,全部列线置为高
电平“1”
if((P1&0xf0)!=0xf0) //列线中有一位为低电平“0”,说明有键按下
delay20ms(); //延时一段时间、软件消抖
if((P1&0xf0)!=0xf0) //确实有键按下
{
P1=0xfe; //第一行置为低电平“0”(P1.0输出低电平
“0”)
if(P14==0) //若是检测到接P1.4引脚的列线为低电平“0”
keyval=1; //可判断是S1键被按下
if(P15==0) //若是检测到接P1.5引脚的列线为低电平
“0”
keyval=2; //可判断是S2键被按下
if(P16==0) //若是检测到接P1.6引脚的列线为低电平
“0”
keyval=3; //可判断是S3键被按下
883/192
“0”
“0”)
“0”
“0”
“0”
“0”)
“0”)
if(P17==0)
keyval=4;
P1=0xfd;
if(P14==0)
keyval=5;
if(P15==0)
keyval=6;
if(P16==0)
keyval=7;
if(P17==0)
keyval=8;
P1=0xfb;
if(P14==0)
keyval=9;
if(P15==0)
keyval=10;
if(P16==0)
keyval=11;
if(P17==0)
keyval=12;
P1=0xf7;
if(P14==0)
keyval=13;
if(P15==0)
keyval=14;
if(P16==0)
keyval=15;
if(P17==0)
keyval=16;
//若是检测到接P1.7引脚的列线为低电平
//可判断是S4键被按下
//第二行置为低电平“0”(P1.1输出低电平
//若是检测到接P1.4引脚的列线为低电平“0”
//可判断是S5键被按下
//若是检测到接P1.5引脚的列线为低电平
//可判断是S6键被按下
//若是检测到接P1.6引脚的列线为低电平
//可判断是S7键被按下
//若是检测到接P1.7引脚的列线为低电平
//可判断是S8键被按下
//第三行置为低电平“0”(P1.2输出低电平
//若是检测到接P1.4引脚的列线为低电平“0”
//可判断是S9键被按下
//若是检测到接P1.5引脚的列线为低电平“0”
//可判断是S10键被按下
//若是检测到接P1.6引脚的列线为低电平“0”
//可判断是S11键被按下
//若是检测到接P1.7引脚的列线为低电平“0”
//可判断是S12键被按下
//第四行置为低电平“0”(P1.3输出低电平
//若是检测到接P1.4引脚的列线为低电平“0”
//可判断是S13键被按下
//若是检测到接P1.5引脚的列线为低电平“0”
//可判断是S14键被按下
//若是检测到接P1.6引脚的列线为低电平“0”
//可判断是S15键被按下
//若是检测到接P1.7引脚的列线为低电平“0”
//可判断是S16键被按下
}
}
TR0=1;
TH0=(65536-500)/256;
TL0=(65536-500)%256;
//开启定时器T0
//定时器T0的高8位赋初值
//定时器T0的高8位赋初值
884/192
#include<reg51.h>
sbitsound=P3^7;
//实例78:矩阵式键盘按键音
//包含51单片机寄存器定义的头文件
//将sound位定义为P3.7
/**************************************************************
函数功能:蜂鸣器发声延时约120ms
**************************************************************/
voiddelay_sound(void)
{
unsignedchari;
for(i=0;i<250;i++)
;
}
/**************************************************************
函数功能:软件延时子程序约20ms
**************************************************************/
voiddelay20ms(void)
{
unsignedchari,j;
for(i=0;i<100;i++)
for(j=0;j<60;j++)
;
}
/**************************************************************
函数功能:主函数
**************************************************************/
voidmain(void)
{
EA=1; //开总中断
ET0=1; //定时器T0中断容许
TMOD=0x01; //使用定时器T0的模式1
TH0=(65536-500)/256; //定时器T0的高8位赋初值
TL0=(65536-500)%256; //定时器T0的高8位赋初值
TR0=1; //启动定时器T0
while(1) //无限循环,等待键盘按下
;
}
/**************************************************************
885/192
函数功能:定时器0的中断服务子程序,进行键盘扫描,判断键位
**************************************************************/
voidtime0_interserve(void)interrupt1using1 //定时器T0的中断编号为1,
使用第一组寄存器
{
unsignedchari;
TR0=0; //关闭定时器T0
P1=0xf0; //全部行线置为低电平“0”,全部列线置为高
电平“1”
if((P1&0xf0)!=0xf0) //列线中有一位为低电平“0”,说明有键按下
delay20ms(); //延时一段时间、软件消抖
if((P1&0xf0)!=0xf0) //确实有键按下
{
for(i=0;i<200;i++) //让P3.7引脚电平不断取反输出音频
{
sound=0;
delay_sound();
sound=1;
delay_sound();
}
}
TR0=1; //开启定时器T0
TH0=(65536-500)/256; //定时器T0的高8位赋初值
TL0=(65536-500)%256; //定时器T0的高8位赋初值
}
//
79
#include<reg51.h>
sbitP14=P1^4;
sbitP15=P1^5;
sbitP16=P1^6;
sbitP17=P1^7;
unsignedcharkeyval;
sbitsound=P3^7;
//实例79:简易电子琴
//包含51单片机寄存器定义的头文件
//将P14位定义为P1.4引脚
//将P15位定义为P1.5引脚
//将P16位定义为P1.6引脚
//将P17位定义为P1.7引脚
//定义变量储存按键值
//将sound位定义为P3.7
unsignedintC;
unsignedintf;
//全局变量,储存定时器的定时常数
//全局变量,储存音阶的频率
//如下是C调低音的音频宏定义
#definel_dao262 //将“l_dao”宏定义为低音“1”的频率262Hz
886/192
#definel_re286
#definel_mi311
#definel_fa349
#definel_sao392
#definel_la440
#definel_xi494
//将“l_re”宏定义为低音“2”的频率286Hz
//将“l_mi”宏定义为低音“3”的频率311Hz
//将“l_fa”宏定义为低音“4”的频率349Hz
//将“l_sao”宏定义为低音“5”的频率392Hz
//将“l_a”宏定义为低音“6”的频率440Hz
//将“l_xi”宏定义为低音“7”的频率494Hz
//如下是C调中音的音频宏定义
#definedao523 //将“dao”宏定义为中音“1”的频率523Hz
#definere587 //将“re”宏定义为中音“2”的频率587Hz
#definemi659 //将“mi”宏定义为中音“3”的频率659Hz
#definefa698 //将“fa”宏定义为中音“4”的频率698Hz
#definesao784 //将“sao”宏定义为中音“5”的频率784Hz
#definela880 //将“la”宏定义为中音“6”的频率880Hz
#definexi987 //将“xi”宏定义为中音“7”的频率53
//如下是C调高音的音频宏定义
#defineh_dao1046 //将“h_dao”宏定义为高音“1”的频率1046Hz
#defineh_re1174 //将“h_re”宏定义为高音“2”的频率1174Hz
#defineh_mi1318 //将“h_mi”宏定义为高音“3”的频率1318Hz
#defineh_fa1396 //将“h_fa”宏定义为高音“4”的频率1396Hz
#defineh_sao1567 //将“h_sao”宏定义为高音“5”的频率1567Hz
#defineh_la1760 //将“h_la”宏定义为高音“6”的频率1760Hz
#defineh_xi1975 //将“h_xi”宏定义为高音“7”的频率1975Hz
/**************************************************************
函数功能:软件延时子程序
**************************************************************/
voiddelay20ms(void)
{
unsignedchari,j;
for(i=0;i<100;i++)
for(j=0;j<60;j++)
;
}
/*******************************************
函数功能:节拍的延时的基本单位,延时200ms
******************************************/
voiddelay()
{
unsignedchari,j;
for(i=0;i<250;i++)
for(j=0;j<250;j++)
887/192
}
;
/*******************************************
函数功能:输出音频
入口参数:F
******************************************/
voidOutput_Sound(void)
{
C=(46083/f)*10; //计算定时常数
TH0=(8192-C)/32; //可证实这是13位计数器TH0高8位的赋初值方法
TL0=(8192-C)%32; //可证实这是13位计数器TL0低5位的赋初值方法
TR0=1; //开定时T0
delay(); //延时200ms,播放音频
TR0=0; //关闭定时器
sound=1; //关闭蜂鸣器
keyval=0xff; //播放按键音频后,将按键值更改,中止播放
}
/*******************************************
函数功能:主函数
******************************************/
voidmain(void)
{
EA=1; //开总中断
ET0=1; //定时器T0中断容许
ET1=1; //定时器T1中断容许
TR1=1; //定时器T1启动,开始键盘扫描
TMOD=0x10; //分别使用定时器T1的模式1,T0的模式0
TH1=(65536-500)/256; //定时器T1的高8位赋初值
TL1=(65536-500)%256; //定时器T1的高8位赋初值
while(1)
{
switch(keyval)
{
//无限循环
中音1的频率赋给f
低音7的频率赋给f
case1:f=dao;
Output_Sound();
break;
case2:f=l_xi;
Output_Sound();
break;
//若是第1个键按下,将
//转去计算定时常数
//若是第2个键按下,将
//转去计算定时常数
888
/
192
6的频率赋给f
低音5的频率赋给f
case3:f=l_la;
Output_Sound();
break;
case4:f=l_sao;
//若是第3个键按下,将低音
//转去计算定时常数
//若是第4个键按下,将
将中音5的频率赋给f
将中音4的频率赋给f
Output_Sound();
break;
case5:f=sao;
Output_Sound();
break;
case6:f=fa;
Output_Sound();
break;
//转去计算定时常数
//若是第5个键按下,
//转去计算定时常数
//若是第6个键按下,
//转去计算定时常数
音3的频率赋给f
中音2的频率赋给f
高音2的频率赋给f
case7:f=mi;
Output_Sound();
break;
case8:f=re;
Output_Sound();
break;
case9:f=h_re;
Output_Sound();
break;
case10:f=h_dao;
//若是第7个键按下,将中
//转去计算定时常数
//若是第8个键按下,将
//转去计算定时常数
//若是第9个键按下,将
//转去计算定时常数
//若是第10个键按
下,将高音1的频率赋给f
Output_Sound();
break;
//转去计算定时常数
音7的频率赋给f
中音6的频率赋给f
将高音6的频率赋给f
case11:f=xi;
Output_Sound();
break;
case12:f=la;
Output_Sound();
break;
case13:f=h_la;
Output_Sound();
break;
889/192
//若是第11个键按下,将中
//转去计算定时常数
//若是第12个键按下,将
//转去计算定时常数
//若是第13个键按下,
//转去计算定时常数
将高音5的频率赋给f
音4的频率赋给f
将高音3的频率赋给f
}
}
}
case14:f=h_sao;
Output_Sound();
break;
case15:f=h_fa;
Output_Sound();
break;
case16:f=h_mi;
Output_Sound();
break;
//若是第14个键按下,
//转去计算定时常数
//若是第15个键按下,将高
//转去计算定时常数
//若是第16个键按下,
//转去计算定时常数
/**************************************************************
函数功能:定时器T0的中断服务子程序,使P3.7引脚输出音频方波
**************************************************************/
voidTime0_serve(void)interrupt1using1
{
TH0=(8192-C)/32; //可证实这是13位计数器TH0高8位的赋初值
方法
TL0=(8192-C)%32; //可证实这是13位计数器TL0低5位的赋初值方
法
sound=!sound; //将P3.7引脚取反,输出音频方波
}
/**************************************************************
函数功能:定时器T1的中断服务子程序,进行键盘扫描,判断键位
**************************************************************/
voidtime1_serve(void)interrupt3using2 //定时器T1的中断编号为3,使用
第2组寄存器
{
TR1=0; //关闭定时器T0
P1=0xf0; //全部行线置为低电平“0”,全部列线置为高
电平“1”
if((P1&0xf0)!=0xf0) //列线中有一位为低电平“0”,说明有键按下
{
delay20ms(); //延时一段时间、软件消抖
if((P1&0xf0)!=0xf0) //确实有键按下
{
990
/
192
输出低电平“0”)
为低电平“0”
线为低电平“0”
线为低电平“0”
线为低电平“0”
输出低电平“0”)
低电平“0”
线为低电平“0”
线为低电平“0”
线为低电平“0”
输出低电平“0”)
电平“0”
为低电平“0”
为低电平“0”
为低电平“0”
P1=0xfe;
if(P14==0)
keyval=1;
if(P15==0)
keyval=2;
if(P16==0)
keyval=3;
if(P17==0)
keyval=4;
P1=0xfd;
if(P14==0)
keyval=5;
if(P15==0)
keyval=6;
if(P16==0)
keyval=7;
if(P17==0)
keyval=8;
P1=0xfb;
if(P14==0)
keyval=9;
if(P15==0)
keyval=10;
if(P16==0)
keyval=11;
if(P17==0)
keyval=12;
991
/
//第一行置为低电平“0”(P1.0
//若是检测到接P1.4引脚的列线
//可判断是S1键被按下
//若是检测到接P1.5引脚的列
//可判断是S2键被按下
//若是检测到接P1.6引脚的列
//可判断是S3键被按下
//若是检测到接P1.7引脚的列
//可判断是S4键被按下
//第二行置为低电平“0”(P1.1
//若是检测到接P1.4引脚的列线为
//可判断是S5键被按下
//若是检测到接P1.5引脚的列
//可判断是S6键被按下
//若是检测到接P1.6引脚的列
//可判断是S7键被按下
//若是检测到接P1.7引脚的列
//可判断是S8键被按下
//第三行置为低电平“0”(P1.2
//若是检测到接P1.4引脚的列线为低
//可判断是S9键被按下
//若是检测到接P1.5引脚的列线
//可判断是S10键被按下
//若是检测到接P1.6引脚的列线
//可判断是S11键被按下
//若是检测到接P1.7引脚的列线
//可判断是S12键被按下
192
输出低电平“0”)
电平“0”
为低电平“0”
为低电平“0”
为低电平“0”
}
}
P1=0xf7;
if(P14==0)
keyval=13;
if(P15==0)
keyval=14;
if(P16==0)
keyval=15;
if(P17==0)
keyval=16;
//第四行置为低电平“0”(P1.3
//若是检测到接P1.4引脚的列线为低
//可判断是S13键被按下
//若是检测到接P1.5引脚的列线
//可判断是S14键被按下
//若是检测到接P1.6引脚的列线
//可判断是S15键被按下
//若是检测到接P1.7引脚的列线
//可判断是S16键被按下
}
TR1=1;
TH1=(65536-500)/256;
TL1=(65536-500)%256;
//开启定时器T1
//定时器T1的高8位赋初值
//定时器T1的高8位赋初值
//
80
//实例80:矩阵式键盘实现的电子密码锁
#include<reg51.h> //包含51单片机寄存器定义的头文件
sbitP14=P1^4; //将P14位定义为P1.4引脚
sbitP15=P1^5; //将P15位定义为P1.5引脚
sbitP16=P1^6; //将P16位定义为P1.6引脚
sbitP17=P1^7; //将P17位定义为P1.7引脚
sbitsound=P3^7; //将sound位定义为P3.7
unsignedcharkeyval; //储存按键值
/**************************************************************
函数功能:延时输出音频
**************************************************************/
voiddelay(void)
{
unsignedchari;
for(i=0;i<200;i++)
;
}
992/192
/**************************************************************
函数功能:软件延时子程序
**************************************************************/
voiddelay20ms(void)
{
unsignedchari,j;
for(i=0;i<100;i++)
for(j=0;j<60;j++)
;
}
/**************************************************************
函数功能:主函数
**************************************************************/
voidmain(void)
{
unsignedcharD[]={0,8,0,8,7,4,11}; //设定密码
EA=1; //开总中断
ET0=1; //定时器T0中断容许
TMOD=0x01; //使用定时器T0的模式1
TH0=(65536-500)/256; //定时器T0的高8位赋初值
TL0=(65536-500)%256; //定时器T0的高8位赋初值
TR0=1; //启动定时器T0
keyval=0xff; //按键值初始化
while(keyval!=D[0]) //第一位密码输入不正确,等待
;
while(keyval!=D[1]) //第二位密码输入不正确,等待
;
while(keyval!=D[2]) //第三位密码输入不正确,等待
;
while(keyval!=D[3]) //第四位密码输入不正确,等待
;
while(keyval!=D[4]) //第五位密码输入不正确,等待
;
while(keyval!=D[5]) //第六位密码输入不正确,等待
;
while(keyval!=D[6]) //没有输入“OK”,等待
;
P3=0xfe; //P3.0引脚输出低电平,点亮LED
}
/**************************************************************
函数功能:定时器0的中断服务子程序,进行键盘扫描,判断键位
993/192
**************************************************************/
voidtime0_interserve(void)interrupt1using1 //定时器T0的中断编号为1,
使用第一组寄存器
{
unsignedchari;
TR0=0; //关闭定时器T0
P1=0xf0; //全部行线置为低电平“0”,全部列线置为高
电平“1”
if((P1&0xf0)!=0xf0) //列线中有一位为低电平“0”,说明有键按下
delay20ms(); //延时一段时间、软件消抖
if((P1&0xf0)!=0xf0) //确实有键按下
{
P1=0xfe; //第一行置为低电平“0”(P1.0输出低电平
“0”)
if(P14==0) //若是检测到接P1.4引脚的列线为低电平“0”
keyval=1; //可判断是S1键被按下
if(P15==0) //若是检测到接P1.5引脚的列线为低电平
“0”
keyval=2; //可判断是S2键被按下
if(P16==0) //若是检测到接P1.6引脚的列线为低电平
“0”
keyval=3; //可判断是S3键被按下
if(P17==0) //若是检测到接P1.7引脚的列线为低电平
“0”
keyval=4; //可判断是S4键被按下
P1=0xfd; //第二行置为低电平“0”(P1.1输出低电平
“0”)
if(P14==0) //若是检测到接P1.4引脚的列线为低电平“0”
keyval=5; //可判断是S5键被按下
if(P15==0) //若是检测到接P1.5引脚的列线为低电平
“0”
keyval=6; //可判断是S6键被按下
if(P16==0) //若是检测到接P1.6引脚的列线为低电平
“0”
keyval=7; //可判断是S7键被按下
if(P17==0) //若是检测到接P1.7引脚的列线为低电平
“0”
keyval=8; //可判断是S8键被按下
P1=0xfb; //第三行置为低电平“0”(P1.2输出低电平
“0”)
if(P14==0) //若是检测到接P1.4引脚的列线为低电平“0”
keyval=9; //可判断是S9键被按下
994/192
if(P15==0)
keyval=0;
if(P16==0)
keyval=11;
if(P17==0)
//若是检测到接P1.5引脚的列线为低电平“0”
//可判断是S10键被按下
//若是检测到接P1.6引脚的列线为低电平“0”
//可判断是S11键被按下
//若是检测到接P1.7引脚的列线为低电平“0”
keyval=12; //可判断是S12键被按下
输出低电平“0”)
电平“0”
为低电平“0”
为低电平“0”
为低电平“0”
P1=0xf7;
if(P14==0)
keyval=13;
if(P15==0)
keyval=14;
if(P16==0)
keyval=15;
if(P17==0)
keyval=16;
//第四行置为低电平“0”(P1.3
//若是检测到接P1.4引脚的列线为低
//可判断是S13键被按下
//若是检测到接P1.5引脚的列线
//可判断是S14键被按下
//若是检测到接P1.6引脚的列线
//可判断是S15键被按下
//若是检测到接P1.7引脚的列线
//可判断是S16键被按下
}
for(i=0;i<200;i++)
{
sound=0;
delay();
sound=1;
delay();
}
//让P3.7引脚电平不断取反输出音频
}
TR0=1;
TH0=(65536-500)/256;
TL0=(65536-500)%256;
//开启定时器T0
//定时器T0的高8位赋初值
//定时器T0的高8位赋初值
/********************************************************
******************液晶显示LCD*********液晶显示LCDLCD********* LCD
*****液晶显示LCD********************液晶显示LCD********************
LCD*********液晶显示LCD*****液晶显示LCD**********
995/192
*********************************************************
**/
#include<reg51.h>
#include<intrins.h>
//实例81:用LCD显示字符''A'
//包含单片机寄存器的头文件
//包含_nop_()函数定义的头文件
sbitRS=P2^0;
sbitRW=P2^1;
sbitE=P2^2;
sbitBF=P0^7;
//寄存器选择位,将RS位定义为P2.0引脚
//读写选择位,将RW位定义为P2.1引脚
//使能信号位,将E位定义为P2.2引脚
//忙碌标志位,,将BF位定义为P0.7引脚
/*****************************************************
函数功能:延时1ms
(3j+2)*i=(3×33+2)×10=1010(微秒),能够认为是1毫秒
***************************************************/
voiddelay1ms()
{
unsignedchari,j;
for(i=0;i<10;i++)
for(j=0;j<33;j++)
;
}
/*****************************************************
函数功能:延时若干毫秒
入口参数:n
***************************************************/
voiddelay(unsignedcharn)
{
unsignedchari;
for(i=0;i<n;i++)
delay1ms();
}
/*****************************************************
函数功能:判断液晶模块的忙碌状态
返回值:result。result=1,忙碌;result=0,不忙
***************************************************/
unsignedcharBusyTest(void)
{
bitresult;
RS=0; //根据规定,RS为低电平,RW为高电平时,能够读状态
996/192
RW=1;
E=1;
_nop_();
_nop_();
_nop_();
_nop_();
result=BF;
E=0;
//E=1,才容许读写
//空操做
//空操做四个机器周期,给硬件反应时间
//将忙碌标志电平赋给result
}
returnresult;
/*****************************************************
函数功能:将模式设置指令或显示地址写入液晶模块
入口参数:dictate
***************************************************/
voidWriteInstruction(unsignedchardictate)
{
while(BusyTest()==1);//若是忙就等待
RS=0; //根据规定,RS和R/W同时为低电平时,能够写
入指令
RW=0;
E=0; //E置低电平(根据表8-6,写指令时,E为高脉冲,
// 就是让E从0到1发生正跳变,因此应先置
"0"
_nop_();
_nop_(); //空操做两个机器周期,给硬件反应时间
P0=dictate; //将数据送入P0口,即写入指令或地址
_nop_();
_nop_();
_nop_();
_nop_(); //空操做四个机器周期,给硬件反应时间
E=1; //E置高电平
_nop_();
_nop_();
_nop_();
_nop_(); //空操做四个机器周期,给硬件反应时间
E=0; //当E由高电平跳变成低电平时,液晶模块开始
执行命令
}
/*****************************************************
函数功能:指定字符显示的实际地址
入口参数:x
***************************************************/
voidWriteAddress(unsignedcharx)
{
997/192
}
WriteInstruction(x|0x80);//显示位置的肯定方法规定为"80H+地址码x"
/*****************************************************
函数功能:将数据(字符的标准ASCII码)写入液晶模块
入口参数:y(为字符常量)
***************************************************/
voidWriteData(unsignedchary)
{
while(BusyTest()==1);
RS=1; //RS为高电平,RW为低电平时,能够写入数据
RW=0;
E=0; //E置低电平(根据表8-6,写指令时,E为高脉冲,
// 就是让E从0到1发生正跳变,因此应先置"0"
P0=y; //将数据送入P0口,即将数据写入液晶模块
_nop_();
_nop_();
_nop_();
_nop_(); //空操做四个机器周期,给硬件反应时间
E=1; //E置高电平
_nop_();
_nop_();
_nop_();
_nop_(); //空操做四个机器周期,给硬件反应时间
E=0; //当E由高电平跳变成低电平时,液晶模块开始执行命令
}
/*****************************************************
函数功能:对LCD的显示模式进行初始化设置
***************************************************/
voidLcdInitiate(void)
{
delay(15); //延时15ms,首次写指令时应给LCD一段较长的反
应时间
WriteInstruction(0x38); //显示模式设置:16×2显示,5×7点阵,8位数据
接口
delay(5); //延时5ms
WriteInstruction(0x38);
delay(5);
WriteInstruction(0x38);
delay(5);
WriteInstruction(0x0f); //显示模式设置:显示开,有光标,光标闪烁
delay(5);
WriteInstruction(0x06); //显示模式设置:光标右移,字符不移
delay(5);
WriteInstruction(0x01); //清屏幕指令,将之前的显示内容清除
998/192
}
delay(5);
voidmain(void)
{
LcdInitiate();
WriteAddress(0x07);
WriteData('A');
}
//主函数
//调用LCD初始化函数
//将显示地址指定为第1行第8列
//将字符常量'A'写入液晶模块
//字符的字形点阵读出和显示由液晶模块自动完成
//实例82:用LCD循环右移显示"WelcometoChiina"
#include<reg51.h> //包含单片机寄存器的头文件
#include<intrins.h> //包含_nop_()函数定义的头文件
sbitRS=P2^0; //寄存器选择位,将RS位定义为P2.0引脚
sbitRW=P2^1; //读写选择位,将RW位定义为P2.1引脚
sbitE=P2^2; //使能信号位,将E位定义为P2.2引脚
sbitBF=P0^7; //忙碌标志位,,将BF位定义为P0.7引脚
unsignedcharcodestring[]={"WelcometoChina"};
/*****************************************************
函数功能:延时1ms
(3j+2)*i=(3×33+2)×10=1010(微秒),能够认为是1毫秒
***************************************************/
voiddelay1ms()
{
unsignedchari,j;
for(i=0;i<10;i++)
for(j=0;j<33;j++)
;
}
/*****************************************************
函数功能:延时若干毫秒
入口参数:n
***************************************************/
voiddelay(unsignedcharn)
{
unsignedchari;
for(i=0;i<n;i++)
delay1ms();
}
999/192
/*****************************************************
函数功能:判断液晶模块的忙碌状态
返回值:result。result=1,忙碌;result=0,不忙
***************************************************/
unsignedcharBusyTest(void)
{
bitresult;
RS=0; //根据规定,RS为低电平,RW为高电平时,能够读状态
RW=1;
E=1; //E=1,才容许读写
_nop_(); //空操做
_nop_();
_nop_();
_nop_(); //空操做四个机器周期,给硬件反应时间
result=BF; //将忙碌标志电平赋给result
E=0;
returnresult;
}
/*****************************************************
函数功能:将模式设置指令或显示地址写入液晶模块
入口参数:dictate
***************************************************/
voidWriteInstruction(unsignedchardictate)
{
while(BusyTest()==1);//若是忙就等待
RS=0; //根据规定,RS和R/W同时为低电平时,能够写
入指令
RW=0;
E=0; //E置低电平(根据表8-6,写指令时,E为高脉冲,
// 就是让E从0到1发生正跳变,因此应先置
"0"
_nop_();
_nop_(); //空操做两个机器周期,给硬件反应时间
P0=dictate; //将数据送入P0口,即写入指令或地址
_nop_();
_nop_();
_nop_();
_nop_(); //空操做四个机器周期,给硬件反应时间
E=1; //E置高电平
_nop_();
_nop_();
_nop_();
_nop_(); //空操做四个机器周期,给硬件反应时间
100
/
192
E=0;
执行命令
}
//当E由高电平跳变成低电平时,液晶模块开始
/*****************************************************
函数功能:指定字符显示的实际地址
入口参数:x
***************************************************/
voidWriteAddress(unsignedcharx)
{
WriteInstruction(x|0x80);//显示位置的肯定方法规定为"80H+地址码x"
}
/*****************************************************
函数功能:将数据(字符的标准ASCII码)写入液晶模块
入口参数:y(为字符常量)
***************************************************/
voidWriteData(unsignedchary)
{
while(BusyTest()==1);
RS=1; //RS为高电平,RW为低电平时,能够写入数据
RW=0;
E=0; //E置低电平(根据表8-6,写指令时,E为高脉冲,
// 就是让E从0到1发生正跳变,因此应先置"0"
P0=y; //将数据送入P0口,即将数据写入液晶模块
_nop_();
_nop_();
_nop_();
_nop_(); //空操做四个机器周期,给硬件反应时间
E=1; //E置高电平
_nop_();
_nop_();
_nop_();
_nop_(); //空操做四个机器周期,给硬件反应时间
E=0; //当E由高电平跳变成低电平时,液晶模块开始执行命令
}
/*****************************************************
函数功能:对LCD的显示模式进行初始化设置
***************************************************/
voidLcdInitiate(void)
{
delay(15); //延时15ms,首次写指令时应给LCD一段较长的反
应时间
WriteInstruction(0x38); //显示模式设置:16×2显示,5×7点阵,8位数据
接口
delay(5); //延时5ms
101/192
}
WriteInstruction(0x38);
delay(5);
WriteInstruction(0x38);
delay(5);
WriteInstruction(0x0f);
delay(5);
WriteInstruction(0x06);
delay(5);
WriteInstruction(0x01);
delay(5);
//显示模式设置:显示开,有光标,光标闪烁
//显示模式设置:光标右移,字符不移
//清屏幕指令,将之前的显示内容清除
voidmain(void)
{
unsignedchari;
LcdInitiate();
delay(10);
while(1)
{
//主函数
//调用LCD初始化函数
WriteInstruction(0x01);//清显示:清屏幕指令
WriteAddress(0x00); //设置显示位置为第一行的第5个字
i=0;
while(string[i]!='\0')
{ // 显示字符
WriteData(string[i]);
i++;
delay(150);
}
for(i=0;i<4;i++)
delay(250);
}
}
//
83
LCD
//实例83:用LCD显示适时检测结果
#include<reg51.h> //包含单片机寄存器的头文件
#include<stdlib.h> //包含随机函数rand()的定义文件
#include<intrins.h> //包含_nop_()函数定义的头文件
sbitRS=P2^0; //寄存器选择位,将RS位定义为P2.0引脚
102/192
sbitRW=P2^1;
sbitE=P2^2;
sbitBF=P0^7;
//读写选择位,将RW位定义为P2.1引脚
//使能信号位,将E位定义为P2.2引脚
//忙碌标志位,,将BF位定义为P0.7引脚
unsignedcharcodedigit[]={"0123456789"};//定义字符数组显示数字
unsignedcharcodestring[]={"TestResult"};//定义字符数组显示提示信息
/*****************************************************
函数功能:延时1ms
(3j+2)*i=(3×33+2)×10=1010(微秒),能够认为是1毫秒
***************************************************/
voiddelay1ms()
{
unsignedchari,j;
for(i=0;i<10;i++)
for(j=0;j<33;j++)
;
}
/*****************************************************
函数功能:延时若干毫秒
入口参数:n
***************************************************/
voiddelay(unsignedcharn)
{
unsignedchari;
for(i=0;i<n;i++)
delay1ms();
}
/*****************************************************
函数功能:判断液晶模块的忙碌状态
返回值:result。result=1,忙碌;result=0,不忙
***************************************************/
unsignedcharBusyTest(void)
{
bitresult;
RS=0; //根据规定,RS为低电平,RW为高电平时,能够读状态
RW=1;
E=1; //E=1,才容许读写
_nop_(); //空操做
_nop_();
_nop_();
_nop_(); //空操做四个机器周期,给硬件反应时间
result=BF; //将忙碌标志电平赋给result
E=0; //将E恢复低电平
returnresult;
}
103/192
/*****************************************************
函数功能:将模式设置指令或显示地址写入液晶模块
入口参数:dictate
***************************************************/
voidWriteInstruction(unsignedchardictate)
{
while(BusyTest()==1);//若是忙就等待
RS=0; //根据规定,RS和R/W同时为低电平时,能够写
入指令
RW=0;
E=0; //E置低电平(根据表8-6,写指令时,E为高脉冲,
// 就是让E从0到1发生正跳变,因此应先置
"0"
_nop_();
_nop_(); //空操做两个机器周期,给硬件反应时间
P0=dictate; //将数据送入P0口,即写入指令或地址
_nop_();
_nop_();
_nop_();
_nop_(); //空操做四个机器周期,给硬件反应时间
E=1; //E置高电平
_nop_();
_nop_();
_nop_();
_nop_(); //空操做四个机器周期,给硬件反应时间
E=0; //当E由高电平跳变成低电平时,液晶模块开始
执行命令
}
/*****************************************************
函数功能:指定字符显示的实际地址
入口参数:x
***************************************************/
voidWriteAddress(unsignedcharx)
{
WriteInstruction(x|0x80);//显示位置的肯定方法规定为"80H+地址码x"
}
/*****************************************************
函数功能:将数据(字符的标准ASCII码)写入液晶模块
入口参数:y(为字符常量)
***************************************************/
voidWriteData(unsignedchary)
{
while(BusyTest()==1);
RS=1; //RS为高电平,RW为低电平时,能够写入数据
104/192
}
RW=0;
E=0;
P0=y;
_nop_();
_nop_();
_nop_();
_nop_();
E=1;
_nop_();
_nop_();
_nop_();
_nop_();
E=0;
//E置低电平(根据表8-6,写指令时,E为高脉冲,
// 就是让E从0到1发生正跳变,因此应先置"0"
//将数据送入P0口,即将数据写入液晶模块
//空操做四个机器周期,给硬件反应时间
//E置高电平
//空操做四个机器周期,给硬件反应时间
//当E由高电平跳变成低电平时,液晶模块开始执行命令
/*****************************************************
函数功能:对LCD的显示模式进行初始化设置
***************************************************/
voidLcdInitiate(void)
{
delay(15); //延时15ms,首次写指令时应给LCD一段较长的反
应时间
WriteInstruction(0x38); //显示模式设置:16×2显示,5×7点阵,8位数据
接口
delay(5); //延时5ms ,给硬件一点反应时间
WriteInstruction(0x38);
delay(5);
WriteInstruction(0x38);//连续三次,确保初始化成功
delay(5);
WriteInstruction(0x0c); //显示模式设置:显示开,无光标,光标不闪烁
delay(5);
WriteInstruction(0x06); //显示模式设置:光标右移,字符不移
delay(5);
WriteInstruction(0x01); //清屏幕指令,将之前的显示内容清除
delay(5);
}
/*****************************************************
函数功能:主函数
***************************************************/
voidmain(void)
{
unsignedchari; //定义变量i指向字符串数组元素
unsignedintx; //定义变量,储存检测结果
105
/
192
unsignedcharD1,D2,D3,D4,D5;
万位数字
//分别储存采集的个位、十位、百位、千位和
LcdInitiate();
delay(10);
WriteAddress(0x02);
i=0;
while(string[i]!='\0')
{
//调用LCD初始化函数
//延时10ms,给硬件一点反应时间
//从第1行第3列开始显示
//指向字符数组的第1个元素
}
while(1)
{
WriteData(string[i]);
i++; //指向下字符数组一个元素
//无限循环
}
}
x=rand();
D1=x%10;
D2=(x%100)/10;
D3=(x%1000)/100;
D4=(x%10000)/1000;
D5=x/10000;
WriteAddress(0x45);
WriteData(digit[D5]);
WriteData(digit[D4]);
WriteData(digit[D3]);
WriteData(digit[D2]);
WriteData('.');
WriteData(digit[D1]);
for(i=0;i<4;i++)
delay(250);
//模拟数据采集
//计算个位数字
//计算十位数字
//计算百位数字
//计算千位数字
//计算万位数字
//从第2行第6列开始显示
//将万位数字的字符常量写入LCD
//将千位数字的字符常量写入LCD
//将百位数字的字符常量写入LCD
//将十位数字的字符常量写入LCD
//将小数点的字符常量写入LCD
//将个位数字的字符常量写入LCD
//延时1s(每1s采集一次数据)
//延时250ms
#include<reg51.h>
#include<stdlib.h>
#include<intrins.h>
//实例84:液晶时钟设计
//包含单片机寄存器的头文件
//包含随机函数rand()的定义文件
//包含_nop_()函数定义的头文件
sbitRS=P2^0;
sbitRW=P2^1;
sbitE=P2^2;
sbitBF=P0^7;
//寄存器选择位,将RS位定义为P2.0引脚
//读写选择位,将RW位定义为P2.1引脚
//使能信号位,将E位定义为P2.2引脚
//忙碌标志位,,将BF位定义为P0.7引脚
unsignedcharcodedigit[]={"0123456789"};//定义字符数组显示数字
106/192
unsignedcharcodestring[]={"BeiJingTime"};//定义字符数组显示提示信息
unsignedcharcount; //定义变量统计中断累计次数
unsignedchars,m,h; //定义变量储存秒、分钟和小时
/*****************************************************
函数功能:延时1ms
(3j+2)*i=(3×33+2)×10=1010(微秒),能够认为是1毫秒
***************************************************/
voiddelay1ms()
{
unsignedchari,j;
for(i=0;i<10;i++)
for(j=0;j<33;j++)
;
}
/*****************************************************
函数功能:延时若干毫秒
入口参数:n
***************************************************/
voiddelay(unsignedcharn)
{
unsignedchari;
for(i=0;i<n;i++)
delay1ms();
}
/*****************************************************
函数功能:判断液晶模块的忙碌状态
返回值:result。result=1,忙碌;result=0,不忙
***************************************************/
unsignedcharBusyTest(void)
{
bitresult;
RS=0; //根据规定,RS为低电平,RW为高电平时,能够读状态
RW=1;
E=1; //E=1,才容许读写
_nop_(); //空操做
_nop_();
_nop_();
_nop_(); //空操做四个机器周期,给硬件反应时间
result=BF; //将忙碌标志电平赋给result
E=0; //将E恢复低电平
returnresult;
}
/*****************************************************
函数功能:将模式设置指令或显示地址写入液晶模块
107/192
入口参数:dictate
***************************************************/
voidWriteInstruction(unsignedchardictate)
{
while(BusyTest()==1);//若是忙就等待
RS=0; //根据规定,RS和R/W同时为低电平时,能够写
入指令
RW=0;
E=0; //E置低电平(根据表8-6,写指令时,E为高脉冲,
// 就是让E从0到1发生正跳变,因此应先置"0"
_nop_();
_nop_(); //空操做两个机器周期,给硬件反应时间
P0=dictate; //将数据送入P0口,即写入指令或地址
_nop_();
_nop_();
_nop_();
_nop_(); //空操做四个机器周期,给硬件反应时间
E=1; //E置高电平
_nop_();
_nop_();
_nop_();
_nop_(); //空操做四个机器周期,给硬件反应时间
E=0; //当E由高电平跳变成低电平时,液晶模块开始
执行命令
}
/*****************************************************
函数功能:指定字符显示的实际地址
入口参数:x
***************************************************/
voidWriteAddress(unsignedcharx)
{
WriteInstruction(x|0x80);//显示位置的肯定方法规定为"80H+地址码x"
}
/*****************************************************
函数功能:将数据(字符的标准ASCII码)写入液晶模块
入口参数:y(为字符常量)
***************************************************/
voidWriteData(unsignedchary)
{
while(BusyTest()==1);
RS=1; //RS为高电平,RW为低电平时,能够写入数据
RW=0;
E=0; //E置低电平(根据表8-6,写指令时,E为高脉冲,
// 就是让E从0到1发生正跳变,因此应先置"0"
108/192
}
P0=y;
_nop_();
_nop_();
_nop_();
_nop_();
E=1;
_nop_();
_nop_();
_nop_();
_nop_();
E=0;
//将数据送入P0口,即将数据写入液晶模块
//空操做四个机器周期,给硬件反应时间
//E置高电平
//空操做四个机器周期,给硬件反应时间
//当E由高电平跳变成低电平时,液晶模块开始执行命令
/*****************************************************
函数功能:对LCD的显示模式进行初始化设置
***************************************************/
voidLcdInitiate(void)
{
delay(15); //延时15ms,首次写指令时应给LCD一段较长的反
应时间
WriteInstruction(0x38); //显示模式设置:16×2显示,5×7点阵,8位数据
接口
delay(5); //延时5ms ,给硬件一点反应时间
WriteInstruction(0x38);
delay(5);
WriteInstruction(0x38);//连续三次,确保初始化成功
delay(5);
WriteInstruction(0x0c); //显示模式设置:显示开,无光标,光标不闪烁
delay(5);
WriteInstruction(0x06); //显示模式设置:光标右移,字符不移
delay(5);
WriteInstruction(0x01); //清屏幕指令,将之前的显示内容清除
delay(5);
}
/********************************************************************
**********
函数功能:显示小时
*********************************************************************
*********/
voidDisplayHour()
{
unsignedchari,j;
i=h/10; //取整运算,求得十位数字
109/192
}
j=h%10;
WriteAddress(0x44);
WriteData(digit[i]);
WriteData(digit[j]);
//取余运算,求得各位数字
//写显示地址,将十位数字显示在第2行第5列
//将十位数字的字符常量写入LCD
//将个位数字的字符常量写入LCD
/********************************************************************
**********
函数功能:显示分钟
*********************************************************************
*********/
voidDisplayMinute()
{
unsignedchari,j;
i=m/10; //取整运算,求得十位数字
j=m%10; //取余运算,求得各位数字
WriteAddress(0x47); //写显示地址,将十位数字显示在第2行第8列
WriteData(digit[i]); //将十位数字的字符常量写入LCD
WriteData(digit[j]); //将个位数字的字符常量写入LCD
}
/********************************************************************
**********
函数功能:显示秒
*********************************************************************
*********/
voidDisplaySecond()
{
unsignedchari,j;
i=s/10; //取整运算,求得十位数字
j=s%10; //取余运算,求得各位数字
WriteAddress(0x4a); //写显示地址,将十位数字显示在第2行第11列
WriteData(digit[i]); //将十位数字的字符常量写入LCD
WriteData(digit[j]); //将个位数字的字符常量写入LCD
}
/********************************************************************
*
mainfunction
*********************************************************************
**/
110/192
voidmain(void)
{
unsignedchari;
LcdInitiate();
TMOD=0x01;
//调用LCD初始化函数
//使用定时器T0的模式1
TH0=(65536-46083)/256;
TL0=(65536-46083)%256;
EA=1;
ET0=1;
TR0=1;
count=0;
s=0;
m=0;
h=0;
//定时器T0的高8位设置初值
//定时器T0的低8位设置初值
//开总中断
//定时器T0中断容许
//启动定时器T0
//中断次数初始化为0
//秒初始化为0
//分钟初始化为0
//小时初始化为0
WriteAddress(0x03);
i=0;
while(string[i]!='\0')
{
//写地址,从第1行第4列开始显示
//从字符数组的第1个元素开始显示
//只要没有显示到字符串的结束标志'\0',就继续
}
WriteData(string[i]);//将第i个字符数组元素写入LCD
i++; //指向下一个数组元素
WriteAddress(0x46);
WriteData(':');
WriteAddress(0x49);
WriteData(':');
while(1)
{
DisplayHour();
delay(5);
//写地址,将第二个分号显示在第2行第7列
//将分号的字符常量写入LCD
//写地址,将第二个分号显示在第2行第10列
//将分号的字符常量写入LCD
//无限循环
//显示小时
//给硬件一点反应时间
}
}
DisplayMinute();
delay(5);
DisplaySecond();
delay(5);
//显示分钟
//给硬件一点反应时间
//显示秒
//给硬件一点反应时间
/*******************************************************
函数功能:定时器T0的中断服务函数
********************************************************/
voidTime0(void)interrupt1using1//定时器T0的中断编号为1,使用第1组工
做寄存器
{
111/192
count++;
//每产生1次中断,中断累计次数加1
if(count==20)
{
//若是中断次数计满20次
}
count=0;
s++;
//中断累计次数清0
//秒加1
if(s==60)
{
s=0;
m++;
}
if(m==60)
{
m=0;
h++;
}
if(h==24)
{
h=0;
}
//若是计满60秒
//秒清0
//分钟加1
//若是计满60分
//分钟清0
//小时加1
//若是计满24小时
//小时清0
}
TH0=(65536-46083)/256;
TL0=(65536-46083)%256;
//定时器T0高8位从新赋初值
//定时器T0低8位从新赋初值
/********************************************************
***********一些芯片的使用*****24c02 DS18B20
X5045 ADC0832 DAC0832 DS1302 红外遥控
**********************************************/
//
85
"0x0ff"
AT24C02
P1
//实例85:将数据"0x0ff"写入AT24C02再读出送P1口显示
#include<reg51.h> // 包含51单片机寄存器定义的头文件
#include<intrins.h> //包含_nop_()函数定义的头文件
#defineOP_READ 0xa1 // 器件地址以及读取操做,0xa1即为10100001B
#defineOP_WRITE0xa0 // 器件地址以及写入操做,0xa1即为10100000B
sbitSDA=P3^4; //将串行数据总线SDA位定义在为P3.4引脚
sbitSCL=P3^3; //将串行时钟总线SDA位定义在为P3.3引脚
112/192
/*****************************************************
函数功能:延时1ms
(3j+2)*i=(3×33+2)×10=1010(微秒),能够认为是1毫秒
***************************************************/
voiddelay1ms()
{
unsignedchari,j;
for(i=0;i<10;i++)
for(j=0;j<33;j++)
;
}
/*****************************************************
函数功能:延时若干毫秒
入口参数:n
***************************************************/
voiddelaynms(unsignedcharn)
{
unsignedchari;
for(i=0;i<n;i++)
delay1ms();
}
/***************************************************
函数功能:开始数据传送
***************************************************/
voidstart()
// 开始位
{
SDA=1; //SDA初始化为高电平“1”
SCL=1; //开始数据传送时,要求SCL为高电平“1”
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
SDA=0; //SDA的降低沿被认为是开始信号
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
SCL=0; //SCL为低电平时,SDA上数据才容许变化(即容许之后的数据传
递)
}
/***************************************************
113/192
函数功能:结束数据传送
***************************************************/
voidstop()
// 中止位
{
SDA=0; //SDA初始化为低电平“0” _n
SCL=1; //结束数据传送时,要求SCL为高电平“1”
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
SDA=1; //SDA的上升沿被认为是结束信号
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
SDA=0;
SCL=0;
}
/***************************************************
函数功能:从AT24Cxx读取数据
出口参数:x
***************************************************/
unsignedcharReadData()
// 从AT24Cxx移入数据到MCU
{
unsignedchari;
unsignedcharx; //储存从AT24Cxx中读出的数据
for(i=0;i<8;i++)
{
SCL=1; //SCL置为高电平
x<<=1; //将x中的各二进位向左移一位
x|=(unsignedchar)SDA; //将SDA上的数据经过按位“或“运算存入x
中
SCL=0; //在SCL的降低沿读出数据
}
return(x); //将读取的数据返回
}
/***************************************************
函数功能:向AT24Cxx的当前地址写入数据
入口参数:y(储存待写入的数据)
***************************************************/
//在调用此数据写入函数前需首先调用开始函数start(),因此SCL=0
bitWriteCurrent(unsignedchary)
114/192
{
后
unsignedchari;
bitack_bit;
for(i=0;i<8;i++)
{
SDA=(bit)(y&0x80);
//
//储存应答位
循环移入8个位
//经过按位“与”运算将最高位数据送到S
//由于传送时高位在前,低位在
_nop_();
SCL=1;
_nop_();
_nop_();
SCL=0;
据所需的8个脉冲
y<<=1;
}
SDA=1;
释放SDA线,
//
//等待一个机器周期
//在SCL的上升沿将数据写入AT24Cxx
//等待一个机器周期
//等待一个机器周期
//将SCL从新置为低电平,以在SCL线造成传送数
//将y中的各二进位向左移一位
发送设备(主机)应在时钟脉冲的高电平期间(SCL=1)
_nop_();
_nop_();
SCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
//以让SDA线转由接收设备(AT24Cxx)控制
//等待一个机器周期
//等待一个机器周期
//根据上述规定,SCL应为高电平
//等待一个机器周期
//等待一个机器周期
//等待一个机器周期
//等待一个机器周期
ack_bit=SDA;//接受设备(AT24Cxx)向SDA送低电平,表示已经接收到一个
字节
//若送高电平,表示没有接收到,传送异常
SCL=0; //SCL为低电平时,SDA上数据才容许变化(即容许之后的数据
传递)
return ack_bit; // 返回AT24Cxx应答位
}
/***************************************************
函数功能:向AT24Cxx中的指定地址写入数据
入口参数:add(储存指定的地址);dat(储存待写入的数据)
***************************************************/
voidWriteSet(unsignedcharadd,unsignedchardat)
// 在指定地址addr处写入数据WriteCurrent
{
start(); //开始数据传递
WriteCurrent(OP_WRITE); //选择要操做的AT24Cxx芯片,并告知要对其写
入数据
115/192
}
WriteCurrent(add);
WriteCurrent(dat);
stop();
delaynms(4);
//写入指定地址
//向当前地址(上面指定的地址)写入数据
//中止数据传递
//1个字节的写入周期为1ms,最好延时1ms以上
/***************************************************
函数功能:从AT24Cxx中的当前地址读取数据
出口参数:x(储存读出的数据)
***************************************************/
unsignedcharReadCurrent()
{
unsignedcharx;
start(); //开始数据传递
WriteCurrent(OP_READ); //选择要操做的AT24Cxx芯片,并告知要读其数
据
x=ReadData(); //将读取的数据存入x
stop(); //中止数据传递
returnx; //返回读取的数据
}
/***************************************************
函数功能:从AT24Cxx中的指定地址读取数据
入口参数:set_addr
出口参数:x
***************************************************/
unsignedcharReadSet(unsignedcharset_addr)
// 在指定地址读取
{
start(); //开始数据传递
WriteCurrent(OP_WRITE); //选择要操做的AT24Cxx芯片,并告知要对
其写入数据
WriteCurrent(set_addr); //写入指定地址
return(ReadCurrent()); //从指定地址读出数据并返回
}
/***************************************************
函数功能:主函数
***************************************************/
main(void)
{
SDA=1; //SDA=1,SCL=1,使主从设备处于空闲状态
SCL=1;
WriteSet(0x36,0x0f); //在指定地址“0x36”中写入数据“0x0f”
P1=ReadSet(0x36); //从指定地址“0x36中读取数据并送P1口显示
}
116
/
192
//实例86:将按键次数写入AT24C02,再读出并用1602LCD
显示
#include<reg51.h> //包含单片机寄存器的头文件
#include<intrins.h> //包含_nop_()函数定义的头文件
sbitRS=P2^0; //寄存器选择位,将RS位定义为P2.0引脚
sbitRW=P2^1; //读写选择位,将RW位定义为P2.1引脚
sbitE=P2^2; //使能信号位,将E位定义为P2.2引脚
sbitBF=P0^7; //忙碌标志位,,将BF位定义为P0.7引脚
sbitS=P1^4; //将S位定义为P1.4引脚
#defineOP_READ 0xa1 // 器件地址以及读取操做,0xa1即为10100001B
#defineOP_WRITE0xa0 // 器件地址以及写入操做,0xa1即为10100000B
sbitSDA=P3^4; //将串行数据总线SDA位定义在为P3.4引脚
sbitSCL=P3^3; //将串行时钟总线SDA位定义在为P3.3引脚
unsignedcharcodedigit[]={"0123456789"};//定义字符数组显示数字
/*****************************************************
函数功能:延时1ms
(3j+2)*i=(3×33+2)×10=1010(微秒),能够认为是1毫秒
***************************************************/
voiddelay1ms()
{
unsignedchari,j;
for(i=0;i<10;i++)
for(j=0;j<33;j++)
;
}
/*****************************************************
函数功能:延时若干毫秒
入口参数:n
***************************************************/
voiddelaynms(unsignedcharn)
{
unsignedchari;
for(i=0;i<n;i++)
delay1ms();
}
/********************************************************************
***********
如下是对液晶模块的操做程序
117/192
*********************************************************************
***********/
/*****************************************************
函数功能:判断液晶模块的忙碌状态
返回值:result。result=1,忙碌;result=0,不忙
***************************************************/
unsignedcharBusyTest(void)
{
bitresult;
RS=0; //根据规定,RS为低电平,RW为高电平时,能够读状态
RW=1;
E=1; //E=1,才容许读写
_nop_(); //空操做
_nop_();
_nop_();
_nop_(); //空操做四个机器周期,给硬件反应时间
result=BF; //将忙碌标志电平赋给result
E=0; //将E恢复低电平
returnresult;
}
/*****************************************************
函数功能:将模式设置指令或显示地址写入液晶模块
入口参数:dictate
***************************************************/
voidWriteInstruction(unsignedchardictate)
{
while(BusyTest()==1); //若是忙就等待
RS=0; //根据规定,RS和R/W同时为低电平时,能够写
入指令
RW=0;
E=0; //E置低电平(根据表8-6,写指令时,E为高脉冲,
// 就是让E从0到1发生正跳变,因此应先置
"0"
_nop_();
_nop_(); //空操做两个机器周期,给硬件反应时间
P0=dictate; //将数据送入P0口,即写入指令或地址
_nop_();
_nop_();
_nop_();
_nop_(); //空操做四个机器周期,给硬件反应时间
E=1; //E置高电平
_nop_();
_nop_();
_nop_();
118/192
_nop_();
E=0;
执行命令
}
//空操做四个机器周期,给硬件反应时间
//当E由高电平跳变成低电平时,液晶模块开始
/*****************************************************
函数功能:指定字符显示的实际地址
入口参数:x
***************************************************/
voidWriteAddress(unsignedcharx)
{
WriteInstruction(x|0x80);//显示位置的肯定方法规定为"80H+地址码x"
}
/*****************************************************
函数功能:将数据(字符的标准ASCII码)写入液晶模块
入口参数:y(为字符常量)
***************************************************/
voidWriteData(unsignedchary)
{
while(BusyTest()==1);
RS=1; //RS为高电平,RW为低电平时,能够写入数据
RW=0;
E=0; //E置低电平(根据表8-6,写指令时,E为高脉冲,
// 就是让E从0到1发生正跳变,因此应先置"0"
P0=y; //将数据送入P0口,即将数据写入液晶模块
_nop_();
_nop_();
_nop_();
_nop_(); //空操做四个机器周期,给硬件反应时间
E=1; //E置高电平
_nop_();
_nop_();
_nop_();
_nop_(); //空操做四个机器周期,给硬件反应时间
E=0; //当E由高电平跳变成低电平时,液晶模块开始执行命令
}
/*****************************************************
函数功能:对LCD的显示模式进行初始化设置
***************************************************/
voidLcdInitiate(void)
{
delaynms(15); //延时15ms,首次写指令时应给LCD一段较
长的反应时间
WriteInstruction(0x38); //显示模式设置:16×2显示,5×7点阵,8位
数据接口
119/192
delaynms(5);
WriteInstruction(0x38);
delaynms(5);
//延时5ms
,给硬件一点反应时间
}
WriteInstruction(0x38);
delaynms(5);
WriteInstruction(0x0c);
delaynms(5);
WriteInstruction(0x06);
delaynms(5);
WriteInstruction(0x01);
delaynms(5);
//连续三次,确保初始化成功
//显示模式设置:显示开,无光标,光标不闪烁
//显示模式设置:光标右移,字符不移
//清屏幕指令,将之前的显示内容清除
/***************************************************
函数功能:显示小时
***************************************************/
voidDisplay(unsignedcharx)
{
unsignedchari,j;
i=x/10; //取整运算,求得十位数字
j=x%10; //取余运算,求得各位数字
WriteAddress(0x44); //写显示地址,将十位数字显示在第2行第5列
WriteData(digit[i]); //将十位数字的字符常量写入LCD
WriteData(digit[j]); //将个位数字的字符常量写入LCD
}
/********************************************************************
***********
如下是对AT24C02的读写操做程序
*********************************************************************
***********/
/***************************************************
函数功能:开始数据传送
***************************************************/
voidstart()
// 开始位
{
SDA=1; //SDA初始化为高电平“1”
SCL=1; //开始数据传送时,要求SCL为高电平“1”
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
SDA=0; //SDA的降低沿被认为是开始信号
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
120/192
_nop_();
_nop_();
SCL=0;
递)
}
//等待一个机器周期
//等待一个机器周期
//SCL为低电平时,SDA上数据才容许变化(即容许之后的数据传
/***************************************************
函数功能:结束数据传送
***************************************************/
voidstop()
// 中止位
{
SDA=0; //SDA初始化为低电平“0”
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
SCL=1; //结束数据传送时,要求SCL为高电平“1”
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
SDA=1; //SDA的上升沿被认为是结束信号
}
/***************************************************
函数功能:从AT24Cxx读取数据
出口参数:x
***************************************************/
unsignedcharReadData()
// 从AT24Cxx移入数据到MCU
{
unsignedchari;
unsignedcharx; //储存从AT24Cxx中读出的数据
for(i=0;i<8;i++)
{
SCL=1; //SCL置为高电平
x<<=1; //将x中的各二进位向左移一位
x|=(unsignedchar)SDA; //将SDA上的数据经过按位“或“运算存入x
中
SCL=0; //在SCL的降低沿读出数据
}
return(x); //将读取的数据返回
}
/***************************************************
函数功能:向AT24Cxx的当前地址写入数据
入口参数:y(储存待写入的数据)
***************************************************/
121/192
//在调用此数据写入函数前需首先调用开始函数start(),因此SCL=0
bitWriteCurrent(unsignedchary)
{
unsignedchari;
bitack_bit; //储存应答位
for(i=0;i<8;i++) // 循环移入8个位
{
SDA=(bit)(y&0x80); //经过按位“与”运算将最高位数据送到S
//由于传送时高位在前,低位在
后
_nop_(); //等待一个机器周期
SCL=1; //在SCL的上升沿将数据写入AT24Cxx
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
SCL=0; //将SCL从新置为低电平,以在SCL线造成传送数
据所需的8个脉冲
y<<=1; //将y中的各二进位向左移一位
}
SDA=1; // 发送设备(主机)应在时钟脉冲的高电平期间(SCL=1)
释放SDA线,
//以让SDA线转由接收设备(AT24Cxx)控制
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
SCL=1; //根据上述规定,SCL应为高电平
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
ack_bit=SDA;//接受设备(AT24Cxx)向SDA送低电平,表示已经接收到一个
字节
//若送高电平,表示没有接收到,传送异常
SCL=0; //SCL为低电平时,SDA上数据才容许变化(即容许之后的数据
传递)
return ack_bit; // 返回AT24Cxx应答位
}
/***************************************************
函数功能:向AT24Cxx中的指定地址写入数据
入口参数:add(储存指定的地址);dat(储存待写入的数据)
***************************************************/
voidWriteSet(unsignedcharadd,unsignedchardat)
// 在指定地址addr处写入数据WriteCurrent
{
start(); //开始数据传递
122/192
WriteCurrent(OP_WRITE);
入数据
WriteCurrent(add);
WriteCurrent(dat);
//选择要操做的AT24Cxx芯片,并告知要对其写
//写入指定地址
//向当前地址(上面指定的地址)写入数据
}
stop();
delaynms(4);
//中止数据传递
//1个字节的写入周期为1ms,
最好延时1ms以上
/***************************************************
函数功能:从AT24Cxx中的当前地址读取数据
出口参数:x(储存读出的数据)
***************************************************/
unsignedcharReadCurrent()
{
unsignedcharx;
start(); //开始数据传递
WriteCurrent(OP_READ); //选择要操做的AT24Cxx芯片,并告知要读其数
据
x=ReadData(); //将读取的数据存入x
stop(); //中止数据传递
returnx; //返回读取的数据
}
/***************************************************
函数功能:从AT24Cxx中的指定地址读取数据
入口参数:set_add
出口参数:x
***************************************************/
unsignedcharReadSet(unsignedcharset_add)
// 在指定地址读取
{
start(); //开始数据传递
WriteCurrent(OP_WRITE); //选择要操做的AT24Cxx芯片,并告知要对
其写入数据
WriteCurrent(set_add); //写入指定地址
return(ReadCurrent()); //从指定地址读出数据并返回
}
/********************************************************************
*
函数功能:主函数
*********************************************************************
**/
voidmain(void)
{
unsignedcharsum; //储存计数值
unsignedcharx; //储存从AT24C02读出的值
123/192
LcdInitiate();
sum=0;
while(1)
{
if(S==0)
{
//调用LCD初始化函数
//将计数值初始化为0
//无限循环
//若是该键被按下
delaynms(80);
if(S==0)
sum++;
if(sum==99)
sum=0;
}
//软件消抖,延时80ms
//确实该键被按下
//计件值加1
//若是计满99
//清0,从新开始计数
}
}
WriteSet(0x01,sum);//将计件值写入AT24C02中的指定地址"0x01"
x=ReadSet(0x01); //从AT24C02中读出计件值
Display(x); //将计件值用1602LCD显示
//
87
I2C
AT24C02
//实例87:对I2C总线上挂接多个AT24C02的读写操做
#include<reg51.h> // 包含51单片机寄存器定义的头文件
#include<intrins.h> //包含_nop_()函数定义的头文件
#defineOP_READ1 0xa1 // 器件1地址以及读取操做,0xa1即为1010
0001B
#defineOP_WRITE10xa0 // 器件1地址以及写入操做,0xa1即为10100000B
#defineOP_READ2 0xaf // 器件2地址以及读取操做,0xa1即为10101111B
#defineOP_WRITE20xae // 器件2地址以及写入操做,0xa1即为10101110B
sbitSDA=P3^4; //将串行数据总线SDA位定义在为P3.4引脚
sbitSCL=P3^3; //将串行时钟总线SDA位定义在为P3.3引脚
/*****************************************************
函数功能:延时1ms
(3j+2)*i=(3×33+2)×10=1010(微秒),能够认为是1毫秒
***************************************************/
voiddelay1ms()
{
unsignedchari,j;
for(i=0;i<10;i++)
for(j=0;j<33;j++)
;
}
/*****************************************************
124/192
函数功能:延时若干毫秒
入口参数:n
***************************************************/
voiddelaynms(unsignedcharn)
{
unsignedchari;
for(i=0;i<n;i++)
delay1ms();
}
/***************************************************
函数功能:开始数据传送
***************************************************/
voidstart()
// 开始位
{
SDA=1; //SDA初始化为高电平“1”
SCL=1; //开始数据传送时,要求SCL为高电平“1”
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
SDA=0; //SDA的降低沿被认为是开始信号
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
SCL=0; //SCL为低电平时,SDA上数据才容许变化(即容许之后的数据传
递)
_nop_(); //等待一个机器周期
}
/***************************************************
函数功能:结束数据传送
***************************************************/
voidstop()
// 中止位
{
SDA=0; //SDA初始化为低电平“0”
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
SCL=1; //结束数据传送时,要求SCL为高电平“1”
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
125/192
}
SDA=1;
//SDA的上升沿被认为是结束信号
/***************************************************
函数功能:从AT24Cxx读取数据
出口参数:x
***************************************************/
unsignedcharReadData()
// 从AT24Cxx移入数据到MCU
{
unsignedchari;
unsignedcharx; //储存从AT24Cxx中读出的数据
for(i=0;i<8;i++)
{
SCL=1; //SCL置为高电平
x<<=1; //将x中的各二进位向左移一位
x|=(unsignedchar)SDA; //将SDA上的数据经过按位“或“运算存入x
中
SCL=0; //在SCL的降低沿读出数据
}
return(x); //将读取的数据返回
}
/***************************************************
函数功能:向AT24Cxx的当前地址写入数据
入口参数:y(储存待写入的数据)
***************************************************/
//在调用此数据写入函数前需首先调用开始函数start(),因此SCL=0
bitWriteCurrent(unsignedchary)
{
unsignedchari;
bitack_bit; //储存应答位
for(i=0;i<8;i++) // 循环移入8个位
{
SDA=(bit)(y&0x80); //经过按位“与”运算将最高位数据送到S
//由于传送时高位在前,低位在后
_nop_(); //等待一个机器周期
SCL=1; //在SCL的上升沿将数据写入AT24Cxx
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
SCL=0; //将SCL从新置为低电平,以在SCL线造成传送
数据所需的8个脉冲
y<<=1; //将y中的各二进位向左移一位
}
126
/
192
SDA=1;
释放SDA线,
//
发送设备(主机)应在时钟脉冲的高电平期间(SCL=1)
_nop_();
_nop_();
SCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
//以让SDA线转由接收设备(AT24Cxx)控制
//等待一个机器周期
//等待一个机器周期
//根据上述规定,SCL应为高电平
//等待一个机器周期
//等待一个机器周期
//等待一个机器周期
//等待一个机器周期
ack_bit=SDA;//接受设备(AT24Cxx)向SDA送低电平,表示已经接收到一个
字节
//若送高电平,表示没有接收到,传送异常
SCL=0; //SCL为低电平时,SDA上数据才容许变化(即容许之后的数据
传递)
return ack_bit;//返回AT24Cxx应答位
}
/***************************************************
函数功能:向第一个AT24Cxx中的指定地址写入数据
入口参数:add(储存指定的地址);dat(储存待写入的数据)
***************************************************/
voidWriteSet1(unsignedcharadd,unsignedchardat)
// 在指定地址addr处写入数据WriteCurrent
{
start(); //开始数据传递
WriteCurrent(OP_WRITE1); //选择要操做的第一个AT24Cxx芯片,并告知要
对其写入数据
WriteCurrent(add); //写入指定地址
WriteCurrent(dat); //向当前地址(上面指定的地址)写入数据
stop(); //中止数据传递
delaynms(4); //1个字节的写入周期为1ms,最好延时1ms以
上
}
/***************************************************
函数功能:向第二个AT24Cxx中的指定地址写入数据
入口参数:add(储存指定的地址);dat(储存待写入的数据)
***************************************************/
voidWriteSet2(unsignedcharadd,unsignedchardat)
// 在指定地址addr处写入数据WriteCurrent
{
start(); //开始数据传递
WriteCurrent(OP_WRITE2); //选择要操做的AT24Cxx芯片,并告知要对其写
入数据
WriteCurrent(add); //写入指定地址
127/192
上
}
WriteCurrent(dat);
stop();
delaynms(4);
//向当前地址(上面指定的地址)写入数据
//中止数据传递
//1个字节的写入周期为1ms,最好延时1ms以
/***************************************************
函数功能:从第一个AT24Cxx中的当前地址读取数据
出口参数:x(储存读出的数据)
***************************************************/
unsignedcharReadCurrent1()
{
unsignedcharx;
start(); //开始数据传递
WriteCurrent(OP_READ1); //选择要操做的第一个AT24Cxx芯片,并告知要
读其数据
x=ReadData(); //将读取的数据存入x
stop(); //中止数据传递
returnx; //返回读取的数据
}
/***************************************************
函数功能:从第二个AT24Cxx中的当前地址读取数据
出口参数:x(储存读出的数据)
***************************************************/
unsignedcharReadCurrent2()
{
unsignedcharx;
start(); //开始数据传递
WriteCurrent(OP_READ2); //选择要操做的第二个AT24Cxx芯片,并告知
要读其数据
x=ReadData(); //将读取的数据存入x
stop(); //中止数据传递
returnx; //返回读取的数据
}
/***************************************************
函数功能:从第一个AT24Cxx中的指定地址读取数据
入口参数:set_addr
出口参数:x
***************************************************/
unsignedcharReadSet1(unsignedcharset_addr)
// 在指定地址读取
{
start(); //开始数据传递
128
/
192
WriteCurrent(OP_WRITE1);
告知要对其写入数据
WriteCurrent(set_addr);
return(ReadCurrent1());
并返回
}
//选择要操做的第一个AT24Cxx芯片,并
//写入指定地址
//从第一个AT24Cxx芯片指定地址读出数据
/***************************************************
函数功能:从第二个AT24Cxx中的指定地址读取数据
入口参数:set_addr
出口参数:x
***************************************************/
unsignedcharReadSet2(unsignedcharset_addr)
// 在指定地址读取
{
start(); //开始数据传递
WriteCurrent(OP_WRITE2); //选择要操做的第二个AT24Cxx芯片,并
告知要对其写入数据
WriteCurrent(set_addr); //写入指定地址
return(ReadCurrent2()); //从第二个AT24Cxx芯片指定地址读出数据
并返回
}
/***************************************************
函数功能:主函数
***************************************************/
main(void)
{
unsignedcharx;
SDA=1; //SDA=1,SCL=1,使主从设备处于空闲状态
SCL=1;
WriteSet1(0x36,0xaa); //将数据"0xaa"写入第一个AT24C02的指定地址
"0x36"
x=ReadSet1(0x36); //从第二个AT24C02中的指定地址"0x36"读出数据
WriteSet2(0x48,x); //将读出的数据写入第二个AT24C02的指定地址
"0x48"?
P1=ReadSet2(0x48); //将从第二个AT24C02的指定地址读出的数据送
P1口显示验证
}
//
88
AT24C02
//实例88:基于AT24C02的多机通讯
读取程序
#include<reg51.h>
//
包含51单片机寄存器定义的头文件
129/192
#include<intrins.h>
#defineOP_READ
0001B
0xa1
//包含_nop_()函数定义的头文件
// 器件1地址以及读取操做,0xa1即为1010
#define
OP_WRITE0xa0
//
器件1地址以及写入操做,0xa1即为10100000B
sbitSDA=P3^4;
sbitSCL=P3^3;
sbitflag=P3^0;
//将串行数据总线SDA位定义在为P3.4引脚
//将串行时钟总线SDA位定义在为P3.3引脚
/*****************************************************
函数功能:延时1ms
(3j+2)*i=(3×33+2)×10=1010(微秒),能够认为是1毫秒
***************************************************/
voiddelay1ms()
{
unsignedchari,j;
for(i=0;i<10;i++)
for(j=0;j<33;j++)
;
}
/*****************************************************
函数功能:延时若干毫秒
入口参数:n
***************************************************/
voiddelaynms(unsignedcharn)
{
unsignedchari;
for(i=0;i<n;i++)
delay1ms();
}
/***************************************************
函数功能:开始数据传送
***************************************************/
voidstart()
// 开始位
{
SDA=1; //SDA初始化为高电平“1”
SCL=1; //开始数据传送时,要求SCL为高电平“1”
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
SDA=0; //SDA的降低沿被认为是开始信号
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
130
/
192
SCL=0;
递)
_nop_();
}
//SCL为低电平时,SDA上数据才容许变化(即容许之后的数据传
//等待一个机器周期
/***************************************************
函数功能:结束数据传送
***************************************************/
voidstop()
// 中止位
{
SDA=0; //SDA初始化为低电平“0”
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
SCL=1; //结束数据传送时,要求SCL为高电平“1”
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
SDA=1; //SDA的上升沿被认为是结束信号
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
}
/***************************************************
函数功能:从AT24Cxx读取数据
出口参数:x
***************************************************/
unsignedcharReadData()
// 从AT24Cxx移入数据到MCU
{
unsignedchari;
unsignedcharx; //储存从AT24Cxx中读出的数据
for(i=0;i<8;i++)
{
SCL=1; //SCL置为高电平
x<<=1; //将x中的各二进位向左移一位
x|=(unsignedchar)SDA; //将SDA上的数据经过按位“或“运算存入x
中
SCL=0; //在SCL的降低沿读出数据
}
return(x); //将读取的数据返回
}
/***************************************************
函数功能:向AT24Cxx的当前地址写入数据
入口参数:y(储存待写入的数据)
131/192
***************************************************/
//在调用此数据写入函数前需首先调用开始函数start(),因此SCL=0
bitWriteCurrent(unsignedchary)
{
unsignedchari;
bitack_bit; //储存应答位
for(i=0;i<8;i++) // 循环移入8个位
{
SDA=(bit)(y&0x80); //经过按位“与”运算将最高位数据送到S
//由于传送时高位在前,低位在后
_nop_(); //等待一个机器周期
SCL=1; //在SCL的上升沿将数据写入AT24Cxx
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
SCL=0; //将SCL从新置为低电平,以在SCL线造成传送
数据所需的8个脉冲
y<<=1; //将y中的各二进位向左移一位
}
SDA=1; // 发送设备(主机)应在时钟脉冲的高电平期间(SCL=1)
释放SDA线,
//以让SDA线转由接收设备(AT24Cxx)控制
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
SCL=1; //根据上述规定,SCL应为高电平
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
ack_bit=SDA;//接受设备(AT24Cxx)向SDA送低电平,表示已经接收到一个
字节
//若送高电平,表示没有接收到,传送异常
SCL=0; //SCL为低电平时,SDA上数据才容许变化(即容许之后的数据
传递)
return ack_bit;//返回AT24Cxx应答位
}
/***************************************************
函数功能:从第一个AT24Cxx中的当前地址读取数据
出口参数:x(储存读出的数据)
***************************************************/
unsignedcharReadCurrent()
{
unsignedcharx;
132/192
据
}
start();
WriteCurrent(OP_READ);
x=ReadData();
stop();
returnx;
//开始数据传递
//选择要操做的AT24Cxx芯片,并告知要读其数
//将读取的数据存入x
//中止数据传递
//返回读取的数据
/***************************************************
函数功能:从AT24Cxx中的指定地址读取数据
入口参数:set_addr
出口参数:x
***************************************************/
unsignedcharReadSet(unsignedcharset_addr)
// 在指定地址读取
{
start(); //开始数据传递
WriteCurrent(OP_WRITE); //选择要操做的AT24Cxx芯片,并告知要对
其写入数据
WriteCurrent(set_addr); //写入指定地址
return(ReadCurrent()); //从第一个AT24Cxx芯片指定地址读出数据并
返回
}
/***************************************************
函数功能:主函数
***************************************************/
main(void)
{
SDA=1; //SDA=1,SCL=1,使主从设备处于空闲状态
SCL=1;
while(1)
{
while(flag==1)
;
P1=ReadSet(0x36); //从第二个AT24C02中的指定地址"0x36"读出数
据
delaynms(90);
}
}
//
88
AT24C02
//实例88:基于AT24C02的多机通讯
133/192
写入程序
#include<reg51.h>
//
包含51单片机寄存器定义的头文件
#include<intrins.h>
#defineOP_READ
0001B
0xa1
//包含_nop_()函数定义的头文件
// 器件1地址以及读取操做,0xa1即为1010
#define
OP_WRITE0xa0
//
器件1地址以及写入操做,0xa1即为10100000B
sbitSDA=P3^4;
sbitSCL=P3^3;
sbitflag=P3^0;
//将串行数据总线SDA位定义在为P3.4引脚
//将串行时钟总线SDA位定义在为P3.3引脚
/*****************************************************
函数功能:延时1ms
(3j+2)*i=(3×33+2)×10=1010(微秒),能够认为是1毫秒
***************************************************/
voiddelay1ms()
{
unsignedchari,j;
for(i=0;i<10;i++)
for(j=0;j<33;j++)
;
}
/*****************************************************
函数功能:延时若干毫秒
入口参数:n
***************************************************/
voiddelaynms(unsignedcharn)
{
unsignedchari;
for(i=0;i<n;i++)
delay1ms();
}
/***************************************************
函数功能:开始数据传送
***************************************************/
voidstart()
// 开始位
{
SDA=1; //SDA初始化为高电平“1”
SCL=1; //开始数据传送时,要求SCL为高电平“1”
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
SDA=0; //SDA的降低沿被认为是开始信号
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
134/192
SCL=0;
递)
_nop_();
}
//SCL为低电平时,SDA上数据才容许变化(即容许之后的数据传
//等待一个机器周期
/***************************************************
函数功能:结束数据传送
***************************************************/
voidstop()
// 中止位
{
SDA=0; //SDA初始化为低电平“0”
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
SCL=1; //结束数据传送时,要求SCL为高电平“1”
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
SDA=1; //SDA的上升沿被认为是结束信号
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
}
/***************************************************
函数功能:向AT24Cxx的当前地址写入数据
入口参数:y(储存待写入的数据)
***************************************************/
//在调用此数据写入函数前需首先调用开始函数start(),因此SCL=0
bitWriteCurrent(unsignedchary)
{
unsignedchari;
bitack_bit; //储存应答位
for(i=0;i<8;i++) // 循环移入8个位
{
SDA=(bit)(y&0x80); //经过按位“与”运算将最高位数据送到S
//由于传送时高位在前,低位在后
_nop_(); //等待一个机器周期
SCL=1; //在SCL的上升沿将数据写入AT24Cxx
_nop_(); //等待一个机器周期
_nop_(); //等待一个机器周期
135
/
192
SCL=0;
数据所需的8个脉冲
y<<=1;
}
SDA=1;
释放SDA线,
//
//将SCL从新置为低电平,以在SCL线造成传送
//将y中的各二进位向左移一位
发送设备(主机)应在时钟脉冲的高电平期间(SCL=1)
_nop_();
_nop_();
SCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
//以让SDA线转由接收设备(AT24Cxx)控制
//等待一个机器周期
//等待一个机器周期
//根据上述规定,SCL应为高电平
//等待一个机器周期
//等待一个机器周期
//等待一个机器周期
//等待一个机器周期
ack_bit=SDA;//接受设备(AT24Cxx)向SDA送低电平,表示已经接收到一个
字节
//若送高电平,表示没有接收到,传送异常
SCL=0; //SCL为低电平时,SDA上数据才容许变化(即容许之后的数据
传递)
return ack_bit;//返回AT24Cxx应答位
}
/***************************************************
函数功能:向AT24Cxx中的指定地址写入数据
入口参数:add(储存指定的地址);dat(储存待写入的数据)
***************************************************/
voidWriteSet(unsignedcharadd,unsignedchardat)
// 在指定地址addr处写入数据WriteCurrent
{
start(); //开始数据传递
WriteCurrent(OP_WRITE); //选择要操做的第一个AT24Cxx芯片,并告知要
对其写入数据
WriteCurrent(add); //写入指定地址
WriteCurrent(dat); //向当前地址(上面指定的地址)写入数据
stop(); //中止数据传递
delaynms(4); //1个字节的写入周期为1ms,最好延时1ms以
上
}
/***************************************************
函数功能:主函数
***************************************************/
main(void)
{
TMOD=0x01;
136/192
TH0=(65536-46083)/256;
TL0=(65536-46083)%256;
EA=1;
ET0=1;
TR0=1;
flag=1;
while(1)
{
while(flag==1)
{
WriteSet(0x36,0xf0);
"0x36"
delaynms(50);
}
while(flag==0)
;
}
}
//将数据"0xf0"写入第一个AT24C02的指定地址
//延时50ms
/***************************************************
函数功能:定时器T0的中断函数,使P3.0引脚输出100ms方波
***************