打印
[文档下载]

N76E003 单片机 IIC 软模拟

[复制链接]
3672|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
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表示非应答


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

/* -----------------------------------------宏定义-----------------------------------------*/
#define IIC_SDA(N) IIC_SDA = N
#define IIC_SCL(N) IIC_SCL = N

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


/* -----------------------------------------全局变量定义-----------------------------------*/
sbit IIC_SDA = P1 ^ 4;
sbit IIC_SCL = P1 ^ 3;
/* -----------------------------------------应用程序---------------------------------------*/
void Delayus(uint16_t i)
{
    while (i--);
}
void Delayms(uint16_t i)
{
    i = i * 1000;
    Delayus(i);
}
/*********************************************
函数名:IIC_Init
功  能:IIC引脚初始化
作  者:薛建强
时  间:2019/06/11
**********************************************/
void IIC_Init(void)
{
    IIC_SDA_Output();
    IIC_SDA(1);
    IIC_SCL(1);
}


/*********************************************
函数名:IIC_Start
功  能:IIC通讯开始
作  者:薛建强
时  间:2019/06/11
**********************************************/
void IIC_Start(void)
{
    IIC_SDA_Output();  // 设置为输出模式
    IIC_SCL(1);
    IIC_SDA(1);
    Delayus(1);
    IIC_SDA(0);
    IIC_SCL(0);
    Delayus(2);
}
/*********************************************
函数名:IIC_Stop
功  能:IIC通讯结束
作  者:薛建强
时  间:2019/06/11
**********************************************/
void IIC_Stop(void)
{
    IIC_SDA_Output();  // 设置为输出模式
    IIC_SCL(0);
    IIC_SDA(0);
    Delayus(2);
    IIC_SCL(1);
    IIC_SDA(1);
    Delayus(2);
}
/*********************************************
函数名:IIC_Wait_ACK
功  能:IIC从设备应答
作  者:薛建强
时  间:2019/06/11
**********************************************/
void IIC_Wait_ACK(void)
{
    uint8_t i = 0;
    IIC_SDA_Input();            //   SDA 设置为输入
    IIC_SCL(1);
    Delayus(1);
    while (IIC_SDA == 1 && i < 250)
        i++;
    IIC_SCL(0);
    IIC_SDA_Output();           //   设置成输出
    Delayus(2);
}

/*********************************************
函数名:IIC_NACK
功  能:主设备非应答
作  者:薛建强
时  间:2019/06/11
**********************************************/
void IIC_NACK(void)
{
    IIC_SCL(1);
    Delayus(1);
    IIC_SDA(1);
    IIC_SCL(0);
    Delayus(2);
}

/*********************************************
函数名:IIC_WriteByte
功  能:发送一个字节
形  参:byte--待发送字节
作  者:薛建强
时  间:2019/06/11
**********************************************/
void IIC_WriteByte(uint8_t byte)
{
    uint8_t len = 0;
    IIC_SCL(0);
    Delayus(2);
    for (len = 0; len < 8; len++)
    {
        if (byte & 0x80)
        {
            IIC_SDA(1);
        }
        else
        {
            IIC_SDA(0);
        }
        Delayus(1);
        IIC_SCL(1);
        byte <<= 1;
        Delayus(1);
        IIC_SCL(0);
        Delayus(2);
    }
    IIC_SDA(1);
    IIC_SCL(0);
    Delayus(2);
}

/*********************************************
函数名:IIC_ReadByte
功  能:向从设备接收一个字节
返回值:Byte--读取到的字节
作  者:薛建强
时  间:2019/06/11
**********************************************/
uint8_t IIC_ReadByte(void)
{
    uint8_t len = 0, Byte = 0;
    IIC_SDA(1);
    IIC_SDA_Input();            // SDA 设置为输入
    for (len = 0; len < 8; len++)
    {
        IIC_SCL(0);
        Delayus(1);
        IIC_SCL(1);
        Delayus(1);
        Byte <<= 1;
        Byte |= IIC_SDA;
        Delayus(1);
        IIC_SCL(0);
        Delayus(1);
    }
    return Byte;
}

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

    for (i = 0; i < 8; i++)
    {
        IIC_SCL(1);
        Delayus(1);
        ReadValue <<= 1;
        if (IIC_SDA != 0)
        {
            ReadValue |= 0x01;
        }
        Delayus(1);
        IIC_SCL(0);
        Delayus(2);
    }
    if (Ack)
    {
        IIC_SCL(0);
        IIC_SDA_Output();   //   设置成输出模式
        IIC_SDA(0);
        Delayus(2);
        IIC_SCL(1);
        Delayus(1);
        IIC_SCL(0);
    }
    else
    {
        IIC_SCL(0);
        IIC_SDA_Output();   //   设置成输出模式
        IIC_SDA(1);
        Delayus(2);
        IIC_SCL(1);
        Delayus(1);
        IIC_SCL(0);
    }
    return ReadValue;
}


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

/* -----------------------------------------宏定义-----------------------------------------*/

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

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

/* -----------------------------------------应用程序---------------------------------------*/
void    IIC_Init(void);                // IIC端口
void    IIC_Start(void);               // 启动信号
void    IIC_Stop(void);                // 停止信号
void    IIC_Wait_ACK(void);            // 应答信号
void    IIC_NACK(void);
void    IIC_WriteByte(uint8_t txd);
uint8_t IIC_ReadByte(void);            // 读取数据
uint8_t IIC_ReceiveData(uint8_t Ack);  // 读取数据

#endif


使用特权

评论回复
沙发
ClarkLLOTP| | 2024-4-15 14:32 | 只看该作者
模拟iic速度能达到多快啊?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

28

主题

1396

帖子

0

粉丝