AT89S52综合接口程序设计报告.docx
《AT89S52综合接口程序设计报告.docx》由会员分享,可在线阅读,更多相关《AT89S52综合接口程序设计报告.docx(31页珍藏版)》请在冰豆网上搜索。
AT89S52综合接口程序设计报告
重庆理工大学
硬件应用系统开发技术综合实验报告
题目:
AT89S52综合接口程序设计
二级学院计算机科学与工程
专业计算机科学与技术
班级
学生姓名学号
教师
时间2014.5.18
成绩
目录
一、实验名称
AT89S52综合接口程序设计
二、实验目的
1、测量PCF8591的AD的IN0电压0.00V到5.00V;
2、通过RS232口送PC串口助手显示实测电压,形如“Voltageis:
2.35V↙”;
3、将测量到的电压送PCF8591的DA输出到DL10,以调节LED量度;
4、读取24C04中存储的报警调节值W0,当测量电压大于W0时蜂鸣器发出报警;
5、通过PC串口助手发送形如“:
3.00V↙”,即修改24C04中存储的报警值W0为3.00V。
其中“↙”为回车键,其ASCII码为0X0D和0X0A
三、实验设备与环境
单片机硕飞开发试验仪;Pc机;Keil开发软件;串口助手软件。
4、实验基本原理
AD0809工作原理:
IN0-IN7:
8条模拟量输入通道,AD0809对输入模拟量要求:
子女好单极性,电压范围是0-5V,若信号太小,必须进行放大;输入的模拟量在转换过程中应该保持不变,如若模拟量变化太快,则需在输入前增加采样电路。
地址输入和控制线:
1条ALE为地址锁存器允许输入线,高电平有效。
当ALE线为高电平时,地址锁存与译码将A、B、C三条地址线的地址信号进行锁存,经锁存后被选中的通道的模拟量进转换器进行转换。
ST为转换启动信号。
当ST上跳沿时,所有内部寄存器清零;下跳沿时,表明转换结束;否则。
表明正在进行A/D转换。
OE为输出允许信号,用于控制三条输出锁存器向单片机输出转换得到的数据。
24C04的写操作。
在主器件发出开始信号以后,主器件再发送四位器件码、3位块地址码以及为逻辑低电平R/W位到总线上。
这指示被寻址的从接收器,一个字地址和一个字节的数据将跟在第九个时钟周期期间产生的确认位之后。
因此,主器件发送的下一个字节是字地址,并且它将被写入带24LC04B/08B的地址指针。
在从24L04B/08B接收带另一个确认信号后,主器件将发送写入带被寻址的存贮器中的数据字节。
24LC04B/08B自此发出确认信号,同时主器件产生停止条件。
1、AT89S52芯片简介
AT89S52是一种低功耗、高性能CMOS8位微控制器,具有8K在系统可编程Flash存储器。
使用Atmel公司高密度非易失性存储器技术制造,与工业80C51产品指令和引脚完全兼容。
片上Flash允许程序存储器在系统可编程,亦适于常规编程器。
在单芯片上,拥有灵巧的8位CPU和在系统可编程Flash,使得AT89S52在众多嵌入式控制应用系统中得到广泛应用。
2、PCF8591芯片简介
2.1PCF8591是一个单片集成、单独供电、低功耗、8-bitCMOS数据获取器件。
PCF8591具有4个模拟输入、1个模拟输出和1个串行I2C总线接口。
PCF8591的3个地址引脚A0,A1和A2可用于硬件地址编程,允许在同个I2C总线上接入8个PCF8591器件,而无需额外的硬件。
在PCF8591器件上输入输出的地址、控制和数据信号都是通过双线双向I2C总线以串行的方式进行传输。
2.2引脚信息
AIN0~AIN3:
模拟信号输入端;PCF8591引脚A0~A2:
引脚地址端;VDD、VSS:
电源端(2.5~6V);SDA、SCL:
I2C总线的数据线、时钟线;OSC:
外部时钟输入端,内部时钟输出端;EXT:
内部、外部时钟选择线,使用内部时钟时EXT接地;AGND:
模拟信号地;AOUT:
D/A转换输出端;VREF:
基准电源端。
2.3I2C接口
1、只要求两条总线线路:
一条串行数据线SDA,一条串行时钟线SCL;
2、每个连接到总线的器件都可以通过唯一的地址和一直存在的简单的主机/从机关系软件设定地址,主机可以作为主机发送器或主机接收器;
3、它是一个真正的多主机总线,如果两个或更多主机同时初始化,数据传输可以通过冲突检测和仲裁防止数据被破坏;
4、串行的8位双向数据传输位速率在标准模式下可达100kbit/s,快速模式下可达400kbit/s,高速模式下可达3.4Mbit/s;
5、连接到相同总线的IC数量只受到总线的最大电容400pF限制。
(3)引脚功能概述:
SDA:
串行数据/地址。
双向传输端,用于传送地址和所有数据的发送或接收。
它是一个漏极开路端,因此要求接一个上拉电到Vcc端(典型值为100kHz时为10K,400kHz时为lK)。
对于一般的数据传输,仅在SCL为低期间SDA才允许变化;在SCL为高期间变化,留给指示Start(开始)和Stop(停止)条件。
WP:
写保护。
如果WP管脚连接到Vcc,则所有的内容都被写保护(只能读):
当WP管脚连接到Vss或悬空时,则允许器件进行正常的读/写操作。
6、起始停止
SCL线是高电平时,SDA线从高电平向低电平切换,这个情况表示起始条件;
SCL线是高电平时,SDA线由低电平向高电平切换,这个情况表示停止条件。
起始和停止条件一般由主机产生,总线在起始条件后被认为处于忙的状态起始和停止条件,在停止条件的某段时间后总线被认为再次处于空闲状态。
如果产生重复起始条件而不产生停止条件,总线会一直处于忙的状态,此时的起始条件(S)和重复起始条件(Sr)在功能上是一样的。
2.4AD、DA应用
PCF8591采用典型的I2C总线接口器件寻址方法,即总线地址由器件地址、引脚地址和方向位组成。
PCF8591片内有控制寄存器,单片机通过向该寄存器写入控制字来控制A/D和D/A转换,为此在转换之前要进行写控制字传送。
其A/D转换部分读数据的操作为:
寻址后要首先写控制字,以进行模拟通道选择、通道增量位和模拟信号输入形式(单端输入和差分输入)等设置。
操作过程中,在PCF8591接收到的每个应答信号的后沿触发A/D转换,随后就是读出转换结果,但读出的是前一次的转换结果。
所以“读数据0”是一次无效的操作。
A/D和D/A:
控制字节用于实现器件的各种功能,如模拟信号由哪几个通道输入等。
其中:
D1、D0两位是A/D通道编号:
00通道0,01通道1,10通道2,11通道3自动增益选择(有效位为1)D5、D4模拟量输入选择:
00为四路单输入、01为三路差分输入、10为单端和差分配合输入、11为模拟输出有效。
当系统为A/D转换时,模拟输出容许为0.模拟量输入选择位取值由输入方式决定,四路单输入时取00,三路差分输入时取01,单端与差分输入时取10,二路差分输入时取11.最低两位时通道编号位,当对0通道的模拟信号进行A/D转换时取00,当对1通道的模拟信号进行A/D转换时取01,当对2通道的模拟信号进行A/D转换时取10,当对3通道的模拟信号进行A/D转换时取11。
3、RS232接口
3.1简介
RS-232是现在主流的串行通信接口之一。
由于RS232接口标准出现较早,难免有不足之处,主要有以下四点:
(1)接口的信号电平值较高,易损坏接口电路的芯片。
RS232接口任何一条信号线的电压均为负逻辑关系。
即:
逻辑“1”为-5—-15V;逻辑“0”:
+5—+15V,噪声容限为2V。
即要求接收器能识别低至+3V的信号作为逻辑“0”,高到-3V的信号作为逻辑“1”,TTL电平为5V为逻辑正,0为逻辑负。
与TTL电平不兼容故需使用电平转换电路方能与TTL电路连接。
(2)传输速率较低,在异步传输时,波特率为20Kbps;因此在“南方的老树51CPLD开发板”中,综合程序波特率只能采用19200,也是这个原因。
3.2通讯方式:
RS-232采取不平衡传输方式,即所谓单端通讯。
收、发端的数据信号是相对于信号地,如从DTE设备发出的数据在使用DB25连接器时是2脚相对7脚(信号地)的电平,DB25各引脚定义参见图1。
典型的RS-232信号在正负电平之间摆动,在发送数据时,发送端驱动器输出正电平在+5~+15V,负电平在-5~-15V电平。
当无数据传输时,线上为TTL,从开始传送数据到结束,线上电平从TTL电平到RS-232电平再返回TTL电平。
接收器典型的工作电平在+3~+12V与-3~-12V。
由于发送电平与接收电平的差仅为2V至3V左右,所以其共模抑制能力差,再加上双绞线上的分布电容,其传送距离最大为约15米,最高速率为20kb/s。
RS-232是为点对点(即只用一对收、发设备)通讯而设计的,其驱动器负载为3~7kù。
所以RS-232适合本地设备之间的通信。
4、24C04:
4.1工作原理
AT24C02的1、2、3脚是三条地址线,用于确定芯片的硬件地址。
在AT89C51试验开发板上它们都接地,第8脚和第4脚分别为正、负电源。
第7脚需要接地。
第5脚SDA为串行数据输入/输出,数据通过这条双向I2C总线串行传送,在AT89C51试验开发板上和单片机的P3.5连接。
第6脚SCL为串行时钟输入线,在AT89C51试验开发板上和单片机的P3.6连接。
SDA和SCL都需要和正电源间各接一个5.1K的电阻上拉。
24C02中带有片内地址寄存器。
每写入或读出一个数据字节后,该地址寄存器自动加1,以实现对下一个存储单元的读写。
所有字节均以单一操作方式读取。
为降低总的写入时间,一次操作可写入多达8个字节的数据。
5、蜂鸣器报警:
由于自激蜂鸣器是直流电压驱动的,不需要利用交流信号进行驱动,只需对驱动口输出驱动电平并通过三极管放大驱动电流就能使蜂鸣器发出声音,很简单,这里就不对自激蜂鸣器进行说明了。
这里只对必须用1/2duty的方波信号进行驱动的他激蜂鸣器进行说明。
单片机驱动他激蜂鸣器的方式有两种:
一种是PWM输出口直接驱动,另一种是利用I/O定时翻转电平产生驱动波形对蜂鸣器进行驱动。
本程序通过在输出一个音频范围的方波,驱动实验板上的蜂鸣器发出蜂鸣声,其中DELAY延时子程序的作用是使输出的方波频率在人耳朵听觉能力之内的20KHZ以下,如果没有这个延时程序的话,输出的频率将大大超出人耳朵的听觉能力,我们将不能听到声音。
更改延时常数,可以改变输出频率,也就可以调整蜂鸣器的音调。
5、实验内容(包括主要算法分析与流程图)
I2C相关流程图:
6、实验源程序及分析
#include
#include
#definePCF8591_WRITE0x90
#definePCF8591_READ0x91
#defineOP_WRITE0xa0//器件地址以及写入操作//24c04
#defineOP_READ0xa1//器件地址以及读取操作
#definedisdataP0//显示数据码输出口
sbitSDA_M=P1^1;//P1.1口模拟数据口
sbitSCL_M=P1^0;//P1.0口模拟时钟口
sbitSDA_c=P3^5;
sbitSCL_c=P3^4;//24c04
sbitBEEP=P3^7;//蜂鸣器驱动口
typedefunsignedcharuchar;
typedefunsignedintuint;
ucharCount;
sbitLCD_RS=P2^0;
sbitLCD_RW=P2^1;
sbitLCD_EN=P2^2;
unsignedchardis1[]="Voltageis:
.V";
unsignedintdatadis[4];
unsignedchardatadis_v[3];
unsignedchardatareceivebuf;//数据接收缓冲区
unsignedchardata_24c[3];//保存从2430中读出来的数据
unsignedcharsendbuf[3]={4,5,0};//24c04中报警值350mA
charcodereserve[3]_at_0x3b;//保留0x3b开始的3个字节
//=========================================
//us延时函数(4.34us
//=========================================
voiddelayNOP()
{
_nop_();
_nop_();
_nop_();
_nop_();
}
//========================================
//ms延时
//=========================================
voiddelayms(unsignedintms)
{
unsignedchari;
while(ms--)
{
for(i=0;i<114;i++)
;
}
}
//=========================================
//检查LCD忙状态
//lcd_busy为1时,忙,等待。
//lcd-busy为0时,闲,可写指令与数据。
//=========================================
bitlcd_busy()
{
bitresult;
LCD_RS=0;
LCD_RW=1;
LCD_EN=1;
delayNOP();
result=(bit)(P0&0x80);
LCD_EN=0;
return(result);
}
//=========================================
//写指令数据到LCD
//=========================================
voidlcd_wcmd(unsignedcharcmd)
{
while(lcd_busy())
;
LCD_RS=0;
LCD_RW=0;
LCD_EN=1;
P0=cmd;
delayNOP();
LCD_EN=0;
}
//=========================================
//RS=H,RW=L,E=高脉冲,D0-D7=数据。
//=========================================
voidlcd_wdat(unsignedchardat)
{
while(lcd_busy())
;
LCD_RS=1;
LCD_RW=0;
LCD_EN=1;
P0=dat;
delayNOP();
LCD_EN=0;
}
//=========================================
//LCD初始化设定
//=========================================
voidlcd_init()
{
delayms(15);
lcd_wcmd(0x38);//16*2显示,5*7点阵,8位数据
delayms(5);
lcd_wcmd(0x38);
delayms(5);
lcd_wcmd(0x38);
delayms(5);
lcd_wcmd(0x0c);//显示开,关光标
delayms(5);
lcd_wcmd(0x06);//移动光标
delayms(5);
lcd_wcmd(0x01);//清除LCD的显示内容
delayms(5);
}
//=========================================
//设定显示位置
//=========================================
voidlcd_pos(unsignedcharpos)
{
lcd_wcmd(pos|0x80);//数据指针=80+地址变量
}
//=========================================
//数据处理与显示
//将采集到的数据进行16进制转换为ASCII码。
//=========================================
voidshow_value(unsignedcharad_data)
{
dis[2]=ad_data/51;//AD值转换为3位BCD码,最大为5.00V。
dis[2]=dis[2]+0x30;//转换为ACSII码
dis[3]=ad_data%51;//余数暂存
dis[3]=dis[3]*10;//计算小数第一位
dis[1]=dis[3]/51;
dis[1]=dis[1]+0x30;//转换为ACSII码
dis[3]=dis[3]%51;
dis[3]=dis[3]*10;//计算小数第二位
dis[0]=dis[3]/51;
dis[0]=dis[0]+0x30;//转换为ACSII码
}
//=========================================
//函数名称:
iic_start()
//函数功能:
启动I2C总线子程序
//时钟保持高,数据线从高到低一次跳变,I2C通信开始
//=========================================
voidiic_start_m(void)
{
SDA_M=1;
SCL_M=1;
delayNOP();//延时5us
SDA_M=0;
delayNOP();
SCL_M=0;
}
//=========================================
//函数名称:
iic_stop()
//函数功能:
停止I2C总线数据传送子程序
//=========================================
voidiic_stop(void)
{
SDA_M=0;
SCL_M=1;
delayNOP();
SDA_M=1;
delayNOP();
SCL_M=0;
}
//=========================================
//函数名称:
iicInit_()
//函数功能:
初始化I2C总线子程序
//=========================================
voidiic_init(void)
{
SCL_M=0;
iic_stop();
}
//=========================================
//函数名称:
slave_ACK
//函数功能:
从机发送应答位子程序
//=========================================
voidslave_ACK(void)
{
SDA_M=0;
SCL_M=1;
delayNOP();
SCL_M=0;
SDA_M=1;
}
//=========================================
//函数名称:
slave_NOACK
//函数功能:
从机发送非应答位子程序,迫使数据传输过程结束
//=========================================
voidslave_NOACK(void)
{
SDA_M=1;
SCL_M=1;
delayNOP();
SDA_M=0;
SCL_M=0;
SDA_M=0;
}
//========================================
//函数名称:
check_ACK
//函数功能:
主机应答位检查子程序,迫使数据传输过程结束
//=========================================
voidcheck_ACK(void)
{
SDA_M=1;//置成输入
SCL_M=1;
F0=0;
delayNOP();
if(SDA_M==1)
//若SDA_M=1表明非应答
F0=1;
//置位非应答标志F0
SCL_M=0;
}
//=========================================
//入口参数:
indata
//函数功能:
发送一个字节
//=========================================
voidIICSendByte(unsignedcharindata)
{
unsignedcharn=8;//发送一字节数据,共八bit
while(n--)
{
SDA_M=(bit)(indata&0x80);
SCL_M=1;
delayNOP();
SCL_M=0;
indata=indata<<1;//数据左移一位
}
}
//=========================================
//函数名称:
IICreceiveByte
//返回接收的数据tdata
//函数功能:
接收一字节子程序
//=========================================
unsignedcharIICreceiveByte_m(void)
{
unsignedcharn=8;//读取一字节数据,共八bit
unsignedchartdata=0;
while(n--)
{
SDA_M=1;
SCL_M=1;
tdata=tdata<<1;//左移一位
if(SDA_M==1)
tdata=tdata|0x01;
//若接收到的位为1,则数据的最后一位置1
else
tdata=tdata&0xfe;
//否则数据的最后一位置0
SCL_M=0;
}
return(tdata);
}
//=========================================
//函数名称:
DAC_PCF8591
//入口参数:
slave_add从机地址
//函数功能:
发送数据子程序
//=========================================
voidDAC_PCF8591(unsignedcharcontrolbyte,unsignedcharw_da