[文档下载] N76E003 单片机 IIC 软模拟

[复制链接]
 楼主| jonas222 发表于 2024-4-14 21:09 | 显示全部楼层 |阅读模式
一、IIC概述

IIC(Inter-IntegratedCircuit)总线是一种由PHILIPS公司开发的两线式串行总线,用于连接微控制器以及其外围设备,IIC也被成为I2C,其实两者是完全相同的,只是名词不一样而已。
它是由数据线SDA和时钟线SCL构成的串行总线,可发送和接收数据。

二、IIC特点
  • 数据线SDA:数据线用来传输数据;时钟线SCL:时钟线用来同步数据收发

  • 总线上每一个器件都有一个唯一的地址识别,所以我们只需要知道器件的地址,根据时序就可以实现微控制器与器件之间的通信。

  • 数据线SDA和时钟线SCL都是双向线路,都通过一个电流源或上拉电阻连接到正的电压,所以当总线空闲的时候,这两条线路都是高电平。

  • 总线上数据的传输速率在标准模式下可达100kbit/s在快速模式下可达400kbit/s在高速模式下可达3.4Mbit/s。

  • 总线支持设备连接个数:同时支持多个主机和多个从机,连接到总线的接口数量只由总线电容是400pF的限制决定,如以下图所示:





注意:注意起始和终止信号都是由主机发出的,总线在起始条件之后,视为忙状态,在停止条件之后被视为空闲状态。

应答:每当主机向从机发送完一个字节的数据,主机总是需要等待从机给出一个应答信号,以确认从机是否成功接收到了数据。

注意:从机应答主机所需要的时钟仍是主机提供的,应答出现在每一次主机完成8个数据位传输后紧跟着的时钟周期,低电平0表示应答,1表示非应答


  1. /* -----------------------------------------头文件-----------------------------------------*/
  2. #include "iic.h"

  3. /* -----------------------------------------宏定义-----------------------------------------*/
  4. #define IIC_SDA(N) IIC_SDA = N
  5. #define IIC_SCL(N) IIC_SCL = N

  6. /*选择SDA的数据方向*/
  7. #define IIC_SDA_Input()     {P13_PushPull_Mode;P14_Input_Mode;}
  8. #define IIC_SDA_Output()    {P13_PushPull_Mode;P14_PushPull_Mode;}
  9. /* -----------------------------------------结构体定义-------------------------------------*/


  10. /* -----------------------------------------全局变量定义-----------------------------------*/
  11. sbit IIC_SDA = P1 ^ 4;
  12. sbit IIC_SCL = P1 ^ 3;
  13. /* -----------------------------------------应用程序---------------------------------------*/
  14. void Delayus(uint16_t i)
  15. {
  16.     while (i--);
  17. }
  18. void Delayms(uint16_t i)
  19. {
  20.     i = i * 1000;
  21.     Delayus(i);
  22. }
  23. /*********************************************
  24. 函数名:IIC_Init
  25. 功  能:IIC引脚初始化
  26. 作  者:薛建强
  27. 时  间:2019/06/11
  28. **********************************************/
  29. void IIC_Init(void)
  30. {
  31.     IIC_SDA_Output();
  32.     IIC_SDA(1);
  33.     IIC_SCL(1);
  34. }


  35. /*********************************************
  36. 函数名:IIC_Start
  37. 功  能:IIC通讯开始
  38. 作  者:薛建强
  39. 时  间:2019/06/11
  40. **********************************************/
  41. void IIC_Start(void)
  42. {
  43.     IIC_SDA_Output();  // 设置为输出模式
  44.     IIC_SCL(1);
  45.     IIC_SDA(1);
  46.     Delayus(1);
  47.     IIC_SDA(0);
  48.     IIC_SCL(0);
  49.     Delayus(2);
  50. }
  51. /*********************************************
  52. 函数名:IIC_Stop
  53. 功  能:IIC通讯结束
  54. 作  者:薛建强
  55. 时  间:2019/06/11
  56. **********************************************/
  57. void IIC_Stop(void)
  58. {
  59.     IIC_SDA_Output();  // 设置为输出模式
  60.     IIC_SCL(0);
  61.     IIC_SDA(0);
  62.     Delayus(2);
  63.     IIC_SCL(1);
  64.     IIC_SDA(1);
  65.     Delayus(2);
  66. }
  67. /*********************************************
  68. 函数名:IIC_Wait_ACK
  69. 功  能:IIC从设备应答
  70. 作  者:薛建强
  71. 时  间:2019/06/11
  72. **********************************************/
  73. void IIC_Wait_ACK(void)
  74. {
  75.     uint8_t i = 0;
  76.     IIC_SDA_Input();            //   SDA 设置为输入
  77.     IIC_SCL(1);
  78.     Delayus(1);
  79.     while (IIC_SDA == 1 && i < 250)
  80.         i++;
  81.     IIC_SCL(0);
  82.     IIC_SDA_Output();           //   设置成输出
  83.     Delayus(2);
  84. }

  85. /*********************************************
  86. 函数名:IIC_NACK
  87. 功  能:主设备非应答
  88. 作  者:薛建强
  89. 时  间:2019/06/11
  90. **********************************************/
  91. void IIC_NACK(void)
  92. {
  93.     IIC_SCL(1);
  94.     Delayus(1);
  95.     IIC_SDA(1);
  96.     IIC_SCL(0);
  97.     Delayus(2);
  98. }

  99. /*********************************************
  100. 函数名:IIC_WriteByte
  101. 功  能:发送一个字节
  102. 形  参:byte--待发送字节
  103. 作  者:薛建强
  104. 时  间:2019/06/11
  105. **********************************************/
  106. void IIC_WriteByte(uint8_t byte)
  107. {
  108.     uint8_t len = 0;
  109.     IIC_SCL(0);
  110.     Delayus(2);
  111.     for (len = 0; len < 8; len++)
  112.     {
  113.         if (byte & 0x80)
  114.         {
  115.             IIC_SDA(1);
  116.         }
  117.         else
  118.         {
  119.             IIC_SDA(0);
  120.         }
  121.         Delayus(1);
  122.         IIC_SCL(1);
  123.         byte <<= 1;
  124.         Delayus(1);
  125.         IIC_SCL(0);
  126.         Delayus(2);
  127.     }
  128.     IIC_SDA(1);
  129.     IIC_SCL(0);
  130.     Delayus(2);
  131. }

  132. /*********************************************
  133. 函数名:IIC_ReadByte
  134. 功  能:向从设备接收一个字节
  135. 返回值:Byte--读取到的字节
  136. 作  者:薛建强
  137. 时  间:2019/06/11
  138. **********************************************/
  139. uint8_t IIC_ReadByte(void)
  140. {
  141.     uint8_t len = 0, Byte = 0;
  142.     IIC_SDA(1);
  143.     IIC_SDA_Input();            // SDA 设置为输入
  144.     for (len = 0; len < 8; len++)
  145.     {
  146.         IIC_SCL(0);
  147.         Delayus(1);
  148.         IIC_SCL(1);
  149.         Delayus(1);
  150.         Byte <<= 1;
  151.         Byte |= IIC_SDA;
  152.         Delayus(1);
  153.         IIC_SCL(0);
  154.         Delayus(1);
  155.     }
  156.     return Byte;
  157. }

  158. /*********************************************
  159. 函数名:IIC_ReceiveData
  160. 功  能:向从设备接收一个字节,并带应答
  161. 作  者:薛建强
  162. 时  间:2019/06/11
  163. **********************************************/
  164. uint8_t IIC_ReceiveData(uint8_t Ack)
  165. {
  166.     uint8_t i = 0, ReadValue = 0;
  167.     IIC_SDA_Output();   //   设置成输出模式
  168.     IIC_SDA(1);
  169.     IIC_SDA_Input();    //   设置为输入模式
  170.     IIC_SCL(0);

  171.     for (i = 0; i < 8; i++)
  172.     {
  173.         IIC_SCL(1);
  174.         Delayus(1);
  175.         ReadValue <<= 1;
  176.         if (IIC_SDA != 0)
  177.         {
  178.             ReadValue |= 0x01;
  179.         }
  180.         Delayus(1);
  181.         IIC_SCL(0);
  182.         Delayus(2);
  183.     }
  184.     if (Ack)
  185.     {
  186.         IIC_SCL(0);
  187.         IIC_SDA_Output();   //   设置成输出模式
  188.         IIC_SDA(0);
  189.         Delayus(2);
  190.         IIC_SCL(1);
  191.         Delayus(1);
  192.         IIC_SCL(0);
  193.     }
  194.     else
  195.     {
  196.         IIC_SCL(0);
  197.         IIC_SDA_Output();   //   设置成输出模式
  198.         IIC_SDA(1);
  199.         Delayus(2);
  200.         IIC_SCL(1);
  201.         Delayus(1);
  202.         IIC_SCL(0);
  203.     }
  204.     return ReadValue;
  205. }


  1. b#ifndef __IIC_H
  2. #define __IIC_H
  3. /* -----------------------------------------头文件-----------------------------------------*/
  4. #include "main.h"

  5. /* -----------------------------------------宏定义-----------------------------------------*/

  6. /* -----------------------------------------结构体定义-------------------------------------*/
  7. typedef struct
  8. {
  9.   uint8_t                DelayTick;             //定义延时,以适应不同器件对速率的不同要求,具体值要在调试中确定
  10.   uint8_t                        ADDR;         //器件地址
  11. }IIC_TYPE;

  12. /* -----------------------------------------全局变量定义-----------------------------------*/

  13. /* -----------------------------------------应用程序---------------------------------------*/
  14. void    IIC_Init(void);                // IIC端口
  15. void    IIC_Start(void);               // 启动信号
  16. void    IIC_Stop(void);                // 停止信号
  17. void    IIC_Wait_ACK(void);            // 应答信号
  18. void    IIC_NACK(void);
  19. void    IIC_WriteByte(uint8_t txd);
  20. uint8_t IIC_ReadByte(void);            // 读取数据
  21. uint8_t IIC_ReceiveData(uint8_t Ack);  // 读取数据

  22. #endif


ClarkLLOTP 发表于 2024-4-15 14:32 来自手机 | 显示全部楼层
模拟iic速度能达到多快啊?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

44

主题

1654

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部