找回密码
 立即注册
搜索
热搜: 中医 针灸 咳嗽
查看: 160|回复: 0

IIC总线EEPROM

[复制链接]

3711

主题

1

回帖

1万

积分

管理员

积分
11937
发表于 2023-2-11 12:16:47 | 显示全部楼层 |阅读模式
  1. /*********************************************************************************
  2. * 【程序功能】:         IIC通信,AT24C02读写数据,数码管显示数据。                                                                                   
  3. * 【使用说明】:
  4. **********************************************************************************/
  5. #include <reg52.h>
  6. #include <intrins.h>

  7. #define uint unsigned int
  8. #define uchar unsigned char
  9. #define At24c02ADDR 0XA0   //AT24C02硬件地址
  10. #define        I2cRead 1                   //I2C读方向位
  11. #define        I2cWrite 0                   //I2C写方向位

  12. sbit DU = P2^6;//数码管段选
  13. sbit WE = P2^7;//数码管段选
  14. sbit SCL = P2^1;//I2C时钟总线
  15. sbit SDA = P2^0;//I2C数据总线
  16. uchar num;//数码管显示的值
  17. bit AckFlag;//应答标志位

  18. //共阴数码管段选表0-9
  19. uchar code SMGduan[]= {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,};
  20. //数码管位选码
  21. uchar code SMGwei[] = {0xfe, 0xfd, 0xfb};

  22. /*====================================
  23. 函数        : delay(uint z)
  24. 参数        :z 延时毫秒设定,取值范围0-65535
  25. 返回值        :无
  26. 描述        :12T/Fosc11.0592M毫秒级延时
  27. ====================================*/
  28. void delay(uint z)
  29. {
  30.         uint x,y;
  31.         for(x = z; x > 0; x--)
  32.                 for(y = 114; y > 0 ; y--);                
  33. }

  34. /*====================================
  35. 函数        :display(uchar i)
  36. 参数        :i 显示数值,取值范围0-255
  37. 返回值        :无
  38. 描述        :三位共阴数码管动态显示
  39. ====================================*/
  40. void display(uchar i)
  41. {
  42.         static uchar wei;                
  43.         P0 = 0XFF;//清除断码
  44.         WE = 1;//打开位选锁存器
  45.         P0 = SMGwei[wei];
  46.         WE = 0;//锁存位选数据
  47.         switch(wei)
  48.         {
  49.                 case 0: DU = 1; P0 = SMGduan[i / 100]; DU = 0; break;
  50.                 case 1: DU = 1; P0 = SMGduan[i % 100 / 10]; DU = 0; break;       
  51.                 case 2: DU = 1; P0 = SMGduan[i % 10]; DU = 0; break;               
  52.         }
  53.         wei++;
  54.         if(wei == 3)
  55.                 wei = 0;
  56. }
  57. //定时器0初始化
  58. void timer0Init()
  59. {
  60.         EA = 1;        //打开总中断
  61.         ET0 = 1;//打开定时器0中断
  62.         TR0 = 1;         //启动定时器0
  63.         TMOD |= 0X01; //定时器工作模式1,16位定时模式
  64.         TH0 = 0xED;
  65.         TL0 = 0xFF; //定时5ms
  66. }
  67. /****************************************************
  68. IIC通信代码
  69. ****************************************************/

  70. /*====================================
  71. 函数        :delay5us()
  72. 参数        :无
  73. 返回值        :无
  74. 描述        :5us延时函数
  75. ====================================*/
  76. void delay5us()
  77. {
  78.         _nop_();
  79. }

  80. /*====================================
  81. 函数        :I2cStart()
  82. 参数        :无
  83. 返回值        :无
  84. 描述        :I2C总线起始信号
  85. ====================================*/
  86. void I2cStart()
  87. {
  88. //时钟总线为高电平期间数据总线又高变低产生起始型号
  89.         SCL = 1;
  90.         SDA = 1;
  91.         delay5us();//状态保持5us
  92.         SDA = 0;
  93.         delay5us();//状态保持5us
  94. }

  95. /*====================================
  96. 函数        :I2cStop()
  97. 参数        :无
  98. 返回值        :无
  99. 描述        :I2C总线停止信号
  100. ====================================*/
  101. void I2cStop()
  102. {
  103. //时钟总线为高电平期间,数据总线从高变低产生终止信号
  104.         SCL = 0;
  105.         SDA = 0;
  106.         SCL = 1;
  107.         delay5us();//状态保持5us
  108.         SDA = 1;
  109.         delay5us();//状态保持5us       
  110. }

  111. /*====================================
  112. 函数        :ReadACK()
  113. 参数        :无
  114. 返回值        :1非应答,0应答
  115. 描述        :I2C总线读从机应答信号
  116. ====================================*/
  117. bit ReadACK()
  118. {
  119.         SCL = 0;//拉低时钟总线,允许从机控制SDA
  120.         SCL = 1;//拉高,读SDA
  121.         delay5us();
  122.         if(SDA)//NOACK
  123.         {
  124.                 SCL = 0;
  125.                 return(1);//返回1
  126.         }
  127.         else//ACK
  128.         {
  129.                 SCL = 0;
  130.                 return(0);//返回0
  131.         }
  132. }

  133. /*====================================
  134. 函数        :SendACK(bit i)
  135. 参数        :1主机发送非应答,0发送应答
  136. 返回值        :无
  137. 描述        :主机发送应答信号
  138. ====================================*/
  139. void SendACK(bit i)
  140. {
  141.         SCL = 0;//拉低时钟总线,允许主机控制SDA
  142.         if(i)        //发非应答
  143.                 SDA = 1;
  144.         else        //发应答
  145.                 SDA = 0;
  146.         SCL = 1;  //拉高总线,让从机读SDA
  147.         delay5us();//保持5us
  148.         SCL = 0; //拉低时钟总线,允许SDA释放
  149.         SDA = 1;//释放数据总线
  150. }

  151. /*====================================
  152. 函数        :I2cSendByte(uchar DAT)
  153. 参数        :DAT需要发送的数据
  154. 返回值        :无
  155. 描述        :I2C发送一个字节数据
  156. ====================================*/
  157. void I2cSendByte(uchar DAT)
  158. {
  159.         uchar i;
  160.         for(i=0; i<8; i++) //分别写8次,每次写1位
  161.         {
  162.                 SCL = 0;//拉低时钟总线,允许SDA变化
  163.                 if(DAT & 0x80)//先写数据最高位
  164.                         SDA = 1;  //写1
  165.                 else
  166.                         SDA = 0;  //写0
  167.                 SCL = 1;          //拉高时钟,让从机读SDA
  168.                 DAT <<= 1;          //为发送下一位左移1位
  169.         }
  170.         SCL = 0; //拉低时钟总线,允许SDA释放
  171.         SDA = 1;//释放数据总线
  172. }

  173. /*====================================
  174. 函数        :At24c02Write(uchar ADDR, DAT)
  175. 参数        :ADDR 单元地址0-255,DAT 需要输入的数据0-255
  176. 返回值        :无
  177. 描述        :At24c02指定单元写入一个字节数据
  178. ====================================*/
  179. void At24c02Write(uchar ADDR, DAT)
  180. {
  181.         I2cStart();//I2C起始信号
  182.         I2cSendByte(At24c02ADDR + I2cWrite);//发送器件地址加读写方向位
  183.         if(ReadACK()) //读从机应答
  184.                 AckFlag = 1;        //NOACK
  185.         else
  186.                 AckFlag = 0;        //ACK
  187.         I2cSendByte(ADDR);//发送储存单元地址字节
  188.         if(ReadACK())//读从机应答
  189.                 AckFlag = 1;        //NOACK
  190.         else
  191.                 AckFlag = 0;        //ACK
  192.         I2cSendByte(DAT);//发送一字节数据
  193.         if(ReadACK())//读从机应答
  194.                 AckFlag = 1;        //NOACK
  195.         else
  196.                 AckFlag = 0;        //ACK
  197.         I2cStop();        //I2C停止信号
  198. }

  199. /*====================================
  200. 函数        :I2cReadByte()
  201. 参数        :无
  202. 返回值        :返回读出的一字节数据
  203. 描述        :I2C总线读一字节数据
  204. ====================================*/
  205. uchar I2cReadByte()
  206. {
  207.         uchar i, DAT;
  208.         for(i=0; i<8; i++)//分别读8次,每次读一位
  209.         {
  210.                 DAT <<= 1; //数据左移1位,准备接收一位
  211.                 SCL = 0;   //拉低时钟总线,允许从机控制SDA变化
  212.                 SCL = 1;   //拉高时钟总线,读取SDA上的数据
  213.                 if(SDA)
  214.                         DAT |= 0X01;//为1则写1,否则不行执行写1,通过左移补0
  215.         }
  216.         return(DAT); //返回读出的数据
  217. }

  218. /*====================================
  219. 函数        :At24c02Read(uchar ADDR)
  220. 参数        :ADDR 单元地址        0-255
  221. 返回值        :返回指定单元的数据
  222. 描述        :读AT24C02指定单元内数据
  223. ====================================*/
  224. uchar At24c02Read(uchar ADDR)
  225. {
  226.         uchar DAT;
  227.         I2cStart();//I2C起始信号
  228.         I2cSendByte(At24c02ADDR + I2cWrite);//发送器件地址加读写方向位
  229.         if(ReadACK())//读从机应答
  230.                 AckFlag = 1;        //NOACK
  231.         else
  232.                 AckFlag = 0;        //ACK
  233.         I2cSendByte(ADDR);//I2C发送一个字节
  234.         ReadACK();//读从机应答
  235.         I2cStart();//再次产生I2C起始信号
  236.         I2cSendByte(At24c02ADDR + I2cRead);//发送器件地址加读写方向位 读
  237.         if(ReadACK())//读从机应答
  238.                 AckFlag = 1;        //NOACK
  239.         else
  240.                 AckFlag = 0;        //ACK
  241.         DAT = I2cReadByte();//读一字节
  242.         SendACK(1);//主机发送非应答
  243.         I2cStop(); //I2C停止信号
  244.         return(DAT);//返回读出数据
  245.                        
  246. }

  247. void main()//main函数自身会循环
  248. {       
  249.         timer0Init();//定时器0初始化
  250.         EA = 0;//屏蔽中断
  251.         At24c02Write(3, 188);//给第3单元写入数据“188”
  252.         delay(5);//延时等待AT24C02处理
  253.         num = At24c02Read(3);//读出第3单元内数据送给显示变量
  254.         if(AckFlag)//当从机非应答
  255.                 P1 = 0;//亮P1所有灯
  256.         else
  257.                 P1 = 0XFF;//灭P1所有灯
  258.         EA = 1;//开中断
  259.         while(1);
  260. }

  261. //定时器0中断函数
  262. void timer0() interrupt 1
  263. {
  264.         TH0 = 0xED;
  265.         TL0 = 0xFF; //定时5ms
  266.         display(num); //数码管显示函数       
  267. }
复制代码
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|私人站点 ( 冀ICP备2023028127号-2 )

GMT+8, 2025-7-5 09:36 , Processed in 0.079632 second(s), 21 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表