51单片机I2C接口实验报告
(完整word版)单片机实验5报告

学号14142200277 序号19单片机原理与接口技术实验报告实验项目序号实验五实验项目名称I2C的DA/ADC转换实验姓名卢志雄专业电子信息工程班级电信14-2BF 完成时间 2016-05-20一、实验目的1、掌握I2C的DA/ADC芯片与单片机接口方法;2、掌握I2C器件编程方法;3、掌握DAC和ADC的使用方法。
二、实验前准备1、完成作业7;2、根据实验内容编写好相关程序,并进行Proteus仿真。
三、实验内容实验内容为3项,其中第1、2项必做。
1、D/A转换实验。
设置一个一维数组data uchar c[4]={0x00,0xa0,0xaa,0xff};按下K1、K2、K3、K4,分别将c[0]、c[1]、c[2]、c[3] 的值转换成模拟量输出,观察发光二极管D23的亮度。
若是仿真,可以通过电压表观察模拟量的电压值。
2、单通道采样与动态显示。
对AIN0通道进行采样,将采样数据在1、2两位动态显示,调节电位器观察显示数据变化。
3、简易电压表实现。
对AIN0通道进行采样,将采样数据转换成4位电压值在1、2、3、4四位动态显示,注意只有1位整数3位小数。
调节电位器观察显示数据变化。
四、实验原理图实验原理图如图3.5所示:图3.5 I2C的DA/ADC转换实验电路原理图电路中,P3.6、P3.4分别连接SCL、SDA,地址引脚A2A1A0=000,PCF8591的特征编码为1001,电路中PCF8591的地址为1001000。
4路模拟输入,AIN0连接一个10KΩ电位器的中心抽头,调节电位器可改变AIN0的模拟电压,AIN1连接电源,AIN2、AIN3连接地。
PCF8591的15脚AOUT是DAC输出的模拟量,AOUT引脚通过50Ω电阻、LED与电源连接,输出模拟量越小,LED越亮。
注意在HNIST-2型实验装置中,将J16的1、2脚短路。
五、软件设计思想1、编程思路仿照例题编写程序,采用例题的I2C的相关函数。
实验八 51系列单片机IIC

I2C总线上的所有器件连接在一个公共的总线上,因此,主器件在进行数据传输前选择需要通信的从器件,即进行总线寻址。 I2C总线上所有外围器件都需要有惟一的地址,由器件地址和引脚地址两部分组成,共7位。器件地址是I2C器件固有的地址编码,器件出厂时就已经给定,不可更改。引脚地址是由I2C总线外围器件的地址引脚(A2,A1,A0)决定,根据其在电路中接电源正极、接地或悬空的不同,形成不同的地址代码。引脚地址数也决定了同一种器件可接入总线的最大数目。 地址位与一个方向位共同构成I2C总线器件寻址字节。寻址字节的格式如表所示。方向位(R/)规定了总线上的主器件与外围器件(从器件)的数据传输送方向。当方向位R/=1,表示主器件读取从器件中的数据;R/=0,表示主器件向从器件发送数据。
从地址中读取一个字节的数据
INT8U read_random(INT8U RomAddress) { INT8U Read_data; I_Start(); I_Write8Bit(WriteDeviceAddress); I_TestAck(); I_Write8Bit(RomAddress); I_TestAck(); I_Start(); I_Write8Bit(ReadDeviceAddress); I_TestAck(); Read_data=I_Read8Bit(); I_NoAck(); I_Stop(); return (Read_data); }
8.4.1 串行EEPROM存储器简介
串行EEPROM存储器是一种采用串行总线的存储器,这类存储器具有体积小、功耗低、允许工作电压范围宽等特点。目前,单片机系统中使用较多的EEPROM芯片是24系列串行EEPROM。其具有型号多、容量大、支持I2C总线协议、占用单片机I/O端口少,芯片扩展方便、读写简单等优点。 目前,Atmel、MicroChip、National等公司均提供各种型号的I2C总线接口的串行EEPROM存储器。下面以Atmel公司的产品为例进行介绍。 AT24C01/02/04/08系列是Atmel公司典型的I2C串行总线的EEPROM。这里以AT24C08为例介绍。AT24C08具有1024×8位的存储容量,工作于从器件模式,可重复擦写100万次,数据可以掉电保存100年。8引脚DIP封装的AT24C08的封装结构,如图所示。
在51上用P1口模拟I2C

在51上用P1口模拟I2C在51上用P1口模拟I2C原文:下面是用普通C51实现的I2C基本电平模拟函数和通用函数。
/* 电平模拟函数和基本读写函数void IIC_Start(void);void IIC_Stop(void);void SEND_0(void);void SEND_1(void);bit Check_Acknowledge(void);void Write_Byte(uchar b)reentrant;bit Write_N_Bytes(uchar *buffer,uchar n)reentrant;bit Read_N_Bytes(uchar SlaveAdr,uchar n,uchar *buffer); uchar Read_Byte(void)reentrant;*/#include<string.h>#include<reg52.h>#include<intrins.h>#include"aiic_51.h"sbit SCL=P1^6;sbit SDA=P1^7;void DELAY(uint t){while(t!=0)t--;}void IIC_Start(void){//启动I2C总线的函数,当SCL为高电平时使SDA产生一个负跳变SDA=1;SCL=1;DELAY(DELAY_TIME);SDA=0;DELAY(DELAY_TIME);SCL=0;DELAY(DELAY_TIME);}void IIC_Stop(void){//终止I2C总线,当SCL为高电平时使SDA产生一个正跳变SDA=0;SCL=1;DELAY(DELAY_TIME);SDA=1;DELAY(DELAY_TIME);SCL=0;DELAY(DELAY_TIME);}void SEND_0(void){//发送0,在SCL为高电平时使SDA信号为低SDA=0;SCL=1;DELAY(DELAY_TIME);SCL=0;DELAY(DELAY_TIME);}void SEND_1(void){//发送1,在SCL为高电平时使SDA信号为高SDA=1;SCL=1;DELAY(DELAY_TIME);SCL=0;DELAY(DELAY_TIME);}bit Check_Acknowledge(void){//发送完一个字节后检验设备的应答信号SDA=1;SCL=1;DELAY(DELAY_TIME/2);F0=SDA;DELAY(DELAY_TIME/2);SCL=0;DELAY(DELAY_TIME);if(F0==1)return FALSE;return TRUE;}void Write_Byte(uchar b)reentrant{//向IIC总线写一个字节uchar i;for(i=0;i<8;i++)if((b<<i)&0x80)SEND_1();elseSEND_0();}bit Write_N_Bytes(uchar *buffer,uchar n)reentrant {//向I2C总线写n个字节uchar i;IIC_Start();for(i=0;i<n;i++){Write_Byte(buffer);if(!Check_Acknowledge()){IIC_Stop();return(i==n);}}IIC_Stop();return TRUE;}uchar Read_Byte(void)reentrant{//从I2C总线读一个字节uchar b=0,i;for(i=0;i<8;i++){SDA=1; //释放总线SCL=1; //接受数据DELAY(10);F0=SDA;DELAY(10);SCL=0;if(F0==1){b=b<<1;b=b|0x01;}elseb=b<<1;}return b;}bit Read_N_Bytes(uchar SlaveAdr,uchar n,uchar *buffer) {//从I2C总线读n个字节uchar i;IIC_Start();Write_Byte(SlaveAdr); //向总线发送接收器地址if(!Check_Acknowledge()) //等待接收器应答信号return FALSE;for(i=0;i<n;i++){buffer=Read_Byte();if(i!=n)SEND_0(); //发送应答elseSEND_1(); //发送非应答}IIC_Stop();return TRUE;}使用上述代码,你可以在51上用P1口模拟I2C。
2单片机IO口控制实验实验报告

MCS-51复位后,IE清0,所有中断请求被禁止。
若使某一个中断源被允许中断,除了IE相应的位的被置“1” ,还必须使EA位=1。
改变IE的内容,可由位操作指令来实现,即:
SETB bit;
CLR bit。
b、中断优先级寄存器IP
两个中断优先级,可实现两级中断嵌套。
SETBIT0;指定INT0为边沿触发方式
SETBEX0;开放INT0中断
SETBEA;开放CPU的中断
SJMP$;等待中断
ORG8200H;INT0中断服务程序
INT0:
CPLP1.0;LED状态取反一次
CPLP1.1
CPLP1.2
RETI
;
END
七、实验记录
1、在keil环境下编辑汇编程序,且调试无差错。将程序下载到单片机后,程序运行顺利,实现了预期的功能,即随着开关S0的状态改变,LED 灯D0、D1、D2点亮或熄灭。
一个数据输出锁存器,用于输出数据的锁存;
两个三态输入缓冲器,BUF1用于读锁存器,BUF2用于读引脚;
一个多路开关MUX,它的一个输入来自锁存器的Q端,另一个输入来自内部地址的高8位;
数据输出驱动电路由非门M,场效应管VT和片内上拉电阻R组成。
⑵ P2口的特点
P2口用作高8位地址输出线应用时,与P0口输出的低8位地址一起构成16位的地址总线,可以寻址64KB地址空间。
当P2口作高8位地址输出口时,其输出锁存器原锁存的内容保持不变。
作为通用I/O口使用时,P2口为准双向口,功能与P1口一样。
P2口能驱动4个TTL负载。
9、P3口结构及特点:
⑴ P3口结构组成
一个数据输出锁存器,用于输出数据的锁存;
51单片机模拟I2C总线的C语言实现

51单片机模拟I2C总线的C语言实现电路原理图EEPROM为ATMEL公司的AT24C01A。
单片机为ATMEL公司的AT89C51。
软件说明C语言为Franklin C V3.2。
将源程序另存为testi2c.c,用命令C51 testi2c.cL51 TESTI2C.OBJOHS51 TESTI2C编译,连接,得到TESTI2C.HEX文件,即可由编程器读入并进行写片,实验。
3.源程序#include <reg51.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned int#define AddWr 0xa0 /*器件地址选择及写标志*/#define AddRd 0xa1 /*器件地址选择及读标志*/#define Hidden 0x0e /*显示器的消隐码*//*有关全局变量*/sbit Sda= P3^7; /*串行数据*/sbit Scl= P3^6; /*串行时钟*/sbit WP= P3^5; /*硬件写保护*/void mDelay(uchar j){ uint i;for(;j>0;j--){ for(i=0;i<125;i--){;}}}/*发送起始条件*/void Start(void) /*起始条件*/{Sda=1;Scl=1;_nop_ ();_nop_ ();_nop_ ();_nop_ ();Sda=0;_nop_ ();_nop_ ();_nop_ ();_nop_ ();}void Stop(void) /*停止条件*/{Sda=0;Scl=1;_nop_ ();_nop_ ();_nop_ ();_nop_ ();Sda=1;_nop_ ();_nop_ ();_nop_ ();_nop_ ();}void Ack(void) /*应答位*/ {Sda=0;_nop_ ();_nop_ ();_nop_ ();_nop_ ();Scl=1;_nop_ ();_nop_ ();_nop_ ();_nop_ ();Scl=0;}void NoAck(void) /*反向应答位*/{Sda=1;_nop_ ();_nop_ ();_nop_ ();_nop_ ();Scl=1;_nop_ ();_nop_ ();_nop_ ();_nop_ ();Scl=0;}void Send(uchar Data) /*发送数据子程序,Data为要求发送的数据*/ {uchar BitCounter=8; /*位数控制*/uchar temp; /*中间变量控制*/do{temp=Data;Scl=0;_nop_ ();_nop_ ();_nop_ ();_nop_ ();if((temp&0x80)==0x80)/* 如果最高位是1*/Sda=1;elseSda=0;Scl=1;temp=Data<<1; /*RLC*/Data=temp;BitCounter--;}while(BitCounter);Scl=0;}uchar Read(void) /*读一个字节的数据,并返回该字节值*/ {uchar temp=0;uchar temp1=0;uchar BitCounter=8;Sda=1;do{Scl=0;_nop_ ();_nop_ ();_nop_ ();_nop_ ();Scl=1;_nop_ ();_nop_ ();_nop_ ();_nop_ ();if(Sda) /*如果Sda=1;*/temp=temp|0x01; /*temp的最低位置1*/elsetemp=temp&0xfe; /*否则temp的最低位清0*/ if(BitCounter-1){ temp1=temp<<1;temp=temp1;}BitCounter--;}while(BitCounter);return(temp);}void WrToROM(uchar Data[],uchar Address,uchar Num) {uchar i;uchar *PData;PData=Data;for(i=0;i<Num;i++){Start(); /*发送启动信号*/Send(0xa0); /*发送SLA+W*/Ack();Send(Address+i); /*发送地址*/Ack();Send(*(PData+i));Ack();Stop();mDelay(20);}}void RdFromROM(uchar Data[],uchar Address,uchar Num) {uchar i;uchar *PData;PData=Data;for(i=0;i<Num;i++){Start();Send(0xa0);Ack();Send(Address+i);Ack();Start();Send(0xa1);Ack();*(PData+i)=Read();Scl=0;NoAck();Stop();}}void main(){uchar Number[4]={1,2,3,4};WP= 1;WrToROM(Number,4,4); /*将初始化后的数值写入EEPROM*/mDelay(20);Number[0]=0;Number[1]=0;Number[2]=0;Number[3]=0; /*将数组中的值清掉,以验证读出的数是否正确*/RdFromROM(Number,4,4);}问题:本程序中未采用块读写的方法,显得有点‘笨’,这是由于项目原因,现项目已完成,程序已写好,短时不会修改,也不会花上一定的精力去做,虽然理论上已很成熟,就这样写一下,未必不对,但与我的本栏目要求不符,所以就未做上去,如果以后我做了,将再补上。
实验八 51系列单片机IIC

•
I_Delay(100);
•
SCL=HIGH;
•
I_Delay(100);
•
S);
•
SCL=LOW;
•
I_Delay(100);
•}
8.3.3 应答信号
• 应答信号用于表明数据传输的结束。I2C总线数据传送时,每传送一个字节 数据后都必须有应答信号。应答信号从主器件产生。主器件在第9个时钟 位上释放数据总线,使其处于高电平状态,此时从器件输出低电平拉低数 据总线为应答信号。
• 如果采用C语言进行程序设计,则发送应答位子程序示例如下:
• void I_Ack()
•{
•
SDA=LOW;
•
I_Delay(100);
•
SCL=HIGH;
•
I_Delay(100);
•
SCL=LOW;
•
I_Delay(100);
•
SDA=HIGH;
•
I_Delay(100);
•}
8.3.4 非应答信号
• 非应答信号用于数据传输出现异常而无法完成时。 在传送完一个字节数据后,在第9个时钟位上从器 件输出高电平为非应答信号。非应答信号的产生 有两种情况。
• 当从器件正在进行其他处理而无法接收总线上的 数据时,从器件不产生应答,此时从器件释放总 线,将数据线置为高电平。这样,主器件可产生 一个停止信号来终止总线数据传输。
51系列单片机与外围接口芯片的实验和技巧

51系列单片机与外围接口芯片的实验和技巧51系列单片机是一种常用的微控制器,具有广泛的应用领域。
为了提高单片机的功能和扩展其外围接口,常常需要使用外围接口芯片。
本文将介绍一些与51系列单片机配合使用的外围接口芯片的实验和技巧。
一、LCD液晶显示屏LCD液晶显示屏是一种常见的外围接口设备,可以用来显示各种信息。
与51系列单片机配合使用时,需要通过IO口进行数据和控制信号的交互。
在使用LCD液晶显示屏时,需要注意以下几点:1. 配置IO口的工作模式:将IO口设置为输出模式,以便向液晶显示屏发送控制信号和数据。
2. 使用延时函数:由于LCD液晶显示屏的响应速度较慢,需要在发送完数据后进行适当的延时,以确保数据能够被正确接收和显示。
3. 熟悉液晶显示屏的命令和数据格式:LCD液晶显示屏有自己的一套命令和数据格式,需要根据具体型号的要求进行设置。
二、ADC模数转换芯片ADC模数转换芯片可以将模拟信号转换为数字信号,常用于采集和处理模拟信号。
与51系列单片机配合使用时,需要注意以下几点:1. 配置IO口的工作模式:将IO口设置为输入模式,以便接收来自ADC芯片的模拟信号。
2. 设置ADC模数转换的精度:根据需要,可以调整ADC芯片的工作精度,以获得更高的准确性或更快的转换速度。
3. 调用ADC转换函数:通过调用相应的函数,可以启动ADC芯片进行模数转换,并获取转换结果。
三、DAC数模转换芯片DAC数模转换芯片可以将数字信号转换为模拟信号,常用于控制模拟设备的输出。
与51系列单片机配合使用时,需要注意以下几点:1. 配置IO口的工作模式:将IO口设置为输出模式,以便向DAC芯片发送数字信号。
2. 设置DAC数模转换的精度:根据需要,可以调整DAC芯片的工作精度,以获得更高的准确性或更大的输出范围。
3. 调用DAC转换函数:通过调用相应的函数,可以向DAC芯片发送数字信号,并控制其输出模拟信号的大小。
四、串口通信芯片串口通信芯片可以实现与其他设备的串口通信,常用于数据传输和远程控制。
51单片机实验报告

51单片机实验报告51单片机是一款非常流行的单片机芯片,被广泛应用于各种电子产品中。
在这篇文章中,我们来探讨一下51单片机的一些实验,以及对于这些实验的理解和体会。
第一部分:实验内容我们进行的51单片机实验主要包括以下几个方面:1. 闪烁LED灯实验:这个实验是入门级别的,主要是为了熟悉51单片机的基本操作和编程方法。
在这个实验中,我们使用了一块51单片机开发板和几个LED灯,通过控制单片机的IO口信号来实现LED灯的闪烁。
2. 按键控制LED实验:这个实验是在闪烁LED实验的基础上进一步延伸的,主要是为了了解如何通过外部按键来控制单片机的输出。
在这个实验中,我们运用了单片机的外部中断和定时器等功能,实现了按键控制LED灯的亮灭。
3. LCD1602显示屏实验:这个实验是为了让我们熟悉如何在51单片机中使用LCD1602液晶显示屏。
在这个实验中,我们使用了I2C总线来与LCD1602进行通信,通过向LCD1602发送命令和数据来实现字符的显示。
4. 电机驱动实验:这个实验是让我们了解如何使用51单片机来控制电机的运转。
在这个实验中,我们运用了单片机的PWM控制功能,通过改变PWM波的占空比来控制电机的转速和方向。
第二部分:实验体会通过这些实验,我对于51单片机有了更深刻的理解和体会。
在这里,我想分享一下我的一些体会。
首先,我认为51单片机具有非常强大的控制能力和灵活性。
通过编写程序,我们可以控制单片机的各种IO口、定时器、PWM输出等功能,从而实现各种复杂的控制任务。
同时,由于其能够直接操作硬件,所以可以快速响应各种外部事件,对实时性要求较高的应用场景有很好的适应性。
其次,我发现在51单片机开发中,良好的软硬件结合非常重要。
由于51单片机具有丰富的外部中断、定时器等功能,因此我们可以很好地利用这些硬件资源来实现各种功能。
同时,在编写程序时,我们也需要充分发挥51单片机的硬件优势,例如使用定时器来完成计时任务,使用外部中断来完成输入检测等等。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
(预习报告)一、实验目的掌握基于MCS-51系统的总线扩展的方法二、实验内容1.利用MCS-51系统的P1口模拟总线接口,扩展串口存储器24C16,每次存入1个数据,并反复读回,用示波器测试读回的波形。
(分别以数据AAH,55H测试)2.将MCS-51系统片内存储器的10个数据存入串口存储器24C16并读回,分别设置存入的地址为页地址+00H和页地址+07H。
读回为地址页地址+00H,将读回的数据存放在片内存储器,并与发送数据进行比较。
三、硬件原理图只需将24C16的SCL与P1.1相连,SDA与P1.0相连即可。
24C16资料:四、程序清单8-4-1ACK BIT 10H ;应答位判断标志SDA BIT P1.0 ;数据线SCL BIT P1.1 ;时钟线ORG 0030HSEND: LCALL START ;启动MOV A,#0A0H ;控制字节为#0A0HLCALL WRBYTE ;发送控制字节LCALL CACK ;接收应答JNB ACK,SEND ;收到无效应答,重新发送 MOV A,#30H ;写入的地址为#30HLCALL WRBYTE ;发送地址LCALL CACK ;接收应答JNB ACK,SEND ;收到无效应答,重新发送 MOV A,#0AAH ;写入的数据位#0AAHLCALL WRBYTE ;发送数据LCALL CACK ;接收应答JNB ACK,SEND ;收到无效应答,重新发送 LCALL STOP ;停止LCALL DELAY ;发送与接收之间加入一段延时READ: LCALL START ;启动MOV A,#0A0H ;控制字节为#0A0HLCALL WRBYTE ;发送控制字节LCALL CACK ;接收应答JNB ACK,READ ;收到无效应答,重新启动MOV A,#30H ;读的地址为#30HLCALL WRBYTE ;发送读地址LCALL CACK ;接收应答JNB ACK,READ ;收到无效应答,重新启动 LCALL START ;重新启动MOV A,#0A1H ;控制字节为#0A1HLCALL WRBYTE ;发送控制字节LCALL CACK ;接收应答JNB ACK,READ ;收到无效应答,重新启动 LCALL RDBYTE ;从24C16的地址30H读回数据 MOV 40H,A ;把数据存入内部存储器40H LCALL MNACK ;发送无效应答LCALL STOP ;停止AJMP READ ;循环读回数据DELAY: MOV R5,#10HD1: MOV R6,#0FFHD2: MOV R7,#0FFHDJNZ R7,$DJNZ R6,D2DJNZ R5,D1RET;发送单字节子程序,字节数据放入ACC WRBYTE:MOV R0,#08HWLP: RLC A ;移出ACC.7到CYJC WR1 ;若CY为1,发送'1'SJMP WR0 ;若CY为0,发送'0'WLP1: DJNZ R0,WLP ;已发送8位二进制数,返回RETWR1: SETB SDA ;发送1NOPSETB SCLNOPNOPNOPNOPCLR SCLAJMP WLP1WR0: CLR SDA ;发送0NOPSETB SCLNOPNOPNOPNOPCLR SCLSJMP WLP1;读取字节子程序,读出的数据存放在ACCRDBYTE:MOV R0,#08HRLP: SETB SDANOPSETB SCL ;时钟线为高,接收数据位NOPNOPMOV C,SDA ;读取数据位MOV A,R2CLR SCL ;将SCL拉低,时间大于4.7usRLC A ;进行数据位的处理MOV R2,ANOPNOPNOPDJNZ R0,RLP ;未够8位,继续读入RET;启动I2C总线子程序START: SETB SDANOPSETB SCL ;发送起始条件的时钟信号NOPNOPNOPNOPNOP ;起始条件锁定时间大于4.7usCLR SDA ;发送起始信号NOPNOPNOPNOP ;起始条件锁定时间大于4.7usCLR SCL ;钳住I2C总线,准备发送或接收数据 NOPRET;停止I2C总线子程序STOP: CLR SDANOPNOPSETB SCL ;发送停止条件的时钟信号NOPNOPNOPNOPNOP ;起始条件建立时间大于4.7us SETB SDA ;发送I2C总线停止信号NOPNOPNOPNOPNOP ;延迟时间大于4.7usRET;发送无效应答信号子程序MNACK: SETB SDANOPNOPSETB SCLNOPNOPNOPNOPNOPCLR SCL ;保持数据时间,大于4.7us NOPNOPRET;接收应答位子程序, ACK=1时表示正常应答CACK: SETB SDANOPNOPSETB SCLCLR ACKNOPNOPMOV C,SDAJC CEND ;判断应答位SETB ACKCEND: NOPCLR SCLNOPRETEND8-4-2、ACK BIT 10H ;应答位判断标志SDA BIT P1.0 ;数据线SCL BIT P1.1 ;时钟线ORG 0030HMAIN: MOV R0,#0AH ;发送数据缓存区初始化MOV R1,#30H ;将30H开始的10个地址分别赋值为00H到09H MOV A,#00HW1: MOV @R1,AINC R1INC ADJNZ R0,W1SEND: MOV R1,#30H ;数据内存地址为30HMOV R2,#0AH ;发送10个数据LCALL START ;启动MOV A,#0A0H ;控制字节为#0A0HLCALL WRBYTE ;发送控制字节LCALL CACK ;接收应答JNB ACK,SEND ;收到无效应答,重新发送MOV A,#00H ;写入的页地址为+00HLCALL WRBYTE ;发送地址LCALL CACK ;接收应答JNB ACK,SEND ;收到无效应答,重新发送S1: MOV A,@R1 ;发送数据LCALL WRBYTELCALL CACK ;接收应答JNB ACK,SEND ;收到无效应答,重新发送INC R1DJNZ R2,S1 ;发送10个数据,写入地址自动加1LCALL STOP ;停止LCALL DELAY ;两次发送之间加入一段延时SEND1: MOV R1,#30H ;数据内存地址为30HMOV R2,#0AH ;发送10个数据LCALL STARTMOV A,#0A0H ;控制字节为#0A0HLCALL WRBYTELCALL CACKJNB ACK,SEND1 ;收到无效应答,重新发送MOV A,#07H ;写入的页地址为+07HLCALL WRBYTELCALL CACKJNB ACK,SEND1S2: MOV A,@R1LCALL WRBYTELCALL CACKJNB ACK,SEND1INC R1DJNZ R2,S2LCALL STOPLCALL DELAY ;发送与接收之间加入一段延时READ: MOV R3,#14H ;从24C16读回20个数据MOV R1,#40H ;存入40H开始的内部存储器LCALL START ;启动MOV A,#0A0H ;控制字节为#0A0HLCALL WRBYTE ;发送控制字节LCALL CACK ;接收应答JNB ACK,READ ;收到无效应答,重新启动MOV A,#00H ;读回的页地址为+00HLCALL WRBYTE ;发送读地址LCALL CACK ;接收应答JNB ACK,READ ;收到无效应答,重新启动LCALL START ;重新启动MOV A,#0A1H ;控制字节为#0A1HLCALL WRBYTE ;发送控制字节LCALL CACK ;接收应答JNB ACK,READ ;收到无效应答,重新启动E2: LCALL RDBYTE ;从24C16读回数据LCALL MACK ;发送应答MOV @R1,A ;读回数据存入内部存储器INC R1DJNZ R3,E2 ;读20个数据LCALL MNACK ;发送无效应答LCALL STOP ;停止HE: AJMP HE;子程序;启动I2C总线START: SETB SDANOPNOPSETB SCL ;发送起始条件的时钟信号NOPNOPNOPNOPNOP ;起始条件锁定时间大于4.7usCLR SDA ;发送起始信号NOPNOPNOPNOP ;起始条件锁定时间大于4.7usCLR SCL ;钳住I2C总线,准备发送或接收数据NOPNOPRET;停止I2C总线STOP: CLR SDANOPNOPSETB SCL ;发送停止条件的时钟信号NOPNOPNOPNOPNOP ;起始条件建立时间大于4.7us SETB SDA ;发送I2C总线停止信号NOPNOPNOPNOPNOP ;延迟时间大于4.7usRET;延时DELAY: MOV R5,#0FHD1: MOV R6,#32HD2: MOV R7,#64HDJNZ R7,$DJNZ R6,D2DJNZ R5,D1RET;发送单字节子程序,字节数据放入ACCWRBYTE:MOV R0,#08HWLP: RLC A ;移出ACC.7到CYJC WR1 ;若CY为1,发送‘1’SJMP WR0 ;若CY为0,发送‘0’WLP1: DJNZ R0,WLP ;已发送8位二进制数,返回RETWR1: SETB SDA ;发送1NOPSETB SCLNOPNOPNOPNOPCLR SCLAJMP WLP1WR0: CLR SDA ;发送0NOPSETB SCLNOPNOPNOPNOPCLR SCLSJMP WLP1;读取字节子程序,读出的数据存放在ACCRDBYTE:MOV R0,#08H ;共读8位RLP: SETB SDANOPSETB SCL ;时钟线为高,接收数据位NOPNOPMOV C,SDA ;读取数据位MOV A,R2CLR SCL ;将SCL拉低,时间大于4.7us RLC A ;进行数据位的处理MOV R2,ANOPNOPNOPDJNZ R0,RLP ;未够8位,继续读入RET;发送应答信号子程序MACK: CLR SDANOPNOPSETB SCLNOPNOPNOPNOPNOP ;保持数据时间,大于4.7usCLR SCLNOPNOPRET;发送无效应答信号子程序MNACK: SETB SDANOPNOPSETB SCLNOPNOPNOPNOPNOPCLR SCL ;保持数据时间,大于4.7us NOPNOPRET;接收应答位子程序, ACK=1时表示正常应答CACK: SETB SDANOPNOPSETB SCLCLR ACKNOPNOPMOV C,SDAJC CEND ;判断应答位SETB ACK ;正常CEND: NOPCLR SCLNOPRETEND(实验报告)一、硬件原理图拿到24C16后发现需要查看一下引脚的连法,于是上网查了24C16的datasheet:其中A0,A1,A2,GND都接地,VCC+5V。