标准80C51单片机模拟I2C总线的主机程序

发布者:AngelicWhisper最新更新时间:2017-11-26 来源: eefocus关键字:标准80C51  单片机  模拟I2C总线  主机程序 手机看文章 扫描二维码
随时随地手机看文章

I2C总线协议程序

在做程序是我在网上找的是周立功的程序,感觉还不错顺便转载;在使用的过程中一定要注意时序、时间的问题。

 

“i2c.h文件”

//I2C总线综合发送函数,向从机发送多个字节的数据

bit I2C_Puts(

unsigned char SlaveAddr,

unsigned int SubAddr,

unsigned char SubMod,

char *dat,

unsigned int Size

);

//I2C总线综合接收函数,从从机接收多个字节的数据

bit I2C_Gets

(

unsigned char SlaveAddr,

unsigned int SubAddr,

unsigned char SubMod,

char *dat,

unsigned int Size

);

#endif

================================================================================================

“i2c.c文件”

#include "I2C.h"

//定义延时变量,用于宏I2C_Delay()

unsigned char I2C_Delay_t;

 

#define I2C_Delay()  {I2C_Delay_t = (I2C_DELAY_VALUE);while ( --I2C_Delay_t != 0 );}

 

void I2C_Start()

{

  I2C_SDA = 1;   I2C_Delay();

  I2C_SCL = 1;   I2C_Delay();

  I2C_SDA = 0;   I2C_Delay();

  I2C_SCL = 0;   I2C_Delay();

}

 

void I2C_Write(char dat)

{

  unsigned char t = 8;

  do

  {

     I2C_SDA = (bit)(dat & 0x80);

     dat <<= 1;

     I2C_SCL = 1;   I2C_Delay();

     I2C_SCL = 0;   I2C_Delay();

  } while ( --t != 0 );

}

 

char I2C_Read()

{

  char dat;

  unsigned char t = 8;

  I2C_SDA = 1; //在读取数据之前,要把SDA拉高

  do

  {

    I2C_SCL = 1;

    I2C_Delay();

    dat <<= 1;

    if ( I2C_SDA ) dat |= 0x01;

    I2C_SCL = 0;

    I2C_Delay();

  } while ( --t != 0 );

return dat;

}

 

bit I2C_GetAck()

{

  bit ack;

  //总线准备,接受应答

  I2C_SDA = 1;  I2C_Delay();

  I2C_SCL = 1;  I2C_Delay();

  ack = I2C_SDA;

  I2C_SCL = 0;

  I2C_Delay();

  return ack;

}


/******************************************************************************

函数:I2C_PutAck()

功能:主机产生应答位或非应答位

参数:

ack=0:主机产生应答位

ack=1:主机产生非应答位

说明:

主机在接收完每一个字节的数据后,都应当产生应答位

主机在接收完最后一个字节的数据后,应当产生非应答位

******************************************************************************/

void I2C_PutAck(bit ack)

{

  I2C_SDA = ack;  I2C_Delay();

  I2C_SCL = 1;    I2C_Delay();

  I2C_SCL = 0;    I2C_Delay();

}

/******************************************************************************

函数:I2C_Stop()

功能:产生I2C总线的停止状态

说明:

SCL处于高电平期间,当SDA出现上升沿时停止I2C总线

不论SDA和SCL处于什么电平状态,本函数总能正确产生停止状态

本函数执行后,I2C总线处于空闲状态

******************************************************************************/

void I2C_Stop()

{

  unsigned int t = I2C_STOP_WAIT_VALUE;

  I2C_SDA = 0;  I2C_Delay();

  I2C_SCL = 1;  I2C_Delay();

  I2C_SDA = 1  I2C_Delay();

  while ( --t != 0 );   //在下一次产生Start之前,要加一定的延时

}


/******************************************************************************

函数:I2C_Puts()

功能:I2C总线综合发送函数,向从机发送多个字节的数据

参数:

SlaveAddr:从机地址(7位纯地址,不含读写位)

SubAddr:从机的子地址

SubMod:子地址模式,0-无子地址,1-单字节子地址,2-双字节子地址

*dat:要发送的数据

Size:数据的字节数

返回:

0:发送成功

1:在发送过程中出现异常

说明:

本函数能够很好地适应所有常见的I2C器件,不论其是否有子地址

当从机没有子地址时,参数SubAddr任意,而SubMod应当为0

******************************************************************************/

bit I2C_Puts

(  unsigned char SlaveAddr , unsigned int SubAddr , unsigned char SubMod , 

  char *dat , unsigned int Size  )

{

  //定义临时变量

  unsigned char i;

  char a[3];

  if ( Size == 0 ) return 0;  //检查长度

  a[0] = (SlaveAddr << 1);  //准备从机地址

  if ( SubMod > 2 ) SubMod = 2;  //检查子地址模式

 

  //确定子地址

  switch ( SubMod )

  {

  case 0:

    break;

  case 1:

    a[1] = (char)(SubAddr);

    break;

  case 2:

    a[1] = (char)(SubAddr >> 8);

    a[2] = (char)(SubAddr);

    break;

  default:

    break;

  }


  //发送从机地址(a[0]),接着发送子地址(如果有子地址的话)(a[1],a[2])

  I2C_Start();

  for ( i=0; i<=SubMod; i++ )

  {

    I2C_Write(a[i]);

    if ( I2C_GetAck() )

    {

      I2C_Stop();

      return 1;

    }

  }

  //发送数据

  do

  {

    I2C_Write(*dat++);

    if ( I2C_GetAck() ) break;

  } while ( --Size != 0 );

  //发送完毕,停止I2C总线,并返回结果

  I2C_Stop();

  if ( Size == 0 )

  {

    return 0;//发送成功

  }

  else

  {

    return 1;//在发送过程中出现异常

  }

}


/******************************************************************************

函数:I2C_Gets()

功能:I2C总线综合接收函数,从从机接收多个字节的数据

参数:

SlaveAddr:从机地址(7位纯地址,不含读写位)

SubAddr:从机的子地址

SubMod:子地址模式,0-无子地址,1-单字节子地址,2-双字节子地址

*dat:保存接收到的数据

Size:数据的字节数

返回:

0:接收成功

1:在接收过程中出现异常

说明:

本函数能够很好地适应所有常见的I2C器件,不论其是否有子地址

当从机没有子地址时,参数SubAddr任意,而SubMod应当为0

******************************************************************************/

bit I2C_Gets

(  unsigned char SlaveAddr , unsigned int SubAddr , unsigned char SubMod , 

  char *dat , unsigned int Size  )

{

  //定义临时变量

  unsigned char i;

  char a[3];

  if ( Size == 0 ) return 0;//检查长度,接收成功

  a[0] = (SlaveAddr << 1);//准备从机地址

  if ( SubMod > 2 ) SubMod = 2;//检查子地址模式

  

 //如果是有子地址的从机,则要先发送从机地址和子地址

  if ( SubMod != 0 )

  {

    //确定子地址

    if ( SubMod == 1 )

    {

      a[1] = (char)(SubAddr);

    }

    else

    {

      a[1] = (char)(SubAddr >> 8);

      a[2] = (char)(SubAddr);

    }

   

   //发送从机地址写,接着发送子地址

   I2C_Start();

   for ( i=0; i<=SubMod; i++ )

   {

     I2C_Write(a[i]);

     if ( I2C_GetAck() )

     {

       I2C_Stop();

       return 1;

     }

   }

}

 

  //这里的I2C_Start()对于有子地址的从机是重复起始状态

  //对于无子地址的从机则是正常的起始状态

  I2C_Start();

  //发送从机地址读

  I2C_Write(a[0]+1);

  if ( I2C_GetAck() )

  {

    I2C_Stop();

    return 1;

  }

  

  //接收数据

  for (;;)

  {

    *dat++ = I2C_Read();

    if ( --Size == 0 )

    {

      I2C_PutAck(1);

      break;

    }

    I2C_PutAck(0);

  }

 

  //接收完毕,停止I2C总线,并返回结果

  I2C_Stop();

  return 0;

}

 

 

I2C读写EEPROM流程图


标准80C51单片机模拟I2C总线的主机程序


关键字:标准80C51  单片机  模拟I2C总线  主机程序 引用地址:标准80C51单片机模拟I2C总线的主机程序

上一篇:STM32 FLASH擦除、写入以及防止误擦除程序代码
下一篇:C51 队列 方式 中断接收 查询发送

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

C8051F350单片机在全自动CCFL观片仪亮度
引 言 跨入21世纪以来,信息的世界变换迅速,说不定今天出了某高科技产品明天就会有更优秀的同类产品面世。其中电子计算机科学技术更新周期大概就是2到3年。随着电子计算机等科学技术的发展,医疗设备的现代化、智能化研究越来越受到人们的关注,大量的科学家及工程技术人员都积极地投入到这一场医疗设备的革命中,其中,对各种类型射线底片观片设备的研究也是医疗设备开发的重点。由于传统的观片设备亮度低、均匀性差、容易引起视疲劳等缺点,已经不能满足现代化医学诊断的要求。利用CCFL(Cold Cathode Fluorescent Lamp)开发的观片仪具有结构简单、灯管表面温升小、灯管表面亮度高、使用寿命长、显色性好、发光均匀等优点。医疗设备至关重
[单片机]
STM8S105K6T6单片机的IIC配置问题
最近在用MCP3421,需要用到IIC接口。MCU用的是STM8S105K6T6。使用MCU内部的IIC外设,这个接口配置折腾一下午,遇到了很坑爹的事情。我使用的是寄存器开发的,该设置了感觉都设置好了,就是不能工作。后来以为没配置好,又用库函数来开发,妈的 ,还是不能工作。后来在群里的一位大神的指导下成功的调通了IIC。 闲话有点多,毕竟是我第一次开通博客来写博客的,心情不免有些激动。现在把经验分享给不知道的小伙伴们,少走些弯路。 在使用STM8S105K6T6的IIC前,必须先通过STVP这个软件来进行配置。 这三个步骤是最重要的,当然还需要选择单片机的下载模式,型号什么的,这个不是本文的重点。特别要强调一点,步骤二
[单片机]
STM8S105K6T6<font color='red'>单片机</font>的IIC配置问题
51单片机C语言调用汇编子程序的简便方法
1、在汇编文件中,程序前边加上如下三句话就可以: PUBLIC _delay, _binrlc ;定义公用子程序名,这里定义了两个子程序(有下划线) LUOYUAN SEGMENT CODE ;程序段命名,LUOYUAN,叫啥名都可以 RSEG LUOYUAN 下边放子程序(程序名要下划线,其它标号不要下划线) ;汇编语言文件 PUBLIC _delay, _binrlc;定义子程序名 LUOYUAN SEGMENT CODE ;命名LUOYUAN的程序段 RSEG LUOYUAN _delay: MOV P1,#55H MOV R2,#30H DJNZ R2,$ RET
[单片机]
旅客列车全自动报站多媒体系统
0 引言 旅客在旅行过程中,为防止坐过站,十分关心列车的前方到站。尤其是夜间行车,列车播音室停止播音,只靠列车到站时列车员才报站名,给广大旅客带来诸多不便。为使旅客能及时了解到自己目前所处位置及前方到站。这里设计一种全自动报站多媒体系统,能全天候自动通报站名、提示列车运行情况,平时可播放录像,歌曲及广告等信息。在列车将要到达车站前以声图并茂的方式自动介绍各个站点的著名旅游景点、交通和住宿情况,极大方便了旅客,改善了乘车环境,也为铁路运输带来了更好的经济效益。 1 控制原理与系统组成 系统由底层单片机系统、上层PC机、车厢播音系统、显示系统及相应软件组成(见图1)。单片机为下位机。位置传感器安放在车门处,用车门的开关
[单片机]
旅客列车全自动报站多媒体系统
PIC单片机在ICD做lcd显示时钟演示程序
;************************************************* ;* CLKTEST.ASM * ;************************************************* ;* ICDDEMO教学实验板 lcd显示时钟演示程序 * ;************************************************* include p16f877.inc ;*---- ; 定义 LCD数据& 控制I/O口 LCD_DATA equ PORTB LCD_CNTL1 equ PORTB LCD_CNTL2 equ PORTA ; 定义 LCD控制相应的I
[单片机]
HOLTEK新推出HT66F0172、HT66F0174 Enhanced A/D Flash MCU系列
Holtek新推出Enhanced A/D Flash Type MCU系列,此系列有两颗MCU分别为HT66F0172及HT66F0174,符合工业上-40℃ ~ 85℃工作温度与高抗噪声之性能要求,并具有2Kx16 Flash程序内存,SRAM为128 Bytes、I/O 18个。 此系列产品内建Holtek新设计的Timer Module,有Capture、Compare、Timer/Event、Single Pulse Output、PWM等5种模式,并内建12-bit快速ADC,可广泛的应用于各式有温控或电压讯号量测需求的家电,如温控电热水瓶、红酒柜、消毒柜、电烤箱、冷暖空调控制器等。 HT66F0172的Osc
[单片机]
51单片机 DAC0832
原理图: 代码如下: //程序功能:D/A转换,D12由灭到亮,蜂鸣器响一次,再由亮到灭,蜂鸣器响一次,依次循环 //头文件 #include #include //延时一个机械周期函数所在头文件(_nop_()) //定义宏 #define uint unsigned int #define uchar unsigned char //控制端声明 sbit duanxuan=P2^6; //数码管段选口 sbit weixuan=P2^7; //数码管位选口 sbit DAC0832_CS=P3^2; /
[单片机]
基于51单片机的锅炉水位温度压力检测系统仿真设计
仿真图proteus7.8及以上 程序编译器:keil 4/keil 5 编程语言:C语言 设计编号:S0056 1.主要功能: 基于51单片机AT89C51/52(与AT89S51/52、AT89C51/52、STC89C51/52等51内核单片机通用) 1.系统实时通过LCD1602显示水位检测值,锅炉炉膛温度值,锅炉内部压力值。 2、可对锅炉的水位上下限、炉膛温度上下限、压力上下限进行设置,第一行显示上限值,第二行显示下限值。 3、如果水位、温度、压力过限则蜂鸣器报警,通过LED指示报警类型。 4、默认水位下限值10cm,上限值40cm,压力下限值30kPa,压力上限值50kPa,温度下限值5℃,温度上限值105℃。 5、温
[单片机]
基于51<font color='red'>单片机</font>的锅炉水位温度压力检测系统仿真设计
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

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

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

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