51单片机C语言程序100例

本文档详细介绍了使用单片机进行多种控制实验的方法,包括灯的亮灭、闪烁及各种逻辑运算显示等基本操作,同时还涉及了利用定时器、键盘扫描等高级应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

目录

目录................................................................................................................................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);    //选择要操作的AT24Cxx芯片,并告知要读其数据

x=ReadData();               //将读取的数据存入x

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

returnx;                       //返回读取的数据

}

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

函数功能:从AT24Cxx中的指定地址读取数据

入口参数:set_addr

出口参数:x

141/192


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

unsignedcharReadSet(unsignedcharset_addr)

{

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

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

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

return(ReadCurrent());    //从指定地址读出数据并返回

}

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

函数功能:主函数

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

main(void)

{

unsignedchari,j;

unsignedchartemp;    //储存压缩后的音频

unsignedcharJi;      //储存音符节拍

unsignedchar   N;    //储存音符的最大个数以在AT24C02中为音符和节拍分

配存储空间

unsignedintfr;      //储存解压缩后的音频

//以下是《渴望》片头曲的一段简谱

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,

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,

0x00};   //以频率0x00作为简谱的结束标

//以下是简谱中每个音符的节拍

unsignedcharcodeJP[]={4,1,1,4,1,1,2,

2,2,2,2,8,

142/192


EA=1;


//开总中断


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

};


ET0=1;

TMOD=0x00;

SDA=1;

SCL=1;

while(1)

{

i=0;


//定时器T0中断允许

//  使用定时器T0的模式113位计数器)

//SDA=1,SCL=1,使主从设备处于空闲状态

//无限循环

//从第1个音符频率f[0]开始写入AT24C02



while(f[i]!=0x01)

{


//只要没有读到结束标志就继续写


的音频


temp=(unsignedchar)(f[i]/8);//将音频压缩为较小的字符变

WriteSet(0x00+i,temp);         //在指定地址写入数据压缩后

i++;                              //指向下一个音符音频

}

N=i;      //将音符的最大个数存于N

i=0;       //从第一个音符节拍JP[0]开始写入AT24C02

while(f[i]!=0x00)

{

WriteSet(0x00+N+i,JP[i]);   //在指定地址写入音符的节拍

i++;                            //指向下一个音符音频

}

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

{

temp=ReadSet(0x00+i);   //读出音频

143/192


位的赋初值方法

位的赋初值方法


Ji=ReadSet(0x00+N+i);

fr=8*temp;

C=460830/fr;

TH0=(8192-C)/32;

TL0=(8192-C)%32;

TR0=1;


//读出节拍

//将音频解压

//定时常数的计算公式

//可证明这是13位计数器TH08

//可证明这是13位计数器TL05

//启动定时器T0


}


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

delay();

TR0=0;


//控制节拍数

//延时1个节拍单位

//关闭定时器T0


播放

}


}


sound=1;

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

delay();


//播放完毕后,关闭蜂鸣器

//播放完毕后,停顿一段时间后继续


 

/

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

函数功能:定时器T0的中断服务子程序,使P3.7引脚输出音频的方波

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

voidTime0(void)interrupt1using1

{

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

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

sound=!sound;      //P3.7引脚输出电平取反,形成方波

}


 


//


90


DS18B20


//实例90DS18B20温度检测及其液晶显示

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

#include<intrins.h>   //包含_nop_()函数定义的头文件

unsignedcharcodedigit[10]={"0123456789"};      //定义字符数组显示数字

unsignedcharcodeStr[]={"TestbyDS18B20"};     //说明显示的是温度

144/192


unsignedcharcodeError[]={"Error!Check!"};

unsignedcharcodeTemp[]={"Temp:"};

unsignedcharcodeCent[]={"Cent"};


//说明没有检测到DS18B20

//说明显示的是温度

//温度单位


 

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

***********

以下是对液晶模块的操作程序

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

**********/

sbitRS=P2^0;              //寄存器选择位,将RS位定义为P2.0引脚

sbitRW=P2^1;              //读写选择位,将RW位定义为P2.1引脚

sbitE=P2^2;               //使能信号位,将E位定义为P2.2引脚

sbitBF=P0^7;              //忙碌标志位,,将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

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

voiddelaynms(unsignedcharn)

{

unsignedchari;

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

delay1ms();

}

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

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

返回值:resultresult=1,忙碌;result=0,不忙

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

bitBusyTest(void)

{

bitresult;

RS=0;         //根据规定,RS为低电平,RW为高电平时,可以读状态

RW=1;

E=1;          //E=1,才允许读写

_nop_();   //空操作

145/192


}


_nop_();

_nop_();

_nop_();

result=BF;

E=0;

returnresult;


//空操作四个机器周期,给硬件反应时间

//将忙碌标志电平赋给result

//E恢复低电平


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

函数功能:将模式设置指令或显示地址写入液晶模块

入口参数: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)写入液晶模块

146/192


入口参数: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

数据接口

delaynms(5);                   //延时5ms   ,给硬件一点反应时间

WriteInstruction(0x38);

delaynms(5);                  //延时5ms   ,给硬件一点反应时间

WriteInstruction(0x38);      //连续三次,确保初始化成功

delaynms(5);                  //延时5ms   ,给硬件一点反应时间

WriteInstruction(0x0c);      //显示模式设置:显示开,无光标,光标不闪烁

delaynms(5);                  //延时5ms   ,给硬件一点反应时间

WriteInstruction(0x06);      //显示模式设置:光标右移,字符不移

delaynms(5);                   //延时5ms   ,给硬件一点反应时间

WriteInstruction(0x01);      //清屏幕指令,将以前的显示内容清除

delaynms(5);                //延时5ms   ,给硬件一点反应时间

}


 


147


/


192


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

****

以下是DS18B20的操作程序

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

***/

sbitDQ=P3^3;

unsignedchartime;    //设置全局变量,专门用于严格延时

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

函数功能:将DS18B20传感器初始化,读取应答信号

出口参数:flag

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

bitInit_DS18B20(void)

{

bitflag;           //储存DS18B20是否存在的标志,flag=0,表示存在;flag=1

表示不存在

DQ=1;             //先将数据线拉高

for(time=0;time<2;time++)//略微延时约6微秒

;

DQ=0;             //再将数据线从高拉低,要求保持480~960us

for(time=0;time<200;time++)   //略微延时约600微秒

;          //以向DS18B20发出一持续480~960us的低电平复位脉冲

DQ=1;             //释放数据线(将数据线拉高)

for(time=0;time<10;time++)

;   //延时约30us(释放总线后需等待15~60usDS18B20输出存在脉冲)

flag=DQ;            //让单片机检测是否输出了存在脉冲(DQ=0表示存在)

for(time=0;time<200;time++)   //延时足够长时间,等待存在脉冲输出完毕

;

return(flag);     //返回检测成功标志

}

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

函数功能:从DS18B20读取一个字节数据

出口参数:dat

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

unsignedcharReadOneChar(void)

{

unsignedchari=0;

unsignedchardat;   //储存读出的一个字节数据

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

{

DQ=1;         //先将数据线拉高

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


 


148


/


192


动读时序

平作准备


DQ=0;

dat>>=1;

_nop_();

DQ=1;


//单片机从DS18B20读书据时,将数据线从高拉低即启

//等待一个机器周期

//将数据线"人为"拉高,为单片机检测DS18B20的输出电


 


复期


}


for(time=0;time<2;time++)

;      //延时约6us,使主机在15us内采样

if(DQ==1)

dat|=0x80;  //如果读到的数据是1,则将1存入dat

else

dat|=0x00;//如果读到的数据是0,则将0存入dat

//将单片机检测到的电平信号DQ存入r[i]

for(time=0;time<8;time++)

;                 //延时3us,两个读时序之间必须有大于1us的恢


}


return(dat);


//返回读出的十进制数据


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

函数功能:向DS18B20写入一个字节数据

入口参数:dat

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

WriteOneChar(unsignedchardat)

{

unsignedchari=0;

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

{

DQ=1;           //先将数据线拉高

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

DQ=0;            //将数据线从高拉低时即启动写时序

DQ=dat&0x01;    //利用与运算取出要写的某位二进制数据,

//并将其送到数据线上等待DS18B20采样

for(time=0;time<10;time++)

;//延时约30usDS18B20在拉低后的约15~60us期间从数据线上采

DQ=1;            //释放数据线

for(time=0;time<1;time++)

;//延时3us,两个写时序间至少需要1us的恢复期

dat>>=1;         //dat中的各二进制位数据右移1

}

for(time=0;time<4;time++)

;//稍作延时,给硬件一点反应时间

}

149/192


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

**********

以下是与温度有关的显示设置

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

*********/

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

函数功能:显示没有检测到DS18B20

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

voiddisplay_error(void)

{

unsignedchari;

WriteAddress(0x00);     //写显示地址,将在第1行第1列开始显

i=0;                   //从第一个字符开始显示

while(Error[i]!='\0')   //只要没有写到结束标志,就继续写

{

WriteData(Error[i]);    //将字符常量写入LCD

i++;                     //指向下一个字符

delaynms(100);          //延时100ms较长时间,以看清关于

显示的说明

}

while(1)                 //进入死循环,等待查明原因

;

}

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

函数功能:显示说明信息

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

voiddisplay_explain(void)

{

unsignedchari;

WriteAddress(0x00);     //写显示地址,将在第1行第1列开始显

i=0;                   //从第一个字符开始显示

while(Str[i]!='\0')   //只要没有写到结束标志,就继续写

{

WriteData(Str[i]);    //将字符常量写入LCD

i++;                     //指向下一个字符

delaynms(100);          //延时100ms较长时间,以看清关于

显示的说明

}

}

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

函数功能:显示温度符号

150/192


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

voiddisplay_symbol(void)

{

unsignedchari;

WriteAddress(0x40);     //写显示地址,将在第2行第1列开始显

i=0;                   //从第一个字符开始显示

while(Temp[i]!='\0')   //只要没有写到结束标志,就继续写

{

WriteData(Temp[i]);    //将字符常量写入LCD

i++;                     //指向下一个字符

delaynms(50);          //延时1ms给硬件一点反应时间

}

}

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

函数功能:显示温度的小数点

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

void    display_dot(void)

{

WriteAddress(0x49);       //写显示地址,将在第2行第10列开始显示

WriteData('.');       //将小数点的字符常量写入LCD

delaynms(50);           //延时1ms给硬件一点反应时间

}

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

函数功能:显示温度的单位(Cent)

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

void    display_cent(void)

{

unsignedchari;

WriteAddress(0x4c);          //写显示地址,将在第2行第13列开

始显示

i=0;                        //从第一个字符开始显示

while(Cent[i]!='\0')      //只要没有写到结束标志,就继续写

{

WriteData(Cent[i]);      //将字符常量写入LCD

i++;                     //指向下一个字符

delaynms(50);          //延时1ms给硬件一点反应时间

}

}

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

函数功能:显示温度的整数部分

入口参数:x

151/192


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

voiddisplay_temp1(unsignedcharx)

{

unsignedcharj,k,l;      //j,k,l分别储存温度的百位、十位和个位

j=x/100;                 //取百位

k=(x%100)/10;     //取十位

l=x%10;                //取个位

WriteAddress(0x46);     //写显示地址,将在第2行第7列开始显示

WriteData(digit[j]);     //将百位数字的字符常量写入LCD

WriteData(digit[k]);     //将十位数字的字符常量写入LCD

WriteData(digit[l]);     //将个位数字的字符常量写入LCD

delaynms(50);           //延时1ms给硬件一点反应时间

}

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

函数功能:显示温度的小数数部分

入口参数:x

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

voiddisplay_temp2(unsignedcharx)

{

WriteAddress(0x4a);       //写显示地址,将在第2行第11列开始显示

WriteData(digit[x]);      //将小数部分的第一位数字字符常量写入LCD

delaynms(50);            //延时1ms给硬件一点反应时间

}

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

函数功能:做好读温度的准备

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

voidReadyReadTemp(void)

{

Init_DS18B20();      //DS18B20初始化

WriteOneChar(0xCC);//  跳过读序号列号的操作

WriteOneChar(0x44);//  启动温度转换

for(time=0;time<100;time++)

;   //温度转换需要一点时间

Init_DS18B20();      //DS18B20初始化

WriteOneChar(0xCC);//跳过读序号列号的操作

WriteOneChar(0xBE);//读取温度寄存器,前两个分别是温度的低位和高位

}


 

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

函数功能:主函数

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


 


152


/


192


voidmain(void)

{

unsignedcharTL;

unsignedcharTH;

unsignedcharTN;

unsignedcharTD;

LcdInitiate();

delaynms(5);


//储存暂存器的温度低位

//储存暂存器的温度高位

//储存温度的整数部分

//储存温度的小数部分

//将液晶初始化

//延时5ms给硬件一点反应时间


 

if(Init_DS18B20()==1)

display_error();

display_explain();

display_symbol();     //显示温度说明

display_dot();         //显示温度的小数点

display_cent();       //显示温度的单位

while(1)                   //不断检测并显示温度

{

ReadyReadTemp();      //读温度准备

TL=ReadOneChar();     //先读的是温度值低位

TH=ReadOneChar();     //接着读的是温度值高位

TN=TH*16+TL/16;       //实际温度值=(TH*256+TL)/16,即:TH*16+TL/16

//这样得出的是温度的整数部分,小数部分被丢

弃了

TD=(TL%16)*10/16;     //计算温度的小数部分,将余数乘以10再除以16

取整,

//这样得到的是温度小数部分的第一位数字(

1位小数)

display_temp1(TN);     //显示温度的整数部分

display_temp2(TD);     //显示温度的小数部分

delaynms(10);

}

}


 

//实例91:将数据"0xaa"写入X5045再读出送P1口显示

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

#include<intrins.h>   //包含_nop_()函数定义的头文件

sbitSCK=P3^4;         //SCK位定义为P3.4引脚

sbitSI=P3^5;          //SI位定义为P3.5引脚

sbitSO=P3^6;          //SO位定义为P3.6引脚

sbitCS=P3^7;          //SCK位定义为P3.7引脚

#defineWREN0x06     //写使能锁存器允许

153/192


#defineWRDI0x04

#defineWRSR0x01

#defineREAD0x03

#defineWRITE0x02


//写使能锁存器禁止

//写状态寄存器

//读出

//写入


 

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

函数功能:延时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();

}

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

函数功能:从X5045的当前地址读出数据

出口参数:x

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

unsignedcharReadCurrent(void)

{

unsignedchari;

unsignedcharx=0x00;       //储存从X5045中读出的数据

SCK=1;                         //SCK置于已知的高电平状态

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

{

SCK=1;                     //拉高SCK

SCK=0;                     //SCK的下降沿输出数据

x<<=1;   //x中的各二进位向左移一位,因为首先读出的是字节的最高

位数据

x|=(unsignedchar)SO;   //SO上的数据通过按位“或“运算存入x

}

return(x);    //将读取的数据返回

}

154/192


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

函数功能:写数据到X5045的当前地址

入口参数:dat

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

voidWriteCurrent(unsignedchardat)

{

unsignedchari;

SCK=0;                     //SCK置于已知的低电平状态

for(i=0;i<8;i++)   //循环移入8个位

{

SI=(bit)(dat&0x80);    //通过按位“与”运算将最高位数据送到S

//因为传送时高位在前,低位在后

SCK=0;

SCK=1;                  //SCK上升沿写入数据

dat<<=1;    //y中的各二进位向左移一位,因为首先写入的是字节的最高

}

}

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

函数功能:写状态寄存器,可以设置看门狗的溢出时间及数据保护

入口参数:rs;   //储存寄存器状态值

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

voidWriteSR(unsignedcharrs)

{

CS=0;                     //拉低CS,选中X5045

WriteCurrent(WREN);    //写使能锁存器允许

CS=1;                     //拉高CS

CS=0;                     //重新拉低CS,否则下面的写寄存器状态指令将被

丢弃

WriteCurrent(WRSR);    //写状态寄存器

WriteCurrent(rs);      //写入新设定的寄存器状态值

CS=1;                     //拉高CS

}

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

函数功能:写数据到X5045的指定地址

入口参数:addr

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

voidWriteSet(unsignedchardat,unsignedcharaddr)

{

SCK=0;                     //SCK置于已知状态

CS=0;                      //拉低CS,选中X5045

WriteCurrent(WREN);     //写使能锁存器允许

155/192


}


CS=1;

CS=0;

WriteCurrent(WRITE);

WriteCurrent(addr);

WriteCurrent(dat);

CS=1;

SCK=0;


//拉高CS

//重新拉低CS,否则下面的写入指令将被丢弃

//写入指令

//写入指定地址

//写入数据

//拉高CS

//SCK置于已知状态


 

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

函数功能:从X5045的指定地址读出数据

入口参数:addr

出口参数:dat

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

unsignedcharReadSet(unsignedcharaddr)

{

unsignedchardat;

SCK=0;                     //SCK置于已知状态

CS=0;                      //拉低CS,选中X5045

WriteCurrent(READ);    //开始读

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

dat=ReadCurrent();     //读出数据

CS=1;                     //拉高CS

SCK=0;                   //SCK置于已知状态

returndat;             //返回读出的数据

}

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

函数功能:看门狗复位程序

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

voidWatchDog(void)

{

CS=1;    //拉高CS

CS=0;    //CS引脚的一个下降沿复位看门狗定时器

CS=1;    //拉高CS

}

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

函数功能:主程序

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

voidmain(void)

{

WriteSR(0x12);          //写状态寄存器(设定看门狗溢出时间为600ms,写不

保护)

delaynms(10);           //X5045的写入周期约为10ms

156/192


}


while(1)

{

WriteSet(0xaa,0x10);

delaynms(10);

P1=ReadSet(0x10);

WatchDog();

}


//将数据“0xaa”写入指定地址“0x10

//X5045的写入周期约为10ms

//将数据读出送P1口显示

//复位看门狗


 


//


92


X5045


P1


//实例92:将流水灯控制码写入X5045并读出送P1口显示

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

#include<intrins.h>   //包含_nop_()函数定义的头文件

sbitSCK=P3^4;         //SCK位定义为P3.4引脚

sbitSI=P3^5;          //SI位定义为P3.5引脚

sbitSO=P3^6;          //SO位定义为P3.6引脚

sbitCS=P3^7;          //SCK位定义为P3.7引脚

#defineWREN0x06     //写使能锁存器允许

#defineWRDI0x04     //写使能锁存器禁止

#defineWRSR0x01     //写状态寄存器

#defineREAD0x03     //读出

#defineWRITE0x02    //写入

unsignedcharlamp[]={0xFF,0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F,

0x7F,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0xFE,0xFF,

0xFF,0xFE,0xFC,0xFB,0xF0,0xE0,0xC0,0x80,0x00,

0xE7,0xDB,0xBD,0x7E,0xFF,0xFF,0x3C,0x18,0x00,

0x81,0xC3,0xE7,0xFF,0xFF,0x7E,0xBD,0xDB,0xE7,

0xBD,0xDB,0x7E,0xFF,0xAA};     //流水灯控制码

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

函数功能:延时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++)

;

}

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

函数功能:延时若干毫秒

157/192


入口参数:n

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

voiddelaynms(unsignedcharn)

{

unsignedchari;

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

delay1ms();

}

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

函数功能:从X5045的当前地址读出数据

出口参数:x

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

unsignedcharReadCurrent(void)

{

unsignedchari;

unsignedcharx=0x00;       //储存从X5045中读出的数据

SCK=1;                         //SCK置于已知的高电平状态

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

{

SCK=1;                     //拉高SCK

SCK=0;                     //SCK的下降沿输出数据

x<<=1;   //x中的各二进位向左移一位,因为首先读出的是字节的最高

位数据

x|=(unsignedchar)SO;   //SO上的数据通过按位“或“运算存入x

}

return(x);    //将读取的数据返回

}

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

函数功能:写数据到X5045的当前地址

入口参数:dat

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

voidWriteCurrent(unsignedchardat)

{

unsignedchari;

SCK=0;                     //SCK置于已知的低电平状态

for(i=0;i<8;i++)   //循环移入8个位

{

SI=(bit)(dat&0x80);    //通过按位“与”运算将最高位数据送到S

//因为传送时高位在前,低位在后

SCK=0;

SCK=1;                  //SCK上升沿写入数据

dat<<=1;    //y中的各二进位向左移一位,因为首先写入的是字节的最高

}

158/192


}

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

函数功能:写状态寄存器,可以设置看门狗的溢出时间及数据保护

入口参数:rs;   //储存寄存器状态值

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

voidWriteSR(unsignedcharrs)

{

CS=0;                     //拉低CS,选中X5045

WriteCurrent(WREN);    //写使能锁存器允许

CS=1;                     //拉高CS

CS=0;                     //重新拉低CS,否则下面的写寄存器状态指令将被

丢弃

WriteCurrent(WRSR);    //写状态寄存器

WriteCurrent(rs);      //写入新设定的寄存器状态值

CS=1;                     //拉高CS

}

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

函数功能:写数据到X5045的指定地址

入口参数:addr

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

voidWriteSet(unsignedchardat,unsignedcharaddr)

{

SCK=0;                     //SCK置于已知状态

CS=0;                      //拉低CS,选中X5045

WriteCurrent(WREN);     //写使能锁存器允许

CS=1;                      //拉高CS

CS=0;                      //重新拉低CS,否则下面的写入指令将被丢弃

WriteCurrent(WRITE);    //写入指令

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

WriteCurrent(dat);      //写入数据

CS=1;                      //拉高CS

SCK=0;                     //SCK置于已知状态

}

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

函数功能:从X5045的指定地址读出数据

入口参数:addr

出口参数:dat

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

unsignedcharReadSet(unsignedcharaddr)

{

unsignedchardat;

159/192


SCK=0;

CS=0;

WriteCurrent(READ);

WriteCurrent(addr);

dat=ReadCurrent();

CS=1;

SCK=0;

returndat;

}


//SCK置于已知状态

//拉低CS,选中X5045

//开始读

//写入指定地址

//读出数据

//拉高CS

//SCK置于已知状态

//返回读出的数据


 

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

函数功能:看门狗复位程序

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

voidWatchDog(void)

{

CS=1;    //拉高CS

CS=0;    //CS引脚的一个下降沿复位看门狗定时器

CS=1;    //拉高CS

}

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

函数功能:主程序

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

voidmain(void)

{

unsignedchari;

WriteSR(0x12);          //写状态寄存器(设定看门狗溢出时间为600ms,写不保

护)

delaynms(10);           //X5045的写入周期约为10ms


 


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

{

WriteSet(lamp[i],0x00+i);


//将数据“0xaa”写入指定地址“0x10


}

while(1)

{


delaynms(10);


//X5045的写入周期约为10ms


}


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

{

P1=ReadSet(0x00+i);

delaynms(100);

WatchDog();

}


//将数据读出送P1口显示

160/192


}


 

//实例93:对SPI总线上挂接多个X5045的读写操作

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

#include<intrins.h>   //包含_nop_()函数定义的头文件

sbitSCK=P3^4;         //SCK位定义为P3.4引脚

sbitSI=P3^5;          //SI位定义为P3.5引脚

sbitSO=P3^6;          //SO位定义为P3.6引脚

sbitCS1=P3^7;          //CS定义为P3.7引脚

sbitCS2=P3^3;          //CS1位定义为P3.7引脚

#defineWREN0x06     //写使能锁存器允许

#defineWRDI0x04     //写使能锁存器禁止

#defineREAD0x03     //读出

#defineWRITE0x02    //写入

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

函数功能:延时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();

}

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

函数功能:从X5045的当前地址读出数据

出口参数:x

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

unsignedcharReadCurrent(void)

{

161/192


unsignedchari;

unsignedcharx=0x00;

SCK=1;

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

{

SCK=1;

SCK=0;


//储存从X5045中读出的数据

//SCK置于已知的高电平状态

//拉高SCK

//SCK的下降沿输出数据


x<<=1;

高位数据


//x中的各二进位向左移一位,因为首先读出的是字节的最



x

}


x|=(unsignedchar)SO;


//SO上的数据通过按位“或“运算存


}


return(x);


//将读取的数据返回


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

函数功能:写数据到X5045的当前地址

入口参数:dat

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

voidWriteCurrent(unsignedchardat)

{

unsignedchari;

SCK=0;                     //SCK置于已知的低电平状态

for(i=0;i<8;i++)   //循环移入8个位

{

SI=(bit)(dat&0x80);    //通过按位“与”运算将最高位数据送到S

//因为传送时高位在前,低位在后

SCK=0;

SCK=1;                  //SCK上升沿写入数据

dat<<=1;    //y中的各二进位向左移一位,因为首先写入的是字节的最高

}

}

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

函数功能:写数据到第一个X5045的指定地址

入口参数:addr

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

voidWriteSet1(unsignedchardat,unsignedcharaddr)

{

CS2=1;                     //使第二个X5045的片选无效

SCK=0;                     //SCK置于已知状态

CS1=0;                      //拉低CS,选中X5045

WriteCurrent(WREN);     //写使能锁存器允许

162/192


}


CS1=1;

CS1=0;

WriteCurrent(WRITE);

WriteCurrent(addr);

WriteCurrent(dat);

CS1=1;

SCK=0;


//拉高CS

//重新拉低CS,否则下面的写入指令将被丢弃

//写入指令

//写入指定地址

//写入数据

//拉高CS

//SCK置于已知状态


 

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

函数功能:写数据到第二个X5045的指定地址

入口参数:addr

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

voidWriteSet2(unsignedchardat,unsignedcharaddr)

{

CS1=1;                     //使第一个X5045的片选无效

SCK=0;                     //SCK置于已知状态

CS2=0;                      //拉低CS,选中X5045

WriteCurrent(WREN);     //写使能锁存器允许

CS2=1;                      //拉高CS

CS2=0;                      //重新拉低CS,否则下面的写入指令将被丢弃

WriteCurrent(WRITE);    //写入指令

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

WriteCurrent(dat);      //写入数据

CS2=1;                      //拉高CS

SCK=0;                     //SCK置于已知状态

}

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

函数功能:从第一个X5045的指定地址读出数据

入口参数:addr

出口参数:dat

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

unsignedcharReadSet1(unsignedcharaddr)

{

unsignedchardat;

CS2=1;                     //使第二个X5045的片选无效

SCK=0;                     //SCK置于已知状态

CS1=0;                      //拉低CS,选中X5045

WriteCurrent(READ);    //开始读

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

dat=ReadCurrent();     //读出数据

CS1=1;                     //拉高CS

SCK=0;                   //SCK置于已知状态

returndat;             //返回读出的数据

163/192


}

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

函数功能:从第二个X5045的指定地址读出数据

入口参数:addr

出口参数:dat

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

unsignedcharReadSet2(unsignedcharaddr)

{

unsignedchardat;

CS1=1;                     //使第一个X5045的片选无效

SCK=0;                     //SCK置于已知状态

CS2=0;                     //拉低CS,选中X5045

WriteCurrent(READ);    //开始读

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

dat=ReadCurrent();     //读出数据

CS2=1;                   //拉高CS

SCK=0;                   //SCK置于已知状态

returndat;             //返回读出的数据

}

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

函数功能:看门狗复位程序

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

voidWatchDog1(void)

{

CS1=1;    //拉高CS

CS1=0;    //CS引脚的一个下降沿复位看门狗定时器

CS1=1;    //拉高CS

}

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

函数功能:看门狗复位程序

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

voidWatchDog2(void)

{

CS2=1;    //拉高CS

CS2=0;    //CS引脚的一个下降沿复位看门狗定时器

CS2=1;    //拉高CS

}

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

函数功能:主程序

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

voidmain(void)

{

unsignedcharx;

164/192


while(1)

{

WriteSet1(0xf0,0x10);

址“0x10

delaynms(10);

x=ReadSet1(0x10);

WriteSet2(x,0x20);

delaynms(10);

P1=ReadSet2(0x20);

,送P1口显示

delaynms(100);

WatchDog1();

WatchDog2();

}

}


//将数据“0xaa”写入第一个X5045的指定地

//X5045的写入周期为约10ms

//将数据从第一个X5045中的指定地址读出来

//将数据x写入第二个X5045的指定地址“0x20

//X5045的写入周期为约10ms

//将数据从第二个X5045中的指定地址读出来

//延时100ms

//复位第一个X5045的看门狗

//复位第二个X5045的看门狗


 


//


94


ADC0832


//实例94:基于ADC0832的数字电压表

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

#include<intrins.h>   //包含_nop_()函数定义的头文件

sbitCS=P3^4;         //CS位定义为P3.4引脚

sbitCLK=P1^0;       //CLK位定义为P1.0引脚

sbitDIO=P1^1;         //DIO位定义为P1.1引脚

//

unsignedcharcodedigit[10]={"0123456789"};    //定义字符数组显示数字

unsignedcharcodeStr[]={"Volt="};               //说明显示的是电压

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

***********

以下是对液晶模块的操作程序

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

**********/

sbitRS=P2^0;              //寄存器选择位,将RS位定义为P2.0引脚

sbitRW=P2^1;              //读写选择位,将RW位定义为P2.1引脚

sbitE=P2^2;               //使能信号位,将E位定义为P2.2引脚

sbitBF=P0^7;              //忙碌标志位,,将BF位定义为P0.7引脚

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

函数功能:延时1ms

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

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

165/192


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

}

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

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

返回值:resultresult=1,忙碌;result=0,不忙

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

bitBusyTest(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同时为低电平时,可以写

入指令

166/192


RW=0;

E=0;

_nop_();

_nop_();

P0=dictate;

_nop_();

_nop_();

_nop_();

_nop_();

E=1;

_nop_();

_nop_();

_nop_();

_nop_();

E=0;

执行命令

}


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

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

//空操作两个机器周期,给硬件反应时间

//将数据送入P0口,即写入指令或地址

//空操作四个机器周期,给硬件反应时间

//E置高电平

//空操作四个机器周期,给硬件反应时间

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

167/192


}


_nop_();

_nop_();

_nop_();

E=0;


//空操作四个机器周期,给硬件反应时间

//E由高电平跳变成低电平时,液晶模块开始执行命令


 

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

函数功能:对LCD的显示模式进行初始化设置

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

voidLcdInitiate(void)

{

delaynms(15);                  //延时15ms,首次写指令时应给LCD一段较

长的反应时间

WriteInstruction(0x38);      //显示模式设置:16×2显示,5×7点阵,8

数据接口

delaynms(5);                   //延时5ms   ,给硬件一点反应时间

WriteInstruction(0x38);

delaynms(5);                  //延时5ms   ,给硬件一点反应时间

WriteInstruction(0x38);      //连续三次,确保初始化成功

delaynms(5);                  //延时5ms   ,给硬件一点反应时间

WriteInstruction(0x0c);      //显示模式设置:显示开,无光标,光标不闪烁

delaynms(5);                  //延时5ms   ,给硬件一点反应时间

WriteInstruction(0x06);      //显示模式设置:光标右移,字符不移

delaynms(5);                   //延时5ms   ,给硬件一点反应时间

WriteInstruction(0x01);      //清屏幕指令,将以前的显示内容清除

delaynms(5);                //延时5ms   ,给硬件一点反应时间

}

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

******

以下是电压显示的说明

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

*****/

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

函数功能:显示电压符号

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

voiddisplay_volt(void)

{

unsignedchari;

WriteAddress(0x03);     //写显示地址,将在第2行第1列开始显示

i=0;                   //从第一个字符开始显示

while(Str[i]!='\0')   //只要没有写到结束标志,就继续写

{

WriteData(Str[i]);    //将字符常量写入LCD

i++;                     //指向下一个字符

168/192


}


}


 

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

函数功能:显示电压的小数点

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

void    display_dot(void)

{

WriteAddress(0x09);       //写显示地址,将在第1行第10列开始显示

WriteData('.');         //将小数点的字符常量写入LCD

}

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

函数功能:显示电压的单位(V)

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

void    display_V(void)

{

WriteAddress(0x0c);//写显示地址,将在第2行第13列开始显示

WriteData('V');      //将字符常量写入LCD

}

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

函数功能:显示电压的整数部分

入口参数:x

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

voiddisplay1(unsignedcharx)

{

WriteAddress(0x08);     //写显示地址,将在第2行第7列开始显示

WriteData(digit[x]);     //将百位数字的字符常量写入LCD

}

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

函数功能:显示电压的小数数部分

入口参数:x

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

voiddisplay2(unsignedcharx)

{

unsignedchari,j;

i=x/10;               //取十位(小数点后第一位)

j=x%10;               //取个位(小数点后第二位)

WriteAddress(0x0a);       //写显示地址,将在第1行第11列开始显示

WriteData(digit[i]);      //将小数部分的第一位数字字符常量写入LCD

WriteData(digit[j]);      //将小数部分的第一位数字字符常量写入LCD

169/192


}

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

函数功能:将模拟信号转换成数字信号

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

unsignedchar   A_D()

{

unsignedchari,dat;

CS=1;   //一个转换周期开始

CLK=0;  //为第一个脉冲作准备

CS=0;  //CS0,片选有效

DIO=1;    //DIO1,规定的起始信号

CLK=1;   //第一个脉冲

CLK=0;   //第一个脉冲的下降沿,此前DIO必须是高电平

DIO=1;   //DIO1通道选择信号

CLK=1;   //第二个脉冲,第23个脉冲下沉之前,DI必须跟别输入两位数

据用于选择通道,这里选通道CH0

CLK=0;   //第二个脉冲下降沿

DIO=0;   //DI0,选择通道0

CLK=1;    //第三个脉冲

CLK=0;    //第三个脉冲下降沿

DIO=1;    //第三个脉冲下沉之后,输入端DIO失去作用,应置1

CLK=1;    //第四个脉冲

for(i=0;i<8;i++)   //高位在前

{

CLK=1;           //第四个脉冲

CLK=0;

dat<<=1;         //将下面储存的低位数据向右移

dat|=(unsignedchar)DIO;      //将输出数据DIO通过或运算储存在dat

低位

}

CS=1;            //片选无效

returndat;  //将读书的数据返回

}

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

函数功能:主函数

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

main(void)

{

unsignedintAD_val;     //储存A/D转换后的值

unsignedcharInt,Dec;    //分别储存转换后的整数部分与小数部分

LcdInitiate();           //将液晶初始化

delaynms(5);             //延时5ms给硬件一点反应时间

display_volt();          //显示温度说明

170/192


display_dot();

display_V();

while(1)

{

AD_val=A_D();

Int=(AD_val)/51;


//显示温度的小数点

//显示温度的单位

//进行A/D转换

//计算整数部分


 


Dec=(AD_val%51)*100/51;


//计算小数部分


}


}


display1(Int);

display2(Dec);

delaynms(250);


//显示整数部分

//显示小数部分

//延时250ms


 

//实例95:用DAC0832产生锯齿波电压

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

#include<absacc.h>      //包含对片外存储器地址进行操作的头文件

sbitCS=P2^7;            //CS位定义为P2.7引脚

sbitWR12=P3^6;          //WR12位定义为P3.6引脚

voidmain(void)

{

unsignedchari;

CS=0;    //输出低电平以选中DAC0832

WR12=0;  //输出低电平以选中DAC0832

while(1)

{

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

XBYTE[0x7fff]=i;      //将数据i送入片外地址07FFFH  ,实际上就是通过

P0口将数据送入DAC0832

}

}


 


//


96


P1


//实例96:用P1口显示红外遥控器的按键值

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

sbitIR=P3^2;             //IR位定义为P3.2引脚

unsignedchara[4];     //储存用户码、用户反码与键数据码、键数据反码

171/192


unsignedintLowTime,HighTime;//储存高、低电平的宽度

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

函数功能:对4个字节的用户码和键数据码进行解码

说明:解码正确,返回1,否则返回0

出口参数:dat

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

bitDeCode(void)

{

unsignedchar   i,j;

unsignedchartemp;     //储存解码出的数据

for(i=0;i<4;i++)        //连续读取4个用户码和键数据码

{

for(j=0;j<8;j++)   //每个码有8位数字

{

temp=temp>>1;   //temp中的各数据位右移一位,因为先读出的是

高位数据

TH0=0;           //定时器清0

TL0=0;           //定时器清0

TR0=1;           //开启定时器T0

while(IR==0)    //如果是低电平就等待

;         //低电平计时

TR0=0;           //关闭定时器T0

LowTime=TH0*256+TL0;     //保存低电平宽度

TH0=0;           //定时器清0

TL0=0;           //定时器清0

TR0=1;           //开启定时器T0

while(IR==1)    //如果是高电平就等待

;

TR0=0;          //关闭定时器T0

HighTime=TH0*256+TL0;    //保存高电平宽度

if((LowTime<370)||(LowTime>640))

return0;          //如果低电平长度不在合理范围,则认

为出错,停止解码

if((HighTime>420)&&(HighTime<620))    //如果高电平时间在560

微秒左右,即计数5601.085516

temp=temp&0x7f;         //(520-100=420,

520+100=620),则该位是0

if((HighTime>1300)&&(HighTime<1800))//如果高电平时间在1680

微秒左右,即计数16801.0851548

temp=temp|0x80;

//(1550-250=1300,1550+250=1800),则该位是1

}


 


172


/


192


}


a[i]=temp;


//将解码出的字节值储存在a[i]


}


if(a[2]=~a[3])

return1;


//验证键数据码和其反码是否相等,一般情况下不必验证用户码

//解码正确,返回1


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

函数功能:执行遥控功能

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

voidFunction(void)

{

P1=a[2];   //将按键数据码送P1口显示

}

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

函数功能:主函数

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

voidmain()

{

EA=1;          //开启总中断

EX0=1;         //开外中断0

ET0=1;         //定时器T0中断允许

IT0=1;         //外中断的下降沿触发

TMOD=0x01;    //使用定时器T0的模式1

TR0=0;         //定时器T0关闭

while(1)    //等待红外信号产生的中断

;

}

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

函数功能:红外线触发的外中断处理函数

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

voidInt0(void)interrupt0using0

{

EX0=0;       //关闭外中断0,不再接收二次红外信号的中断,只解码当前

红外信号

TH0=0;       //定时器T0的高8位清0

TL0=0;       //定时器T0的低8位清0

TR0=1;         //开启定时器T0

while(IR==0)            //如果是低电平就等待,给引导码低电平计时

;

TR0=0;                   //关闭定时器T0

LowTime=TH0*256+TL0;   //保存低电平时间

TH0=0;       //定时器T0的高8位清0

TL0=0;       //定时器T0的低8位清0

TR0=1;         //开启定时器T0

173/192


while(IR==1)

;

TR0=0;


//如果是高电平就等待,给引导码高电平计时

//关闭定时器T0


HighTime=TH0*256+TL0;


//保存引导码的高电平长度


 

if((LowTime>7800)&&(LowTime<8800)&&(HighTime>3600)&&(HighTime<4700))

{

//如果是引导码,就开始解码,否则放弃,引导码的低电平计时

//次数=9000us/1.085=8294,判断区间:830050078008300

5008800.

if(DeCode()==1)

Function();     //如果满足条件,执行遥控功能

}

EX0=1;   //开启外中断EX0

}


 

//实例97:用红外遥控器控制继电器

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

sbitIR=P3^2;             //IR位定义为P3.2引脚

unsignedchara[4];     //储存用户码、用户反码与键数据码、键数据反码

unsignedintLowTime,HighTime;//储存高、低电平的宽度

sbitRelay=P1^3;       //Relay位定义为P1.3引脚

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

函数功能:对4个字节的用户码和键数据码进行解码

说明:解码正确,返回1,否则返回0

出口参数:dat

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

bitDeCode(void)

{

unsignedchar   i,j;

unsignedchartemp;     //储存解码出的数据

for(i=0;i<4;i++)        //连续读取4个用户码和键数据码

{

for(j=0;j<8;j++)   //每个码有8位数字

{

temp=temp>>1;   //temp中的各数据位右移一位,因为先读出的是

高位数据

TH0=0;           //定时器清0

TL0=0;           //定时器清0

174/192


TR0=1;

while(IR==0)

;

TR0=0;


//开启定时器T0

//如果是低电平就等待

//低电平计时

//关闭定时器T0


 


LowTime=TH0*256+TL0;


//保存低电平宽度


TH0=0;

TL0=0;

TR0=1;

while(IR==1)

;

TR0=0;


//定时器清0

//定时器清0

//开启定时器T0

//如果是高电平就等待

//关闭定时器T0


 


HighTime=TH0*256+TL0;


//保存高电平宽度


if((LowTime<370)||(LowTime>640))

return0;          //如果低电平长度不在合理范围,则认

为出错,停止解码

if((HighTime>420)&&(HighTime<620))    //如果高电平时间在560

微秒左右,即计数5601.085516

temp=temp&0x7f;         //(520-100=420,

520+100=620),则该位是0

if((HighTime>1300)&&(HighTime<1800))//如果高电平时间在1680

微秒左右,即计数16801.0851548

temp=temp|0x80;

//(1550-250=1300,1550+250=1800),则该位是1

}

a[i]=temp;   //将解码出的字节值储存在a[i]

}

if(a[2]=~a[3])   //验证键数据码和其反码是否相等,一般情况下不必验证用户码

return1;      //解码正确,返回1

}

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

函数功能:执行遥控功能

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

voidFunction(void)

{

Relay=!Relay;    //P1.3引脚取反,控制继电器的吸合、释放

}

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

函数功能:主函数

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

voidmain()

{

EA=1;          //开启总中断

175/192


EX0=1;

ET0=1;

IT0=1;

TMOD=0x01;

TR0=0;


//开外中断0

//定时器T0中断允许

//外中断的下降沿触发

//使用定时器T0的模式1

//定时器T0关闭


}


while(1)

;


//等待红外信号产生的中断


 

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

函数功能:红外线触发的外中断处理函数

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

voidInt0(void)interrupt0using0

{

EX0=0;       //关闭外中断0,不再接收二次红外信号的中断,只解码当前

红外信号

TH0=0;       //定时器T0的高8位清0

TL0=0;       //定时器T0的低8位清0

TR0=1;         //开启定时器T0

while(IR==0)            //如果是低电平就等待,给引导码低电平计时

;

TR0=0;                   //关闭定时器T0

LowTime=TH0*256+TL0;   //保存低电平时间

TH0=0;       //定时器T0的高8位清0

TL0=0;       //定时器T0的低8位清0

TR0=1;         //开启定时器T0

while(IR==1)   //如果是高电平就等待,给引导码高电平计时

;

TR0=0;          //关闭定时器T0

HighTime=TH0*256+TL0;   //保存引导码的高电平长度

if((LowTime>7800)&&(LowTime<8800)&&(HighTime>3600)&&(HighTime<4700))

{

//如果是引导码,就开始解码,否则放弃,引导码的低电平计时

//次数=9000us/1.085=8294,判断区间:830050078008300

5008800.

if(DeCode()==1)

Function();     //如果满足条件,执行遥控功能

}

EX0=1;   //开启外中断EX0

}


 


176


/


192


//


98


DS1302


//实例98:基于DS1302的日历时钟

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

#include<intrins.h>    //包含_nop_()函数定义的头文件

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

***

以下是DS1302芯片的操作程序

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

***/

unsignedcharcodedigit[10]={"0123456789"};    //定义字符数组显示数字

sbitDATA=P1^1;    //位定义1302芯片的接口,数据输出端定义在P1.1引脚

sbitRST=P1^2;     //位定义1302芯片的接口,复位端口定义在P1.1引脚

sbitSCLK=P1^0;    //位定义1302芯片的接口,时钟输出端口定义在P1.1引脚

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

函数功能:延时若干微秒

入口参数:n

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

voiddelaynus(unsignedcharn)

{

unsignedchari;

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

;

}

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

函数功能:向1302写一个字节数据

入口参数:x

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

voidWrite1302(unsignedchardat)

{

unsignedchari;

SCLK=0;               //拉低SCLK,为脉冲上升沿写入数据做好准备

delaynus(2);         //稍微等待,使硬件做好准备

for(i=0;i<8;i++)        //连续写8个二进制位数据

{

DATA=dat&0x01;     //取出dat的第0位数据写入1302

delaynus(2);         //稍微等待,使硬件做好准备

SCLK=1;             //上升沿写入数据

delaynus(2);        //稍微等待,使硬件做好准备

SCLK=0;             //重新拉低SCLK,形成脉冲

dat>>=1;            //dat的各数据位右移1位,准备写入下一个数

据位

}

}

177/192


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

函数功能:根据命令字,向1302写一个字节数据

入口参数:Cmd,储存命令字;dat,储存待写的数据

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

voidWriteSet1302(unsignedcharCmd,unsignedchardat)

{

RST=0;             //禁止数据传递

SCLK=0;            //确保写数居前SCLK被拉低

RST=1;             //启动数据传输

delaynus(2);      //稍微等待,使硬件做好准备

Write1302(Cmd);   //写入命令字

Write1302(dat);   //写数据

SCLK=1;            //将时钟电平置于已知状态

RST=0;             //禁止数据传递

}

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

函数功能:从1302读一个字节数据

入口参数:x

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

unsignedcharRead1302(void)

{

unsignedchari,dat;

delaynus(2);         //稍微等待,使硬件做好准备

for(i=0;i<8;i++)    //连续读8个二进制位数据

{

dat>>=1;         //dat的各数据位右移1位,因为先读出的是字节的最

低位

if(DATA==1)     //如果读出的数据是1

dat|=0x80;     //1取出,写在dat的最高位

SCLK=1;         //SCLK置于高电平,为下降沿读出

delaynus(2);   //稍微等待

SCLK=0;         //拉低SCLK,形成脉冲下降沿

delaynus(2);   //稍微等待

}

returndat;          //将读出的数据返回

}

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

函数功能:根据命令字,从1302读取一个字节数据

入口参数:Cmd

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

unsignedchar   ReadSet1302(unsignedcharCmd)

{

unsignedchardat;

RST=0;                     //拉低RST

178/192


}


SCLK=0;

RST=1;

Write1302(Cmd);

dat=Read1302();

SCLK=1;

RST=0;

returndat;


//确保写数居前SCLK被拉低

//启动数据传输

//写入命令字

//读出数据

//将时钟电平置于已知状态

//禁止数据传递

//将读出的数据返回


 

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

函数功能:1302进行初始化设置

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

voidInit_DS1302(void)

{

WriteSet1302(0x8E,0x00);                     //根据写状态寄存器命令字,写

入不保护指令

WriteSet1302(0x80,((0/10)<<4|(0%10)));    //根据写秒寄存器命令字,写入秒

的初始值

WriteSet1302(0x82,((0/10)<<4|(0%10)));    //根据写分寄存器命令字,写入分

的初始值

WriteSet1302(0x84,((12/10)<<4|(12%10)));//根据写小时寄存器命令字,写入

小时的初始值

WriteSet1302(0x86,((16/10)<<4|(16%10)));//根据写日寄存器命令字,写入日

的初始值

WriteSet1302(0x88,((11/10)<<4|(11%10)));//根据写月寄存器命令字,写入月

的初始值

WriteSet1302(0x8c,((8/10)<<4|(8%10)));    //根据写小时寄存器命令字,写入

小时的初始值

}

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

***********

以下是对液晶模块的操作程序

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

**********/

sbitRS=P2^0;              //寄存器选择位,将RS位定义为P2.0引脚

sbitRW=P2^1;              //读写选择位,将RW位定义为P2.1引脚

sbitE=P2^2;               //使能信号位,将E位定义为P2.2引脚

sbitBF=P0^7;              //忙碌标志位,,将BF位定义为P0.7引脚

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

函数功能:延时1ms

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

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

voiddelay1ms()

{

unsignedchari,j;

179/192


}


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

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

;


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

函数功能:延时若干毫秒

入口参数:n

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

voiddelaynms(unsignedcharn)

{

unsignedchari;

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

delay1ms();

}

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

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

返回值:resultresult=1,忙碌;result=0,不忙

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

bitBusyTest(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"

180/192


_nop_();

_nop_();

P0=dictate;

_nop_();

_nop_();

_nop_();

_nop_();

E=1;

_nop_();

_nop_();

_nop_();

_nop_();

E=0;

执行命令

}


//空操作两个机器周期,给硬件反应时间

//将数据送入P0口,即写入指令或地址

//空操作四个机器周期,给硬件反应时间

//E置高电平

//空操作四个机器周期,给硬件反应时间

//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_();          //空操作四个机器周期,给硬件反应时间

181/192


}


E=0;


//E由高电平跳变成低电平时,液晶模块开始执行命令


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

函数功能:对LCD的显示模式进行初始化设置

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

voidLcdInitiate(void)

{

delaynms(15);                  //延时15ms,首次写指令时应给LCD一段较

长的反应时间

WriteInstruction(0x38);      //显示模式设置:16×2显示,5×7点阵,8

数据接口

delaynms(5);                   //延时5ms   ,给硬件一点反应时间

WriteInstruction(0x38);

delaynms(5);                  //延时5ms   ,给硬件一点反应时间

WriteInstruction(0x38);      //连续三次,确保初始化成功

delaynms(5);                  //延时5ms   ,给硬件一点反应时间

WriteInstruction(0x0c);      //显示模式设置:显示开,无光标,光标不闪烁

delaynms(5);                  //延时5ms   ,给硬件一点反应时间

WriteInstruction(0x06);      //显示模式设置:光标右移,字符不移

delaynms(5);                   //延时5ms   ,给硬件一点反应时间

WriteInstruction(0x01);      //清屏幕指令,将以前的显示内容清除

delaynms(5);                //延时5ms   ,给硬件一点反应时间

}

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

以下是1302数据的显示程序

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

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

函数功能:显示秒

入口参数:x

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

voidDisplaySecond(unsignedcharx)

{

unsignedchari,j;      //j,k,l分别储存温度的百位、十位和个位

i=x/10;//取十位

j=x%10;//取个位

WriteAddress(0x49);     //写显示地址,将在第2行第7列开始显示

WriteData(digit[i]);     //将百位数字的字符常量写入LCD

WriteData(digit[j]);     //将十位数字的字符常量写入LCD

delaynms(50);           //延时1ms给硬件一点反应时间

}

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

函数功能:显示分钟

182/192


入口参数:x

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

voidDisplayMinute(unsignedcharx)

{

unsignedchari,j;      //j,k,l分别储存温度的百位、十位和个位

i=x/10;//取十位

j=x%10;//取个位

WriteAddress(0x46);     //写显示地址,将在第2行第7列开始显示

WriteData(digit[i]);     //将百位数字的字符常量写入LCD

WriteData(digit[j]);     //将十位数字的字符常量写入LCD

delaynms(50);           //延时1ms给硬件一点反应时间

}

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

函数功能:显示小时

入口参数:x

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

voidDisplayHour(unsignedcharx)

{

unsignedchari,j;      //j,k,l分别储存温度的百位、十位和个位

i=x/10;//取十位

j=x%10;//取个位

WriteAddress(0x43);     //写显示地址,将在第2行第7列开始显示

WriteData(digit[i]);     //将百位数字的字符常量写入LCD

WriteData(digit[j]);     //将十位数字的字符常量写入LCD

delaynms(50);           //延时1ms给硬件一点反应时间

}

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

函数功能:显示日

入口参数:x

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

voidDisplayDay(unsignedcharx)

{

unsignedchari,j;      //j,k,l分别储存温度的百位、十位和个位

i=x/10;//取十位

j=x%10;//取个位

WriteAddress(0x0c);     //写显示地址,将在第2行第7列开始显示

WriteData(digit[i]);     //将百位数字的字符常量写入LCD

WriteData(digit[j]);     //将十位数字的字符常量写入LCD

delaynms(50);           //延时1ms给硬件一点反应时间

}

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

函数功能:显示月

入口参数:x

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

183/192


voidDisplayMonth(unsignedcharx)

{

unsignedchari,j;      //j,k,l分别储存温度的百位、十位和个位

i=x/10;//取十位

j=x%10;//取个位

WriteAddress(0x09);     //写显示地址,将在第2行第7列开始显示

WriteData(digit[i]);     //将百位数字的字符常量写入LCD

WriteData(digit[j]);     //将十位数字的字符常量写入LCD

delaynms(50);           //延时1ms给硬件一点反应时间

}

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

函数功能:显示年

入口参数:x

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

voidDisplayYear(unsignedcharx)

{

unsignedchari,j;      //j,k,l分别储存温度的百位、十位和个位

i=x/10;//取十位

j=x%10;//取个位

WriteAddress(0x06);     //写显示地址,将在第2行第7列开始显示

WriteData(digit[i]);     //将百位数字的字符常量写入LCD

WriteData(digit[j]);     //将十位数字的字符常量写入LCD

delaynms(50);           //延时1ms给硬件一点反应时间

}

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

函数功能:主函数

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

voidmain(void)

{

unsignedcharsecond,minute,hour,day,month,year;       //分别储存苗、分、小

时,日,月,年

unsignedcharReadValue;    //储存从1302读取的数据

LcdInitiate();                //将液晶初始化

WriteAddress(0x01);   //Date的显示地址,将在第1行第2列开始显示

WriteData('D');       //将字符常量写入LCD

WriteData('a');        //将字符常量写入LCD

WriteData('t');       //将字符常量写入LCD

WriteData('e');       //将字符常量写入LCD

WriteData(':');       //将字符常量写入LCD

WriteAddress(0x08);   //写年月分隔符的显示地址,显示在第1行第9

WriteData('-');       //将字符常量写入LCD

WriteAddress(0x0b);   //写月日分隔符的显示地址,显示在第1行第12

WriteData('-');       //将字符常量写入LCD

184/192


WriteAddress(0x45);

WriteData(':');


//写小时与分钟分隔符的显示地址,

//将字符常量写入LCD


显示在第2行第6


WriteAddress(0x48);

WriteData(':');

Init_DS1302();

while(1)

{


//写分钟与秒分隔符的显示地址,

//将字符常量写入LCD

//1302初始化


显示在第2行第9


ReadValue=ReadSet1302(0x81);


//从秒寄存器读数据


 


}


second=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);//将读出数据转化

DisplaySecond(second);            //显示秒

ReadValue=ReadSet1302(0x83);   //从分寄存器读

minute=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);//将读出数据转化

DisplayMinute(minute);             //显示分

ReadValue=ReadSet1302(0x85);   //从分寄存器读

hour=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);//将读出数据转化

DisplayHour(hour);                //显示小时

ReadValue=ReadSet1302(0x87);   //从分寄存器读

day=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);//将读出数据转化

DisplayDay(day);                   //显示日

ReadValue=ReadSet1302(0x89);   //从分寄存器读

month=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);//将读出数据转化

DisplayMonth(month);               //显示月

ReadValue=ReadSet1302(0x8d);   //从分寄存器读

year=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);//将读出数据转化

DisplayYear(year);                 //显示年

}


 


//


99


#include<reg51.h>


//实例99:单片机数据发送程序

//包含单片机寄存器的头文件


 

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

函数功能:向PC发送一个字节数据

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

voidSend(unsignedchardat)

{

SBUF=dat;

while(TI==0)

;

TI=0;

}

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

;

}

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

函数功能:延时若干毫秒

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

voiddelaynms(unsignedcharx)

{

unsignedchari;

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

delay1ms();

}

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

函数功能:主函数

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

voidmain(void)

{

unsignedchari;

TMOD=0x20;  //定时器T1工作于方式2

TH1=0xfd;   //根据规定给定时器T1赋初值

TL1=0xfd;   //根据规定给定时器T1赋初值

PCON=0x00;  //波特率9600

TR1=1;       //启动定时器t1

SCON=0x40;  //串口工作方式1

while(1)

{

for(i=0;i<200;i++)    //模拟检测数据

{

Send(i);          //发送数据i

delaynms(100);    //100ms发送一次检测数据

}

}

}


 


//


100


//实例100:电机转速表设计

186/192


#include<reg51.h>

#include<intrins.h>


//包含单片机寄存器的头文件

//包含_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"};//定义字符数组显示数字

unsignedintv;    //储存电机转速

unsignedcharcount;   //储存定时器T0中断次数

bitflag;       //计满1秒钟标志位

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

函数功能:延时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_();

187/192


}


_nop_();

_nop_();

result=BF;

E=0;

returnresult;


//空操作四个机器周期,给硬件反应时间

//将忙碌标志电平赋给result

//E恢复低电平


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

函数功能:将模式设置指令或显示地址写入液晶模块

入口参数: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(为字符常量)

188/192


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

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(0x0c);   //显示模式设置:显示开,无光标,光标不闪烁

delay(5);

WriteInstruction(0x06);   //显示模式设置:光标右移,字符不移

delay(5);

WriteInstruction(0x01);   //清屏幕指令,将以前的显示内容清除

delay(5);

}

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

**********

189/192


函数功能:显示速度提示符

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

*********/

voiddisplay_sym(void)

{

WriteAddress(0x00);   //写显示地址,将在第1行第1列开始显示

WriteData('v');       //将字符常量v写入LCD

WriteData('=');       //将字符常量=写入LCD

}

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

**********

函数功能:显示速度数值

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

*********/

voiddisplay_val(unsignedintx)

{

unsignedchari,j,k,l;      //j,k,l分别储存温度的百位、十位和个位

i=x/1000;           //取千位

j=(x%1000)/100;    //取百位

k=(x%100)/10;      //取十位

l=x%10;             //取个位

WriteAddress(0x02);      //写显示地址,将在第1行第3列开始显示

WriteData(digit[i]);     //将千位数字的字符常量写入LCD

WriteData(digit[j]);     //将百位数字的字符常量写入LCD

WriteData(digit[k]);     //将十位数字的字符常量写入LCD

WriteData(digit[l]);     //将个位数字的字符常量写入LCD

}

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

函数功能:显示速度单位“r/min

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

voiddisplay_unit(void)

{

WriteAddress(0x06);     //写显示地址,将在第2行第7列开始显示

WriteData('r');     //将字符常量r写入LCD

WriteData('/');     //将字符常量/写入LCD

WriteData('m');     //将字符常量m写入LCD

WriteData('i');     //将字符常量i写入LCD

WriteData('n');     //将字符常量n写入LCD

}

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

函数功能:主函数

190/192


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

voidmain(void)

{

LcdInitiate();               //调用LCD初始化函数

TMOD=0x51;                    //定时器T1工作于计数模式1,定时器T0

作于计时模式1

TH0=(65536-46083)/256;     //定时器T0的高8位设置初值,每50ms产生一

次中断

TL0=(65536-46083)%256;     //定时器T0的低8位设置初值,每50ms产生

一次中断

EA=1;                          //开总中断

ET0=1;                        //定时器T0中断允许

TR0=1;                        //启动定时器T0

count=0;                      //T0中断次数初始化为0

display_sym();               //显示速度提示符

display_val(0000);           //显示器工作正常标志

display_unit();               //显示速度单位

while(1)                     //无限循环

{

TR1=1;               //定时器T1启动

TH1=0;               //定时器T18位赋初值0

TL1=0;               //定时器T18位赋初值0

flag=0;              //时间还未满1分钟

while(flag==0)     //时间未满等待

;

v=(TH1*256+TL1)*60/16;//计算速度,每周产生16个脉冲

display_val(v);          //显示速度

}

}

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

函数功能:定时器T0的中断服务函数

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

voidTime0(void)interrupt1using1//定时器T0的中断编号为1,使用第1组工作

寄存器

{

count++;            //T0每中断1次,count1

if(count==20)      //若累计满20次,即计满1秒钟

{

flag=1;          //计满1秒钟标志位置1

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

}

TH0=(65536-46083)/256;    //定时器T08位重新赋初值

TL0=(65536-46083)%256;    //定时器T08位重新赋初值

}

191/192


#include<reg51.h>


//模拟霍尔脉冲


sbitcp=P3^2;


//cp位定义为P3.2引脚,从此脚输出脉冲信号


 

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

函数功能:延时约600微秒

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

voiddelay()

{

unsignedchari;

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

;

}

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

函数功能:主函数

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

voidmain(void)

{

while(1)

{

cp=1;     //置高电平

delay();  //等待600微秒

cp=0;     //置低电平

delay();   //等待600微秒

}

}


 


192


/


192

第一章.... 4 【实1】使用累加器进行简单加法运算:... 4 【实2】使用B寄存器进行简单乘法运算:... 4 【实3】通过设置RS1,RS0选择工作寄存器区1:... 4 【实4】使用数据指针DPTR访问外部数据数据存储器:... 4 【实5】使用程序计数器PC查表:... 4 【实6】if语句实:... 4 【实7】switch-case语句实:... 4 【实8】for语句实:... 4 【实9】while语句实:... 5 【实10】do…while语句实:... 5 【实11】语句形式调用实:... 5 【实12】表达式形式调用实:... 5 【实13】以函数的参数形式调用实:... 5 【实14】函数的声明实:... 5 【实15】函数递归调用的简单实:... 5 【实16】数组的实:... 6 【实17】指针的实:... 6 【实18】数组与指针实:... 6 【实19】P1口控制直流电动机实... 6 第二章.... 8 【实20】用74LS165实现串口扩展并行输入口... 8 【实21】用74LS164实现串口扩展并行输出口... 10 【实22】P0 I/O扩展并行输入口... 12 【实23】P0 I/O扩展并行输出口... 12 【实24】用8243扩展I/O端口... 12 【实25】用8255A扩展I/O口... 14 【实26】用8155扩展I/O口... 19 第三章.... 26 【实29】与AT24系列EEPROM接口及驱动程序... 26 【实30】EEPROM(X5045)接口及驱动程序... 30 【实31】与铁电存储器接口及驱动程序... 33 【实32】与双口RAM存储器接口及应用实... 35 【实33】与NANDFLASH(K9F5608)接口及驱动程序... 35 第四章.... 43 【实34】独立键盘控制... 43 【实35】矩阵式键盘控制... 44 【实36】改进型I/O端口键盘... 46 【实37】PS/2键盘的控制... 49 【实38】LED显示... 53 【实39】段数码管(HD7929)显示实... 54 【实40】16×2字符型液晶显示实... 55 【实41】点阵型液晶显示实... 61 【实42】LCD显示图片实... 63 第五章.... 70 【实43】简易电子琴的设计... 70 【实44】基于MCS-51单片机的四路抢答器... 71 【实45】电子调光灯的制作... 76 【实46】数码管时钟的制作... 81 【实47】LCD时钟的制作... 96 【实48】 数字化语音存储与回放... 103 【实49】电子标签设计... 112 第六章.... 120 【实50】指纹识别模块... 121 【实51】数字温度传感器... 121 第七章.... 124 【实53】超声波测距... 124 【实54】数字气压计... 125 【实55】基于单片机的电压表设计... 132 【实56】基于单片机的称重显示仪表设计... 133 【实57】基于单片机的车轮测速系统... 136 第八章.... 138 【实58】电源切换控制... 138 【实59】步进电机控制... 140 【实60】单片机控制自动门系统... 141 【实61】控制微型打印机... 144 【实62】单片机控制的EPSON微型打印头... 144 【实63】简易智能电动车... 145 【实64】洗衣机控制器... 149 第九章.... 152 【实65】串行A/D转换... 152 【实66】并行A/D转换... 153 【实67】模拟比较器实现A/D转换... 154 【实68】串行D/A转换... 155 【实69】并行电压型D/A转换... 156 【实70】并行电流型D/A转换... 156 【实71】file:///C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\msohtmlclip1\01\clip_image002.gif接口的A/D转换... 157 【实72】file:///C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\msohtmlclip1\01\clip_image002.gif接口的D/A转换... 161 第十章.... 164 【实73】单片机间双机通信... 164 【实74】单片机间多机通信方法之一... 166 【实75】单片机间多机通信方法之二... 171 【实76】 PC与单片机通信... 176 【实77】红外通信接口... 178 第十一章.... 180 【实79】单片机实现PWM信号输出... 180 【实80】实现基于单片机的低频信号发生器... 182 【实81】软件滤波方法... 183 【实82】FSK信号解码接收... 186 【实83】单片机浮点数运算实现... 187 【实84】神经网络在单片机中的实现... 192 【实85】信号数据的FFT变换... 194 第十二章.... 198 【实86】file:///C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\msohtmlclip1\01\clip_image005.gif总线接口的软件实现... 198 【实87】SPI总线接口的软件实现... 200 【实88】1-WIRE总线接口的软件实现... 205 【实89】单片机外挂CAN总线接口... 207 【实90】单片机外挂USB总线接口... 210 【实91】单片机实现以太网接口... 214 【实92】单片机控制GPRS传输... 221 【实93】单片机实现TCP/IP协议... 223 第十三章.... 229 【实94】读写U盘... 229 【实95】非接触IC卡读写... 234 【实96】SD卡读写... 238 【实97】高精度实时时钟芯片的应用... 242 第十四章.... 247 【实98】智能手机充电器设计... 247 【实99】单片机控制门禁系统... 248
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值