IIC(Inter-Integrated Circuit(集成电路总线))

2C串行总线一般有两根信号线,一根是双向的数据线SDA,另一根是时钟线SCL。所有接到I2C总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上。

IC(Inter-Integrated Circuit)总线是一种由NXP(原PHILIPS)公司开发的两线式串行总线,用于连接微控制器及其外围设备。多用于主控制器和从器件间的主从通信,在小数据量场合使用,传输距离短,任意时刻只能有一个主机等特性。

传输方式:

在I2C总线传输过程中,将两种特定的情况定义为开始和停止条件:当SCL保持“高”时,SDA由“高”变为“低”为开始条件;当SCL保持“高”且SDA由“低”变为“高”时为停止条件。开始和停止条件均由主控制器产生。使用硬件接口可以很容易地检测到开始和停止条件,没有这种接口的微机必须以每时钟周期至少两次对SDA取样,以检测这种变化。

所以在参照时序图编写IIC的代码时,需要编写开始函数,应答函数,停止函数,以及发送数据的函数。

IIC.C代码:

IIc初始化:

void IIC_Init(void)
{                        GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(    RCC_APB2Periph_GPIOB, ENABLE ); //使能GPIOB时钟GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7);   //PB6,PB7 输出高
}

开始信号:

void IIC_Start(void)
{SDA_OUT();     //sda线输出IIC_SDA=1;       IIC_SCL=1;delay_us(4);IIC_SDA=0;//START:when CLK is high,DATA change form high to low delay_us(4);IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
}     

停止信号:

void IIC_Stop(void)
{SDA_OUT();//sda线输出IIC_SCL=0;IIC_SDA=0;//STOP:when CLK is high DATA change form low to highdelay_us(4);IIC_SCL=1; IIC_SDA=1;//发送I2C总线结束信号delay_us(4);
}

应答函数:

void IIC_Ack(void)
{IIC_SCL=0;SDA_OUT();IIC_SDA=0;delay_us(2);IIC_SCL=1;delay_us(2);IIC_SCL=0;
}

发送数据以及读取数据:

void IIC_Send_Byte(u8 txd)
{                        u8 t;   SDA_OUT();         IIC_SCL=0;//拉低时钟开始数据传输for(t=0;t<8;t++){              IIC_SDA=(txd&0x80)>>7;txd<<=1;      delay_us(2);   //对TEA5767这三个延时都是必须的IIC_SCL=1;delay_us(2); IIC_SCL=0;    delay_us(2);}
}
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
u8 IIC_Read_Byte(unsigned char ack)
{unsigned char i,receive=0;SDA_IN();//SDA设置为输入for(i=0;i<8;i++ ){IIC_SCL=0; delay_us(2);IIC_SCL=1;receive<<=1;if(READ_SDA)receive++;   delay_us(1); }                   if (!ack)IIC_NAck();//发送nACKelseIIC_Ack(); //发送ACK   return receive;
}

IIC.H

#ifndef __MYIIC_H
#define __MYIIC_H
#include "sys.h"#define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}
#define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}#define IIC_SCL    PBout(6) //SCL
#define IIC_SDA    PBout(7) //SDA
#define READ_SDA   PBin(7)  //输入SDA void IIC_Init(void);                //初始化IIC的IO口
void IIC_Start(void);               //发送IIC开始信号
void IIC_Stop(void);                //发送IIC停止信号
void IIC_Send_Byte(u8 txd);         //IIC发送一个字节
u8 IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
u8 IIC_Wait_Ack(void);              //IIC等待ACK信号
void IIC_Ack(void);                 //IIC发送ACK信号
void IIC_NAck(void);                //IIC不发送ACK信号void IIC_Write_One_Byte(u8 daddr,u8 addr,u8 data);
u8 IIC_Read_One_Byte(u8 daddr,u8 addr);
#endif

向EEPROM存储芯片读取和写入数据

24C02是一个2Kbit的串行EEPROM存储芯片,可存储256个字节数据。工作电压范围为1.8V到6.0V,具有低功耗CMOS技术,自定时擦写周期,1000000次编程/擦除周期,可保存数据100年。24C02有一个16字节的页写缓冲器和一个写保护功能。通过I2C总线通讯读写芯片数据,通讯时钟频率可达400KHz。

24C02.c代码如下:

//初始化IIC接口
void AT24CXX_Init(void)
{IIC_Init();
}
//在AT24CXX指定地址读出一个数据
//ReadAddr:开始读数的地址
//返回值  :读到的数据
u8 AT24CXX_ReadOneByte(u16 ReadAddr)
{                 u8 temp=0;                                                                                IIC_Start();  if(EE_TYPE>AT24C16){IIC_Send_Byte(0XA0);     //发送写命令IIC_Wait_Ack();IIC_Send_Byte(ReadAddr>>8);//发送高地址IIC_Wait_Ack();         }else IIC_Send_Byte(0XA0+((ReadAddr/256)<<1));   //发送器件地址0XA0,写数据    IIC_Wait_Ack(); IIC_Send_Byte(ReadAddr%256);   //发送低地址IIC_Wait_Ack();      IIC_Start();           IIC_Send_Byte(0XA1);           //进入接收模式             IIC_Wait_Ack();   temp=IIC_Read_Byte(0);           IIC_Stop();//产生一个停止条件        return temp;
}
//在AT24CXX指定地址写入一个数据
//WriteAddr  :写入数据的目的地址
//DataToWrite:要写入的数据
void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite)
{                                                                                            IIC_Start();  if(EE_TYPE>AT24C16){IIC_Send_Byte(0XA0);      //发送写命令IIC_Wait_Ack();IIC_Send_Byte(WriteAddr>>8);//发送高地址}else{IIC_Send_Byte(0XA0+((WriteAddr/256)<<1));   //发送器件地址0XA0,写数据 }   IIC_Wait_Ack();       IIC_Send_Byte(WriteAddr%256);   //发送低地址IIC_Wait_Ack();                                                      IIC_Send_Byte(DataToWrite);     //发送字节                              IIC_Wait_Ack();                     IIC_Stop();//产生一个停止条件 delay_ms(10);
}
//在AT24CXX里面的指定地址开始写入长度为Len的数据
//该函数用于写入16bit或者32bit的数据.
//WriteAddr  :开始写入的地址
//DataToWrite:数据数组首地址
//Len        :要写入数据的长度2,4
void AT24CXX_WriteLenByte(u16 WriteAddr,u32 DataToWrite,u8 Len)
{   u8 t;for(t=0;t<Len;t++){AT24CXX_WriteOneByte(WriteAddr+t,(DataToWrite>>(8*t))&0xff);}
}//在AT24CXX里面的指定地址开始读出长度为Len的数据
//该函数用于读出16bit或者32bit的数据.
//ReadAddr   :开始读出的地址
//返回值     :数据
//Len        :要读出数据的长度2,4
u32 AT24CXX_ReadLenByte(u16 ReadAddr,u8 Len)
{   u8 t;u32 temp=0;for(t=0;t<Len;t++){temp<<=8;temp+=AT24CXX_ReadOneByte(ReadAddr+Len-t-1);                      }return temp;
}
//检查AT24CXX是否正常
//这里用了24XX的最后一个地址(255)来存储标志字.
//如果用其他24C系列,这个地址要修改
//返回1:检测失败
//返回0:检测成功
u8 AT24CXX_Check(void)
{u8 temp;temp=AT24CXX_ReadOneByte(255);//避免每次开机都写AT24CXX              if(temp==0X55)return 0;           else//排除第一次初始化的情况{AT24CXX_WriteOneByte(255,0X55);temp=AT24CXX_ReadOneByte(255);   if(temp==0X55)return 0;}return 1;
}//在AT24CXX里面的指定地址开始读出指定个数的数据
//ReadAddr :开始读出的地址 对24c02为0~255
//pBuffer  :数据数组首地址
//NumToRead:要读出数据的个数
void AT24CXX_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead)
{while(NumToRead){*pBuffer++=AT24CXX_ReadOneByte(ReadAddr++);  NumToRead--;}
}
//在AT24CXX里面的指定地址开始写入指定个数的数据
//WriteAddr :开始写入的地址 对24c02为0~255
//pBuffer   :数据数组首地址
//NumToWrite:要写入数据的个数
void AT24CXX_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite)
{while(NumToWrite--){AT24CXX_WriteOneByte(WriteAddr,*pBuffer);WriteAddr++;pBuffer++;}
}

24C02.h:

#ifndef __24CXX_H
#define __24CXX_H
#include "myiic.h" #define AT24C02        255
#define EE_TYPE AT24C02u8 AT24CXX_ReadOneByte(u16 ReadAddr);                            //指定地址读取一个字节
void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite);        //指定地址写入一个字节
void AT24CXX_WriteLenByte(u16 WriteAddr,u32 DataToWrite,u8 Len);//指定地址开始写入指定长度的数据
u32 AT24CXX_ReadLenByte(u16 ReadAddr,u8 Len);                   //指定地址开始读取指定长度数据
void AT24CXX_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite);   //从指定地址开始写入指定长度的数据
void AT24CXX_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead);      //从指定地址开始读出指定长度的数据u8 AT24CXX_Check(void);  //检查器件
void AT24CXX_Init(void); //初始化IIC
#endif

2021-11-3 软件模拟IIC时序,并和EEPROM存储芯片24C02双向通信以及显示功能相关推荐

  1. 软件模拟SPI时序实现25Q64读写操作

    软件模拟SPI时序实现25Q64读写操作 单片机采用SPI/IIC通讯协议访问外围电子模块如:显示屏.EEPROM.FLASH.各种电子传感器等等越来越多,掌握SPI/IIC通讯协议访问外设非常必要. ...

  2. STM32 软件模拟 IIC 代码,标准库、HAL库可用

    1 #ifndef _IIC_H 2 #define _IIC_H 3 4 #include "stdio.h" 5 #include "stm32f1xx_hal.h& ...

  3. 【STM32】IIC的基本原理(实例:普通IO口模拟IIC时序读取24C02)(转载)

    版权声明:本文为博主原创文章,允许转载,但希望标注转载来源. https://blog.csdn.net/qq_38410730/article/details/80312357 IIC的基本介绍 I ...

  4. STM32 Cube MX 之hal库软件模拟IIC 可直接移植使用

    此为软件模拟IIC,可以直接移植到HAL库使用..h文件需要自己做函数声明这里就不再放出,如有问题大家可以讨论. 使用的时候只需要更改SDA 和SCL引脚的宏定义就可以移植使用,当然IIC协议其实就是 ...

  5. STM32F103单片机软件模拟IIC并读取TMP112数字温度传感器

    本文利用STM32F103系列单片机读取TMP112数字温度传感器的温度信息,TMP112数字传感器采用IIC总线协议通信.STM32自身含有硬件IIC资源,分别是PB6-->SCL.PB7-- ...

  6. 基于stm32单片机的模拟IIC时序(附源码)

    我下面要说的是基于stm32单片机的模拟IIC时序,以及是一些要注意的事项:结合自己所做的MMA7455加速度传感器,我把模拟IIC的源代码贴了出来,大家可以参考一下. 1.因为在IIC协议中,当总线 ...

  7. 软件模拟IIC主从机

    软件模拟IIC 从机部分 从机接收部分 从机发送部分 主机部分 阻塞式发送 定时器中断方式发送 从机部分 因为项目简单,就只有数据接收,数据命令处理,显示.显示部分使用定时器中断动态扫描方式,主函数用 ...

  8. 【蓝桥杯嵌入式】【STM32】5_IICEEPROM之软件模拟IIC

    文章目录 1.原理图 2.源代码   下载工程文件:   https://gitee.com/Joseph_Cooper/blue-bridge-embedded 1.原理图 顺便指出了该器件的地址. ...

  9. STM32基于软件模拟IIC进行AHT21B温湿度采集

    STM32基于软件模拟IIC进行AHT21B温湿度采集 一. IIC简介 1.1 IIC简介 1.2 实现方式 1.3 实现方式对比 二. AHT21B简介 2.1 简介 2.2 产品特点 2.3 外 ...

最新文章

  1. Linux上oracle的安装
  2. LeetCode hard 84. Largest Rectangle in Histogram--python,java 15行,c++ 15行 解法
  3. HPE谢少毅:更敏捷的企业服务,做有生命力的落地实践
  4. 持续集成工具Hudson安装实例
  5. 32位网卡驱动 2008_DPDK之网卡收包流程
  6. c java c时间格式处理_c:foreach 对时间类型进行格式化
  7. 用MATLAB玩转机器人--第五章 机器人的数学建模
  8. Ubuntu 安装 Redis
  9. 8-过滤器Filter和监听器Listener
  10. CentOS 7中源码安装MySQL 5.7.16 ----已测试验证
  11. 零基础实战Keras模型转化为RKNN格式模型成功运行在RK3399Pro板子上
  12. 今天解决了首页无头像被显示的问题
  13. Excel K4宏病毒专杀
  14. 数据分析-kaggle泰坦尼克号生存率分析
  15. 使用SwiftyJSON解析JSON
  16. nginx配置及基本优化
  17. idea中类和方法创建文档注释
  18. 李章洙:受伤的老虎更凶猛
  19. Mac上的日程和任务管理工具Things3你get了吗
  20. 伪类和伪元素的区别是什么?

热门文章

  1. 【ubuntu拷贝目录】cp: omitting directory”错误的解释和解决办法
  2. autocad2014点击保存闪退_AutoCAD2014闪退的原因和解决方法 一打开就闪退怎么办
  3. artemis服务_Artemis
  4. 我的第一篇文章——stm32的ADC+DMA+滤波算法
  5. 杨辉三角形【找规律】
  6. JAVA学习笔记 03 - JAVA语言程序结构
  7. 太极图用html做的原理,用HTML画个太极图
  8. FPGA中高时钟频率计数器设计
  9. 青春不负韶光,梦想再次起航——记JavaEE班毕业典礼
  10. mysql关键字释义_数据库连接字符串ConnectionString 中的关键字值释义