单片机c语言代码计时

2018-12-19 16:01:10 h_5649512 阅读数 4605

单片机C语言程序设计实训100例大集合

本书基于Keil μVision程序设计平台和Proteus硬件仿真平台,精心编写了100余个8051单片机C语言程序设计案例。完整的资料已经上传到闯客网技术论坛了,关于这个资料已经创建了一个单片机和嵌入式C语言的资料群,用于获取资料和交流用的:813238832
原文链接:https://bbs.usoftchina.com/thread-204854-1-5.html

全书基础设计类案例贯穿8051单片机最基本的端口编程、定时/计数器应用、中断和串口通信;硬件应用类案例涵盖常用外部存储器扩展、接口扩展、译码、编码、驱动、光机、机电、A/D与D/A转换等内容;综合设计类案例涉及大量消费类电子产品、仪器仪表及智能控制设备的相关技术。
本书可作为大专院校学生学习实践单片机c语言程序设计的教材或参考书,也可作为电子工程技术
人员或单片机技术爱好者的参考资料。
第1章 8051单片机C语言程序设计概述
 1.1 8051单片机引脚
 1.2 数据与程序内存
 1.3 特殊功能寄存器
 1.4 外部中断、定时/计数器及串口应用
 1.5 有符号与无符号数应用、数位分解、位操作
 1.6 变量、存储类型与存储模式
 1.7 数组、字符串与指针
 1.8 流程控制
 1.9 可重入函数和中断函数
 1.10 C语言在单片机系统开发中的优势
第2章 Proteus操作基础
 2.1 Proteus操作界面简介
 2.2 仿真电路原理图设计
 2.3 元件选择
 2.4 调试仿真
 2.5 Proteus与 V3的联合调试
第3章 基础程序设计
 3.1 闪烁的LED
 3.2 从左到右的流水灯
 3.3 左右来回循环的流水灯
 3.4 花样流水灯
 3.5 LED模拟交通灯
 3.6 单只数码管循环显示0~9
 3.7 8只数码管滚动显示单个数字
 3.8 8只数码管显示多个不同字符
 3.9 数码管闪烁显示
 3.10 8只数码管滚动显示数字串
 3.11 K1~K4控制LED移位
 3.12 K1~K4按键状态显示
 3.13 K1~K4分组控制LED
 3.14 K1~K4控制数码管移位显示
 3.15 K1~K4控制数码管加减演示
 3.16 4×4键盘矩阵控制条形LED显示
 3.17 数码管显示4×4键盘矩阵按键
 3.18 开关控制LED
 3.19 继电器控制照明设备
 3.20 数码管显示拨码开关编码
 3.21 开关控制报警器
 3.22 按键发音
 3.23 播放音乐
 3.24 INT0中断计数
 3.25 INT0中断控制LED
 3.26 INT0及INT1中断计数
 3.27 TIMER0控制单只LED闪烁
 3.28 TIMER0控制流水灯
 3.29 TIMER0控制4只LED滚动闪烁
 3.30 T0控制LED实现二进制计数
 3.31 TIMER0与TIMER1控制条形LED
 3.32 10s的秒表
 3.33 用计数器中断实现100以内的按键计数
 3.34 10 000s以内的计时程序
 3.35 定时器控制数码管动态显示
 3.36 8×8 LED点阵屏显示数字
 3.37 按键控制8×8 LED点阵屏显示图形
 3.38 用定时器设计的门铃
 3.39 演奏音阶
 3.40 按键控制定时器选播多段音乐
 3.41 定时器控制交通指示灯
 3.42 报警器与旋转灯
 3.43 串行数据转换为并行数据
 3.44 并行数据转换为串行数据
 3.45 甲机通过串口控制乙机LED闪烁
 3.46 单片机之间双向通信
 3.47 单片机向主机发送字符串
 3.48 单片机与PC串口通信仿真
第4章 硬件应用
 4.1 74LS138译码器应用
 4.2 74HC154译码器应用
 4.3 74HC595串入并出芯片应用
 4.4 用74LS148扩展中断
 4.5 I2C-24C04与蜂鸣器
 4.6 I2C-24C04与数码管
 4.7 用6264扩展内存
 4.8 用8255实现接口扩展
在这里插入图片描述
在这里插入图片描述

2018-07-14 10:40:42 youyoumo123 阅读数 463

/*  名称:10s 的秒表

说明:首次按键计时开始,http://www.jiakang021.com再次按键暂停,第三次按键清零。

 

*/

#include<reg51.h>

#define uchar unsigned char

#define uint unsigned int

sbit K1=P3^7; 

uchar

i,Second_Counts,Key_Flag_Idx;

bit Key_State; 

uchar

 

DSY_CODE[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

//延时

void DelayMS(uint ms)

{

uchar t;

while(ms--) for(t=0;t<120;t++);

}

//处理按键事件

void Key_Event_Handle()

{

if(Key_State==0)

{

Key_Flag_Idx=(Key_Flag_Idx+1)%3;

switch(Key_Flag_Idx)

case 1:EA=1;ET0=1;TR0=1;break;

case 2:EA=0;ET0=0;TR0=0;break;

case 0:P0=0x3f;P2=0x3f;i=0;Second_Counts=0;

                      }

           }

//主程序

void main()

{

 

P0=0x3f;            //显示 00

P2=0x3f;

i=0;

 

 

Second_Counts=0;

Key_Flag_Idx=0;          //按键次数(取值 0,1,2,3)

Key_State=1;      //按键状态

 

TMOD=0x01;    //定时器 0 方式 1

 

TH0=(65536-50000)/256;    //定时器 0:15ms 

TL0=(65536-50000)%256;

while(1)

{

if(Key_State!=K1)

DelayMS(10); 

Key_State=K1;

Key_Event_Handle();

}

}

 

/T0 中断函数

void DSY_Refresh() interrupt 1

{

TH0=(65536-50000)/256;   //恢复定时器 0 初值

TL0=(65536-50000)%256;

if(++i==2)

 

  {

i=0; 

Second_Counts++;   //50ms*2=0.1s 转换状态

P0=DSY_CODE[Second_Counts/10];

P2=DSY_CODE[Second_Counts%10];

if(Second_Counts==100) Second_Counts=0; //满 100(10s)后显示 00 

  }

}

 

2018-04-13 13:08:30 WhiteNebula 阅读数 51979

 

目录

目录................................................................................................................................1

函数的使用和熟悉********************************/.......................................4

实例3:用单片机控制第一个灯亮.............................................................................4

实例4:用单片机控制一个灯闪烁:认识单片机的工作频率.................................4

实例5:将P1口状态分别送入P0P2P3口:认识I/O口的引脚功能............5

实例6:使用P3口流水点亮8LED.......................................................................5

实例7:通过对P3口地址的操作流水点亮8LED...............................................6

实例8:用不同数据类型控制灯闪烁时间.................................................................7

实例9:用P0口、P1口分别显示加法和减法运算结果.........................................8

实例10:用P0P1口显示乘法运算结果................................................................9

实例11:用P1P0口显示除法运算结果................................................................9

实例12:用自增运算控制P08LED流水花样..............................................10

实例13:用P0口显示逻辑""运算结果...............................................................10

实例14:用P0口显示条件运算结果.......................................................................11

实例15:用P0口显示按位"异或"运算结果...........................................................11

实例16:用P0显示左移运算结果...........................................................................11

实例17"万能逻辑电路"实验.................................................................................11

实例18:用右移运算流水点亮P18LED.......................................................12

实例19:用if语句控制P08LED的流水方向..............................................13

实例20:用swtich语句的控制P08LED的点亮状态..................................13

实例21:用for语句控制蜂鸣器鸣笛次数..............................................................14

实例22:用while语句控制LED...............................................................................16

实例23:用do-while语句控制P08LED流水点亮......................................16

实例24:用字符型数组控制P08LED流水点亮..........................................17

实例25P0口显示字符串常量.........................................................................18

实例26:用P0口显示指针运算结果......................................................................19

实例27:用指针数组控制P08LED流水点亮..............................................19

实例28:用数组的指针控制P08LED流水点亮........................................20

实例29:用P0P1口显示整型函数返回值........................................................21

实例30:用有参函数控制P08LED流水速度..............................................22

实例31:用数组作函数参数控制流水花样.............................................................23

实例32:用指针作函数参数控制P08LED流水点亮..................................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查询方式P28位控制LED闪烁....................................31

实例43:用定时器T1查询方式控制单片机发出1KHz音频.................................31

实例44:将计数器T0计数的结果送P18LED显示....................................32

实例45:用定时器T0的中断控制1LED闪烁...................................................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

实例71CPU控制的独立式键盘扫描实验.............................................................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

实例90DS18B20温度检测及其液晶显示...........................................................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=11111110BP1.0输出低电平

delay();   //延时一段时间

P1=0xff;   //P1=11111111BP1.0输出高电平

delay();  //延时一段时间

}

}

4/192


 


//


5


P1


P0


P2


P3


I/O


//实例5:将

#include<reg51.h>


P1口状态分别送入P0P2P3口:认识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口流水点亮8LED

#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口地址的操作流水点亮8LED

#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.3P1.4P1.7


口的灯被点亮


}


P0=n-m;


//P0=17=00010001B,结果P0.0P0.4的灯被熄灭


 

//实例10:用P0P1口显示乘法运算结果

#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

//因此,高816进制数H3*16+H2必然等于17,即4544

除以256的商

//816进制数H1*16+H0必然等于192,即4544除以

256的余数

P1=s/256;      //8位送P1P1=17=11H=00010001B,P1.0P1.4口灭

其余亮

P0=s%256;      //8位送P0,P3=192=c0H=11000000B,P3.1,P3.6,P3.7

灭,其余亮

}


 

//实例11:用P1P0口显示除法运算结果

#include<reg51.h>    //包含单片机寄存器的头文件

voidmain(void)

{

P1=36/5;            //求整数

P0=((36%5)*10)/5;//求小数

while(1)

9/192


}


;


//无限循环防止程序“跑飞”


 

//实例12:用自增运算控制P08LED流水花样

#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:用右移运算流水点亮P18LED

#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语句控制P08LED的流水方向

#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语句的控制P08LED的点亮状态

#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小于0xff255)时执行循环体

{

P0=i;          //iP0口显示

delay60ms();//延时

i++;           //i自增1

}

}

}


 

//实例23:用do-whiile语句控制P08LED流水点亮

#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);      //无限循环,使8LED循环流水点亮

}


 

//实例24:用字符型数组控制P08LED流水点亮

#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.3P0.5引脚LED熄灭,其余点亮

while(1)

;             //无限循环,防止程序“跑飞”


 


//


27


P0


8


LED


//实例27:用指针数组控制P08LED流水点亮

#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:用有参函数控制P08LED流水速度

#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++)

;

}

/*************************************************

函数功能:流水点亮P08LED

*************************************************/

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:用指针作函数参数控制P08LED流水点亮

#include<reg51.h>

223/192


/*************************************************

函数功能:延时约150ms

*************************************************/

voiddelay(void)

{

unsignedcharm,n;

for(m=0;m<200;m++)

for(n=0;n<250;n++)

;

}

/*************************************************

函数功能:流水点亮P08LED

*************************************************/

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++)

;

}

/**************************************************************

函数功能:流水点亮P08LED

**************************************************************/

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;


//带参数的宏定义,ab为形参


}


P3=F(i,j+k);

while(1)

;


//ij+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查询方式P28位控制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计数的结果送P18LED显示

#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;//计数器TL01后送P1口显示

//计数器溢出后,将TF00


 

//实例45:用定时器T0的中断控制1LED闪烁

#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;  //Countor0,重新从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;   //Countor10,重新从0开始计数

}

if(Countor2==8)   //若累计满8次,即计时满400ms

{

D2=~D2;      //按位取反操作,将P2.1引脚输出电平取反

Countor2=0;   //Countor10,重新从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的模式113位计数器)

while(1)         //无限循环

{

i=0;   //从第1个音符f[0]开始播放

while(f[i]!=0xff)               //只要没有读到结束标志就继续播放

{

C=460830/f[i];

TH0=(8192-C)/32;    //可证明这是13位计数器TH08位的赋

初值方法

TL0=(8192-C)%32;    //可证明这是13位计数器TL05位的赋初

值方法

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位计数器TH08位的赋初值方法

TL0=(8192-C)%32;    //可证明这是13位计数器TL05位的赋初值方法

}


 


//


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;         //计数器T08位赋初值

TL0=0;         //计数器T08位赋初值

while(1)  //无限循环,不停地将TL0计数结果送P1

P1=TL0;

}


 

//实例51-2:定时器T0的模式2测量正脉冲宽度

#include<reg51.h>    //包含51单片机寄存器定义的头文件

sbitui=P3^2;   //ui位定义为P3.0INT0)引脚,表示输入电压

/*******************************************

函数功能:主函数

******************************************/

voidmain(void)

{

TMOD=0x0a;    //TMOD=00001010B,使用定时器T0的模式2GATE1

EA=1;           //开总中断

440/192


ET0=0;

TR0=1;

TH0=0;

TL0=0;

while(1)

{

while(ui==0)

;

TL0=0;


//不使用定时器T0的中断

//启动T0

//计数器T08位赋初值

//计数器T08位赋初值

//无限循环,不停地将TL0计数结果送P1

//INT0为低电平,T0不能启动

//INT0为高电平,启动T0计时,所以将TL00


 


}


}


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信号,对74LS1640

_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;      //为了接收下一帧数据,需将RI0

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,

//SM20,不使用多机通信,TB80

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;      //为了接收下一帧数据,需将RI0

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;      //为了接收下一帧数据,需将RI0

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};

//数码管显示09的段码表,程序运行中当数组值不发生变化

时,

//前面加关键字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};

//数码管显示09的段码表

/********************************************************************

***

函数功能:快速动态扫描延时,延时约0.9毫秒

*********************************************************************

***/

voiddelay(void)

{

unsignedinti;

for(i=0;i<300;i++)

;

}

/********************************************************************

***

函数功能:4位数的数码显示器显示

入口参数:k

出口参数:无

*********************************************************************

***/

voiddisplay(unsignedintk)

{

P2=0xfe;   //P2=11111110BP2.0引脚输出低电平,数码显示器DS0

通电源

P0=Tab[k/1000];          //显示千位

delay();

P2=0xfd;   //P2=11111101BP2.1引脚输出低电平,数码显示器DS1接通

电源

P0=Tab[(k%1000)/100];            //显示百位

delay();

P2=0xfb;   //P2=11111011BP2.2引脚输出低电平,数码显示器DS2接通

电源

P0=Tab[(k%100)/10];   //显示十位

delay();

P2=0xf7;   //P2=11110111BP2.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;      //随机产生一个从032767的整数,再将其除以10

获得一个随机4位数,模拟检测结果

i=0;                //i0,重新统计中断次数

}

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};

//数码管显示09的段码表

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引脚取反


 

//实例71CPU控制的独立式键盘扫描实验

#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;     //关闭8LED

}

/*************************************************

函数功能:闪烁点亮LED

**************************************************/

voidflash(void)

{

P3=0xff;        //关闭8LED

led_delay();

P3=0x00;       //点亮8LED

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;            //位定义S1P1.4

sbitS2=P1^5;            //位定义S2P1.5

sbitS3=P1^6;            //位定义S3P1.6

sbitS4=P1^7;            //位定义S4P1.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;            //位定义S1P1.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位计数器TH08位的赋初值方法

TL0=(8192-C)%32;      //可证明这是13位计数器TL05位的赋初值方法

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的模式1T0的模式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位计数器TH08位的赋初值

方法

TL0=(8192-C)%32;      //可证明这是13位计数器TL05位的赋初值方

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();

}

/*****************************************************

函数功能:判断液晶模块的忙碌状态

返回值:resultresult=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;                      //根据规定,RSR/W同时为低电平时,可以写

入指令

RW=0;

E=0;                       //E置低电平(根据表8-6,写指令时,E为高脉冲,

//  就是让E01发生正跳变,所以应先置

"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为高脉冲,

//  就是让E01发生正跳变,所以应先置"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


/*****************************************************

函数功能:判断液晶模块的忙碌状态

返回值:resultresult=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;                      //根据规定,RSR/W同时为低电平时,可以写

入指令

RW=0;

E=0;                       //E置低电平(根据表8-6,写指令时,E为高脉冲,

//  就是让E01发生正跳变,所以应先置

"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为高脉冲,

//  就是让E01发生正跳变,所以应先置"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();

}

/*****************************************************

函数功能:判断液晶模块的忙碌状态

返回值:resultresult=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;                      //根据规定,RSR/W同时为低电平时,可以写

入指令

RW=0;

E=0;                       //E置低电平(根据表8-6,写指令时,E为高脉冲,

//  就是让E01发生正跳变,所以应先置

"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为高脉冲,

//  就是让E01发生正跳变,所以应先置"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();

}

/*****************************************************

函数功能:判断液晶模块的忙碌状态

返回值:resultresult=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;                      //根据规定,RSR/W同时为低电平时,可以写

入指令

RW=0;

E=0;                       //E置低电平(根据表8-6,写指令时,E为高脉冲,

//  就是让E01发生正跳变,所以应先置"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为高脉冲,

//  就是让E01发生正跳变,所以应先置"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;


//定时器T08位重新赋初值

//定时器T08位重新赋初值


 

/********************************************************

***********一些芯片的使用*****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


*********************************************************************

***********/

/*****************************************************

函数功能:判断液晶模块的忙碌状态

返回值:resultresult=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;                      //根据规定,RSR/W同时为低电平时,可以写

入指令

RW=0;

E=0;                       //E置低电平(根据表8-6,写指令时,E为高脉冲,

//  就是让E01发生正跳变,所以应先置

"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为高脉冲,

//  就是让E01发生正跳变,所以应先置"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方波

***************************************************/

voidTime0(void)interrupt1using1

{

TH0=(65536-46083)/256;

TL0=(65536-46083)%256;

flag=!flag;

}


 

//实例89:将"渴望"乐谱写入AT24C02并读出播放

#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引脚

sbitsound=P3^7;             //sound位定义为P3.7,从该引脚输出音频

unsignedintC;               //储存定时器的定时常数

//以下是C调低音的音频宏定义

#definel_dao262    //将“l_dao”宏定义为低音“1”的频率262Hz

#definel_re286     //将“l_re”宏定义为低音“2”的频率286Hz

137/192


#definel_mi311

#definel_fa349

#definel_sao392

#definel_la440

#definel_xi494


//将“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”的频率523Hz

//以下是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

/*******************************************

函数功能:节拍的延时的基本单位,延时200ms

******************************************/

voiddelay()

{

unsignedchari,j;

for(i=0;i<250;i++)

for(j=0;j<250;j++)

;

}

/********************************************************************

******

以下是对AT24C02进行读写操作的源程序

*********************************************************************

****/

/*****************************************************

函数功能:延时1ms

(3j+2)*i=(3×33+2)×10=1010(微秒),可以认为是1毫秒

***************************************************/

voiddelay1ms()

{

unsignedchari,j;

138/192


}


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_();    //等待一个机器周期

SCL=0;      //SCL为低电平时,SDA上数据才允许变化(即允许以后的数据传

)

}

/***************************************************

函数功能:结束数据传送

***************************************************/

voidstop()

{

SDA=0;      //SDA初始化为低电平"0"

_nop_();      //等待一个机器周期

_nop_();      //等待一个机器周期

SCL=1;       //结束数据传送时,要求SCL为高电平"1"

_nop_();      //等待一个机器周期

_nop_();      //等待一个机器周期

_nop_();      //等待一个机器周期

_nop_();      //等待一个机器周期

139/192


}


SDA=1;


//SDA的上升沿被认为是结束信号


/***************************************************

函数功能:从AT24Cxx读取数据

出口参数:x

***************************************************/

unsignedcharReadData()

{

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中的各二进位向左移一位

}

SDA=1;//  发送设备(主机)应在时钟脉冲的高电平期间(SCL=1)释放SDA线,

//以让SDA线转由接收设备(AT24Cxx)控制

_nop_();      //等待一个机器周期

_nop_();      //等待一个机器周期

140/192


SCL=1;

_nop_();

_nop_();

_nop_();

_nop_();


//根据上述规定,SCL应为高电平

//等待一个机器周期

//等待一个机器周期

//等待一个机器周期

//等待一个机器周期


)

}


ack_bit=SDA;//接受设备(AT24Cxx)SDA送低电平,表示已经接收到一个字

//若送高电平,表示没有接收到,传送异常

SCL=0;       //SCL为低电平时,SDA上数据才允许变化(即允许以后的数据传

return  ack_bit;//返回AT24Cxx应答位


/***************************************************

函数功能:向AT24Cxx中的指定地址写入数据

入口参数:add(储存指定的地址);dat(储存待写入的数据)

***************************************************/

voidWriteSet(unsignedcharadd,unsignedchardat)

{

start();                       //开始数据传递

WriteCurrent(OP_WRITE);   //选择要操作的AT24Cxx芯片,并告知要对其写入

数据

WriteCurrent(add);          //写入指定地址

WriteCurrent(dat);          //向当前地址(上面指定的地址)写入数据

stop();                      //停止数据传递

delaynms(4);                //1个字节的写入周期为1ms,最好延时1ms

}

/***************************************************

函数功能:从AT24Cxx中的当前地址读取数据

出口参数:x(储存读出的数据)

***************************************************/

unsignedcharReadCurrent()

{

unsignedcharx;

start();                       //开始数据传递

WriteCurrent(OP_READ);    //