[整理]51单片机100例程序设计

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

100例程序设计范例汇总
第一章 (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】P0I/O扩展并行输入口 (12)
【实例23】P0I/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)
【实例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】2I C接口的A/D转换 (157)
【实例72】2I C接口的D/A转换 (161)
【实例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】
2
I C总线接口的软件实现 (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)
第一章
【实例1】使用累加器进行简单加法运算:
MOV A,#02H ;A←2
ADD A,#06H ;A←A+06H
【实例2】使用B寄存器进行简单乘法运算:
MOV A,#02H ; A←2
MOV B,#06H ; B←6
MUL AB ; BA←A*B=6*2
【实例3】通过设置RS1,RS0选择工作寄存器区1:
CLR PSW.4 ; PSW.4←0
SETB PSW.5 ; PSW.5←1
【实例4】使用数据指针DPTR访问外部数据数据存储器:
MOV DPTR, #data16 ; DPTR←data16
MOVX A, @ DPTR ; A←((DPTR))
MOVX @ DPTR, A ; (DPTR)←A
【实例5】使用程序计数器PC查表:
MOV A, #data ;A←data
MOVC A, @ A+DPTR ; PC←(PC)+1 ,A←((A)+(PC)) 【实例6】if语句实例:
void main()
{ int a,b,c,min;
printf("\n please input three number:");
scanf("%d%d%d ",&a,&b,&c);
if(a<b&&a<c) printf("min=%d\n",a );
else if(b<a&&b<c) printf("min=%d\n",b);
else if(c<a&&c<c) printf("min=%d\n",c);
else printf("There at least two numbers are equal\n");
}
【实例7】switch-case语句实例:
void main()
{ int num; printf("input one number:");
scanf("%d",& num);
switch(num)
{ case 1: printf("num =%d\n", num);break;
case 2: printf("num =%d\n", num);break;
case 3: printf("num =%d\n", num);break;
case 4: printf("num =%d\n", num);break;
default: printf("The number is out of the range\n", num);
}
}
【实例8】for语句实例:
void main()
{ for(int a=10;n>0;a --)
printf("%d",a);
}
【实例9】while语句实例:
void main()
{ int i=0;
while(i<=10) i++;
}
【实例10】do…while语句实例:
void main()
{ int i=0;
do{ i++;}
while(i<=10);
}
【实例11】语句形式调用实例:
void main()
{ int i=0; while(i<=10) i++; ……
Sum(); /*函数调用*/
}
【实例12】表达式形式调用实例:
void main()
{ int a,b,i=0; while(i<=10) i++; ……
i=4*Sum(a,b); /*函数调用*/
}
【实例13】以函数的参数形式调用实例:void main()
{ int a,b,c,i=0; while(i<=10) i++; ……
i= max(c,Sum(a,b)); /*函数调用*/ }
【实例14】函数的声明实例:
void main()
{ int max(int x,int y); /*函数的声明*/ int a,b,c,i=0; while(i<=10) i++; ……
i= max(c,Sum(a,b)); /*函数调用*/ }
【实例15】函数递归调用的简单实例:void fun()
{ int a=1, result,i;
for(i=0;i<10;)
{ i=a+I;
result = fun(); /*函数调用*/
}
return result;
}
【实例16】数组的实例:
void main()
{ char num[3] [3]={{ '','#',''},{'#','','#'},{'','#',''}}; /*定义多维数组*/ int i=0,j=0;
for(;i<3;i++)
{ for(;j<3;j++) printf(“%c”,num[i][j]);
printf(“/n”);
}
【实例17】指针的实例:
void main()
{ int a=3,*p;
p=&a; /*将变量a的地址赋值给指针变量p*/
printf(“%d,%d”,a,*p); /*输出二者的数值进行对比*/
}
【实例18】数组与指针实例:
void main()
{ int i=3,num[3]={1,2,3},*p;
p=num; /*将数组num[]的地址赋值给指针变量p*/
result =max(p,3); /*函数调用,计算数组的最大值*/
}
【实例19】P1口控制直流电动机实例
sfr p1=0x90;
sbit p10=p1^0;
sbit p11=p1^1;
void main ()
{
int i, m;
int j=100;
int k=20;
// 正快转
for (i=0; i<100; i++)
{
P10=1;
for (j=0; j<50; j++)
{
m=0;
}
}
P10=0;
for (j=0; j<10; j++)
{
m=0
}
//正慢转
for (i=0; i<100; i++) {
P10=1;
for (j=0; j<10; j++) {
m=0
}
}
p10=0;
for (j=0; j<50; j++) {
m=0
}
// 负快转
for (i=0; i<100; i++) {
p11=1;
for (j=0; j<50; j++) {
m=0;
}
}
p11=0;
for (j=0; j<10; j++) {
m=0;
}
// 负慢转
for (i=0; i<100; i++) {
p11=1;
for (j=0;j<10;j++) {
m=0;
}
}
p11=0
for (j=0; j<50; j++) {
m=0;
}
}
第二章
【实例20】用74LS165实现串口扩展并行输入口
(1)函数声明管脚定义
//---------------------------------------库函数声明,管脚定义------------------------------------------ #include<reg52.h>
sbit LOAD=P1^7;
//用P1^7控制SH/ 管脚
(2)串口初始化函数UART_init()
//-------------------------------------------------------------------------------------------------------------- // 函数名称:UART_init()
// 功能说明:串口初始化,设定串口工作在方式0
//-------------------------------------------------------------------------------------------------------------- void UART_init(void)
{
SCON=0x10;
//设串行口方式0,允许接收,启动接收过程
ES=0;
//禁止串口中断
}
(3)数据接收函数PA()
//-------------------------------------------------------------------------------------------------------------- // 函数名称:PA()
// 输入参数:无
// 输出参数:返回由并口输入的数据
// 功能说明:接收八位串行数据
//-------------------------------------------------------------------------------------------------------------- unsigned char PA(void)
{
unsigned char PA_data;
LOAD=0;
//当P1.7输出低电平,74LS165将并行数据装入寄存器//当中
LOAD=1;
//当P1.7输出高电平,74LS165在时钟信号下进行移位
UART_init();
//74LS165工作在时钟控制下的串行移位状态
while(RI==0);
//循环等待
RI=0;
PA_data=SBUF;
return PA_data;
//返回并行输入的数据
}
(1)函数声明管脚定义
//---------------------------------------库函数声明,管脚定义------------------------------------------ #include<reg52.h>
sbit a7=ACC^7;
sbit simuseri_CLK=P1^6;
//用P1^6模拟串口时钟
sbit simuseri_DATA=P1^5;
//用P1^5模拟串口数据
sbit drive74165_LD=P1^7;
//用P1^7控制SH/ 管脚
(2)数据输入函数in_simuseri()
//-------------------------------------------------------------------------------------------------------------- // 函数名称:in_simuseri()
// 输入参数:无
// 输出参数:data_buf
// 功能说明:8位同位移位寄存器,将simuseri_DATA串行输入的数据按从低位到
// 高位
// 保存到data_buf
//-------------------------------------------------------------------------------------------------------------- unsigned char in_simuseri(void)
{
unsigned char i;
unsigned char data_buf;
i=8;
do
{
ACC=ACC>>1;
for(;simuseri_CLK==0;);
a7= simuseri_DA TA;
for(;simuseri_CLK==1;);
}
while(--i!=0);
simuseri_CLK=0;
data_buf=ACC;
return(data_buf);
}
(3)数据输出函数PAs()
//-------------------------------------------------------------------------------------------------------------- // 函数名称:PAs()
// 输入参数:无
// 输出参数:PAs _buf,返回并行输入74LS165的数据
// 功能说明:直接调用,即可读取并行输入74LS165的数据,不需要考虑74LS165的
// 工作原理
//--------------------------------------------------------------------------------------------------------------
unsigned char PAs(void)
{
unsigned char PAs_buf;
drive74165_LD=0;
drive74165_LD=1;
PAs_buf= in_simuseri();
return(PAs_buf);
}
【实例21】用74LS164实现串口扩展并行输出口
单片机串口驱动74LS164的程序主要包括函数声明管脚定义部分、串口初始化函数以及数据发送函数。

(1)函数声明管脚定义
//-------------------------------------库函数声明,管脚定义--------------------------------------------
#include <reg52.h>
sbit CLR=P1^7;
//用P1^7控制CLR
(2)串口初始化函数UART_init()
//-------------------------------------------------------------------------------------------------------
// 函数名称:UART_init()
// 功能说明:串口初始化,设定串口工作在方式0
//--------------------------------------------------------------------------------------------------------
void UART_init(void)
{
SCON =0x00;
//没串行口方式0,允许发送,启动发送过程
ES=0;
// 禁止串口中断
}
(3)数据发送函数PA_out()
//-------------------------------------------------------------------------------------------------------
// 函数名称:PA_out()
// 输入参数:PA_data,需要从74LS164并行口输出的数据
// 输出参数:无
// 功能说明:发送八位串行数据至并口
//--------------------------------------------------------------------------------------------------------
void PA_out(unsigned char PA_data)
{
CLR=0;
//并口输出清零
CLR=1;
//开始串行移位
UART_init();
//74LS165工作在时钟控制下的串行移位状态
while(TI==0);
//循环等待
TI=0;
SBUF=PA_data;
}
单片机I/O端口驱动74LS164主要包括函数声明管脚定义部分、数据输入函数以及数据输出函数。

(1)函数声明管脚定义
//-------------------------------------库函数声明,管脚定义--------------------------------------------
#include <reg52.h>
sbit simuseri_CLK=P1^6;
//用P1^6模拟串口时钟
sbit simuseri_DATA=P1^5;
//用P1^5模拟串口数据
sbit drive74164_CLR=P1^7;
//用P1^7控制CLR
sbit a0=ACC^0;
(2)数据输入函数out_simuseri ()
//---------------------------------------------------------------------------------------------------------------
// 函数名称:out_simuseri
// 输入参数:data_buf
// 输出参数:无
// 功能说明:8位同步移位寄存器,将data_buf的数据逐位输出到simuseri_DATA
//---------------------------------------------------------------------------------------------------------------
void out_simuseri(char data_buf)
{
char i;
i=8;
ACC=data_buf;
do
{
simuseri_CLK=0;
simuseri_DATA=a0;
simuseri_CLK=1;
ACC=ACC>>1;
}
while(--i!=0);
simuseri_CLK=0;
}
(3)数据输出函数PA_out ()
//------------------------------------------------------------------------------------------------------- // 函数名称:PA_out
// 输入参数:Pseri_out,需要输出的8位数据
// 输出参数:无
// 功能说明:将Pseri_out中的数据送到74165并行口A-G输出
//--------------------------------------------------------------------------------------------------------
void PA_out (char Pseri_out )
{
drive74164_CLR =0;
//并口输出清零
drive74164_CLR =1;
//开始串行移位
out_simuseri(Pseri_out);
}
【实例22】P0 I/O扩展并行输入口
I/O口对应的地址为:
1111 1110 1111 1111 B=FEFFH
CPU操作指令为:
#define 244_addr xbyte[0XFEFF]
unsigned char I/O_DA TA;
I/O_DA TA=244_addr;
【实例23】P0 I/O扩展并行输出口
I/O端口对应的地址为:
1111 1101 1111 1111 B=FDFFH
CPU操作指令为:
#define 273_addr xbyte[0XFDFF]
unsigned char I/O_DA TA;
244_addr =I/O_DA TA;
【实例24】用8243扩展I/O端口
#include<reg52.h>
sbit ContrBit0=P1^0;
sbit ContrBit1=P1^1;
sbit ContrBit2=P1^2;
sbit ContrBit3=P1^3;
sbit PROG=P1^4;
sbit CS=P1^5;
char driver8243(char sele_P,char sele_M,char out_data)
{
char in_data=0;
char data_buf;
PROG=1;
//置PROG为高电平
//----------------------------------------------开始写控制字----------------------------------------------- if((sele_P&0x01)==0) //将控制字最低位送到8243的p2.0
ContrBit0=0;
else
ContrBit0=1;
if((sele_P&0x02)==0) //将控制字第二位送到8243的p2.1
ContrBit1=0;
else
ContrBit1=1;
//以上两位共同指定端口地址
//----------------------------------------写端口工作模式控制字---------------------------------------- if((sele_M&0x01)==0) //将端口工作模式控制字低位送到8243的p2.2 ContrBit2=0;
else
ContrBit2=1;
if((sele_M&0x01)==0) //将端口工作模式控制字高位送到8243的p2.3 ContrBit3=0;
else
ContrBit3=1;
//完成写控制字
PROG=0;
//在PROG上产生下降沿
switch(sele_M&0x03) //判断工作模式
{
case 0: break;
//sele_M=B00为输入,不处理,等待上升沿
case 1: data_buf=out_data;
break;
//sele_M=B01为输出,直接送数据
case 2: data_buf=out_data;
break;
//sele_M=B10为逻辑或,直接送数据
case 3: data_buf=out_data;
break;
//sele_M=B11为逻辑与,直接送数据
}
PROG=1;
//产生上升沿
if((sele_M&0x03)==0) //sele_M=B00为输入,接收数据
in_data=(data_buf&0x0F);
return(in_data);
//sele_M=B00,返回接收到的数据
}
//sele_M!=B00,返回0
void main( void)
{
char receive_data;
receive_data=driver8243(1,0,5);
}
【实例25】用8255A扩展I/O口
//----------------------------------------------------------------------------------------------------
// 函数名称:rd_PA
// 输入函数:无
// 输出参数:PA_data,PA输入的数据
// 功能说明:驱动PA实现输入功能,读入PA的并行数据
//----------------------------------------------------------------------------------------------------
unsigned char rd_PA(void) //读PA
(1)管脚定义及函数声明
//-------------------------------------------函数声明,管脚定义------------------------------------------- #include<reg52.h>
#include<ABSACC.H>
#define a8255_PA XBYTE[0x7F7C] //PA地址
#define a8255_PB XBYTE[0x7F7D] //PB地址
#define a8255_PC XBYTE[0x7F7E] //PC地址
#define a8255_CON XBYTE[0x7F7F] //控制字地址
unsigned char bdata IO_flags;
//用于表示PA、PB、PC的当前输入输出状态
//内容不能被其他程序改写
sbit IO_flagsA=IO_flags^0;
//PA的当前输入输出状态
sbit IO_flagsB=IO_flags^1;
//PB的当前输入输出状态
sbit IO_flagsC=IO_flags^2;
//PC的当前输入输出状态
unsigned char const cfg_table[8]=
{
0x80, //10000000b, c=out b=out a=out
0x90, //10010000b, c=out b=out a=in
0x82, //10000010b, c=out b=in a=out
0x92, //10010010b, c=out b=in a=in
0x89, //10001001b, c=in b=out a=out
0x99, //10011001b, c=in b=out a=in
0x8B, //10001011b, c=in b=in a=out
0x9B, //10011011b, c=in b=in a=in
}
unsigned char rd_PA(void);
//读PA
unsigned char rd_PB(void);
//读PB
unsigned char rd_PC(void);
//读PC
void wr_PA(unsigned char PA_data);
//写PA
void wr_PB(unsigned char PB_data);
//写PB
void wr_PC(unsigned char PC_data);
//写PC
void set_PC(unsigned char PC_num);
//PC位操作,置位,PC_num为端口号0~7
void clr_PC(unsigned char PC_num);
//PC位操作,复位,PC_num为端口号0~7
void PABC_config(void);
//写8255A控制字
(2)端口A、B、C读写函数
{
unsigned char PA_data;
ACC=IO_flags;
//把状态标志字读到ACC便于进行位操作
do
{
IO_flagsA=1;
//置PA状态标志位为高--输入
IO_flags=ACC;
PABC_config();
//调用配置子程序,完成对8255的设置
ACC=IO_flags;
}
while(IO_flagsA==0);
//判断状态标志位是否为高
//控制字设置完成
PA_data=a8255_PA;
//把PA的数据读到PA_data
return(PA_data);
//返回PA_data
}
//---------------------------------------------------------------------------------------------------- // 函数名称:rd_PB
// 输入函数:无
// 输出参数:PB_data,PB输入的数据
// 功能说明:驱动PB实现输入功能,读入PB的并行数据
//---------------------------------------------------------------------------------------------------- unsigned char rd_PB(void) //读PB
{
unsigned char PB_data;
ACC=IO_flags;
//把状态标志字读到ACC便于进行位操作
do
{
IO_flagsB=1;
//置PB状态标志位为高--输入
IO_flags=ACC;
PABC_config();
//调用配置子程序,完成对8255的设置
}
while(IO_flagsB==0);
//判断状态标志位是否为高
//控制字设置完成
PB_data=a8255_PB;
//把PB的数据读到PB_data
return(PB_data);
//返回PB_data
}
//---------------------------------------------------------------------------------------------------- // 函数名称:rd_PC
// 输入函数:无
// 输出参数:PC_data,PC输入的数据
// 功能说明:驱动PC实现输入功能,读入PC的并行数据
//---------------------------------------------------------------------------------------------------- unsigned char rd_PC(void) //读PC
{
unsigned char PC_data;
ACC=IO_flags;
//把状态标志字读到ACC便于进行位操作
do
{
IO_flagsC=1;
//置PC状态标志位为高--输入
IO_flags=ACC;
PABC_config();
//调用配置子程序,完成对8255的设置
//ACC=IO_flags;
}
while(IO_flagsC==0);
//判断状态标志位是否为高
//控制字设置完成
PC_data=a8255_PC;
//把PC的数据读到PC_data
return(PC_data);
//返回PC_data
}
//---------------------------------------------------------------------------------------------------- // 函数名称:wr_PA
// 输入函数:PA_data,送PA输出的数据
// 输出参数:无
// 功能说明:驱动PA实现输出功能,输出数据到PA
//---------------------------------------------------------------------------------------------------- void wr_PA(unsigned char PA_data) //写PA
{
ACC=IO_flags;
//把状态标志字读到ACC便于进行位操作
{
IO_flagsA=0;
//置PA状态标志位为低--输出
IO_flags=ACC;
//位操作完成,把ACC的内容写回状态标志字
PABC_config();
//调用配置子程序,完成对8255的设置
ACC=IO_flags;
}
while(IO_flagsA==1);
//判断状态标志位是否为高,
//为高,设置未完成,需从新设置
a8255_PA=PA_data;
//将PA_data的内容送到PA
}
//---------------------------------------------------------------------------------------------------- // 函数名称:wr_PB
// 输入函数:PB_data,送PB输出的数据
// 输出参数:无
// 功能说明:驱动PB实现输出功能,输出数据到PA
//---------------------------------------------------------------------------------------------------- void wr_PB(unsigned char PB_data) //写PB
{
ACC=IO_flags;
//把状态标志字读到ACC便于进行位操作
{
IO_flagsB=0;
//置PB状态标志位为低--输出
IO_flags=ACC;
//位操作完成,把ACC的内容写回状态标志字
PABC_config();
//调用配置子程序,完成对8255的设置
ACC=IO_flags;
}
while(IO_flagsB==1);
//判断状态标志位是否为高,为高,设置未完成,
//需从新设置
a8255_PB=PB_data;
//将PB_data的内容送到PB
}
//---------------------------------------------------------------------------------------------------- // 函数名称:wr_PC
// 输入函数:PC_data,送PC输出的数据
// 输出参数:无
// 功能说明:驱动PC实现输出功能,输出数据到PC
//---------------------------------------------------------------------------------------------------- void wr_PC(unsigned char PC_data) //写PC
{
ACC=IO_flags;
//把状态标志字读到ACC便于进行位操作
{
IO_flagsC=0;
//置PC状态标志位为低--输出
IO_flags=ACC;
//位操作完成,把ACC的内容写回状态标志字
PABC_config();
//调用配置子程序,完成对8255的设置
ACC=IO_flags;
}
while(IO_flagsC==1);
//判断状态标志位是否为高,
//为高,设置未完成,需从新设置
a8255_PC=PC_data;
//将PC_data的内容送到PC
}
(3)端口C配置函数
//---------------------------------------------------------------------------------------------------- // 函数名称:set_PC
// 输入函数:PC_num,范围0~7
// 输出参数:无
// 功能说明:对PC进行位操作,置PC(PC_num)为高
//----------------------------------------------------------------------------------------------------
void set_PC(unsigned char PC_num)
{
ACC=IO_flags;
IO_flagsC=0;
ACC=IO_flags;
PC_num=PC_num<<1;
PC_num=(PC_num|0x01);
a8255_CON=PC_num;
}
//----------------------------------------------------------------------------------------------------
// 函数名称:clr_PC
// 输入函数:PC_num,范围0~7
// 输出参数:无
// 功能说明:对PC进行位操作,清PC(PC_num)为低
//----------------------------------------------------------------------------------------------------
void clr_PC(unsigned char PC_num)
{
ACC=IO_flags;
IO_flagsC=1;
ACC=IO_flags;
PC_num=PC_num<<1;
PC_num=(PC_num&0xFE);
a8255_CON=PC_num;
}
(4)写控制字函数
//----------------------------------------------------------------------------------------------------
// 函数名称:PABC_config
// 功能说明:写8255A的控制字寄存器
//----------------------------------------------------------------------------------------------------
void PABC_config(void)
{
a8255_CON=cfg_table[IO_flags];
}
【实例26】用8155扩展I/O口
(1)相关函数声明及管脚定义
//-----------------------------------函数声明,管脚定义----------------------------------------*/ #include<reg52.h>
#include<ABSACC.H>
#define a8155_PA XBYTE[0x7E00] //控制字地址
#define a8155_PB XBYTE[0x7E01] //PA地址
#define a8155_PC XBYTE[0x7E02] //PB地址
#define a8155_CON XBYTE[0x7E03] // PC地址
#define Timer_A XBYTE[0x7E04] // 定时器寄存器A #define Timer_B XBYTE[0x7E05] // 定时器寄存器B #define mem_head XBYTE[0x7F00] // 存储器首地址unsigned char bdata IO_flags;
//用于表示PA、PB、PC的当前输入输出状态
//内容不能被其他程序改写
sbit IO_flagA=IO_flags^0;
//PA的当前输入输出状态
sbit IO_flagB=IO_flags^1;
//PB的当前输入输出状态
sbit IO_flagC=IO_flags^2;
//PC的当前输入输出状态
sbit IO_flagC1=IO_flags^3;
//PC的当前输入输出状态
sbit Int_flagA=state_flags^4;
//PA的当前输入输出状态
sbit Int_flagB=state_flags^5;
//PB的当前输入输出状态
sbit Timer_flag1=state_flags^6;
sbit Timer_flag2=state_flags^7;
//Timer 的状态置位表示计数中
unsigned char rd_mem(unsigned char mem_ad);
//读存储器
void wr_mem(unsigned char mem_ad,unsigned char mem_data); //写存储器
char rd_PA(void);
//读PA
char rd_PB(void);
//读PB
char rd_PC(void);
//读PC
void wr_PA(unsigned char PA_data);
//写PA
void wr_PB(unsigned char PB_data);
//写PB
void wr_PC(unsigned char PC_data);
//写PC
void Dint_PA(void);
//关端口A中断
void Eint_PA(void);
//开端口A中断
void Dint_PB(void);
//关端口B中断
void Eint_PB(void);
//开端口B中断
void setting_PC0int(void);
void setting_PC4int(void);
void start_timer(void);
//开始计数器计数
void stop_timer(void);
//停止计数器计数
void setting_zero_stop(void);
//设定计数到零停止计数
int rd_timer(void);
//读计数值
void setting_timerout_mode(unsigned char mode);
//设定输出模式
(2)读写外RAM函数
读写外RAM函数对外部存储器指定单元数据进行读写,程序代码如下://-------------------------------------------------------------------------------------------------------------- // 函数名称:rd_mem
// 输入函数:mem_ad,范围0~255
// 输出参数:mem_data,存储对应数据
// 功能说明:读外部RAM,输入相对地址,返回数据
//-------------------------------------------------------------------------------------------------------------- unsigned char rd_mem(unsigned char mem_ad) //读存储器
{
unsigned char mem_data;
unsigned int AD_mem;
AD_mem=&mem_head;
AD_mem=AD_mem+mem_ad;
mem_data=XBYTE[AD_mem];
return(mem_data);
}
//-------------------------------------------------------------------------------------------------------------- // 函数名称:wr_mem
// 输入函数:mem_ad,mem_data 相对地址和数据
// 输出参数:无
// 功能说明:写数据到外部RAM,把数据写到相应的地址
//-------------------------------------------------------------------------------------------------------------- void wr_mem(unsigned char mem_ad, unsigned char mem_data) //写存储器
{
unsigned int AD_mem;
AD_mem=&mem_head;
AD_mem=AD_mem+mem_ad;
XBYTE[AD_mem]=mem_data;
}
(3)端口PA、端口PB以及端口PC的读写设置函数
端口PA、端口PB以及端口PC的读写设置函数主要完成对8155端口的输入输出设置及
数据读写,程序代码如下:
//----------------------------------------------------------------------------------------------------
// 函数名称:rd_PA
// 输入函数:无
// 输出参数:PA_data
// 功能说明:返回PA数据
//----------------------------------------------------------------------------------------------------
char rd_PA(void) //读PA
{
unsigned char PA_data;
ACC=state_flags;
//把状态标志字读到ACC便于进行位操作
do
{
IO_flagA=0;
//置PA状态标志位为低--输入
state_flags=ACC;
a8155_CON=state_flags;
//重写控制字,完成对8155的设置
}
while(IO_flagA==1);
//判断状态标志位是否为高
//控制字设置完成
PA_data=a8155_PA;
//把PA的数据读到PA_data
return(PA_data);
//返回PA_data
}
//----------------------------------------------------------------------------------------------------
// 读PB、PC的函数:rd_PB和rd_PC程序代码与rd_PA类似,不再赘述
//----------------------------------------------------------------------------------------------------
// 函数名称:wr_PA
// 输入函数:PA_data
// 输出参数:无
// 功能说明:把PA_data送到PA输出
//----------------------------------------------------------------------------------------------------
void wr_PA(unsigned char PA_data) //写PA
{
ACC=state_flags;
//把状态标志字读到ACC便于进行位操作
{
IO_flagA=1;
//置PA状态标志位为高--输出
state_flags=ACC;
//位操作完成,把ACC的内容写回状态标志字
a8155_CON=state_flags;
//写控制字,完成对8155的设置
}
while(IO_flagA==0);
//判断状态标志位是否为低
//为低,设置未完成,需从新设置
a8155_PA=PA_data;
//将PA_data的内容送到PA
}
//----------------------------------------------------------------------------------------------------
// 写PB、PC的函数:wr_PB和wr_PC程序代码与wr_PA类似,不再赘述
//----------------------------------------------------------------------------------------------------
(4)端口PA、端口PB以及端口PC的中断设置函数
端口PA、端口PB以及端口PC的中断设置函数完成各个端口的中断开启和关断,程序代码如下:
// 函数名称:Eint_PA
// 输入函数:无
// 输出参数:无
// 功能说明:PA中断允许
//----------------------------------------------------------------------------------------------------
void Eint_PA(void) //开端口A中断
{
ACC=state_flags;
//把状态标志字读到ACC便于进行位操作
Int_flagA=1;
state_flags=ACC;
//位操作完成,把ACC的内容写回状态标志字
a8155_CON=state_flags;
//写控制字,完成对8155的设置
}
//----------------------------------------------------------------------------------------------------
// 函数名称:Dint_PA
// 输入函数:无
// 输出参数:无
// 功能说明:PA中断禁止
//----------------------------------------------------------------------------------------------------
void Dint_PA(void) //关端口A中断
{
ACC=state_flags;
//把状态标志字读到ACC便于进行位操作
Int_flagA=0;
state_flags=ACC;
//位操作完成,把ACC的内容写回状态标志字
a8155_CON=state_flags;
//写控制字,完成对8155的设置
}
//----------------------------------------------------------------------------------------------------
// 开关PB中断的函数Eint_PB、Dint_PB和Eint_PA、Dint_PA程序代码类似,不再赘述
//----------------------------------------------------------------------------------------------------
端口PC上下半口配置函数:
端口PC上下半口配置函数可实现端口PC上半口配置为PA状态输出和PC下半口配置为PB状态输出。

程序代码如下:
//--------------------------------------------------------------------------------------------------------------
// 函数名称:PC0_PAint
// 输入函数:无
// 输出参数:无
// 功能说明:设置PC上半口为PA状态输出,PC0=INTRa,PC1=BFa,PC3=/STBb
//--------------------------------------------------------------------------------------------------------------
void PC0_PAint(void) //PC上半口为PA状态输出
{
//PC0=INTRa,PC1=BFa,PC3=
ACC=state_flags;
//把状态标志字读到ACC便于进行位操作
Int_flagA=1;
IO_flagC1=1;
state_flags=ACC;
//位操作完成,把ACC的内容写回状态标志字
a8155_CON=state_flags;
//写控制字,完成对8155的设置
}
//--------------------------------------------------------------------------------------------------------------
// 函数名称:PC4_PBint
// 输入函数:无
// 输出参数:无
// 功能说明:设置PC下半口为PB状态输出,PC4=INTRb,PC5=BFb,PC6=
//--------------------------------------------------------------------------------------------------------------
void PC4_PBint(void) //PC下半口为PB状态输出
{
//PC0=INTRa,PC1=BFa,PC3=
ACC=state_flags;
//把状态标志字读到ACC便于进行位操作
Int_flagA=1;
IO_flagC1=1;
IO_flagC=1;
state_flags=ACC;
//位操作完成,把ACC的内容写回状态标志字
a8155_CON=state_flags;
//写控制字,完成对8155的设置
}
计数器设置函数:
计数器设置函数完成计数器的起停和读写和输出模式设置,具体程序代码如下://--------------------------------------------------------------------------------------------------------------
// 函数名称:start_timer
// 输入函数:无
// 输出参数:无
// 功能说明:开始计数器计数
//--------------------------------------------------------------------------------------------------------------
void start_timer(void) //开始计数器计数
{
ACC=state_flags;
//把状态标志字读到ACC便于进行位操作
Timer_flag1=1;
Timer_flag2=1;
state_flags=ACC;
//位操作完成,把ACC的内容写回状态标志字
a8155_CON=state_flags;
//写控制字,完成对8155的设置
}
//--------------------------------------------------------------------------------------------------------------
// 函数名称:stop_timer
// 输入函数:无
// 输出参数:无
// 功能说明:停止计数器计数
//--------------------------------------------------------------------------------------------------------------
void stop_timer(void) //停止计数器计数
{
ACC=state_flags;
//把状态标志字读到ACC便于进行位操作
Timer_flag1=1;
Timer_flag2=0;
state_flags=ACC;
//位操作完成,把ACC的内容写回状态标志字
a8155_CON=state_flags;
//写控制字,完成对8155的设置
}
//--------------------------------------------------------------------------------------------------------------
// 函数名称:size_zero_stop
// 输入函数:无
// 输出参数:无
// 功能说明:设定计数到零停止计数
//-------------------------------------------------------------------------------------------------------------- void stop_timer(void) //停止计数器计数
{
ACC=state_flags;
//把状态标志字读到ACC便于进行位操作
Timer_flag1=1;
Timer_flag2=0;
state_flags=ACC;
//位操作完成,把ACC的内容写回状态标志字
a8155_CON=state_flags;
//写控制字,完成对8155的设置
}
//-------------------------------------------------------------------------------------------------------------- // 函数名称:rd_timer
// 输入函数:无
// 输出参数:time
// 功能说明:读计数值
//-------------------------------------------------------------------------------------------------------------- int rd_timer(void) //读计数值
{
int time;
char timea;
time=Timer_B;
timea=Timer_A;
time=time<<8;
time=((time&timea)&0x3F);
return(time);
}
//-------------------------------------------------------------------------------------------------------------- // 函数名称:setting_timerout_mode
// 输入函数:mode,范围0~3
// 输出参数:无
// 功能说明:设定输出模式
//-------------------------------------------------------------------------------------------------------------- void setting_timerout_mode(unsigned char mode)//设定输出模式
{
Timer_B=(mode&0x03);
//写控制字
}
第三章
【实例29】与AT24系列EEPROM接口及驱动程序。

相关文档
最新文档