I2C总线及其驱动程序

合集下载

51单片机的I2C底层驱动程序(IO口模拟)

51单片机的I2C底层驱动程序(IO口模拟)

51单片机的I2C底层驱动程序(IO口模拟)/*Title:I2C for 80C51Author:yuyouliang51单片机(本人使用STC89C52单片机,12T模式)的I2C驱动程序,使用逻辑分析仪对该协议进行分析,发现波形比较美观,SCL 的频率在70KHz左右(11.0592M晶振),低于标准的100K,可以适应大多数的I2C器件。

如果感觉速度过快或过慢,可以自行修改延时。

希望可以给读者一个参考,给读者一些帮助!*//*i2c.h文件 */#ifndef __I2C_H_#define __I2C_H_sbit SCL = P2^1;sbit SDA = P2^0;void start_i2c(); //启动I2C总线:SCL高电平期间,SDA由高变低void stop_i2c(); //停止I2C总线:SCL高电平期间,SDA由低变高void send_i2c(unsigned char c); //主机发送一个字节,先发送最高位unsigned char receive_i2c(); //主机接收一个字节,先接收最高位void master_ack(bit ack); //主机非应答信号(填参数0)或应答信号(填参数1)void slave_ack(); //等待从机应答信号#endif/* i2c.c文件 */#include#include#include#define nop() _nop_()void start_i2c() //启动I2C总线:SCL高电平期间,SDA由高变低{SDA=1;SCL=1;nop();nop();nop();nop();SDA=0;SCL=0;}void stop_i2c() //停止I2C总线,SCL高电平期间,SDA由低变高{SDA=0;SCL=1;nop();nop();nop();nop();SDA=1;}void slave_ack() //等待从机应答信号,如果从机迟迟没有应答,则结束总线。

I2C设备与驱动的关联

I2C设备与驱动的关联

I2C设备与驱动的关联作者:leeoo 联系方式:neu_linuxer@在Linux操作系统中,驱动程序的加载分为两种:内核启动时自动加载和用户手动加载;硬件设备也可以采用两种方式添加到系统中:在系统启动前及系统运行时的热插拨。

下面,我们以arm体系结构下的at91处理器中的I2C控制器为例,介绍一下硬件设备及相关的驱动程序是如何绑定及松绑的。

1.平台驱动注册过程1.1 at91_i2c_init()函数在文件drivers/i2c/busses/i2c-at91.c中,定义了结构体struct platform_driver并进行了初始化,通过使用module_init()宏进行声明,当模块被加载到内核时会调用 at91_i2c_init()函数。

在此函数中,调用了platform_driver_register()函数来完成注册。

static struct platform_driver at91_i2c_driver = {.probe = at91_i2c_probe,.remove = __devexit_p(at91_i2c_remove),.suspend = at91_i2c_suspend,.resume = at91_i2c_resume,.driver = {.name = "at91_i2c",.owner = THIS_MODULE,},};static int __init at91_i2c_init(void){return platform_driver_register(&at91_i2c_driver);}1.2 platform_driver_register()函数在文件drivers/base/platform.c中,实现并导出了platform_driver_register()函数,以便使其他模块中的函数可以调用此函数。

I2C总线8位远程IO扩展口芯片PCF8574的驱动程序

I2C总线8位远程IO扩展口芯片PCF8574的驱动程序

//...‎.....‎.....‎.....‎.....‎.....‎.....‎.....‎//名称‎: PCF‎8574(‎A).c ‎I2C扩展‎8位I/O‎芯片的接口‎程序//‎编程: 不‎详//日‎期: 20‎11102‎5//‎//发现‎问题请指点‎,谢谢!‎//...‎.....‎.....‎.....‎.....‎.....‎.....‎.....‎//CP‎U: 89‎C55 1‎1.059‎2MHz‎//环境:‎Keil‎C51 ‎V8.01‎//引脚‎定义:/‎/CPU‎_P2.0‎--- ‎P CF85‎74X_S‎C L 时钟‎// C‎P U_P2‎.1 --‎-PCF‎8574X‎_SDA ‎数据//‎CPU_‎P2.2 ‎--- P‎C F857‎4X_IN‎T中断‎//...‎.....‎.....‎.....‎.....‎.....‎.....‎.....‎#inc‎l ude ‎<Publ‎i c.h>‎#inc‎l ude ‎<Intr‎i ns.h‎>#in‎c lude‎"del‎a y_s.‎h"#i‎n clud‎e "pc‎f8574‎.h"‎//PC‎F8574‎(A)芯片‎指令的定义‎#def‎i ne P‎C F857‎4_WRI‎T E 0x‎40 /‎/器件地址‎= 011‎1 A2 ‎A1 A0‎r/w‎#defi‎n e PC‎F8574‎_READ‎0x41‎//器‎件地址= ‎0111 ‎A2 A1‎A0 r‎/w#d‎e fine‎PCF8‎574A_‎W RITE‎0x70‎//器‎件地址= ‎0111 ‎A2 A1‎A0 r‎/w#d‎e fine‎PCF8‎574A_‎R EAD ‎0x71 ‎//器件‎地址= 0‎111 A‎2 A1 ‎A0 r/‎w#d‎e fine‎P CF8‎574X_‎R EGIS‎T ER_A‎D DR_M‎A X 7 ‎//器件内‎部寄存器地‎址的最大值‎//‎内部函数‎s tati‎c voi‎d i2‎c_sta‎r t_co‎n d(vo‎i d);‎s tati‎c voi‎d i2‎c_sto‎p_con‎d(voi‎d);s‎t atic‎ucha‎r i2c‎_read‎_byte‎(void‎);st‎a tic ‎u char‎i2c_‎r ead_‎b yte_‎n ack(‎v oid)‎;sta‎t ic v‎o id ‎i2c_w‎r ite_‎b yte(‎u char‎da);‎//=‎=====‎=====‎=====‎=====‎=====‎=====‎=====‎=====‎=====‎=====‎=====‎=====‎= ====‎=====‎=====‎=//接‎口调用函数‎部分//‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎//序号‎:// ‎HD_P‎C F857‎4X_S0‎1//功‎能:/‎/读出‎芯片的复位‎状态‎// i‎s_pcf‎8574a‎=1 是‎A芯片‎// a‎d d_of‎_part‎器件的子‎地址 0~‎3//输‎出:/‎/端口‎的数据/‎/****‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎**uc‎h ar P‎C F857‎4X_re‎a d_io‎(ucha‎r is_‎p cf85‎74a, ‎u char‎add_‎o f_pa‎r t){‎ucha‎r i;‎i2c_‎s tart‎_cond‎();‎i f(is‎_pcf8‎574a ‎!=0)‎{‎i2c_w‎r ite_‎b yte(‎P CF85‎74A_R‎E AD |‎((add‎_of_p‎a rt <‎<1) &‎0x0E)‎);//器‎件地址=0‎111 A‎2 A1 ‎A0 r/‎w}‎else‎{‎i2c‎_writ‎e_byt‎e(PCF‎8574_‎R EAD ‎|((ad‎d_of_‎p art ‎<<1) ‎&0x0E‎));//‎器件地址=‎0100 ‎A2 A1‎A0 r‎/w}‎i =‎i2c_r‎e ad_b‎y te_n‎a ck()‎;/‎/顺序读的‎方式读出一‎个字节‎i2c_s‎t op_c‎o nd()‎;re‎t urn(‎i);}‎//*‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎****‎//序号:‎// ‎H D_PC‎F8574‎X_S02‎//功能‎://‎写数据‎到I/O端‎口//输‎入:/‎/is‎_pcf8‎574a ‎=1 是A‎芯片/‎/ad‎d_of_‎p art:‎器件的‎子地址 0‎~7//‎dat‎:写入‎的字节/‎/输出: ‎// ‎无//*‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎*****‎void‎PCF8‎574X_‎w rite‎_io(u‎c har ‎i s_pc‎f8574‎a, uc‎h ar a‎d d_of‎_part‎, uch‎a r da‎t){‎i2c_‎s tart‎_cond‎();‎i f(is‎_pcf8‎574a ‎!=0)‎{‎i2c_w‎r ite_‎b yte(‎P CF85‎74A_W‎R ITE ‎|((ad‎d_of_‎p art ‎<<1) ‎&0x0E‎)); /‎/器件地址‎=0111‎A2 A‎1 A0 ‎r/we‎l se‎{i‎2c_wr‎i te_b‎y te(P‎C F857‎4_WRI‎T E |(‎(add_‎o f_pa‎r t <<‎1) &0‎x0E))‎;//器‎件地址=0‎100 A‎2 A1 ‎A0 r/‎w}‎i2c‎_writ‎e_byt‎e(dat‎);‎i2c_s‎t op_c‎o nd()‎;}‎//===‎=====‎=====‎=//内‎部调用函数‎部分//‎=====‎=====‎====‎//--‎-----‎-----‎-----‎-----‎-----‎-----‎-----‎-----‎----‎//I2C‎发启始条‎件:时钟线‎为高时数据‎线发生下降‎沿跳变/‎/----‎-----‎-----‎-----‎-----‎-----‎-----‎-----‎-----‎--st‎a tic ‎v oid ‎i2c_s‎t art_‎c ond(‎v oid)‎{C‎O DE_S‎C L_LO‎W;_‎D ELAY‎_NOP3‎;CO‎D E_SD‎A_HIG‎H;_‎D ELAY‎_NOP3‎;CO‎D E_SC‎L_HIG‎H;_‎D ELAY‎_NOP3‎;CO‎D E_SD‎A_LOW‎;_D‎E LAY_‎N OP3;‎}/‎/----‎-----‎-----‎-----‎-----‎-----‎-----‎-----‎-//I‎2C 发结‎束条件:时‎钟线为高时‎数据线发生‎上升沿跳变‎//--‎-----‎-----‎-----‎-----‎-----‎-----‎-----‎---s‎t atic‎void‎i2c_‎s top_‎c ond(‎v oid)‎{C‎O DE_S‎C L_LO‎W;_‎D ELAY‎_NOP3‎;CO‎D E_SD‎A_LOW‎;_D‎E LAY_‎N OP3;‎COD‎E_SCL‎_HIGH‎;_D‎E LAY_‎N OP3;‎COD‎E_SDA‎_HIGH‎;_D‎E LAY_‎N OP3;‎}/‎/----‎-----‎-----‎-----‎-----‎-----‎-----‎-----‎-// ‎I2C 读‎取一个中间‎字节的数据‎//--‎-----‎-----‎-----‎-----‎-----‎-----‎-----‎---/‎*sta‎t ic u‎c har ‎i2c_r‎e ad_b‎y te(v‎o id)‎{uc‎h ar i‎;uc‎h ar d‎a=0;‎for(‎i =0;‎i<8;‎i++)‎{‎da <‎<=1; ‎//传输‎的数据高位‎在前‎C ODE_‎S CL_L‎O W;‎_DEL‎A Y_NO‎P3;‎CODE‎_SCL_‎H IGH;‎//时‎钟为高时读‎数据‎//‎N OP3;‎if‎(JUD‎G E_PC‎F8574‎X_SDA‎) da+‎+;}‎COD‎E_SCL‎_LOW;‎_DE‎L AY_N‎O P3;‎CODE‎_SDA_‎L OW; ‎//发‎送应答位‎_DEL‎A Y_NO‎P3;‎C ODE_‎S CL_H‎I GH;‎_DEL‎A Y_NO‎P3;‎C ODE_‎S CL_L‎O W;‎_DELA‎Y_NOP‎3;C‎O DE_S‎D A_HI‎G H;‎r etur‎n(da)‎;}*‎///-‎-----‎-----‎-----‎-----‎-----‎-----‎-----‎----‎// I2‎C读取一‎个结尾字节‎的数据/‎/----‎-----‎-----‎-----‎-----‎-----‎-----‎-----‎-sta‎t ic u‎c har ‎i2c_r‎e ad_b‎y te_n‎a ck(v‎o id)‎{uc‎h ar i‎;uc‎h ar d‎a =0;‎for‎(i =‎0; i<‎8; i+‎+){‎da‎<<=1‎;C‎O DE_S‎C L_LO‎W;‎_DELA‎Y_NOP‎3;‎C ODE_‎S CL_H‎I GH;‎‎//NOP‎3;‎i f(JU‎D GE_P‎C F857‎4X_SD‎A) da‎++;‎}CO‎D E_SC‎L_LOW‎;_D‎E LAY_‎N OP3;‎COD‎E_SDA‎_HIGH‎;_D‎E LAY_‎N OP3;‎COD‎E_SCL‎_HIGH‎;_D‎E LAY_‎N OP3;‎COD‎E_SCL‎_LOW;‎ret‎u rn( ‎d a );‎}/‎/----‎-----‎-----‎-----‎-----‎-----‎-----‎-----‎-// ‎I2C 写‎入一个字节‎的数据/‎/----‎-----‎-----‎-----‎-----‎-----‎-----‎-----‎-sta‎t ic v‎o id i‎2c_wr‎i te_b‎y te(u‎c har ‎d a )‎{uc‎h ar i‎;fo‎r(i =‎0; i<‎8; i+‎+){‎CO‎D E_SC‎L_LOW‎;i‎f(da&‎0x80)‎{‎CO‎D E_SD‎A_HIG‎H;‎}e‎l se‎{‎CODE‎_SDA_‎L OW;‎}‎CODE‎_SCL_‎H IGH;‎da‎<<=1‎;}‎CODE‎_SCL_‎L OW; ‎//第8‎个SCL下‎降沿,写入‎8位数据‎_DEL‎A Y_NO‎P3;‎C ODE_‎S DA_H‎I GH;‎_DEL‎A Y_NO‎P3;‎C ODE_‎S CL_H‎I GH;‎}//‎=====‎=====‎=====‎=====‎=====‎=====‎=====‎=====‎=====‎=====‎=====‎=====‎== ===‎=====‎=====‎==/‎/End ‎O f Fi‎l e‎‎。

I2C通信原理及程序详细讲解

I2C通信原理及程序详细讲解

I2C通信原理及程序详细讲解I2C(Inter-Integrated Circuit)是一种串行通信协议,常用于连接微控制器、传感器和其他外部设备。

I2C通信协议由荷兰飞利浦公司于1982年开发,它使用两根信号线(SDA和SCL)进行数据传输。

I2C通信协议采用主从结构,一个主设备(如微控制器)可以连接多个从设备(如传感器)。

主从设备之间通过SDA和SCL线进行数据传输。

SDA线是双向数据线,用于传输数据,SCL线是时钟线,用于同步数据传输。

I2C通信协议中,设备的地址是一个重要概念。

每个设备都有一个唯一的地址,通过该地址可以选择和通信特定的设备。

地址由7个位组成,其中最高位是固定的,并取决于设备是主设备还是从设备。

如果最高位为0,则表示该设备是主设备;如果最高位为1,则表示该设备是从设备。

通过以下步骤,让我们详细了解如何在I2C总线上进行通信。

1.初始化I2C总线:在程序开始时,需要初始化I2C总线。

这通常包括初始化SDA和SCL引脚,设置时钟频率等。

具体的初始化步骤取决于使用的硬件和软件环境。

2.发送开始信号:开始信号表示I2C数据传输的开始。

它由主设备发送,并且SDA线从高电平转为低电平时发出。

发送开始信号后,SDA线上的数据将被解释为地址数据。

3.发送设备地址:主设备发送一个包含设备地址和读/写位(R/W)的数据字节。

设备地址是唯一的,并且由主设备选择。

读/写位指示从设备是要读取数据还是写入数据。

4.等待从设备响应:主设备发送设备地址后,会等待从设备的响应。

从设备将响应一个应答位(ACK)来确认地址接收成功。

如果收到ACK位,则继续进行下一步,否则可能是设备未连接或通信错误。

5.发送数据:主设备发送数据给从设备。

数据可以是命令、配置或实际数据,具体取决于应用场景。

发送数据的方式是将每个数据字节传输到SDA线上,并在每个数据字节后发送一个ACK位。

6.接收数据:从设备将数据发送给主设备。

数据可以是传感器读数、存储器数据等。

I2C 24CXX驱动程序(真正实用 全)

I2C 24CXX驱动程序(真正实用 全)

#define _24cXX_H/* Includes ----------------------------------------------------------------*/#include "stm32f10x.h"#include "value.h"//#include "stdbool.h"/* Define ------------------------------------------------------------------*//* EEPROM Addresses defines *///注:32 64 的字地址是16位2个字节如果使用32或64请简单修改驱动即可#define WC24cXX 0x00 // 器件地址写#define RC24cXX 0x01 // 器件地址读#define USE_24C08 //使用24C08#ifdef USE_24C02#define MAXSIZE24cXX 256 // 总容量Bytes //级联时请修改本参数和硬件驱动#define BLOCK_SIZE 256 // 块容量Bytes#define I2C_PAGESIZE 8 // 8个字节每页#endif#ifdef USE_24C04#define MAXSIZE24cXX 512 // 总容量Bytes //级联时请修改本参数和硬件驱动#define BLOCK_SIZE 256 // 块容量Bytes#define I2C_PAGESIZE 16 // 16个字节每页#endif#ifdef USE_24C08#define MAXSIZE24cXX 1024 // 总容量Bytes //级联时请修改本参数和硬件驱动#define BLOCK_SIZE 256 // 块容量Bytes#define I2C_PAGESIZE 16 // 16个字节每页/* user define */#define YBCV_ADDR_0 0x0000 //定义仪表控制数据结构体的EEPROM存储地址0#define YBCV_ADDR_1 0x0200 //定义仪表控制数据结构体的EEPROM存储地址1#define EEPROM_VERIFY YB_CTRL_V ALE_SIZE //EEPROM仪表通道修正参数存储地址#endif#ifdef USE_24C16#define MAXSIZE24cXX 2048 // 总容量Bytes#define I2C_PAGESIZE 16 // 16个字节每页#endif#define MAXSIZE24cXX 4096 // 总容量Bytes //级联时请修改本参数和硬件驱动#define BLOCK_SIZE 4096 // 块容量Bytes#define I2C_PAGESIZE 32 // 16个字节每页#endif#ifdef USE_24C64#define MAXSIZE24cXX 8192 // 总容量Bytes //级联时请修改本参数和硬件驱动#define BLOCK_SIZE 8192 // 块容量Bytes#define I2C_PAGESIZE 32 // 16个字节每页#endif#define I2CInit I2C_GPIO_Config#define SCL(a) if (a) \GPIO_SetBits(GPIOB, GPIO_Pin_10);\else \GPIO_ResetBits(GPIOB,GPIO_Pin_10)#define SDA(a) if (a) \GPIO_SetBits(GPIOB, GPIO_Pin_11);\else \GPIO_ResetBits(GPIOB,GPIO_Pin_11)#define SCLO GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_10)#define SDAO GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11)/* Private ------------------------------------------------------------------*//* Public -------------------------------------------------------------------*//*uint idata ucSendBuffer[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};uint idata ucReceData;uint idata ucReceiveBuffer[8];//从器件中读出的多字节数据暂存区*//* Function Declaration -----------------------------------------------------*/extern bool I2C2_Init(void);//I2C初始化//extern bool I2C_ByteWrite(u8* pBuffer, u8 WriteAddr); //向24cXX中写入1个字节extern bool I2C_PageWrite(u8* pBuffer, u8 BlockCode, u16 WriteAddr, u8 n); //24cXX 页写(不超过一页)extern bool I2C_BlockWrite(u8* pBlock, u8 BlockCode, u16 WriteAddr, u16 n);//24cXX数据块写(不超过BLOCK_SIZE个字节)extern bool I2C_BufferWrite(u8* pBuffer, u16 WriteAddr, u16 n); //24cXX数据写(不超过MAXSIZE24cXX个字节)extern bool I2C_BufferRead(u8* pBuffer, u16 ReadAddr, u16 n); //从24cXX中读出N 字节数据(不超过MAXSIZE24cXX个字节)//extern void I2C_EE_WaitEepromStandbyState(void); //等待24CXX内部写周期结束#endif /*_24cXX_H*//******************** (C) COPYRIGHT 2015 XXXXX *********************************** 文件名:24cXX.c* 描述:本函数是xx项目的24cXX的读写函数* 平台:Keil 4 MDK \ stm32 3.5.0库* 库版本:基于野火相关资料及程序上优化修改* 作者:天涯月下红颜醉* 时间:2015.4.19******************************************************************************* ***//* Includes ------------------------------------------------------------------*/#include "24cXX.h"#include "value.h"#include "systick.h"#include <stdlib.h>/** 函数名:I2C2_Init* 描述:I2C2初始化* 输入:无* 输出:无* 调用:内部调用*/bool I2C2_Init(void){bool s = true;GPIO_InitTypeDef GPIO_InitStructure;/* 使能与I2CGPIO 有关的时钟*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);/* PB10-I2C2_SCL、PB11-I2C2_SDA*/GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; // 普通开漏输出GPIO_Init(GPIOB, &GPIO_InitStructure);SDA(1);SCL(1);Delay_nop();Delay_nop();if(!SDAO) s = false;if(!SCLO) s = false;SDA(0);Delay_nop();Delay_nop();if(SDAO) s = false;SCL(0);Delay_nop();SDA(0);SCL(0);Delay_nop();Delay_nop();if(SDAO) s = false;if(SCLO) s = false;SCL(1);Delay_nop();Delay_nop();SDA(1);return s;}/********开启24cXX的I2C总线********/static bool I2CStart(void){SDA(1);SCL(1);Delay_nop();Delay_nop();if(!SDAO)return false; //SDA线为低电平则总线忙,退出SDA(0);Delay_nop();Delay_nop();if(SDAO)return false; //SDA线为高电平则总线出错,退出SCL(0);Delay_nop();return true;}/********关闭24cXX的I2C总线*******/static void I2CStop(void){SDA(0);SCL(0);Delay_nop();Delay_nop();SCL(1);Delay_nop();Delay_nop();SDA(1);}/*********发送ACK*********/static void I2CAck(void){SDA(0);SCL(0);Delay_nop();// Delay_nop();SCL(1);Delay_nop();// Delay_nop();SCL(0);}/*********发送NO ACK*********/static void I2CNoAck(void){SDA(1);SCL(0);Delay_nop();// Delay_nop();SCL(1);Delay_nop();// Delay_nop();SCL(0);}/*********读取ACK信号*********/static bool I2CWaitAck(void) //返回为:1=有ACK,0=无ACK{SCL(0);SDA(1); //设置SDA为输入Delay_nop();// Delay_nop();SCL(1);Delay_nop();// Delay_nop();if(SDAO){SCL(0);return false;}SCL(0);return true;}/************MCU向24cXX发送一个字节数据*************/ static void I2CSendByte(u8 demand) //数据从高位到低位//{u8 i=8;while(i--){SCL(0);Delay_nop();SDA((bool)(demand&0x80));demand<<=1;Delay_nop();// Delay_nop();SCL(1);Delay_nop();// Delay_nop();}SCL(0);}/*********MCU从24cXX读入一字节数据*********/static u8 I2CReceiveByte(void) //数据从高位到低位//{u8 i=8;u8 ddata=0;SDA(1); //设置SDA为输入while(i--){ddata<<=1; //数据从高位开始读取SCL(0);Delay_nop();// Delay_nop();SCL(1);Delay_nop(); //从高位开始ddata|=SDA;ddata<<=1// Delay_nop();if(SDAO){ddata|=0x01;}}SCL(0);return ddata;}/** 函数名:I2C_EE_WaitEepromStandbyState* 描述:Wait for EEPROM Standby state* 输入:无* 输出:无* 返回:无* 调用:*/static void I2C_EE_WaitEepromStandbyState(u8 BlockCode){int i = 50;do{Delay_us(100);I2CStart();I2CSendByte(BlockCode | WC24cXX);//发送器件地址写}while(I2CWaitAck() == 0 && i-- > 0);I2CStop();}/****************向24cXX中写入1个字节****************/ /*static bool I2C_ByteWrite(u8* pBuffer, u8 WriteAddr){I2CStart();//启动I2CI2CSendByte(WC24cXX);//发送器件地址写return false;I2CSendByte(WriteAddr);if(I2CWaitAck() == 0)return false;I2CSendByte(*pBuffer);if(I2CWaitAck() == 0)return false;I2CStop();return true;}*//** 函数名:I2C_PageWrite* 描述:在EEPROM的一个写循环中可以写多个字节,但一次写入的字节数* 不能超过EEPROM页的大小。

I2C总线驱动在嵌入式系统中的两种实现,I2C,嵌入式,AR.

I2C总线驱动在嵌入式系统中的两种实现,I2C,嵌入式,AR.

I2C总线驱动在嵌入式系统中的两种实现,I2C,嵌入式,ARM,软件模拟1引言I2C总线(Inter-ICBus)是一种通用的串行总线,是用于IC器件之间连接的二线制总线。

他通过串行数据线(SerialDataLines,SDL)及串行时钟线(SerialClockLine,SCL)两线在连接到总线上的器件之间传送信息,并根据地址识别每个器件。

一个或多个微控制器以及外围器件可以通过I2C总线接口非常方便的连接在一起构成系统。

这种总线结构的连线和连接引脚少,器件间总线简单。

结构紧凑,因此其构成系统的成本较低;并且在总线上增加器件不1 引言I2C总线(Inter-IC Bus)是一种通用的串行总线,是用于IC器件之间连接的二线制总线。

他通过串行数据线(SerialData Lines,SDL)及串行时钟线(Serial ClockLine,SCL)两线在连接到总线上的器件之间传送信息,并根据地址识别每个器件。

一个或多个微控制器以及外围器件可以通过I2C总线接口非常方便的连接在一起构成系统。

这种总线结构的连线和连接引脚少,器件间总线简单。

结构紧凑,因此其构成系统的成本较低;并且在总线上增加器件不会影响系统的正常工作,所有的I。

C 器件共用一套总线,因此其系统修改和可扩展性好。

即使有不同时钟速度的器件连接到总线上,时间同步机制也能够很方便地确定总线时钟,因此在嵌入式系统中得到了广泛的应用。

2 I2C总线原理2.1 I2C工作原理I2C总线是由数据线SDA和时钟线SCL构成的串行总线,可发送和接收数据。

每个连接到总线的器件都可以通过惟一的地址与主机通讯,主机可以作为主机发送器或主机接收器。

他是一个真正的多主机总线,如果两个或更多主机同时初始化,数据传输可以通过冲突检测和仲裁防止数据被破坏。

串行的8位双向数据传输位速率在标准模式下可达100kb/s,快速模式下可达400 kb/s,高速模式下可达3.4 Mb/s。

TI-I2C驱动

TI-I2C驱动

TI-I2C驱动一、与I2C驱动相关的文件分成两部分:1)应用层接口部分:程序在svn中的路径如下:在https://dareglob-971006/svn/eocOS/branches/eocOS_v4/branches/bsp/user/i2c目录下,i2ctest.c文件,提供了lm75a_temp_read()方法,用来读取LM75A设备温度寄存器中的温度信息的功能。

2)内核驱动部分:内核位于svn中的路径如下:https://dareglob-971006/svn/eocOS/branches/eocOS_v4/branches/bsp/kernel(1)总线驱动:i2c-davinci.c:在内核目录中driver/i2c/busses目录下,适用于TI的I2C总线驱动程序。

I2C总线驱动是对I2C硬件体系结构中适配器端的实现。

(2)I2C驱动代码核心:i2c-core.c:在内核目录中driver/i2c/目录下,是I2C代码的核心,用于沟通虚拟文件系统与底层实现。

该文件提供了I2C总线驱动和设备驱动的注册、注销方法,I2C通信方法上层的、与具体适配器无关的代码以及探测设备、检测设备地址的上层代码等。

(3)I2C设备驱动:lm75.c:在内核目录中driver/hwmon目录下,是针对LM75A以及其他能兼容的温度传感器的设备驱动。

I2C设备驱动是对I2C硬件体系结构中设备端的实现,设备一般挂接在受CPU控制的I2C适配器上,通过I2C适配器与CPU交换数据。

二、I2C简要工作流程1)在总线驱动初始化时候,当通过Linux内核源代码/driver/base/platform.c文件中定义platform_driver_register()函数注册platform_driver结构体时,其中probe指针指向的davinci_i2c_probe()函数将被调用,以初始化适配器硬件。

2)而davinci_i2c_remove()函数则完成与davinci_i2c_probe()相反的功能。

I2C驱动架构

I2C驱动架构

I2C驱动架构I2C 概述I2C是philips提出的外设总线.I2C只有两条线,一条串行数据线:SDA,一条是时钟线SCL ,使用SCL,SDA这两根信号线就实现了设备之间的数据交互,它方便了工程师的布线。

因此,I2C总线被非常广泛地应用在EEPROM,实时钟,小型LCD等设备与CPU的接口中。

linux下的驱动思路在linux系统下编写I2C驱动,目前主要有两种方法,一种是把I2C设备当作一个普通的字符设备来处理,另一种是利用linux下I2C驱动体系结构来完成。

下面比较下这两种方法:第一种方法:优点:思路比较直接,不需要花很多时间去了解linux中复杂的I2C子系统的操作方法。

缺点:要求工程师不仅要对I2C设备的操作熟悉,而且要熟悉I2C的适配器(I2C控制器)操作。

要求工程师对I2C的设备器及I2C的设备操作方法都比较熟悉,最重要的是写出的程序可以移植性差。

对内核的资源无法直接使用,因为内核提供的所有I2C设备器以及设备驱动都是基于I2C子系统的格式。

第一种方法的优点就是第二种方法的缺点,第一种方法的缺点就是第二种方法的优点。

I2C架构概述Linux的I2C体系结构分为3个组成部分:I2C核心:I2C核心提供了I2C总线驱动和设备驱动的注册,注销方法,I2C通信方法(”algorithm”)上层的,与具体适配器无关的代码以及探测设备,检测设备地址的上层代码等。

I2C总线驱动:I2C总线驱动是对I2C硬件体系结构中适配器端的实现,适配器可由CPU控制,甚至可以直接集成在CPU内部。

I2C设备驱动:I2C设备驱动(也称为客户驱动)是对I2C 硬件体系结构中设备端的实现,设备一般挂接在受CPU控制的I2C适配器上,通过I2C适配器与CPU交换数据。

linux驱动中i2c驱动架构上图完整的描述了linux i2c驱动架构,虽然I2C硬件体系结构比较简单,但是i2c体系结构在linux中的实现却相当复杂。

I2C设备驱动介绍

I2C设备驱动介绍

I2C设备驱动介绍I2C(Inter-Integrated Circuit)是一种串行通信协议,用于连接并使多个外部设备与主控制器进行通信。

在嵌入式系统中,I2C设备驱动起着至关重要的作用,负责将操作系统与I2C总线上的设备进行通信,促进数据的传输和交互。

1.初始化:驱动程序需要初始化I2C控制器,包括设置时钟频率、地址范围等。

2.设备注册:设备驱动需要在操作系统中注册I2C设备,以便操作系统能够识别和管理设备。

3.读写操作:驱动程序需要实现读写设备寄存器的功能,包括发送开始和停止信号、以及发送、接收数据等。

4.错误处理:驱动程序需要处理I2C通信过程中可能出现的错误,例如传输失败、设备无响应等情况。

5.中断处理:驱动程序需要支持I2C设备的中断机制,以便及时处理设备的状态变化或数据传输完成的中断信号。

6.电源管理:驱动程序需要支持设备的电源管理功能,包括设备的唤醒、睡眠等操作。

7.设备控制:驱动程序需要实现设备特定的控制功能,例如设置传感器的采样率、配置设备的工作模式等。

8. 虚拟文件系统接口:在Linux系统中,驱动程序通常通过虚拟文件系统接口(如/dev)与用户空间进行交互,提供读写设备寄存器的功能。

1.确定设备:首先,开发者应该确定需要驱动的I2C设备。

这可能包括传感器、EEPROM、显示器等。

2.确定硬件连接:确定I2C设备与主控制器之间的硬件连接和电气特性。

这包括设备的I2C地址、I2C总线上的物理接口等。

3.编写驱动程序:在操作系统中,开发者可以根据设备的文档或芯片厂商提供的驱动程序框架,编写自己的I2C设备驱动程序。

驱动程序需要实现上述提到的功能,并且根据设备的特点进行相应的适配和优化。

4.编译和测试:完成驱动程序的编写后,需要将其编译成与操作系统内核匹配的模块或静态链接库。

然后,通过加载驱动模块或重新编译内核来使驱动程序生效。

最后,进行测试,确保驱动程序在各种场景下的正常运行。

Android平台Camera及I2C总线驱动学习小结

Android平台Camera及I2C总线驱动学习小结

Android平台Camera及I2C总线驱动学习⼩结Android平台Camera及I2C总线驱动学习⼩结——基于MSM8x60平台硬件开发⼆部BSP科党潇⼯号:101131511.MSM8x60平台简介High-performance high-level operating system(HLOS) platform(45nm)多核处理器(Modem+Dual Apps in a single chip),⽀持Android TMDual 1.2GHz Scorpion TM +512kB shared L2 cache,eMMC LPDDR2内存专属ARM7 ⽤于功率资源控制及传感器外设操作1080pHD 编解码,Adreno TM 220图形处理器,4-lane MIPI摄像头,最⾼⽀持12M像素WCDMA,GSM,HSDPA,1x advanced,1xEV-DO Rev A/BgpsOne,BT3.0,FM Rx/Tx,WIFI WCN1314AAC,AMR-NB,EVRC,QCELP,etc2.MSM8x60平台Camera及Graphics特性Camera特性:VFE 3.1,MIPI接⼝(4-lane)优异的3A算法(AF,AE,AWB),⾃动帧率AFR(Auto Frame Rate)最⾼⽀持12MegaPixel,12bit/pixel,⽀持BAYER和YUV模式1080p预览@30fps闪光灯⽀持,触摸屏⾃动对焦⽀持业界领先的图像特效集:Hand Jitter Reduction(HJR),Motion ISO,Best-Shot mode,Anti-banding,EV control,JPEG encode & decodeGraphics特性:Adreno 220(MSM v2.0)图形处理器,88M triangles/sOpenGL ES 1.1/ OpenGL ES 1.1/ OpenVG 1.1/SVG tiny 1.2LCD显⽰最⾼⽀持到WSXGA(1440×900),60Hz刷新率。

linux i2c注册流程

linux i2c注册流程

linux i2c注册流程Linux I2C注册流程I2C(Inter-Integrated Circuit)是一种串行通信协议,用于连接在计算机系统中的多个外部设备。

在Linux系统中,I2C总线的设备驱动程序通过I2C核心子系统进行注册和管理。

本文将介绍Linux I2C注册流程的具体步骤,帮助读者了解Linux系统中I2C设备的注册过程。

1. 硬件连接和配置在开始之前,首先需要进行硬件连接以及相关I2C控制器的配置。

通常,I2C总线上的每个设备都有一个唯一的7位或10位地址。

在Linux系统中,I2C控制器通过设备树(Device Tree)或Platform数据结构进行配置。

根据硬件和芯片特定的要求,需要指定控制器的一些参数,例如时钟频率、地址模式等。

2. I2C核心子系统I2C核心子系统是Linux内核中用于管理I2C设备的模块,包含了驱动程序和各种API函数。

它将I2C设备的操作进行了抽象,并提供了一组统一的接口供驱动程序使用。

I2C核心的代码位于"drivers/i2c"目录下。

3. I2C驱动程序I2C设备驱动程序是一种与特定硬件相关的内核模块,用于与I2C设备进行通信和控制。

驱动程序的代码一般位于"drivers/i2c/busses"目录下。

Linux内核已经提供了一些通用的I2C驱动程序供使用,例如“i2c-gpio”用于模拟I2C总线。

4. I2C设备结构体在编写自定义I2C驱动程序之前,需要定义一个I2C设备结构体。

该结构体用于描述设备的各种属性,包括设备的名称、地址、信号模式以及设备特定的配置等。

通常可以基于设备树或Platform数据结构进行初始化。

5. I2C适配器I2C适配器是用于控制I2C设备的总线控制器。

在Linux系统中,每个适配器都对应一个I2C控制器,通过/sys/bus/i2c/devices目录进行管理。

适配器结构体定义了适配器和它管理的设备之间的关系。

嵌入式Linux中I2C总线驱动程序设计

嵌入式Linux中I2C总线驱动程序设计

Ke r s e e d d L n x I C b s I C d v c ; d v c r e ; AT 1 ywo d : mb d e ; i u ; 2 u ; 2 e i e e ie d i r v 9 RM 9 0 2 0
0 引 言
ICit - tga d i u ) 线 , 由菲利 浦 公 司开 发 的一 2 ( e i ert c ci总 n rn e r t 是 种 同步 串行 总 线 协 议 , 于 连 接 微 控 制 器 及 其 外 围 设 备 。最 用 初 是 为 音 频 和 视 频 设 备 开 发 的 ,如 今 IC在 各 种 电 子 设 备 中 2
中图法分类 号 : P9 T 3 T 3 ; P
文献标 识码 : A
文章编 号 :0 072 (0 8 1—570 10 —0 4 2 0 ) 02 1—3
De in o C u r e n e mb d e n x s se sg f 2 b s i ru d r I d v e e d dLiu y tm
IC总 线 在 传 送 数 据 过 程 中共 有 3 类 型 信 号 , 们 分 别 2 种 它 是 开 始 信 号 、 束 信 号 和 应 答 信 号( 图 l 图 2 示 ) 结 如 、 所 。
得 到 了 广 泛 的 应 用 。嵌 入 式 系 统 中 常 常 使 用 这 个 总 线 连 接
HEYa u , DE jn NGF i i e— q
( o ee f uo t nS i c n n ier g o t C ia iesyo T cn lg,G agh u 6 0 C ia C lg A tmao ce e d gn e n ,S u h v r t f eh oo y un z o 1 4 , hn) l o i n a E i h n Un i 50

i2c总线(pfc8563)驱动子法度模范集[精华]

i2c总线(pfc8563)驱动子法度模范集[精华]

I2C总线(PFC8563)驱动子程序集;I2C总线说明:;I2_SDA =1时,即总线空闲;I2_SDA =0时,即总线忙,即正在使用; 本程序集在I2_SDA =0时,使I2_SCL=0,;此时即可改变I2_SDA 的数据,或接受I2_SDA 数据的改变;I2_SCL=0时,数据是可以改变的;I2_SCL=1时,数据的改变视为控制信号,如0到1则为停止控制;如1到0则为启动控制;========================================================== =;I2C总线(PFC8563)驱动子程序集I2_SCL EQU P2.6I2_SDA EQU P2.7I2ADDRW EQU 0A2HI2ADDRR EQU 0A3HI2TIMER EQU 02HI2TIMERN EQU 07HORG 0000HJMP MAINORG 0030HMAIN:MOV SP,#80HMOV R0,#20HCALL I2_WRTIME ;写时间初始值ED:MOV R0,#28H ;此处断点,不停执行,观测CALL I2_RDTIME ;读时间值JMP ED;================================================== 开始I2CU总线子程序I2_START: SETB I2_SDANOPSETB I2_SCLNOP ;建立起始条件的时间大于4.7usNOPNOPNOPNOPCLR I2_SDA ;起始条件NOPNOPNOPNOPNOPCLR I2_SCL ;钳隹总线NOPRET;===================================================结束I2CU总线子程序I2_STOP: CLR I2_SDANOPSETB I2_SCL ;结束总线时间大于4usNOPNOPNOPNOPNOPSETB I2_SDA ;结束总线NOPNOPNOPNOPRET;=============================================发送应答信号子程序:即发送0I2_SDACK: CLR I2_SDANOPNOPSETB I2_SCLNOPNOPNOPNOPNOPCLR I2_SCLSETB I2_SDANOPNOPRET;===========================================发送非应答信号子程序,即发送1I2_SDNACK: SETB I2_SDANOPNOPSETB I2_SCLNOPNOPNOPNOPNOPCLR I2_SCLCLR I2_SDANOPNOPRET;==================================================== ;检查应答子程序,即读应答信号:若读出结果为0;证明有应答,即总线上有器件响应,否则可能无器件或器件坏;出口参数:;FO=O有应答I2_CHKACK: SETB I2_SDANOPNOPSETB I2_SCLNOPNOPNOPNOPCLR F0MOV C, I2_SDAJNC CENDSETB F0CEND: CLR I2_SCLRET;=============================================发送字节子程序;入口参数;A: 被发送数;占用资源:;R2;说明:每写一字节要调用一次I2_CHKACK取应答位I2_WRBYTE: MOV R2, #08HI2_WRBYTELP1: RLC AMOV I2_SDA, CNOPSETB I2_SCLNOPNOPNOPNOPNOPCLR I2_SCLDJNZ R2, I2_WRBYTELP1NOPNOPRET;==================================================读取字节子程序;出口参数:;A: 读出的数;占用资源;R2;说明: 每读取一字节要发送一应答/非应答位I2_RDBYTE: MOV R2, #08HI2_RDLP: SETB I2_SDANOPSETB I2_SCLNOPNOPMOV C, I2_SDANOPCLR I2_SCLRLC ANOPNOPNOPNOPDJNZ R2, I2_RDLPRET;===================================BCD码转二进制子程序;入口参数:;A: BCD码;出口参数;A: 二进制数;占用资源: A R2 R3BCD2BIN: MOV R3, AANL A, #0F0HRR AMOV R2, ARR ARR AADD A, R2MOV R2, AMOV A, R3ANL A, #0FHADD A, R2RET;========================================写8563万年历子程序;入口参数:;R0: 参数区首址: 参数区格式(秒分钟小时日星期月年,BCD码表示);占用资源:;A;R0;R2;R3I2_WRTIME:CALL I2_START ;发送起始条件MOV A, #I2ADDRWCALL I2_WRBYTE ;发送8563地址 CALL I2_CHKACK ;检查应答JB F0,I2_WRTIMEMOV A, #I2TIMER ;发送8563时间寄存器地址CALL I2_WRBYTECALL I2_CHKACKJB F0,I2_WRTIMEMOV R3, #I2TIMERNI2_WRTIMELP1:MOV A, @R0CALL I2_WRBYTE ;向8563写时间CALL I2_CHKACKJB F0,I2_WRTIMEINC R0DJNZ R3, I2_WRTIMELP1CALL I2_STOP ;发送停止条件 RET;===================================读8563万年历子程序;入口参数:;R0: 参数区首址(格式同上);出口参数:参数区存放万年历数据(二进制);占用资源:;A;R0;R2;R3I2_RDTIME:CALL I2_START ;发送起始条件MOV A, #I2ADDRW ;发送8563写地址CALL I2_WRBYTECALL I2_CHKACKJB F0,I2_RDTIMEMOV A, #I2TIMER ;发送8563时间寄存器首址CALL I2_WRBYTECALL I2_CHKACKJB F0,I2_RDTIMECALL I2_START ;发送起始条件MOV A, #I2ADDRR ;发送8563读地址CALL I2_WRBYTECALL I2_CHKACKJB F0,I2_RDTIMEMOV R3, #I2TIMERN-1I2_RDTIMELP1:CALL I2_RDBYTE ;读取8563万年历数据MOV @R0, ACALL I2_SDACK ;发送应答信号INC R0DJNZ R3, I2_RDTIMELP1CALL I2_RDBYTE ;读取8563万年历年数据MOV @R0, ACALL I2_SDNACK ;发送非应答信号 CALL I2_STOP ;发送停止条件 RET;等长一点: acc = 0 时,为 errorI2_CHKACK:SETB I2_SDANOPNOPSETB I2_SCLCLR F0MOV A, #20I2_CHKACK_L1:JNB I2_SDA, I2_CHKACK_L2DJNZ ACC, I2_CHKACK_L1SETB F0I2_CHKACK_L2:CLR I2_SCLRETEND。

I2C设备驱动介绍

I2C设备驱动介绍

I2C设备驱动介绍I2C(Inter-Integrated Circuit)是一种简单的串行通信协议,用于在微控制器和外部设备之间传输数据。

它是由飞利浦公司(现在的恩智浦)于1982年推出的,现在已成为一种广泛应用的通信接口。

总线驱动是与I2C总线硬件相关的组件,它负责控制总线的时钟频率和数据传输速度。

它还提供了与硬件相关的函数,如初始化总线、发送数据和接收数据。

设备驱动是与特定设备相关的组件,它负责控制设备的初始化和配置,并提供与设备相关的功能函数。

设备驱动还负责将数据从总线读取到设备或从设备写入总线。

用户接口是设备驱动和应用程序之间的接口,通常是通过设备文件或命令行界面实现的。

用户接口提供了一组API函数,允许应用程序通过设备驱动与I2C设备进行通信。

1.初始化:驱动程序负责初始化I2C总线和设备,包括设置速率、地址和模式等。

2.读操作:驱动程序负责从设备读取数据,并将其传输到应用程序。

它可以使用主动读取或中断读取的方式来获取数据。

3.写操作:驱动程序负责将数据从应用程序写入设备,并通过I2C总线将其传输。

它可以使用主动写入或中断写入的方式发送数据。

4.错误处理:驱动程序需要能够检测和处理I2C传输中的错误,例如总线冲突、超时和校验错误等。

5.设备控制:驱动程序提供了控制设备状态和功能的功能函数。

6.多设备支持:驱动程序可以支持多个I2C设备,并提供适当的接口来选择和操作特定的设备。

1.可移植性:驱动程序应该是可移植的,适用于不同的硬件平台和操作系统。

2.灵活性:驱动程序应该具有足够的灵活性,以允许根据不同的应用需求进行配置和定制。

3.可靠性:驱动程序应该能够处理各种异常情况,并提供合适的错误处理机制。

4.性能:驱动程序应该能够实现高速数据传输,并尽可能减少处理延迟。

5.易用性:驱动程序应该提供简单易用的接口,以便应用程序能够方便地使用和控制I2C设备。

总之,I2C设备驱动是控制和管理I2C设备的关键组成部分。

i2c读写程序的详细讲解

i2c读写程序的详细讲解

i2c读写程序的详细讲解I2C即Inter-IntegratedCircuit(内部集成电路),是一种同步串行总线技术,它可以用来连接多个芯片,并使用它们之间的2条双向数据总线进行通信。

I2C总线可以通过5根线实现,其中2条用于数据传输,另外3条用于控制传输过程:SCL(时间同步线)、SDA(数据线)、VCC(电源线)。

I2C在光学芯片、DSP和ARM芯片等领域都得到了广泛应用,能够实现在一个系统或介质中共享数据,有助于节省系统开发成本和实现系统节能。

第二部分:I2C读写程序I2C读写程序是通过I2C总线实现数据读写的特定程序,主要由以下步骤构成:1、设置I2C总线:通过一系列硬件设置完成I2C总线的初始化,以满足对应数据读写的要求;2、发送I2C开始信号:在进行数据读写前,需要发送一个开始信号,以通知主从端可以进行通信;3、发送I2C地址:根据读写操作,发送I2C地址;4、发送I2C数据:根据读写操作,发送相关数据;5、接收I2C数据:根据读写操作,接收相关数据;6、发送I2C停止信号:发送I2C停止信号,结束数据读写过程。

第三部分:I2C读写程序实例下面以C语言为例,介绍在I2C通讯操作中读写程序的编写流程: 1、I2C总线的初始化:可以使用如下函数来设置I2C总线的参数,完成I2C总线的初始化:#include <linux/i2c.h>#include <linux/i2c-dev.h>int i2c_init (int busno);其中busno表示I2C总线号;2、发送I2C开始信号:可以使用如下函数来发送I2C开始信号:int i2c_smbus_write_start(int busno, int addr);其中busno表示I2C总线号,addr表示要发送的I2C地址;3、发送I2C地址:可以使用如下函数来发送I2C地址:int i2c_smbus_write_byte(int busno, int addr);其中busno表示I2C总线号,addr表示要发送的I2C地址;4、发送I2C数据:可以使用如下函数发送I2C数据:int i2c_smbus_write_byte_data(int busno, int addr, int data);其中busno表示I2C总线号,addr表示要发送的I2C地址,data 表示要发送的数据;5、接收I2C数据:可以使用如下函数接收I2C数据:int i2c_smbus_read_byte_data(int busno, int addr);其中busno表示I2C总线号,addr表示要读取的I2C地址;6、发送I2C停止信号:可以使用如下函数发送I2C停止信号:int i2c_smbus_write_stop(int busno);其中busno表示I2C总线号;第四部分:结论以上就是I2C读写程序的详细讲解,可以看出,I2C读写程序的实现步骤非常简单,只需要对每个步骤做出正确的设置,就可以实现I2C数据读写操作。

一文了解I2C----总线概述

一文了解I2C----总线概述

一文了解I2C----总线概述I2C(Inter-Integrated Circuit)总线是一种由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备。

I2C总线产生于在80年代,最初为音频和视频设备开发,如今主要在服务器管理中使用,其中包括单个组件状态的通信。

I2C版本概况:版本1.0-1992l 删除了用软件编程从机地址的内容, 因为实现这个功能相当复杂,而且不被使用.l 删除了”低速模式”,实际上这个模式是整个I2C总线规范的子集,不需要明确的详细说明.l 增加了快速模式,它将位速率增加4倍到达400kbit/s,快速模式器件都向下兼容,即她们可以在0~100kbit/s的I2C总线系统中使用.l 增加了10位寻址,允许1024个额外的从机地址. l 快速模式器件的斜率控制和输入滤波改善了EMC性能.版本2.0-1998l 增加了高速模式(Hs模式),它将位速率增加到3.4Mbit/s,Hs模式的器件可以和I2C总线系统中快速和标准模式器件混合使用,位速率从0~3.4Mbit/s.l 电源电压是2V或更低的器件的低输出电平和滞后调整到符合噪声容限的要求,而且保持和电源电压更高的器件兼容.l 快速模式输出级的0.6V6mA要求被删除. l 新器件的固定输入电平被总线电压相关的电平代替. l 增加了双向电平转换器的应用信息.版本2.1-2000l在Hs模式的重复起始条件后,可以延长始终信号SCLH.l Hs模式中的一些时序参数变得更随意.I2C总线支持任何IC生产过程(NMOS,CMOS,双极性).两线—串行数据(SDA)和串行时钟(SCL)线在连接到总线的器件间传递信息.每个器件都有唯一的地址识别(无论是微控制器,LCD驱动器,存储器或键盘接口),而且都可以作为一个发送机或接收机(由器件的功能决定).I2C总线是一个多主机的总线,可以连接多个能控制总线的器件到总线.。

rk linux下i2c总线驱动读写原理

rk linux下i2c总线驱动读写原理

RK Linux下I2C总线驱动读写原理RK Linux,一个开源的、强大的、可定制的操作系统,广泛应用于各种嵌入式系统。

I2C总线是一种常用的通信协议,常用于连接低速外围设备,如传感器、EEPROM等。

在RK Linux下,I2C总线驱动的读写原理是什么呢?首先,我们来了解下I2C总线的基本概念。

I2C总线是一种双线串行通信总线,由数据线SDA和时钟线SCL组成。

通过这两根线,多个设备可以在同一总线上进行通信。

每个设备都有一个唯一的地址,主机可以通过发送设备的地址来选择与之通信的设备。

在RK Linux下,I2C总线驱动的读写操作主要依赖于内核提供的API。

这些API 包括i2c_read()、i2c_write()等,它们提供了与I2C设备通信的接口。

那么,这些API是如何实现读写操作的呢?在内核中,I2C驱动程序负责管理I2C总线上所有的设备和它们的通信。

当需要从设备读取数据时,驱动程序首先会向设备发送读请求。

设备接收到请求后,会将数据写入SDA线。

驱动程序会持续监听SDA线,一旦接收到数据,就会将其保存并通知应用程序。

同样地,当需要向设备写入数据时,驱动程序会向设备发送写请求。

设备接收到请求后,会准备好接收数据。

驱动程序会将数据写入SDA线,设备接收到数据后,会将数据保存到内部寄存器中。

需要注意的是,I2C总线的读写操作都是通过驱动程序来完成的。

应用程序只需要调用内核提供的API即可与I2C设备进行通信。

这样设计的好处是应用程序可以专注于自己的业务逻辑,而不需要关心底层的通信细节。

同时,这也使得应用程序与具体的I2C设备无关,具有更好的可移植性和扩展性。

嵌入式Linux系统下I2C设备驱动程序的开发

嵌入式Linux系统下I2C设备驱动程序的开发

嵌入式Linux系统下I2C设备驱动程序的开发【摘要】 I2C总线是一种很通用的总线,具有简单、高效等特点,广泛应用在各种消费类电子产品及音视频设备上,在嵌入式系统的开发中也经常用到。

本文分析了嵌入式 linux系统中I2C驱动程序的结构,并结合一个具体的I2C 时钟芯片DS1307,说明在嵌入式linux系统下开发I2C设备驱动程序的一般流程。

【关键字】I2C总线嵌入式linux 驱动开发1、I2C总线简介I2C (Inter-Integrated Circuit)总线是一种由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备。

I2C总线最主要的优点就是简单性和有效性。

1.1 I2C总线工作原理I2C总线是由数据线SDA和时钟SCL构成的串行总线,各种被控制器件均并联在这条总线上,每个器件都有一个唯一的地址识别,可以作为总线上的一个发送器件或接收器件(具体由器件的功能决定) [1]。

I2C总线的接口电路结构如图1所示。

图1 I2C总线接口电路[1]1.2 I2C总线的几种信号状态[1]1. 空闲状态:SDA和SCL都为高电平。

2. 开始条件(S):SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据。

3. 结束条件(P):SCL为低电平时,SDA由低电平向高电平跳变,结束传送数据。

4. 数据有效:在SCL的高电平期间, SDA保持稳定,数据有效。

SDA的改变只能发生在SCL的底电平期间。

5. ACK信号: 数据传输的过程中,接收器件每接收一个字节数据要产生一个ACK信号,向发送器件发出特定的低电平脉冲,表示已经收到数据。

1.3 I2C总线基本操作I2C总线必须由主器件(通常为微控制器)控制,主器件产生串行时钟(SCL),同时控制总线的传输方向,并产生开始和停止条件。

数据传输中,首先主器件产生开始条件,随后是器件的控制字节(前七位是从器件的地址,最后一位为读写位)。

接下来是读写操作的数据,以及 ACK响应信号。

如何对AT24C02编写驱动程序——IIC总线协议

如何对AT24C02编写驱动程序——IIC总线协议

如何对AT24C02编写驱动程序——IIC总线协议AT24C02是一种2Kbit(256字节)的串行EEPROM芯片,采用I2C总线协议进行通信。

编写AT24C02的驱动程序需要了解I2C总线协议的工作原理以及AT24C02的读写操作。

以下是编写AT24C02驱动程序的步骤:1. 硬件配置:首先,需要在单片机上配置I2C总线的硬件连接。

I2C 总线需要两根信号线,即SDA(Serial Data Line)和SCL(Serial Clock Line)。

将SDA和SCL引脚连接到AT24C02的对应引脚,并通过上拉电阻将其拉高。

2.初始化I2C总线:在驱动程序中,需要初始化I2C总线的相关寄存器和配置参数。

这包括设置I2C总线的通信速率、使能I2C模块、使能中断等。

3.开始信号和设备地址:发送开始信号START,然后发送AT24C02的设备地址,设备地址由3位固定的值和一个读/写位组成。

读写位为0代表写操作,为1代表读操作。

4.发送数据:如果是写操作,发送要写入的数据到AT24C02的指定地址。

数据写入时,需要注意AT24C02的内存地址范围,以及页写操作的限制。

如果是读操作,发送读取的目标地址。

5.停止信号:传输完成后,发送停止信号STOP,结束通信。

6.延时和轮询:在I2C总线通信中,需要一定的延时等待数据传输完成。

在写入大量数据或读取数据时,还需要轮询等待操作完成。

7.错误处理:在驱动程序中,需要考虑到可能发生的错误和异常情况。

例如,设备地址未响应、通信超时、数据传输错误等,都需要进行相应的错误处理。

8.封装函数接口:为了方便上层应用调用,可以将上述操作封装成函数接口。

例如,提供读写函数、擦除函数和查询设备ID的函数等。

除了以上的驱动程序,还可以根据实际需求进行功能扩展。

例如,可以实现批量写入数据、随机读取数据、擦除操作等。

总之,编写AT24C02的驱动程序主要包括硬件配置、初始化I2C总线、发送开始信号和设备地址、发送数据、发送停止信号、延时和轮询、错误处理等步骤。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

SDA SCL 起始 信号 static void __zyI2cAckSend (void) { __ZY_I2C_SDA = 0; __ZY_I2C_DELAY(); __ZY_I2C_SCL = 1; __ZY_I2C_DELAY(); __ZY_I2C_SCL = 0; } 1 2 8 9 应答 信号 1 2 8 9 非应答 信号 停止 信号
1 0 1 0 1 0 1 0
MSB LSB
主机
MSB
LSB
从机
接收一个字节的数据
程序示例
static unsigned char __zyI2cByteReceive(void) { unsigned char ucRt; unsigned char i; // 接收数据 i = 8; do { ucRt = (ucRt << 1) + __zyI2cBitReceive(); } while (--i != 0); }
空闲时SDA状态未知, 需手动拉低
发送重复起始信号
在I2C总线忙时,产生起始条件,以改变数据收发方向。
SDA(I/O) SDA
80C51
SCL(I/O)
I2C从机
SCL
static void __zyI2cStartSend (void) { __ZY_I2C_SDA = 1; __ZY_I2C_DELAY(); __ZY_I2C_SCL = 1; __ZY_I2C_DELAY(); __ZY_I2C_SDA = 0; __ZY_I2C_DELAY(); __ZY_I2C_SCL = 0; }
从机具有I2C地址,内部寄存器均对应具体地址 主机对从机的操作即对寄存器的读写操作
初始化
读操作
写操作
I2C软件接口 初始化
/************************************************************************* ** Function name: char zyI2cInit (void) ** Descriptions: 初始化I2C为主模式 ** input parameters: 无 ** output parameters: 无 ** Returned value: 0:成功 -1:失败 *************************************************************************/
SCL SDA
R/W
ACK
ACK ACK
起始 信号
7位地址 + 读写位
应答 8位数据位 信号
N-1个数据 应答 结束 信号 信号
寄存器地址
从机地址
在I2C总线上被主机寻址的地址
MSB
LSB
主机
1 0 1 0 1 0 1 0
MSB LSB
从机
从机地址
I2C总线
从机2
从机4
从机6
从机1
从机3
从机5
各从机地址不能冲突!
从机地址
地址格式
MSB
D7 D6 D5 D4 D3 D2 D1
LSB
R/W
从机地址 发送写地址
__zyI2cByteSend(ucAddr & 0xfe);
读写 标志
I2C软件接口 写数据
/************************************************************************* ** Function name: unsigned char zyI2cWrite (unsigned char ucAddr, unsigned int uiRegAddr, unsigned char ucRegAddrLen, unsigned char *pucData, unsigned char ucDataLen) ** Descriptions: 将数据写入I2C从器件 ** input parameters: ucAddr:从机地址 ** uiRegAddr:寄存器地址 ** ucRegAddrLen:寄存器地址长度(单位为字节) ** pucData:要写入的数据 ** ucDataLen:要写入的数据长度 ** output parameters: 无 ** Returned value: 已写入的数据字节数 *************************************************************************/
仅实现主机功能 仅支持一条I2C总线 通信速率 仅支持7位地址模式
总线仲裁
地址模式
只有一个主机—80C51 删除I2C主机总线仲裁


1 3 5 7
I2C简介
2 4 6 8
决策
软件接口
基本时序代码 E2PROM读写范例
外部接口代码
CAT1024驱动程序
温度的测量
I2C软件接口
I2C总线 主机 从机
// 接收应答准备
// 接收到应答
// 接收到非应答
发送一个字节的数据
程序示例
static void __zyI2cByteSend (unsigned char ucData) { unsigned char i; // 发送数据 i = 8; do { __zyI2cBitSend(ucData); ucData=ucData << 1; } while (--i ! = 0); }
发送读地址
__zyI2cByteSend(ucAddr | 0x01);
举例
E2PROM存储器
CAT 24C02
1
0
1
0
A2
A1
A0
R/W
器件类型码
器件地址选择
读写 标志
带7位地址的完整数据传输
产生起始信号 发送7位地址和读写位 接收ACK信号
读取或者写一个字节的数据 接收或者发送ACK信号 产生结束信号
接收一位数据函数
SDA(I/O)
SDA
80C51
SCL(I/O)
I2C从机
SCL
static unsigned char __zyI2cBitReceive(void) { unsigned char ucRt; //返回值 __ZY_I2C_DELAY(); __ZY_I2C_SCL = 1; __ZY_I2C_DELAY(); ucRt = __ZY_I2C_SDA; __ZY_I2C_SCL = 0; return ucRt; }
I2C软件接口 读数据
/************************************************************************* ** Function name: unsigned char zyI2cRead (unsigned char ucAddr, unsigned int uiRegAddr, unsigned char ucRegAddrLen, unsigned char *pucData, unsigned char ucDataLen) ** Descriptions: 从I2C器件读数据 ** input parameters: ucAddr:从机地址 ** uiRegAddr:寄存器地址 ** ucRegAddrLen:寄存器地址长度(单位为字节) ** ucDataLen:要写入的数据长度 ** output parameters: pucData:读到的数据 ** Returned value: 已读到的数据字节数 *************************************************************************/
发送起始信号
在SCL处于高电平期间,SDA从高电平向低电平跳变
SDA(I/O)
80C51
SCL(I/O)

……
SDA
I2C从机
SCL
static void __zyI2cStartSend (void) { __ZY_I2C_DELAY(); __ZY_I2C_SDA = 0; __ZY_I2C_DELAY(); __ZY_I2C_SCL = 0; }
空闲时两线均为高电平
发送停止信号
在SCL处于高电平期间,SDA从低电平向高电平跳变
SDA(I/O)
80C51
SCL(I/O)

……
SDA
I2C从机
SCL
static void __zyI2cStartSend (void) { __ZY_I2C_SDA = 0; __ZY_I2C_DELAY(); __ZY_I2C_SCL = 1; __ZY_I2C_DELAY(); __ZY_I2C_SDA = 1; }
SCL(I/O)
I2C从机
SCL
static void __zyI2cBitSend(unsigned char ucData) { if (ucData & 0x80) { __ZY_I2C_SDA = 1; } else { __ZY_I2C_SDA = 0; } __ZY_I2C_DELAY(); __ZY_I2C_SCL = 1; __ZY_I2C_DELAY(); __ZY_I2C_SCL = 0; }
兼顾高低速 率通讯


1 3 5 7
I2C简介
2 4 6 8
决策
软件接口
基本时序代码 E2PROM读写范例
外部接口代码
CAT1024驱动程序
温度的测量
I2C驱动决策 原因 实现
标准80C51单片机无硬件I2C接口 使用I/O模拟I2C总线时序难以实现完整协议
相关文档
最新文档