网站导航: 首页 > 设计参考 > 正文 文章搜索
用51单片机模拟I2C接口实例
 
文章编号:
090107114949
文章分类: 单片机 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 <reg51.h>   
  2.   
  3. #include <intrins.h>    
  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<Num;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<Num;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.   

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

 
相关文章:

 
最新开源项目
 
 
  查看更多...  
 
本站相关产品   淘宝网店
 




 
  查看更多...  

 

本站程序由百合电子工作室开发和维护
Copyright @ baihe electric studio
渝ICP备09006681号-4