用51单片机模拟I2C接口实例

发布者:柔情细语最新更新时间:2017-01-18 来源: eefocus关键字:51单片机  模拟I2C 手机看文章 扫描二维码
随时随地手机看文章

电路原理图

  

 
EEPROM为ATMEL公司的AT24C01A。单片机为ATMEL公司的AT89C51。


软件说明

C语言为Franklin C V3.2。将源程序另存为testi2c.c,用命令

C51 testi2c.c

L51 TESTI2C.OBJ

OHS51 TESTI2C

编译,连接,得到TESTI2C.HEX文件,即可由编程器读入并进行写片,实验。

3.源程序

  1. #include    

  2.   

  3. #include     

  4.   

  5. #define uchar unsigned char   

  6.   

  7. #define uint unsigned int  

  8.   

  9. #define AddWr 0xa0 /*器件地址选择及写标志*/   

  10.   

  11. #define AddRd 0xa1 /*器件地址选择及读标志*/   

  12.   

  13. #define Hidden 0x0e /*显示器的消隐码*/   

  14.   

  15. /*有关全局变量*/  

  16.   

  17. sbit Sda= P3^7; /*串行数据*/  

  18.   

  19. sbit Scl= P3^6; /*串行时钟*/  

  20.   

  21. sbit WP= P3^5; /*硬件写保护*/  

  22.   

  23. void mDelay(uchar j)   

  24. {    

  25.     uint i;   

  26.     for(;j>0;j--)   

  27.     {    

  28.         for(i=0;i<125;i--)   

  29.         {   

  30.             ;   

  31.         }   

  32.     }   

  33. }   

  34.   

  35. /*发送起始条件*/  

  36.   

  37. void Start(void) /*起始条件*/  

  38.   

  39. {   

  40.        

  41.     Sda=1;   

  42.        

  43.     Scl=1;   

  44.        

  45.     _nop_ ();   

  46.        

  47.     _nop_ ();   

  48.        

  49.     _nop_ ();   

  50.        

  51.     _nop_ ();   

  52.        

  53.     Sda=0;   

  54.        

  55.     _nop_ ();   

  56.        

  57.     _nop_ ();   

  58.        

  59.     _nop_ ();   

  60.        

  61.     _nop_ ();   

  62.        

  63. }   

  64.   

  65. void Stop(void) /*停止条件*/  

  66.   

  67. {   

  68.        

  69.     Sda=0;   

  70.        

  71.     Scl=1;   

  72.        

  73.     _nop_ ();   

  74.        

  75.     _nop_ ();   

  76.        

  77.     _nop_ ();   

  78.        

  79.     _nop_ ();   

  80.        

  81.     Sda=1;   

  82.        

  83.     _nop_ ();   

  84.        

  85.     _nop_ ();   

  86.        

  87.     _nop_ ();   

  88.        

  89.     _nop_ ();   

  90.        

  91. }   

  92.   

  93. void Ack(void) /*应答位*/  

  94.   

  95. {   

  96.        

  97.     Sda=0;   

  98.        

  99.     _nop_ ();   

  100.        

  101.     _nop_ ();   

  102.        

  103.     _nop_ ();   

  104.        

  105.     _nop_ ();   

  106.        

  107.     Scl=1;   

  108.        

  109.     _nop_ ();   

  110.        

  111.     _nop_ ();   

  112.        

  113.     _nop_ ();   

  114.        

  115.     _nop_ ();   

  116.        

  117.     Scl=0;   

  118.        

  119. }   

  120.   

  121. void NoAck(void) /*反向应答位*/  

  122. {   

  123.        

  124.     Sda=1;   

  125.        

  126.     _nop_ ();   

  127.        

  128.     _nop_ ();   

  129.        

  130.     _nop_ ();   

  131.        

  132.     _nop_ ();   

  133.        

  134.     Scl=1;   

  135.        

  136.     _nop_ ();   

  137.        

  138.     _nop_ ();   

  139.        

  140.     _nop_ ();   

  141.        

  142.     _nop_ ();   

  143.        

  144.     Scl=0;     

  145. }   

  146.   

  147. void Send(uchar Data) /*发送数据子程序,Data为要求发送的数据*/  

  148. {   

  149.        

  150.     uchar BitCounter=8; /*位数控制*/  

  151.        

  152.     uchar temp; /*中间变量控制*/  

  153.        

  154.     do     

  155.     {          

  156.         temp=Data;   

  157.            

  158.         Scl=0;   

  159.            

  160.         _nop_ ();   

  161.            

  162.         _nop_ ();   

  163.            

  164.         _nop_ ();   

  165.            

  166.         _nop_ ();   

  167.            

  168.         if((temp&0x80)==0x80)/* 如果最高位是1*/              

  169.             Sda=1;         

  170.         else               

  171.             Sda=0;   

  172.            

  173.         Scl=1;   

  174.            

  175.         temp=Data<<1; /*RLC*/  

  176.            

  177.         Data=temp;   

  178.            

  179.         BitCounter--;          

  180.     }while(BitCounter);   

  181.        

  182.     Scl=0;   

  183.        

  184. }   

  185.   

  186.   

  187. uchar Read(void) /*读一个字节的数据,并返回该字节值*/  

  188. {   

  189.        

  190.     uchar temp=0;   

  191.        

  192.     uchar temp1=0;   

  193.        

  194.     uchar BitCounter=8;   

  195.        

  196.     Sda=1;   

  197.        

  198.     do{        

  199.         Scl=0;   

  200.            

  201.         _nop_ ();   

  202.            

  203.         _nop_ ();   

  204.            

  205.         _nop_ ();   

  206.            

  207.         _nop_ ();   

  208.            

  209.         Scl=1;   

  210.            

  211.         _nop_ ();   

  212.            

  213.         _nop_ ();   

  214.            

  215.         _nop_ ();   

  216.            

  217.         _nop_ ();   

  218.            

  219.         if(Sda) /*如果Sda=1;*/               

  220.             temp=temp|0x01; /*temp的最低位置1*/         

  221.         else               

  222.             temp=temp&0xfe; /*否则temp的最低位清0*/  

  223.            

  224.         if(BitCounter-1)               

  225.         {    

  226.             temp1=temp<<1;             

  227.             temp=temp1;            

  228.         }   

  229.            

  230.         BitCounter--;   

  231.            

  232.     }while(BitCounter);   

  233.        

  234.     return(temp);   

  235.        

  236. }   

  237.   

  238.   

  239. void WrToROM(uchar Data[],uchar Address,uchar Num)   

  240.   

  241. {   

  242.        

  243.     uchar i;   

  244.        

  245.     uchar *PData;   

  246.        

  247.     PData=Data;   

  248.        

  249.     for(i=0;i

  250.     {   

  251.            

  252.         Start(); /*发送启动信号*/  

  253.            

  254.         Send(0xa0); /*发送SLA+W*/  

  255.            

  256.         Ack();   

  257.            

  258.         Send(Address+i); /*发送地址*/  

  259.            

  260.         Ack();   

  261.            

  262.         Send(*(PData+i));   

  263.            

  264.         Ack();   

  265.            

  266.         Stop();   

  267.            

  268.         mDelay(20);        

  269.     }      

  270. }   

  271.   

  272. void RdFromROM(uchar Data[],uchar Address,uchar Num)   

  273. {   

  274.        

  275.     uchar i;   

  276.        

  277.     uchar *PData;   

  278.        

  279.     PData=Data;   

  280.        

  281.     for(i=0;i

  282.     {   

  283.            

  284.         Start();   

  285.            

  286.         Send(0xa0);   

  287.            

  288.         Ack();   

  289.            

  290.         Send(Address+i);   

  291.            

  292.         Ack();   

  293.            

  294.         Start();   

  295.            

  296.         Send(0xa1);   

  297.            

  298.         Ack();   

  299.            

  300.         *(PData+i)=Read();   

  301.            

  302.         Scl=0;   

  303.            

  304.         NoAck();   

  305.            

  306.         Stop();        

  307.     }      

  308. }   

  309.   

  310. void main()   

  311. {      

  312.     uchar Number[4]={1,2,3,4};   

  313.        

  314.     WP= 1;   

  315.        

  316.     WrToROM(Number,4,4); /*将初始化后的数值写入EEPROM*/  

  317.        

  318.     mDelay(20);   

  319.        

  320.     Number[0]=0;   

  321.        

  322.     Number[1]=0;   

  323.        

  324.     Number[2]=0;   

  325.        

  326.     Number[3]=0; /*将数组中的值清掉,以验证读出的数是否正确*/  

  327.        

  328.     RdFromROM(Number,4,4);     

  329. }   

  330.   

问题:本程序中未采用块读写的方法,显得有点‘笨’,这是由于项目原因,现项目已完成,程序已写好,短时不会修改,也不会花上一定的精力去做,虽然理论上已很成熟,就这样写一下,未必不对,但与我的本栏目要求不符,所以就未做上去,如果以后我做了,将再补上


关键字:51单片机  模拟I2C 引用地址:用51单片机模拟I2C接口实例

上一篇:单片机 模糊控制 算法 c语言
下一篇:有关51单片机读端口、读引脚的问题

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

用软件编程的方法来模拟51单片机产生PWM波
89C51芯片没有自带PWM发生器,如果要用51来产生PWM波就必须要用软件编程的方法来模拟。方法大概可以分为软件延时和定时器产生两种方法。下面将逐一介绍。 1 软件延时法 利用软件延时函数,控制电平持续的时间,达到模拟pwm的效果。 程序如下: #include sbit pwm=P1^0; main() { while(1) { pwm=1; delayus(60);//置高电平后延时60us,占空比60% pwm=0; delayus(40); } } void delayus(uint x) { while(x--); } proteus软件仿真结果如下: 可见,用这种延时函数的方法就能简单地模拟出pwm输出。
[单片机]
用软件编程的方法来<font color='red'>模拟</font><font color='red'>51单片机</font>产生PWM波
51单片机振荡周期时钟周期机器周期指令周期
(1)振荡周期 振荡周期指为单片机提供定时信号的振荡源的周期或外部输入时钟的周期。 (2)时钟周期 时钟周期又称作状态周期或状态时间S,它是振荡周期的两倍,分为P1节拍和P2节拍,通常在P1节拍完成算术逻辑操作,在P2节拍完成内部寄存器之间的数据传送操作。(注意P1 和P2的相位关系 ) (3)机器周期 一个机器周期由6个状态组成,如果把一条指令的执行过程分作几个基本操作,则将完成一个基本操作所需的时间称作机器周期。单片机的单周期指令执行时间就为一个机器周期。 (4)指令周期 指令周期是执行一条指令所需的全部时间。MCS-51单片机的指令周期通常由1、2、4个机器周期组成。 例:若晶
[单片机]
51单片机学习知识点
1.单片机内部资源三大指标: a.FLASH(程序存储控件 ROM ) 相当于: 电脑硬盘(断点后还保存在) b.RAM(内存) 相当于: 电脑内存(存储一些) c.SFR(特殊功能寄存器) 2.单片机的选择: a.STC89C52 (国内生产的) 1k=1024字节 b.P89V51RD+ 支持与KEIL联机进行在线仿真。 3.单片机最小系统 三要素:电源电路,复位电路,晶振电路。 特点:单片机可以运行程序,是单片机控制系统的核心。 可以独立运行的模块,叫做最小系统. 4. 5V就是高电频,0V就是低电平,数字电路,就是一个高一个低 高电平(正极)接VCC ,低电平(负极)接GND,这样就给单片机供电了。 电流对直流来说相当于
[单片机]
<font color='red'>51单片机</font>学习知识点
8051单片机的串行接口结构及工作方式设置寄存器
8051单片机的串行接口结构 8051单片机串行接口是一个可编程的全双工串行通信接口。它可用作异步通信方式(UART),与串行传送信息的外部设备相连接,或用于通过标准异步通信协议进行全双工的8051多机系统也能通过同步方式,使用TTL或CMOS移位寄存器来扩充I/O口。 8051单片机通过管脚RXD(P3.0,串行数据接收端)和管脚TXD(P3.1,串行数据发送端)与外界通信。SBUF是串行口缓冲寄存器,包括发送寄存器和接收寄存器。它们有相同名字和地址空间,但不会出现冲突,因为它们两个一个只能被CPU读出数据,一个只能被CPU写入数据。 串行口的控制与状态寄存器 串行口控制寄存器SCON 它用于定义串行口的工作方式及实施
[单片机]
80<font color='red'>51单片机</font>的串行接口结构及工作方式设置寄存器
以AT89C51单片机为核心的量程自动切换频率设计
近年来,随着科学技术的快速发展,特别是类似单片机等相关集成电路生产技术的快速堀起,推动了仪器仪表及家电产业的快速发展,用程序代码来简化硬件电路的复杂程度,使其不断向着体积小,价格低廉,功能更加多样化、智能化的方向发展。功能齐全,价格低廉的产品越来越受到人们的青睐,当然,科技的发展最先受益的 还是从事前沿科技研究领域的人员,对于他们来说,一款好的测量设备将为他们的研究工作带来便利的同时也减轻很多负担。就目前而言,高端仪器设备很多均依赖进口,研究并制造出属于我们国家自己的高端仪器设备将是我们一直努力的方向,而且也具有非常广阔的发展前景。 1 硬件电路设计 本设计主要由信号采集电路、放大整形电路、分频电路、信号处理电路、电源电路和显
[单片机]
以AT89C<font color='red'>51单片机</font>为核心的量程自动切换频率设计
74HC595与AT89C2051单片机接口的显示电路
74HC595与AT89C2051单片机接口设计的显示面板电路。P1 口的P115 、P116 、P117 用来控制LED 的显示,分别接到SLCK、SCLK和SDA 脚。三个数码管用来显示电压值的大小。在电路板上, LED3 在最左边,LED1 在最右边, 送数据时, 先送LED3 的显示码,最后送LED1 的显示码。LED 的亮度用PR1~ PR3 的阻值来控制。
[单片机]
74HC595与AT89C20<font color='red'>51单片机</font>接口的显示电路
51单片机定时器2捕获模式测脉冲频率
常规方法测量脉冲的频率,利用51单片机的两个定时器来测量,一个定时器来定时,一个定时器作为计数方式;能不能有一个更好的方法,不使用这么多硬件,只使用一个定时器就可以满足需求? 当然可以的,定时器2有输入捕获功能,P1.1接外部脉冲,当来一个脉冲,定时2就进入中断服务程序中断一次,同时也有定时功能。下面是主要的程序: #include reg52.h #define uint unsigned int #define uchar unsigned char #define ulong unsigned long uint timer2_count; uint cap_count; uchar code dispbit ={0
[单片机]
TMS320VC5402的HPI与51单片机的接口设计
0 引言 TMS320VC5402是TI公司推出的性价比极高的定点数字信号处理器(DSP)。它具有先进的多总线结构(三条16位数据存储器总线和一条程序存储器总线);其数据/程序寻址空间为1 M×16 bit: 内置4 k×16 bitP/DROM和16 k×16 bit-DARAM;此外,该DSP内含两个多通道缓冲串行口,一个8位并行与外部处理器通信的HPI口,2个16位定时器以及6通道DMA控制器;具有低功耗,适合电池供电设备等特点 。 51系列单片机是一种很经典的单片机。20多年来一直久盛不衰。而且Intel通过授权5l内核,目前已出现了很多第三方生产的51系列产品。这些产品一般都具有较高的时钟频率和较大的存储空间,而且还
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

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

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

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