C51单片机模拟I2C总线驱动程序

合集下载

51单片机的I2C底层驱动程序(IO口模拟)

51单片机的I2C底层驱动程序(IO口模拟)

51单片机的I2C底层驱动程序(IO口模拟)/*Title:I2C for 80C51Author:yuyouliang51单片机(本人使用STC89C52单片机,12T模式)的I2C驱动程序,使用逻辑分析仪对该协议进行分析,发现波形比较美观,SCL 的频率在70KHz左右(11.0592M晶振),低于标准的100K,可以适应大多数的I2C器件。

如果感觉速度过快或过慢,可以自行修改延时。

希望可以给读者一个参考,给读者一些帮助!*//*i2c.h文件 */#ifndef __I2C_H_#define __I2C_H_sbit SCL = P2^1;sbit SDA = P2^0;void start_i2c(); //启动I2C总线:SCL高电平期间,SDA由高变低void stop_i2c(); //停止I2C总线:SCL高电平期间,SDA由低变高void send_i2c(unsigned char c); //主机发送一个字节,先发送最高位unsigned char receive_i2c(); //主机接收一个字节,先接收最高位void master_ack(bit ack); //主机非应答信号(填参数0)或应答信号(填参数1)void slave_ack(); //等待从机应答信号#endif/* i2c.c文件 */#include#include#include#define nop() _nop_()void start_i2c() //启动I2C总线:SCL高电平期间,SDA由高变低{SDA=1;SCL=1;nop();nop();nop();nop();SDA=0;SCL=0;}void stop_i2c() //停止I2C总线,SCL高电平期间,SDA由低变高{SDA=0;SCL=1;nop();nop();nop();nop();SDA=1;}void slave_ack() //等待从机应答信号,如果从机迟迟没有应答,则结束总线。

C51单片机模块驱动程序参考

C51单片机模块驱动程序参考
{0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
0x38,0x39,0x41,0x42,0x43,0x44,0x45,0x46
};定义在函数外部
unsigned char Key_ASC2(unsigned char key)
{
unsigned char key_asc2;
{
StartI2C();
Write8Bit(0xA2);
ChackAck();
Write8Bit(RomAddress);
ChackAck();
StartI2C();
Write8Bit(0xA3);
ChackAck();
for(;bytes!=1;bytes--)
{
*RamAddress=Read8Bit();
i=*ptr;
i &=பைடு நூலகம்0x80;
if(i==0)
break;
}
}
函数功能描述:向1602指令寄存器写指令;
void WriteW(uint a)
{
ptr=0xAFF0;//RS=0,R/W=0
*ptr=a;
}
函数功能描述:LCD初始化;
void LCD_Init(void)
{
CheckBF();
WriteW(0x38);
函数功能描述:键盘初始化,将标志位置1;
void Key_Init(void)
{
bKeyUp_Flag=1;//标志(全局变量)位置1
}
函数功能描述:键盘扫描函数,得到键的行列位置;
unsigned char GetScanKey(void)
{
unsigned char key, i, temp;

I2C总线(主)C51源程序

I2C总线(主)C51源程序

I2C总线(主)C51源程序#define ROMADDRESS 0xA0sfr IIC_CON = 0xA0;sbit WP = IIC_CON^5;sfr IIC_INTER = 0x90;sbit SCL = IIC_INTER^6;sbit SDA = IIC_INTER^7;bit ack; /*应答标志位*/void DelayMs(unsigned char i){unsigned int count;for(i;i!=0;i--)for(count=6;count!=0;count--);}/************************************************************** *********//*名称: IIC_Start()/*说明: 启动I2C总线,即发送I2C起始条件./*输入: 无/*输出: 无/************************************************************** *********/void IIC_Start(void){SCL=1; DelayMs(1);SDA=1; DelayMs(1);SDA=0; DelayMs(1); /*发送起始信号*/SCL=0; DelayMs(1); /*钳住I2C总线,准备发送或接收数据 */ }/***********************************************************************//*名称: IIC_Stop()/*说明: 结束I2C总线,即发送I2C结束条件./*输入: 无/*输出: 无/************************************************************** *********/void IIC_Stop(void){SCL=1; DelayMs(1); /*发送结束条件的时钟信号*/SDA=0; DelayMs(1);SDA=1; DelayMs(1); /*发送I2C总线结束信号*/SCL=0; DelayMs(1);}/************************************************************** *********//*名称: IIC_DataSend()/*说明: 将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对此状态位进行操作.(不应答或非应答都使ack=0)ack=1表示发送数据正常; ack=0表示被控器无应答或损坏。

周立功—I2C 总线实验

周立功—I2C 总线实验

I2C 总线实验(实时时钟、EEPROM 和ZLG7290 的实验)一.实验目的加深用户对I2C 总线的理解,熟悉I2C 器件的使用,提供用户实际开发的能力。

二.实验设备及器件IBM PC 机一台DP-51PROC 单片机综合仿真实验仪一台三.实验内容进行I2C 总线控制的实时时钟、EEPROM、ZLG7290 键盘LED 控制器实验。

四.实验要求熟练掌握I2C 总线的控制,灵活运用I2C 主控器软件包,深刻理解实时时钟、EEPROM、ZLG7290 键盘LED 控制的各种功能。

五.实验步骤1.使用导线连接D5 区的SCL、SDA 到A2 区的P16、P17(SCL~P16、SDA~P17),连接D5 区的RST_L、INT_KEY 到A2 区的P10、INT0(RST_L~P10、INT_KEY~INT0),短接D5 区的JP1 跳线。

2.把模拟I2C 软件包“VIIC_C51.C”文件加入到Keil C51 的项目中,程序源文件的开头包含“VIIC_C51.H”头文件。

修改VIIC_C51.C 文件中的sbit SDA=P1^7;和sbit SCL=P1^6;。

图3.21 RTC原理图3.使用函数ISendStr(uchar sla,uchar suba,uchar *s,uchar no)对PCF8563T实时时钟进行设置初始时间,再使用IRcvStr(uchar sla,uchar suba,uchar*s,uchar no)对PCF8563T 实时时钟的时间进行读取。

EEPROM 原理图4.使用函数ISendStr(uchar sla,uchar suba,uchar *s,uchar no);对24WC02EEPROM 进行写入,再使用IRcvStr(uchar sla,uchar suba,uchar *s,uchar no);对24WC02 EEPROM 进行读取。

ZLG7290 原理图5.对ZLG7290 键盘LED 控制器的操作也同理,只是在程序开始的地方增加复位操作和程序中间增加查询是否有键按下。

在51上用P1口模拟I2C

在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。

C51实现I2C总线单主多从通信

C51实现I2C总线单主多从通信
长沙航空职业技术学院
设计论文
C51 实现 I2C 单主多从通信
专业: 航空电子信息
班级:
航电 1203
姓名:
陈瑞金
指 导 老 师 : 鄢立、程秀玲
时 间:
2014.04
1
陈瑞金
________________________________________________________________________________________________________________
五、程序的编写
1、设计思路--------------------------------------------------------------12
2、参考程序
a.主机程序------------------------------------------------------------14
2、关于 24C02 的读写---------------------------------------------------7
四、硬件电路
1、Proteurs 绘制的电路图----------------------------------------------8
2、Proteurs 仿真效果图------------------------------------------------10
当主机接收数据时,它收到最后一个数据字节后,必须向从机发出一个结束传送的信号。这个信号是由对从机 的“非应答”来实现的。然后,从机释放 SDA 线,以允许主机产生终止信号。
(2)数据帧率格式 I2C 总线上传送的数据信号是广义的,既包括地址信号,又包括真正的数据信号。在起始信号后必须传送一个

第16章 C51模拟I2C总线

第16章  C51模拟I2C总线

16.1.3
2C总线数据操作 I
在I2C总线上,数据是伴随着时钟脉冲,一位一位地传
送的,数据位由低到高传送,每位数据占一个时钟脉 冲。I2C总线上的在时钟线SCL高电平期间,数据线 SDA的状态就表示要传送的数据,高电平为数据1,低 电平为数据0。在数据传送时,SDA上数据的改变在时 钟线为低电平时完成,而SCL为高电平时,SDA必须 保持稳定,否则SDA上的变化会被当作起始或终止信 号而致使数据传输停止。
16.3.9 多字节写子函数
启动I2C
多字节写子函数用于主器件发送
发送写寻址地 址
多个字节的数据。首先发送起始 位,接着是寻址字节,然后是数 据的所要存入单元的首地址,外 围器件此时产生正确的应答后, 主器件便将开始多个字节的数据 传输。多字节写子函数的流程图, 如图所示。
应答检查
写数据存储首 地址
16.3.8 单字节读子函数
单字节读子函数用于从I2C数据总
线读入单个字节的数据。程序中, 可以通过for循环语句,逐位将数 据读入。该函数在使用之前,同样 需要先使用起始信号子函数启动 I2C总线数据传输。单字节读子函 数emp=0?

左移一位
读一个bit
返回数据
16.2 I2C总线接口EEPROM存储器
目前,市场上I2C总线接口器件有多种,例如A/D转换器、D/A转换器、时钟芯 片和存储器等。这里以典型的I2C总线接口的存储器为例进行介绍。
I2C总线接口EEPROM存储器是一种采用I2C总线接口的串行总线存储器,这类 存储器具有体积小、引脚少、功耗低、工作电压范围宽等特点。目前,Atmel、 MicroChip、National等公司均提供各种型号的I2C总线接口的串行EEPROM存 储器。在单片机系统中使用较多的EEPROM存储器是24系列串行EEPROM。 其具有型号多、容量大、支持I2C总线协议、占用单片机I/O端口少,芯片扩展 方便、读写简单等优点。

软件模拟I2C总线的C51实现.

软件模拟I2C总线的C51实现.

软件模拟I2C总线的C51实现摘要:介绍51系列单片机上的I2C总线主节点模拟程序,从而实现与具有I2C接口的器件通信。

1I2C总线简介1.1硬件结构I2C串行总线支持所有NMOS、CMOS、I2L工艺制造的器件。

从物理上看由两根双向I/O线组成,一根为数据线(SDA),一根为时钟线(SCL),通过这两根线把所有器件连接到总线上,并通过SDA和SCL在各器件间传递信息(根据地址识别每个器件)。

SDA和SCL通过上拉电阻接正电源,总线空闲时,两根线都是高电平。

这两根I/O线在电气上允许“线与”操作,其输出的驱动形式为集电极开路或漏极开路。

根据通信速度的不同,I2C总线分为三种工作模式:标准模式、快速模式和高速模式。

它们分别对应不同的波特率:100kb/s、400kb/s和3.4Gb/s。

总线上允许的设备数以总线上的电容量不超过400pF为限。

1.2数据传输I2C总线上数据为同步传输。

挂在I2C总线上的每一个器件都有一个独立的地址,而且在传输过程中有主节点和从节点的区分,主节点的作用是启动和结束一次通信,并负责控制总线时钟,总线上可以有多个主节点或多个从节点,但是在一次通信中只能有一个节点作为主节点。

主从机之间一次数据的传输称为一帧,由启动信号、地址信息、应答位及停止位组成。

其传送格式见图1。

2MCS-51与I2C总线芯片接口及程序2.18051经I2C总线扩展存储器PCF8582对于内部没有硬件I2C总线接口的51系列单片机,可以采用软件模拟的方法实现I2C总线接口功能。

硬件连接如图2所示。

用8051的P1.6和P1.7作为I2C总线的SCL利SDA信号,在总线上连接256*8的EEPROM芯片PCF8582。

8051单片机与PCF8582进行数据传递时,首先传送器件的从机地址SLA,格式如下:START为起始信号,从机地址的固定部分是4位——1010,可编程部分由,则该片的从机地址为引脚A2、A1、A0确定。

8051模拟i2C总线24c02读写源代码C语言

8051模拟i2C总线24c02读写源代码C语言
I2C_Start();
WriteI2CByte(0xa0);
acktemp=Check_Acknowledge();
WriteI2CByte(addr);/*address*/
acktemp=Check_Acknowledge();
I2C_Start();
WriteI2CByte(addr);/*address*/
acktemp=Check_Acknowledge();
WriteI2CByte(thedata);/*thedata*/
acktemp=Check_Acknowledge();
I2C_Stop();
实例1
/* 51系列单片机在使用时,有时需要模拟I2C总线_nbsp; */
/* 这里举出一个实例(读写串行EEPROM芯片at24C02_nbsp; */
/************************************************************************/
Write_A_Page(myarray2,0x18);
mybyte=Read_One_Byte(0x20);
Read_N_Bytes(rdarray,16,0x10);
}
实例2
/********************************** I2C总线驱动 *************************************
}
void SEND_1(void)
{
/*发逿,在SCL为高电平时使SDA信号为高*/
SDA=1;
SCL=1;
DELAY(DELAY_TIME);

51单片机i2c读写程序的详细讲解

51单片机i2c读写程序的详细讲解

51单片机i2c读写程序的详细讲解下载提示:该文档是本店铺精心编制而成的,希望大家下载后,能够帮助大家解决实际问题。

文档下载后可定制修改,请根据实际需要进行调整和使用,谢谢!本店铺为大家提供各种类型的实用资料,如教育随笔、日记赏析、句子摘抄、古诗大全、经典美文、话题作文、工作总结、词语解析、文案摘录、其他资料等等,想了解不同资料格式和写法,敬请关注!Download tips: This document is carefully compiled by this editor. I hope that after you download it, it can help you solve practical problems. The document can be customized and modified after downloading, please adjust and use it according to actual needs, thank you! In addition, this shop provides you with various types of practical materials, such as educational essays, diary appreciation, sentence excerpts, ancient poems, classic articles, topic composition, work summary, word parsing, copy excerpts, other materials and so on, want to know different data formats and writing methods, please pay attention!《51单片机i2c读写程序的详细讲解》一、概述51单片机是一种常用的单片机,在很多应用中使用的最多的是i2c接口,那么如何在51单片机上进行i2c的读写操作呢?下面将详细讲解i2c读写操作的程序设计过程。

I2C总线规范与I2C器件C51读写程序

I2C总线规范与I2C器件C51读写程序
2、I2C规范:
I2C总线规范可以参考有关资料,本文仅给出有关硬件操作的基本概念。
2.1、I2C 总线名词解释:
发送器:发送数据到总线上的器件
接收器:从总线上接收数据的器件
主器件:启动数据传送并产生时钟信号的器件
从器件:被主器件寻址的器件
2.2、I2C总线时序定义:
起始位:SCL=1时,在SDA上有下降延
应答检测:采用应答检测读命令测试从机是否<页写>结束(通过从应答来识别)
*当从器件完成内部写周期后将发送一个应答信号(从应答)给主器件,以便可以继续进行下一次读操作
3、I2C器件C51读写程序
3.1、数据定义说明:
sbit sda=P0^0; //I2C器件SDA数据线
sbit scl=P0^1; //I2C器件SCL时钟线
for(i=0;i<8;i++){
_nop_();
scl=0; //置时钟线为低,准备接收数据位
nops();
scl=1; //置时钟线为高,使数据线上数据有效
_nop_();
c<<=1;
if(sda)c+=1; //读数据位,将接收的数据存c
}
scl=0;
return c;
}
uchar i;
i2c_start();
send_byte(ad_main); //发送器件地址
send_byte(ad_sub); //发送器件子地址
for(i=0;i<num;i++){
send_byte(*buf); //发送数据*buf
buf++;

51单片机模拟串口的三种方法

51单片机模拟串口的三种方法

51单片机模拟串口的三种方法51单片机模拟串口的三种方法随着单片机的使用日益频繁,用其作前置机进行采集和通信也常见于各种应用,一般是利用前置机采集各种终端数据后进行处理、存储,再主动或被动上报给管理站。

这种情况下下,采集会需要一个串口,上报又需要另一个串口,这就要求单片机具有双串口的功能,但我们知道一般的51系列只提供一个串口,那么另一个串口只能靠程序模拟。

本文所说的模拟串口,就是利用51的两个输入输出引脚如P1.0和P1.1,置1或0分别代表高低电平,也就是串口通信中所说的位,如起始位用低电平,则将其置0,停止位为高电平,则将其置1,各种数据位和校验位则根据情况置1或置0。

至于串口通信的波特率,说到底只是每位电平持续的时间,波特率越高,持续的时间越短。

如波特率为9600BPS,即每一位传送时间为1000ms/9600=0.104ms,即位与位之间的延时为为0.104毫秒。

单片机的延时是通过执行若干条指令来达到目的的,因为每条指令为1-3个指令周期,可即是通过若干个指令周期来进行延时的,单片机常用11.0592M的的晶振,现在我要告诉你这个奇怪数字的来历。

用此频率则每个指令周期的时间为(12/11.0592)us,那么波特率为9600BPS每位要间融多少个指令周期呢?指令周期s=(1000000/9600)/(12/11.0592)=96,刚好为一整数,如果为4800BP S则为96x2=192,如为19200BPS则为48,别的波特率就不算了,都刚好为整数个指令周期,妙吧。

至于别的晶振频率大家自已去算吧。

现在就以11.0592M的晶振为例,谈谈三种模拟串口的方法。

方法一:延时法通过上述计算大家知道,串口的每位需延时0.104秒,中间可执行96个指令周期。

#define uchar unsigned charsbit P1_0 = 0x90;sbit P1_1 = 0x91;sbit P1_2 = 0x92;#define RXD P1_0#define TXD P1_1#define WRDYN 44 //写延时#define RDDYN 43 //读延时//往串口写一个字节void WByte(uchar input){uchar i=8;TXD=(bit)0; //发送启始位Delay2cp(39);//发送8位数据位while(i--){TXD=(bit)(input&0x01); //先传低位Delay2cp(36);input=input>>1;}//发送校验位(无)TXD=(bit)1; //发送结束位Delay2cp(46);}//从串口读一个字节uchar RByte(void){uchar Output=0;uchar i=8;uchar temp=RDDYN;//发送8位数据位Delay2cp(RDDYN*1.5); //此处注意,等过起始位 while(i--){Output >>=1;if(RXD) Output |=0x80; //先收低位Delay2cp(35); //(96-26)/2,循环共占用26个指令周期}while(--temp) //在指定的时间内搜寻结束位。

模拟I_2C总线实现AVR与MCS_51单片机通讯

模拟I_2C总线实现AVR与MCS_51单片机通讯
2 I C; M CS- 51; AVR; 总线
中图分类号 : TN 913 文献标识码 : A 文3
Simu la ting th e I2 C to Realize AVR and the M CS- 51 Comm unication GAN H u i (T echnical Institute of YiChun University, YiChun J iangX i 336000, China ) Abstrac : t T he I C has the connection si m ply , the easy tooperate , T his techno logy obta ined the w idespread app lication in the industry
第 30 卷
2 uchar rdbyt ( ) /* 从 I C 总线上读 取 1 个数据字节 * /
{ ucha r nn= 0x f,f mm = 0x80 , uu= 0x7 ; f uchar ; j for ( j= 0; SDA = 1; nn= else nn= } re turn ( nn); } ( nn | mm ); nn= cro l ( nn, 1) ; SCL = 0;
2 2 2 2 2 2 2
( 或接收器 ), 这取决 于它所 要完成 的功能。 CPU 发出 的控 制信号分为 地址码 和控 制量两 部分 , 地 址码 用来选 址 , 即 接通需要控 制的电 路 , 确定 控制 的种类 ; 控制量 决定 该调 整的类别及 需要调 整的 量。这样 , 各 控制 电路虽 然挂 在同 一条总线上 , 却彼此独立 , 互不相关。 I2 C 总线在传 送数据 过程中共有三种 类型 信 号 , 它们 分别 是 : 起 始 信号、 结束 信号和应答信 号。起始 信 号 : 电平时 , SCL 为高 电平 时 , SDA 由高 SCL 为低 电平向低电平跳 变 , 开 始 传送 数据。 结束 信 号 :

51单片机模拟I2C总线的汇编源代码

51单片机模拟I2C总线的汇编源代码
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
CLR SCL
NOP
NOP
NOP
NOP
NOP
SJMP WLP1
;启动IIC总线子程序
START:SETB SDA
NOP
NOP
SETB SCL ;起始条件建立时间大于4.7us
NOP
NOP
NOP
NOP
NOP
CLR SDA ;起始条件锁定大于4us
NOP
SETB SCL ;结束总线时间大于4us
NOP
NOP
NOP
NOP
NOP
SETB SDA ;结束总线
NOP ;保证一个终止信号和起始信号的空闲时间大于4.7us
NOP
RET
;发送字节子程序
;字节数据放入ACC
;每发送一个字节调用一次CACK子程序,取应答位
WRBYTE: MOV R0,#08H
WLP: RLC A ;取数据位
JC WR1
SJMP WR0 ;判断数据位
NOP
NOP
NOP
NOP
CLR SCL
NOP
NOP
NOP
NOP
NOP
SJMP WLP1
IWRNBYTE1:LCALL STOP
IWRNBYTE:LCALL START ;启动总线
MTD EQU 32H ;发送的数据
ORG 0000H
LJMP MAIN
;延时子程序,12M,125mS秒
DELAY:MOV R6,#00H

完整的I2C 模拟总线 C 程序

完整的I2C 模拟总线 C 程序
delay(1);
if ( I2C_SDA )
i2c_ack=1;
else
i2c_ack=0;
I2C_SCL = 0;
delay(1);
}
//‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
//‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
// 读取 24xx 一字节数据 ‥‥‥‥‥‥‥
nop();
// delay(2); // 延迟 47uSec
}
// nop();
I2C_SCL = 0;
nop();
//-------
SDAIO = 1;
I2C_SDA = 1;
//-------
delay(1);
I2C_SCL=1;
//‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
// I2C 模拟总线
//‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
//-----------
unsigned char dfefer[8];
delay(1);
I2C_SCL = 0;
}
// }
}
stop_i2c();
}
//‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥‥
/**********END**************/
// 程序结束
// SCLIO = 0;
nop();
I2C_SDA = 1;
nop();
I2C_SCL = 1;
delay(1); // 24LCxx 要求建立时间大于 Delay40uSec

I2C模拟程序

I2C模拟程序

2.1 虚拟I2C总线汇编程序软件包2.1.1 概述为了非常方便地对I2C从器件进行快速的、正确的读写操作,我们为此而设计出虚拟I2C总线操作平台软件包。

本软件包是主方式下的虚拟I2C总线软件包,只要用户给子程序提供几个主要的参数,即可轻松地完成任何I2C总线外围器件的应用程序设计。

2.1.2I2C串行总线I2C总线是PHILIPS公司推出的芯片间串行数据传输总线,2根线(SDA、SCL)即可实现完善的全双工同步数据传送,能够十分方便地地构成多机系统和外围器件扩展系统。

I2C器件是把I2C的协议植入器件的I/O接口,使用时器件直接挂到I2C总线上,这一特点给用户在设计应用系统带来了极大的便利。

I2C器件无须片选信号,是否选中是由主器件发出的I2C从地址决定的,而I2C器件的从地址是由I2C总线委员会实行统一发配。

我们推出的I2C总线的操作平台软件包,只要你给出器件从地址[,子地址(注:PCF8574无子地址)],即可进行字节读,字节写,多字节读,多字节写,能够非常方便地使用I2C器件,无须你介入底层的I2C操作协议。

2.1.3汇编软件包说明此软件包是用在单主I2C总线上,硬件接口是SDA,SCL,使用MCU的I/O口来模拟SDA/SCL总线。

设计有/无子地址的子程序是根据I2C器件的特点,目的在于将地址和数据彻底分开。

软件包的接口界面为:IRDBYTE (无子地址)读单字节数据(现行地址读)IWRBYTE (无子地址)写单字节数据(现行地址写)IRDNBYTE (有子地址)读N字节数据IWRNBYTE (有子地址)写N字节数据说明:现行地址读/写即专指无子地址的器件,不给定子地址的读/写操作。

;平台占用内部资源:R0,R1,R2,R3,ACC,Cy。

;使用前须定义变量:SLA 器件从地址,SUBA器件子地址,NUMBYTE读/写的字节数,位变量ACK ;使用前须定义常量:SDA 、SCL 总线位,MTD 发送数据缓冲区首址,MRD 接收数据缓冲区首址;(※子程序出口参数ACK为0时表示从器件无应答)2.1.4软件包清单;--------------------------------------------------------------------------------------------------------;VI2C_ASM.ASM;I2C 软件包的底层子程序,使用前要定义好SCL和SDA。

I2C总线及其驱动程序

I2C总线及其驱动程序

SDA SCL 起始 信号 static void __zyI2cAckSend (void) { __ZY_I2C_SDA = 0; __ZY_I2C_DELAY(); __ZY_I2C_SCL = 1; __ZY_I2C_DELAY(); __ZY_I2C_SCL = 0; } 1 2 8 9 应答 信号 1 2 8 9 非应答 信号 停止 信号
1 0 1 0 1 0 1 0
MSB LSB
主机
MSB
LSB
从机
接收一个字节的数据
程序示例
static unsigned char __zyI2cByteReceive(void) { unsigned char ucRt; unsigned char i; // 接收数据 i = 8; do { ucRt = (ucRt << 1) + __zyI2cBitReceive(); } while (--i != 0); }
空闲时SDA状态未知, 需手动拉低
发送重复起始信号
在I2C总线忙时,产生起始条件,以改变数据收发方向。
SDA(I/O) SDA
80C51
SCL(I/O)
I2C从机
SCL
static void __zyI2cStartSend (void) { __ZY_I2C_SDA = 1; __ZY_I2C_DELAY(); __ZY_I2C_SCL = 1; __ZY_I2C_DELAY(); __ZY_I2C_SDA = 0; __ZY_I2C_DELAY(); __ZY_I2C_SCL = 0; }
从机具有I2C地址,内部寄存器均对应具体地址 主机对从机的操作即对寄存器的读写操作
初始化
读操作

C51单片机10(I2C总线)

C51单片机10(I2C总线)

启动I2C总线
void start(void) { sda = 1; flash(); scl = 1; flash(); sda = 0; //在SCL高电平期间,SDA下降沿启动I2C总线 flash(); scl = 0; flash(); }
停止I2C总线
void stop() { sda = 0; flash(); scl = 1; flash(); sda = 1; //在SCL高电平期间,SDA上升沿停止I2C总线 flash(); }
CAT24WCXX系列E2PROM框图
CAT24WCXX系列E2PROM写入方式
• 字节写入 • 页写入——在一个写周期内编程写入一页
型号 CAT24WC01 CAT24WC02 CAT24WC04 CAT24WC08 CAT24WC16
容量(Kb) 1 2 4 8 16
类型码 1010 1010 1010 1010 1010
//把最高位移入CY //SCL低电平期间才允许SDA数据变化 //把CY送上SDA
uchar readx(void) { uchar i, j, k = 0; scl = 0; flash(); sda = 1; for(i=0; i<8; i++) { flash(); scl = 1; flash(); if(sda == 1) { j = 1; } else j = 0; k = (k << 1) | j; scl = 0; } flash(); return(k); }
4. 主器件发送“停止”信号,从器件启动内部写周期,
将数据写到数据区
I2C总线信息传送时序——页写
1. 2. 3. 4. 5. 6. 主器件发送“开始”信号和从器件地址,等待从器件送 回应答信号 主器件收到应答信号后,再发送器件内单元地址,写入 从器件,等待从器件送回应答信号 主器件收到应答信号后,发送1字节数据,写入从器件 指定存储单元,等待从器件送回应答信号 主器件收到应答信号后,再发送1字节数据,写入从器 件内部地址修正的后续存储单元 ……持续上述过程 一页写完后,主器件发送“停止”信号,从器件启动内 部写周期,将数据写到数据区(页长度见后续内容)

51单片机I2C通信程序

51单片机I2C通信程序

51单片机I2C通信程序#include#include#define ACK 0#define NOACK 1#define OUTPUT 1#define INPUT 0#define WRITE 0#define READ 1#define TRIALS 100#define ERR_CRC 2#define ERR_BUSY 1#define ERR_OK 0#define uchar unsigned char#define uint unsigned int#define uchar unsigned char#define uint unsigned intuchar EI2C1_SendChar(uchar DevAdr,uchar MemAdr,uchar Chr);uchar EI2C1_RecvChar(uchar DevAdr, uchar *Chr);uchar ReceiveRand(uchar DevAdr, uchar MemAdr, uchar* Chr);uchar PageWrite(uchar DevAdr, uchar MemAdr, uchar* Chr, uchar Siz); uchar SeqRead(uchar DevAdr, uchar MemAdr, uchar* ReceivedChr,uchar Siz);static void Delay(void);static void Write(uchar Data);static uchar Read(void);static bit GetAck(void); static void SetAck(bit Ack); static void start(void); static void stop(void);sbit SDA = P2^5;sbit SCL = P3^6;static void Delay(void){_nop_();_nop_();_nop_();}static void Write(uchar Data) {uchar Shift;uchar I;uchar timeout;Shift = 128;for (I = 8; I != 0; I--) {if (Data & Shift) {SDA = 1;}else {SDA = 0;}Shift >>= 1;SCL = 1;Delay();timeout = 255;while((SCL == 0)&&(timeout!=0)) {timeout--;}SCL = 0;Delay();}}static uchar Read(void){uchar Shift;uchar I;uchar timeout;Shift = 0;SDA = 1;for (I = 8; I != 0; I--) {SCL = 1;Delay();timeout = 255;while((SCL==0)&&(timeout!=0)) { /* WAIT FOR CLOCK HIGH PULSE */ timeout--;}Shift <<= 1;if (SDA) {Shift++;}SCL = 0;Delay();}return Shift;}static bit GetAck(void){uint timeout;SDA = 1; /* SDA HIGH */SCL = 1; /* CLOCK HIGH PULSE */Delay();timeout = 255;while((SCL==0)&&(timeout!=0)) { /* WAIT FOR CLOCK HIGH PULSE */ timeout--;}return(SDA); /* ACKNOWLEDGE V ALUE */}static void SetAck(bit Ack){uint timeout;if (Ack) {SDA = 1; /* MASTER NOACKNOWLEDGE - SDA HIGH */}else {SDA = 0; /* MASTER ACKNOWLEDGE - SDA LOW */ }SCL = 1; /* HIGH CLOCK PULSE */Delay();timeout = 255;while((SCL ==0 )&&(timeout!=0)) { /* WAIT FOR CLOCK HIGH PULSE */ timeout--;}SCL = 0; /* LOW CLOCK PULSE */SDA = 1; /* ACKNOWLEDGE END - SDA HIGH */}static void start(void){SDA = 1; /* SDA HIGH - START SETUP*/SCL = 1; /* CLOCK HIGH PULSE */Delay(); /* CLOCK HIGH PULSE & BUS FREE TIME */ SDA = 0; /* START CONDITION */Delay(); /* START HOLD TIME */SCL = 0; /* CLOCK LOW PULSE */Delay();}static void stop(void){SDA = 0; /* STOP SETUP */SCL = 1; /* CLOCK HIGH PULSE + STOP SETUP TIME */Delay();SDA = 1; /* STOP CONDITION */}uchar EI2C1_SendChar(uchar DevAdr,uchar MemAdr,uchar Chr){uchar Trial;bit Acknowledge;Trial = TRIALS;do {start();Write((uchar)(DevAdr + WRITE));Acknowledge = GetAck();--Trial;} while (Trial && Acknowledge);if (Acknowledge) { /* WRONG ACKNOWLEDGE */SCL = 0; /* CLOCK LOW PULSE */return ERR_BUSY;}else {SCL = 0; /* CLOCK LOW PULSE */Delay();}Write(MemAdr);if (GetAck()) { /* WRONG ACKNOWLEDGE */ SCL = 0; /* CLOCK LOW PULSE */stop();return ERR_BUSY;}else {SCL = 0; /* CLOCK LOW PULSE */Delay();}Write(Chr);if (GetAck()) { /* WRONG ACKNOWLEDGE */ SCL = 0; /* CLOCK LOW PULSE */stop();return ERR_BUSY;}else {SCL = 0; /* CLOCK LOW PULSE */Delay();}stop();return ERR_OK;}uchar EI2C1_RecvChar(uchar DevAdr, uchar *Chr){uchar Trial;bit Acknowledge;Trial = TRIALS;do {start();Write((uchar)(DevAdr + READ)); //写设备地址。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
函数名:bit I2C_IRcvB(uchar sla, uchar suba, uchar *c) 入口:从器件地址 sla, 子地址 suba, 收到的数据在 c 出口:1(操作成功),0(操作有误)
功能描述:从启动总线到发送地址、读数据,结束总线的全过程。
I2C_IRcvB
调用函数: I2CS_tart(), I2C_SendB(uchar c), I2C_RcvB(), I2C_Ackn(bit a), I2C_Stop()
需要注意的是,函数是采用延时方法产生 SCL 脉冲,对高晶振频率要做一定的修改!! 在写 E2PROM 的时候一定要延时!!!
说明:
1us 机器周期,晶振频率要小于 12MHz 返回 1 则操作成功,返回 0 则操作失败。 sla 为器件从地址,suba 为器件子地址。
******************************************************************************* ******/
调用函数: 全局变量:
******************************************************************************* ***/
uchar I2C_RcvB()
{
uchar retc;
uchar BitCnt;
//位
retc = 0; SDA = 1;
功能描述: 检验 I2C 总线应答信号,有应答则返回 1,否则返回 0,超时值取 255.
解释:I2C 总线协议中规定传输的每个字节之后必须跟一个应答位,所以从器件在接收到每个 字节之后必须反馈一个应答信号给主控制器,而主控制器就需要检测从器件回传的应答信号, 根据其信息做出相应的处理.另外,主从之别是相对的,接收数据的即为从,发送数据的及为主.
bit I2C_ISendB(uchar sla, uchar suba, uchar c) { I2C_Start(); //启动总线
I2C_SendB(sla); if(!I2C_Ack) {
return(0); }
//发送器件地址
I2C_SendB(suba); //发送器件子地址
if(!I2C_Ack) {
SomeNOP();//结束条件建立时间大于 4us,延时
SDA = 1;
//发送 I2C 总线结束信号
SomeNOP();
}
/************************************ ************************************
I2C_CheckAck
函数名:bit I2C_CheckAck(void) 入口: 出口:0(无应答),1(有应答)
#i nclude "AT89X52.h" #i nclude <intrins.h>
#define SomeNOP(); {_nop_();_nop_();_nop_();_nop_();_nop_();} //定义空指令
sbit SDA = P1^3; sbit SCL = P1^2;
//模拟 I2C 数据传输位 //模拟 I2C 时钟控制位
/******************************** ************************************
I2C_ISendB
函数名:bit I2C_ISendB(uchar sla, uchar suba, uchar c) 入口:从器件地址 sla,子地址 suba, 发送字节 c 出口:0(操作有误),1(操作成功)
再看看应答信号的格式:在由发送器产生的时钟响应周期里,发送器先释放 SDA(置高),然后 由接受器将 SDA 拉低,并在这个时钟脉冲周期的高电平期间保持稳定的低电平.即表示从器 件做出了应答.
调用函数:void I2C_Stop() 全局变量:
******************************************************************************* ***/
/************************************ ************************************
I2C_RcvB
函数名:uchar I2C_RcvB() 入口: 出口:uchar 型数据
功能描述: 接收从器件传来的数据,并判断总线错误(不发应答信号),收完后需要调用应答函数。
SDA = 0;
//发送起始信号
SomeNOP(); //起始条件建立时间大于 4us,延时
SCL = 0;
//钳住 I2C 总线准备发送或接收数据
/******解释:I2C 总线在空闲状态下都是被上拉为高电平的,所以当它们处于低电平时就表示 忙的状态.***/ _nop_(); _nop_(); }
void I2C_SendB(uchar c) { uchar BitCnt;
for (BitCnt=0; BitCnt<8; BitCnt++) //要传送的数据长度为 8 位
{ if((c<<BitCnt)&0x80)
//判断发送位(从高位起发送)
{
SDA = 1;
} else { SDA = 0; }
******************************************************************************* ***/
void I2C_Stop()
{ SDA = 0;
//发送结束条件的数据信号
_Nop(); SCL = 1;
//发送结束条件的时钟信号
void I2C_Ackn(bit a)
{ if(a==0) {
SDA = 0; } else {
SDA = 1; } SomeNOP(); SCL = 1; SomeNOP(); SCL = 0; _nop_(); _nop_(); }
//在此发送应答或非应答信号
//时钟电平周期大于 4 us //清时钟线钳住 I2C 总线以便继续接收
bit bdata I2C_Ack; //应答标志位
/************************************ ************************************
函数名:void I2C_Start() 入口: 出口:
功能描述:启动 I2C 总线,即发送 I2C 初始条件
return(0); }
I2C_SendB(c); if(!I2C_Ack) {
return(0); }
//发送数据
I2C_Stop(); return(1); }
//结束总线
/********************************** ************************************
函数名:void I2C_Ackn(bit a) 入口:0 或 1 出口:
Ackn
功能描述:主控制器进行应答信号(可以是应答或非应答信号)
说明:作为接收方的时候,必须根据当前自己的状态向发送器反馈应答信号 调用函数: 全局变量:
******************************************************************************* ***/
******************************************************************************* ***/
void I2C_Start()
{
SDA = 1;
//发送起始条件的数据信号
_Nop();
SCL = 1;
SomeNOP(); //起始条件建立时间大于 4.7us,延时
I2C_Start
解释: 在 I2C 总线协议中规定的起始位格式是:在 SCL 高电平期间,SDA 发生从高到低的电平 跳变.它与其它数据格式的区别在于,协议中规定有效的数据必须在 SCL 的高电平期间保持 不变,只有在 SCL 的低电平期间才能发生跳变.所以这一有别与其它格式的数据才能做为起 始位. 调用函数: 全局变量:
注意:在传送数据时,数据(SDA)的改变只能发生在 SCL 的低电平期间,在 SCL 的高电平期间 保持不变
调用函数:bit I2C_CheckAck() 全局变量:I2C_Ack
******************************************************************************* ***/
/**********************************
I2C
*************************************

线


模块名:I2C 总线驱动 型号:I2C
创建人:陈曦 日期:2005-6-15 修改人:陈曦 日期:2005-6-19
功能描述:
此模块包括发送数据及接收数据,应答位发送,并提供了几个直接面对器件的操作函数,能 很 方便的与用户程序进行连接并扩展。
retc = retc<<1;
if(SDA==1)
{ retc = retc + 1;
//读数据位,接收的数据放入 retc 中
}
_nop_();
_nop_();
}
SCL = 0; _nop_(); _nop_();
return(retc); }
/************************************ ************************************
相关文档
最新文档