I2C总线(主)C51源程序

发布者:czc天天最新更新时间:2016-11-14 来源: eefocus关键字:I2C总线  C51 手机看文章 扫描二维码
随时随地手机看文章
#define  ROMADDRESS  0xA0

sfr 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表示被控器无应答或损坏。
/*输入: cmd 要输入的指令数据 
/*输出: 无
/***********************************************************************/ 
void IIC_DataSend(unsigned char byte)  
{
 unsigned char BitCnt;
 
 for(BitCnt=0;BitCnt<8;BitCnt++)  /*要传送的数据长度为8位*/
 {
  if(byte&0x80)
   SDA=1;        /*判断发送位*/
  else  
   SDA=0;                
  DelayMs(1);
  SCL=1; DelayMs(1);    /*置时钟线为高,通知被控器开始发送数据位*/        
  SCL=0; DelayMs(1);
  byte = byte<<1;
 }  
 SDA=0; DelayMs(1);      /*8位发送完后释放数据线,准备接收应答位*/  
 SCL=1; DelayMs(1);
 if(SDA==1)
  ack=0;     
 else 
  ack=1;       /*判断是否接收到应答信号*/
 SCL=0; DelayMs(1);
}


/***********************************************************************/
/*名称: IIC_DataRcv()
/*说明: 用来接收从器件传来的数据,并判断总线错误(不发应答信号),
        发完后请用应答函数应答从机。
/*输入: 无
/*输出: 从器件传来的数据
/***********************************************************************/ 
unsigned char IIC_DataRcv(void)  
{
 unsigned char BitCnt,Result = 0;

 SDA=1;        /*置数据线为输入方式*/
 for(BitCnt=0;BitCnt<8;BitCnt++)
 {
  SCL=0; DelayMs(1);    /*置时钟线为低,准备接收数据位*/      
  SCL=1; DelayMs(1);    /*置时钟线为高使数据线上数据有效*/
  Result <<= 1;
  if(SDA)
   Result++;     /*读数据位,接收的数据位放入Result中 */
 }
 SCL=0; DelayMs(1);    
 return Result;
}

/***********************************************************************/
/*名称: IIC_Ack()
/*说明: 主控器进行应答信号(可以是应答或非应答信号,由位参数a决定)
/*输入: 应答信号
/*输出: 无
/***********************************************************************/ 
void IIC_Ack(bit a)

 if(a)
    SDA=1;       /*在此发出应答或非应答信号 */
 else
  SDA=0;
 Delay(20);     
 SCL=1; DelayMs(1);     /*时钟低电平周期大于4μs*/       
 SCL=0; DelayMs(1);     /*清时钟线,钳住I2C总线以便继续接收*/
 
}

/***********************************************************************/
/*名称: IIC_StrWrite()
/*说明: 向有子地址器件发送多字节数据程序
/*输入: addrh 存储器子地址高8位 
/*  addrl 存储器子地址低8位
/*  *str 数据指针
/*  length 数据长度
/*输出: 写入是否成功
/***********************************************************************/ 
bit IIC_ByteWrite(unsigned char addrh,unsigned char addrl,unsigned char byte)

 WP = 0;
    IIC_Start();      /*启动总线*/
 IIC_DataSend(ROMADDRESS);   /*发送器件地址*/
 if(ack==0)return(0);
 IIC_DataSend(addrh);    /*发送存储器子地址高8位*/
 if(ack==0)return(0);
 IIC_DataSend(addrl);    /*发送存储器子地址低8位*/
 if(ack==0)return(0);  
 IIC_DataSend(byte);     /*发送数据*/
 if(ack==0)return(0);
 IIC_Stop();       /*结束总线*/ 
 DelayMs(100);
 WP = 1;
 return(1);
}

/***********************************************************************/
/*名称: IIC_StrWrite()
/*说明: 向有子地址器件发送多字节数据程序
/*输入: addrh 存储器子地址高8位 
/*  addrl 存储器子地址低8位
/*  *str 数据指针
/*  length 数据长度
/*输出: 写入是否成功
/***********************************************************************/ 
bit IIC_StrWrite(unsigned char addrh,unsigned char addrl,unsigned char *str,unsigned char length)

 unsigned char i;

 WP = 0;
    IIC_Start();      /*启动总线*/
 IIC_DataSend(ROMADDRESS);   /*发送器件地址*/
 if(ack==0)return(0);
 IIC_DataSend(addrh);    /*发送存储器子地址高8位*/
 if(ack==0)return(0);
 IIC_DataSend(addrl);    /*发送存储器子地址低8位*/
 if(ack==0)return(0);
 
 for(i=0;i  {   
  IIC_DataSend(*(str++));   /*发送数据*/
  if(ack==0)return(0);
 } 
 IIC_Stop();       /*结束总线*/ 
 DelayMs(100);
 WP = 1;
 return(1);
}

/***********************************************************************/
/*名称: IIC_ByteRead()
/*说明: 向有子地址器件读取单字节数据程序
/*输入: addrh 存储器子地址高8位 
/*  addrl 存储器子地址低8位
/*输出: 读取的数据
/***********************************************************************/ 
bit IIC_ByteRead(unsigned char addrh,unsigned char addrl,unsigned char byte)
{
 IIC_Start();      /*启动总线*/
 IIC_DataSend(ROMADDRESS);   /*发送器件地址*/
 if(ack==0)return(0);
 IIC_DataSend(addrh);    /*发送存储器子地址高8位*/
 if(ack==0)return(0);
 IIC_DataSend(addrl);    /*发送存储器子地址低8位*/
 if(ack==0)return(0);

 IIC_Start();      /*重新启动总线*/
    IIC_DataSend(ROMADDRESS+1);   /*设置读*/
 if(ack==0)return(0);
 byte = IIC_DataRcv();    /*读取数据*/
 IIC_Ack(1);       /*发送非应位*/
 IIC_Stop();       /*结束总线*/
 DelayMs(100);
 return(1);   
}

/***********************************************************************/
/*名称: IIC_StrRead()
/*说明: 向有子地址器件发送多字节数据程序
/*输入: addrh 存储器子地址高8位 
/*  addrl 存储器子地址低8位
/*输出: 读取是否成功
/***********************************************************************/ 
bit IIC_StrRead(unsigned char addrh,unsigned char addrl,unsigned char *str,unsigned char length)
{
    unsigned char i;

 IIC_Start();      /*启动总线*/
 IIC_DataSend(ROMADDRESS);   /*发送器件地址*/
 if(ack==0)return(0);
 IIC_DataSend(addrh);    /*发送存储器子地址高8位*/
 if(ack==0)return(0);
 IIC_DataSend(addrl);    /*发送存储器子地址低8位*/
 if(ack==0)return(0);

 IIC_Start();      /*重新启动总线*/
    IIC_DataSend(ROMADDRESS+1);   /*设置读*/
 if(ack==0)return(0);
 for(i=0;i  {   
  *(str++) = IIC_DataRcv();  /*读取数据*/
  IIC_Ack(0);      /*发送就答位*/  
 } 
 *str=IIC_DataRcv();     /*读取数据*/
 IIC_Ack(1);       /*发送非应位*/
 IIC_Stop();       /*结束总线*/
 DelayMs(100);
 return(1);   
}

关键字:I2C总线  C51 引用地址:I2C总线(主)C51源程序

上一篇:P89C669 串口C51源程序
下一篇:C51+CH375读U盘实例

推荐阅读最新更新时间:2024-03-16 15:20

C51---示波器---2ms方波
/* //查询方式,输出方波 #include sbit p1_0=P1^0; void main() { p1_0=1; TMOD=0x01;//选择定时器0,工作方式为1 TH0=(65535-1000)/256; TL0=(65536-1000)%256; TR0=1;//启动定时器0 p1_0=0; while(1) { if(TF0==1) { p1_0=~p1_0; TF0=0;//清空中断标志位 TH0=(65535-1000)/256; TL0=(65536-1000)%256; TR0=1;//启动定时器0 } } } */ //中断方式,输出方波 #i
[单片机]
C51---示波器---2ms方波
C51汇编伪指令
1、DS ---预留存储区命令 格式: 〔标号:〕 DS 表达式值 其功能是从指定地址开始,定义一个存储区,以备源程序使用。 存储区预留的存储单元数由表达式的值决定。 TMP: DS 1 从标号TEP地址处开始保留1个存储单元(字节)。 2、BIT---定义位命令 格式: 字符名称 BIT 位地址 其功能用于给字符名称定义位地址。 SPK BIT P3.7 经定义后,允许在指令中用SPK代替P3.7。 3、USING指令 USING指令通知汇编器使用8051的哪一个工作寄存器组。 格式: USING 表达式 (值必须为0-3,默认值为0。) USING 0 使用第0组工作寄存器。 4、SEGMENT指令 SEGMEN
[单片机]
基于CPLD的系统中I2C总线的设计
摘要:在介绍I2C总线协议的基础上,讨论了基于CPLD的系统中I2C总线的设计技术,并结合工程实例设计了I2C总线IP核,给出了部分源代码和仿真结果。 关键词:I2C总线 IP核 CPLD I2C总线是PHILIPS公司推出的新一代串行总线,其应用日渐广泛1~2。目前许多单片机都带有I2C总线接口,能方便地实现I2C总线设计;对没有I2C总线的微控制器(MCU),可以采用两条I/O口线进行模拟。在以单片机为MCU的系统中很容易实现I2C总线的模拟扩展,有现成的通用软件包可以使用2~3。 对有些基于CPLD的系统,要与带有I2C总线接口的外围器件连接,实现起来相对复杂一些。为实现系统中的I2C总线接口,可以另外引入单片机,也可
[半导体设计/制造]
I2C总线信号时序总结
总线空闲状态   I2C总线总线的SDA和SCL两条信号线同时处于高电平时,规定为总线的空闲状态。此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高。 启动信号   在时钟线SCL保持高电平期间,数据线SDA上的电平被拉低(即负跳变),定义为I2C总线总线的启动信号,它标志着一次数据传输的开始。启动信号是一种电平跳变时序信号,而不是一个电平信号。启动信号是由主控器主动建立的,在建立该信号之前I2C总线必须处于空闲状态。 重启动信号   在主控器控制总线期间完成了一次数据通信(发送或接收)之后,如果想继续占用总线再进行一次数据通信(发送或接收),而又不释放总线,就需要利用重
[单片机]
<font color='red'>I2C总线</font>信号时序总结
单片机C语言教程:C51数组的使用
数组不过就是同一类型变量的有序集合。形象的能这样去理解,就像一个 学校在操场上排队,每一个级代表一个数据类型,每一个班级为一个数组,每一个学生就是 数组中的一个数据。数据中的每个数据都能用唯一的下标来确定其位置,下标能是一维 或多维的。就如在学校的方队中要找一个学生,这个学生在 I 年级 H 班 X 组 Y 号的,那么 能把这个学生看做在 I 类型的 H 数组中(X,Y)下标位置中。数组和普通变量一样,要 求先定义了才能使用,下面是定义一维或多维数组的方式: “数据类型”是指数组中的各数据单元的类型,每个数组中的数据单元只能是同一数据 类型。“数组名”是整个数组的标识,命名方法和变量命名方法是一样的。在编译时系统会 根据数
[单片机]
单片机C语言教程:<font color='red'>C51</font>数组的使用
C51 定时器/计数器
//外部连接:P1.0 与 T1计数器输入端P3.5 连接。 #include reg52.h sbit out=P1^0; void main() { //T0定时器,工作方式2。其中断函数使 out 脚 输出脉冲 //T1 计数器,工作方式1. 其中断函数使 P2 输出脉冲 TMOD=0x52; //中断允许 ET0=1; ET1=1; EA=1; //设置 T0 时间常数,定时200us, TH0=56; TL0=56; //设置 T1 时间常数,计数2500 TH1=(65536-2500)/256 ; TL1=(65536-2500)%256; //启动 TR0=1; TR1=1;
[单片机]
单片机c语言教程第十六章--C51指针的使用
指针就是指变量或数据所在的存储区地址。如一个字符型的变量 STR 存放在内存单元DATA 区的 51H 这个地址中,那么 DATA 区的 51H 地址就是变量 STR 的指针。在 C 语言中 指针是一个很重要的概念,正确有效的使用指针类型的数据,能更有效的表达复杂的数据 结构,能更有效的使用数组或变量,能方便直接的处理内存或其它存储区。指针之所以 能这么有效的操作数据,是因为无论程序的指令、常量、变量或特殊寄存器都要存放在内 存单元或相应的存储区中,这些存储区是按字节来划分的,每一个存储单元都能用唯一的 编号去读或写数据,这个编号就是常说的存储单元的地址,而读写这个编号的动作就叫做寻 址,通过寻址就能访问到存储区中的任一个能访问的
[单片机]
单片机c语言教程第十六章--<font color='red'>C51</font>指针的使用
一种C51单片机并行口扩展设计及应用
1 引言 C51单片机是我们生活中最常用的系列,MCS-51系列单片机有4个并行口(P0,P1,P2,P3口),但对一个稍微复杂的应用系统来说,真正可供用户使用的并行口,只有P1口可用,况且常常因扩展I2C和SPI的器件需占用某些P1口,迫使用户不得不扩展并行口以满足实际的需要。习惯上,常用的并行口接口芯片有8255、8155,这两种芯片功能比较齐全,可以使用在相对比较复杂的系统中,但如是对一般的系统而言,这些功能往往闲置不用。那么就可以选用一些本来闲置不用的口线作为选通信号来进行并行口的扩展,这样就能充分利用单片机有限的I/O资源,在本设计中是将P1口扩展成一个或几个8位并行口,在每一个八位口上接入8个发光二极管做为输出,二
[单片机]
一种<font color='red'>C51</font>单片机并行口扩展设计及应用
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved