GPIO模拟I2C总线应用设计说明书
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() //等待从机应答信号,如果从机迟迟没有应答,则结束总线。
gpio模拟i2c串联电阻

gpio模拟i2c串联电阻在嵌入式系统中,I2C(Inter-Integrated Circuit)是一种通信协议,用于在芯片之间传输数据。
它是一种串行通信协议,可以通过两根信号线(SDA和SCL)实现多个设备之间的通信。
然而,在某些情况下,我们可能需要在电路中模拟一个串联电阻来模拟I2C总线上的电阻。
GPIO(General Purpose Input/Output)是通用输入输出引脚,可以通过编程控制其输入和输出状态。
在一些嵌入式系统中,我们可以利用GPIO模拟I2C总线上的电阻。
本文将介绍如何使用GPIO来模拟I2C串联电阻。
我们需要了解I2C的电气特性。
I2C总线上的电阻主要有两种:上拉电阻和下拉电阻。
上拉电阻通常连接到VCC电源,而下拉电阻通常连接到地。
这些电阻的作用是在总线上产生高电平和低电平。
要模拟上拉电阻,我们可以使用GPIO输出高电平。
GPIO输出高电平时,相当于连接到了VCC电源,从而模拟了上拉电阻。
同样,要模拟下拉电阻,我们可以使用GPIO输出低电平,相当于连接到了地。
接下来,我们需要了解GPIO的工作模式。
在模拟I2C串联电阻时,我们需要将GPIO设置为输出模式。
通过编程,我们可以控制GPIO 的输出状态,从而模拟I2C总线上的电阻。
在开始模拟之前,我们需要确定哪些GPIO引脚可以用作模拟串联电阻。
通常,芯片手册会提供GPIO引脚的详细信息,包括其编号和功能。
我们可以根据芯片手册选择合适的GPIO引脚进行模拟。
一旦确定了GPIO引脚,我们可以使用编程语言(如Python)来控制GPIO的输出状态。
在Python中,我们可以使用第三方库(如RPi.GPIO)来操作GPIO。
具体的代码如下所示:```pythonimport RPi.GPIO as GPIO# 设置GPIO引脚SDA_PIN = 18SCL_PIN = 19# 初始化GPIOGPIO.setmode(GPIO.BCM)GPIO.setup(SDA_PIN, GPIO.OUT)GPIO.setup(SCL_PIN, GPIO.OUT)# 模拟上拉电阻GPIO.output(SDA_PIN, GPIO.HIGH)GPIO.output(SCL_PIN, GPIO.HIGH)# 模拟下拉电阻GPIO.output(SDA_PIN, GPIO.LOW)GPIO.output(SCL_PIN, GPIO.LOW)# 关闭GPIOGPIO.cleanup()```在上述代码中,我们首先通过`GPIO.setmode(GPIO.BCM)`设置GPIO 的编号模式为BCM模式。
防止gpio模拟iic驱动被其他线程打断的方法

防止gpio模拟iic驱动被其他线程打断的方法防止GPIO模拟I2C驱动在多线程环境下被打断是一个重要的问题。
在这篇文章中,我将介绍一些方法来解决这个问题,以确保GPIO模拟I2C驱动的稳定性和可靠性。
首先,让我们了解一下什么是GPIO和I2C。
GPIO是通用输入输出端口,它可以用来控制外部设备或读取外部设备的状态。
而I2C是一种通信协议,它可以用于连接和控制多个设备,通过两根线进行数据传输。
在使用GPIO模拟I2C驱动时,我们需要保证驱动程序能够正确地处理并发访问和时序要求。
为了实现这一点,我们可以采取以下几个步骤:1. 锁定访问:在GPIO模拟I2C驱动中,我们可以使用信号量或互斥锁来实现对共享资源的访问控制。
当一个线程访问I2C总线时,它可以获得锁,阻止其他线程同时访问。
2. 设置优先级:在多线程环境中,我们可以通过设置线程的优先级来控制它们的执行顺序。
将GPIO模拟I2C驱动的线程设置为较高的优先级,可以确保它能够及时地响应,并且不会被低优先级的线程打断。
3. 中断处理:在一些特殊情况下,我们可能需要使用中断来处理GPIO模拟I2C驱动的数据请求。
通过配置中断处理程序,我们可以在需要时及时响应外部设备的请求,而不会被其他线程的操作打断。
4. 错误处理:在GPIO模拟I2C驱动中,我们应该实现错误处理机制,以便在发生错误时进行适当的处理。
例如,在发送或接收数据时发生错误,我们可以采取一些补救措施,如重新发送或重新接收数据,以确保数据的可靠性。
综上所述,要防止GPIO模拟I2C驱动在多线程环境下被打断,我们可以采取一系列的措施来确保驱动程序的稳定性和可靠性。
通过锁定访问、设置优先级、中断处理和错误处理等方法,我们可以保证GPIO模拟I2C驱动能够正确地处理并发访问和时序要求,从而实现可靠的数据传输和外设控制。
希望本文能够对需要实现GPIO模拟I2C驱动的开发者有所帮助,并能够在实际应用中发挥指导作用。
gpio模拟i2c 自适应频率

gpio模拟i2c 自适应频率GPIO 模拟 I2C 自适应频率GPIO 模拟 I2C 是一种利用通用输入/输出 (GPIO) 引脚模拟I2C 总线的技术,无需专用的 I2C 硬件接口。
这种方法具有一定的优势,包括:低成本:无需额外的 I2C 硬件,降低了成本。
灵活性:可以通过软件配置 GPIO 引脚,允许在不同设备上灵活实现。
可扩展性:可以用额外的 GPIO 引脚扩展 I2C 总线,增加连接的设备数量。
自适应频率自适应频率是指 GPIO 模拟 I2C 能够根据设备的响应动态调整I2C 总线频率。
这对于与时钟速率不同的设备进行通信非常有用,确保稳定可靠的数据传输。
实现自适应频率实现自适应频率 GPIO 模拟 I2C 时,需要考虑以下因素:硬件设置:确保 GPIO 引脚正确配置为 I2C 模式,并且具有合适的时钟源。
软件算法:使用自适应频率算法来监测设备响应并相应调整总线频率。
时序控制:精确控制 I2C 总线时序,包括时钟高低电平时间和数据传输时间。
自适应频率算法常用的自适应频率算法包括:二分法:通过连续调整总线频率并监测设备响应,缩小到合适的频率范围。
PID 控制器:基于设备响应的误差值,使用比例积分微分(PID) 控制器动态调整频率。
神经网络:训练神经网络来预测设备的最佳频率,并根据实时反馈进行调整。
优点GPIO 模拟 I2C 自适应频率具有以下优点:提高通信可靠性:通过使用设备的最佳频率,确保稳定可靠的数据传输。
优化性能:根据设备的实际情况调整频率,优化 I2C 总线性能。
减少功耗:通过使用较低的频率与设备通信,可以节省功耗。
应用GPIO 模拟 I2C 自适应频率广泛应用于各种领域,包括:嵌入式系统:在受限于成本和空间的嵌入式系统中,实现 I2C连接。
物联网:连接各种物联网设备,实现数据传输和控制。
工业自动化:控制和监控工业设备,实现可靠的通信。
注意事项在使用 GPIO 模拟 I2C 自适应频率时,需要注意以下事项:总线长度限制:GPIO 模拟 I2C 的时序控制能力有限,因此总线长度受到限制。
STM8L051F3串口通讯,模拟I2C读写MPU6050

STM8L051F3串口通讯,模拟I2C读写MPU6050/* Includes ------------------------------------------------------------------*/#include "stm8l15x.h"#include "stm8_eval.h"/** @addtogroup STM8L15x_StdPeriph_Examples* @{*//*** @addtogroup USART_HyperT erminal_Interrupts* @{*//* Private typedef -----------------------------------------------------------*//* Private define ------------------------------------------------------------*///****************************************// 定义MPU6050内部地址//****************************************#define SMPLRT_DIV 0x19 //陀螺仪采样率,典型值:0x07(125Hz)#define CONFIG 0x1A //低通滤波频率,典型值:0x06(5Hz)#define GYRO_CONFIG 0x1B //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)#define ACCEL_CONFIG 0x1C //加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz)#define ACCEL_XOUT_H 0x3B#define ACCEL_XOUT_L 0x3C#define ACCEL_YOUT_H 0x3D#define ACCEL_YOUT_L 0x3E#define ACCEL_ZOUT_H 0x3F#define ACCEL_ZOUT_L 0x40#define TEMP_OUT_H 0x41#define TEMP_OUT_L 0x42#define GYRO_XOUT_H 0x43#define GYRO_XOUT_L 0x44#define GYRO_YOUT_H 0x45#define GYRO_YOUT_L 0x46#define GYRO_ZOUT_H 0x47#define GYRO_ZOUT_L 0x48#define PWR_MGMT_1 0x6B //电源管理,典型值:0x00(正常启用)#define WHO_AM_I 0x75 //IIC地址寄存器(默认数值0x68,只读)#define SlaveAddress 0xD0 //IIC写入时的地址字节数据,+1为读取/* Private macro -------------------------------------------------------------*//* Private variables ---------------------------------------------------------*///extern uint8_t data1;uint8_t CY;uint8_t OutData1=0;uint8_t DataFlag=0;uint8_t OutData[];/* Private function prototypes -----------------------------------------------*/void I2C_Start(void);uint8_t I2C_RecvACK();void I2C_SendACK(uint8_t ack);void I2C_SendByte(uint8_t dat);uint8_t I2C_RecvByte();void I2C_Stop();void Single_WriteI2C(uint8_t REG_Address,uint8_t REG_data);uint8_t Single_ReadI2C(uint8_t REG_Address);uint16_t GetData(uint8_t REG_Address);void InitMPU6050();void Delay();void Delay2(uint16_t nCount);void Usart_Tx(void);//**************************************//I2C起始信号//**************************************void I2C_Start(void){GPIO_Init(GPIOC,GPIO_Pin_1,GPIO_Mode_Out_PP_High_Slo w);//set SCL pin as output highGPIO_Init(GPIOC,GPIO_Pin_0,GPIO_Mode_Out_PP_High_Slo w);//set SDA pin as output highDelay();GPIO_Init(GPIOC,GPIO_Pin_0,GPIO_Mode_Out_PP_Low_Slow );//set SDA pin as output lowDelay();GPIO_Init(GPIOC,GPIO_Pin_1,GPIO_Mode_Out_PP_Low_Slow );//set SDA pin as output low}//**************************************//I2C接收应答信号//**************************************uint8_t I2C_RecvACK(){GPIO_Init(GPIOC,GPIO_Pin_1,GPIO_Mode_Out_PP_High_Slo w);//set SCL pin as output highGPIO_Init(GPIOC,GPIO_Pin_0,GPIO_Mode_In_PU_No_IT); //set sda as input with pull upDelay();if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_4)){CY=1;}else CY=0;GPIO_Init(GPIOC,GPIO_Pin_1,GPIO_Mode_Out_PP_Low_Slow ); //set SCL pin as output lowDelay();return CY;}//**************************************//I2C发送应答信号//入口参数:ack (0:ACK 1:NAK)//**************************************void I2C_SendACK(uint8_t ack){if (ack==1){GPIO_Init(GPIOC,GPIO_Pin_0,GPIO_Mode_Out_PP_High_Slow);//set SDA pin as output high}else{GPIO_Init(GPIOC,GPIO_Pin_0,GPIO_Mode_Out_PP_Low_Slow );//set SDA pin as output low}GPIO_Init(GPIOC,GPIO_Pin_1,GPIO_Mode_Out_PP_High_Slo w);//set SCL pin as output highDelay(); //延时GPIO_Init(GPIOC,GPIO_Pin_1,GPIO_Mode_Out_PP_Low_Slow ); //set SCL pin as output lowDelay(); //延时}//**************************************//向I2C总线发送一个字节数据//**************************************void I2C_SendByte(uint8_t dat){uint8_t i;for (i=0; i<8; i++) //8位计数器{if (dat&0x80){GPIO_Init(GPIOC,GPIO_Pin_0,GPIO_Mode_Out_PP_High_Slo w);//set SDA pin as output high}else{GPIO_Init(GPIOC,GPIO_Pin_0,GPIO_Mode_Out_PP_Low_Slow );//set SDA pin as output low}dat <<= 1; //移出数据的最高位GPIO_Init(GPIOC,GPIO_Pin_1,GPIO_Mode_Out_PP_High_Slo w);//set SCL pin as output highDelay();GPIO_Init(GPIOC,GPIO_Pin_1,GPIO_Mode_Out_PP_Low_Slow ); //set SCL pin as output lowDelay();}I2C_RecvACK();}//**************************************//从I2C总线接收一个字节数据//**************************************uint8_t I2C_RecvByte(){uint8_t i;uint8_t dat = 0;GPIO_Init(GPIOC,GPIO_Pin_0,GPIO_Mode_Out_PP_High_Slo w);//set SDA pin as output high//使能内部上拉,准备读取数据,GPIO_Init(GPIOC,GPIO_Pin_0,GPIO_Mode_In_PU_No_IT);//set sda as input with pull upfor (i=0; i<8; i++) //8位计数器{dat <<= 1;GPIO_Init(GPIOC,GPIO_Pin_1,GPIO_Mode_Out_PP_High_Slow);//set SCL pin as output highDelay(); //延时if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_0)){dat|=0x01;}else dat|=0;GPIO_Init(GPIOC,GPIO_Pin_1,GPIO_Mode_Out_PP_Low_Slow ); //set SCL pin as output lowDelay(); //延时}return dat;}//**************************************//I2C停止运行////**************************************void I2C_Stop(){GPIO_Init(GPIOC,GPIO_Pin_0,GPIO_Mode_Out_PP_Low_Slow );//set SDA pin as output lowGPIO_Init(GPIOC,GPIO_Pin_1,GPIO_Mode_Out_PP_High_Slow);//set SCL pin as output highDelay();;GPIO_Init(GPIOC,GPIO_Pin_0,GPIO_Mode_Out_PP_High_Slo w);//set SCL pin as output highDelay();}//**************************************//向I2C设备写入一个字节数据//**************************************void Single_WriteI2C(uint8_t REG_Address,uint8_t REG_data) {I2C_Start(); //起始信号I2C_SendByte(SlaveAddress); //发送设备地址+写信号I2C_SendByte(REG_Address); //内部寄存器地址,I2C_SendByte(REG_data); //内部寄存器数据,I2C_Stop(); //发送停止信号}//**************************************//从I2C设备读取一个字节数据//**************************************uint8_t Single_ReadI2C(uint8_t REG_Address){uint8_t REG_data;I2C_Start(); //起始信号I2C_SendByte(SlaveAddress); //发送设备地址+写信号I2C_SendByte(REG_Address); //发送存储单元地址,从0开始I2C_Start(); //起始信号I2C_SendByte(SlaveAddress|0x01); //发送设备地址+读信号REG_data=I2C_RecvByte(); //读出寄存器数据I2C_SendACK(1); //接收应答信号I2C_Stop(); //停止信号return REG_data;}/*** @brief Mpu6050int program.* @param None* @retval None*/void InitMPU6050(){Single_WriteI2C(PWR_MGMT_1, 0x00); //解除休眠状态Single_WriteI2C(SMPLRT_DIV, 0x07);Single_WriteI2C(CONFIG, 0x06);Single_WriteI2C(GYRO_CONFIG, 0x18);Single_WriteI2C(ACCEL_CONFIG, 0x01);}//**************************************//合成数据//**************************************uint16_t GetData(uint8_t REG_Address){uint8_t H,L;H=Single_ReadI2C(REG_Address);L=Single_ReadI2C(REG_Address+1);return (H<<8)|L; //合成数据}/*//**************************************//通过串口发送指定数据//**************************************void Usart_Tx(void){while((USART1->SR&0x80)==0x00);USART_SendData8(USART1,DataFlag);//USART_ClearITPendingBit(USART1,USART_IT_TXE);while((USART1->SR&0x80)==0x00);USART_SendData8(USART1,OutData1);//USART_ClearITPendingBit(USART1,USART_IT_TXE);}*///**************************************//主函数//**************************************void main(void){// uint8_t data2;uint8_t i=0;/* High speed external clock prescaler: 1*/CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_1);//USART 默认PC2,PC3影射到 PA2 PA3;SYSCFG_REMAPDeInit();SYSCFG_REMAPPinConfig(REMAP_Pin_USART1TxRxPortA, ENABLE);CLK_PeripheralClockConfig(CLK_Peripheral_USART1, ENABLE);//usart 设置USART_Init(USART1, (uint32_t)9600, USART_WordLength_8b, USART_StopBits_1,USART_Parity_No, USART_Mode_Tx | USART_Mode_Rx);/* Enable general interrupts */enableInterrupts();/* Enable the USARTReceive interrupt: this interrupt is generated when the USARTreceive data register is not empty */USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);/* Enable USART */USART_Cmd(USART1, ENABLE);InitMPU6050();while (1){//Delay2(0x000f);/*switch(i){case 0:OutData=Single_ReadI2C(ACCEL_XOUT_H); DataFlag=0XA1;Usart_Tx();break;case 1:OutData=Single_ReadI2C(ACCEL_XOUT_L); DataFlag=0XA2;Usart_Tx();break;case 2:OutData=Single_ReadI2C(ACCEL_YOUT_H); DataFlag=0XB1;Usart_Tx();break;case 3:OutData=Single_ReadI2C(ACCEL_YOUT_L); DataFlag=0XB2;Usart_Tx();break;case 4:OutData=Single_ReadI2C(ACCEL_ZOUT_H); DataFlag=0XC1;Usart_Tx();break;case 5:OutData=Single_ReadI2C(ACCEL_ZOUT_L); DataFlag=0XC2;Usart_Tx();break;case 6:OutData=Single_ReadI2C(GYRO_XOUT_H); DataFlag=0XA3;Usart_Tx();break;case 7:OutData=Single_ReadI2C(GYRO_XOUT_L); DataFlag=0XA4;Usart_Tx();break;case 8:OutData=Single_ReadI2C(GYRO_YOUT_H); DataFlag=0XB3;Usart_Tx();break;case 9:OutData=Single_ReadI2C(GYRO_YOUT_L); DataFlag=0XB4;Usart_Tx();break;case 10:OutData=Single_ReadI2C(GYRO_ZOUT_H); DataFlag=0XC3;Usart_Tx();break;case 11:OutData=Single_ReadI2C(GYRO_ZOUT_L); DataFlag=0XC4;Usart_Tx();break;}*/OutData[0]=0XA1;OutData[1]=Single_ReadI2C(ACCEL_XOUT_H); //读取陀螺仪X 轴高八位数据OutData[2]=0XA2;OutData[3]=Single_ReadI2C(ACCEL_XOUT_L); //读取陀螺仪X 轴低八位数据OutData[4]=0XB1;OutData[5]=Single_ReadI2C(ACCEL_YOUT_H);//读取陀螺仪Y 轴高八位数据OutData[6]=0XB2;OutData[7]=Single_ReadI2C(ACCEL_YOUT_L); //读取陀螺仪Y 轴低八位数据OutData[8]=0XC1;OutData[9]=Single_ReadI2C(ACCEL_ZOUT_H); //读取陀螺仪Z 轴高八位数据OutData[10]=0XC2;OutData[11]=Single_ReadI2C(ACCEL_ZOUT_L); //读取陀螺仪Z轴低八位数据OutData[12]=0XA3;OutData[13]=Single_ReadI2C(GYRO_XOUT_H);//读取加速计X 轴高八位数据OutData[14]=0XA4;OutData[15]=Single_ReadI2C(GYRO_XOUT_L); //读取加速计X 轴低八位数据OutData[16]=0XB3;OutData[17]=Single_ReadI2C(GYRO_YOUT_H); //读取加速计Y轴高八位数据OutData[18]=0XB4;OutData[19]=Single_ReadI2C(GYRO_YOUT_L);//读取加速计Y 轴低八位数据OutData[20]=0XC3;OutData[21]=Single_ReadI2C(GYRO_ZOUT_H);//读取加速计Z 轴高八位数据OutData[22]=0XC4;OutData[23]=Single_ReadI2C(GYRO_ZOUT_L);//读取加速计Z 轴低八位数据for(i=0;i<24;i++){while((USART1->SR&0x80)==0x00);USART_SendData8(USART1,OutData[i]);}//Delay2(0x000f);// i++;//if(i>11)//i=0;}}//**************************************//I2C延时函数//**************************************void Delay(void){nop();nop();nop();nop();nop();nop();}//**************************************//延时函数//**************************************void Delay2(uint16_t nCount){unsigned int j=0,i=0;for(;i<ncount;i++)for(;j<65535;j++);}#ifdef USE_FULL_ASSERT/*** @brief Reports the name of the source file and the source line number* where the assert_param error has occurred.* @param file: pointer to the source file name* @param line: assert_param error line source number* @retval None*/void assert_failed(uint8_t* file, uint32_t line){/* User can add his own implementation to report the file name and line number,ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* Infinite loop */while (1){}}#endif/*** @}*//*** @}*//******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/</ncount;i++)。
STM32F0系列软件模拟i2c接口

STM32F0系列软件模拟i2c接口#ifndef _I2C_H_#define _I2C_H_#include "stm32f0xx.h"#define WRITE_MASK 0xFE#define READ_MASK 0x01/************************* SDA-->PA10(输出) ** SCL-->PA9(输出) *************************///I2C输入端口定义#define SDA GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_10) //I2C输出端口定义#define SDA_0 GPIO_ResetBits(GPIOA, GPIO_Pin_10)#define SDA_1 GPIO_SetBits(GPIOA, GPIO_Pin_10)#define SCL_0 GPIO_ResetBits(GPIOA, GPIO_Pin_9)#define SCL_1 GPIO_SetBits(GPIOA, GPIO_Pin_9)/*********************************************函数功能:初始化硬件I2C2接口**参数:无**返回值:无*********************************************/void I2C_Configuration(void);void I2C_Start(void);void I2C_Stop(void);void I2C_Write_Byte(u8 data);u8 I2C_Read_Byte(u8 flag);/*************************************************************函数功能:通过I2C2接口向从机写数据函数* *参数:addr:从机的设备地址,buff:数据缓冲区,length:数据长度**返回值:无*************************************************************/ void I2C_Write_Data(u8 addr,u8 *buff,u16 length);/*************************************************************函数功能:通过I2C从从机读数据函数* *参数:addr:从机的设备地址,buff:数据缓冲区,length:数据长度* *返回值:无* ************************************************************/ void I2C_Read_Data(u8 addr,u8 *buff,u16 length);#endif//以下是源文件#include "i2c.h"/*********************************************函数功能:初始化模拟I2C接口**参数:无**返回值:无*********************************************/void I2C_Configuration(void){/************************* SDA-->PA10(输出) ** SCL-->PA9(输出) *************************/GPIO_InitTypeDef GPIO_InitStructure;RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//输出GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;//开漏GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_Init(GPIOA,&GPIO_InitStructure);GPIO_SetBits(GPIOA,GPIO_Pin_9|GPIO_Pin_10);}void I2C_Start(void){SCL_1;SDA_0;}void I2C_Stop(void){SCL_1;SDA_1;}void I2C_Write_Byte(u8 data){u8 i;for(i=0;i<8;i++){SCL_0;(data&0x80)?SDA_1:SDA_0;SCL_1;data = data<<1;}SCL_0;SDA_1;//输出高电平,可以读取外设的输出SCL_1;while(SDA);//等待应答SCL_0;SDA_0;}u8 I2C_Read_Byte(u8 flag){u8 i;u8 data = 0x00;SCL_0;SDA_1;//输出高电平,可以读取外设的输出for(i=0;i<8;i++){data = data<<1;SCL_1;if(SDA){data |= 0x01;}else{data &= ~0x01;}SCL_0;}(flag)?SDA_0:SDA_1;//应答/不应答SCL_1;SCL_0;SDA_0;return data;}/************************************************************ *函数功能:通过I2C接口向从机写数据函数* *参数:addr:从机的设备地址,buff:数据缓冲区,length:数据长度**返回值:无*************************************************************/ void I2C_Write_Data(u8 addr,u8 *buff,u16 length){u16 i;addr = addr<<1;addr &= WRITE_MASK;I2C_Start();I2C_Write_Byte(addr);//写地址并判断是否写成功for(i=0;i<="">{I2C_Write_Byte(buff[i]);}I2C_Stop();}/************************************************************ *函数功能:通过I2C从从机读数据函数**参数:addr:从机的设备地址,buff:数据缓冲区,length:数据长度**返回值:无*************************************************************/ void I2C_Read_Data(u8 addr,u8 *buff,u16 length){u16 i;addr = addr<<1;addr |= READ_MASK;I2C_Start();I2C_Write_Byte(addr);for(i=0;i<length;i++)< bdsfid="203" p=""></length;i++)<> {if(i==(length-1))//是否为最后一个字节{buff[i] = I2C_Read_Byte(0);//读且不应答} else{buff[i] = I2C_Read_Byte(1);//读且应答} }I2C_Stop();}。
STC51单片机普通IO口模拟IIC(I2C)接口通讯的程序代码
STC51单片机普通IO口模拟IIC(I2C)接口通讯的程序代码STC 51单片机普通IO口模拟IIC(I2C)接口通讯的程序代码原文:(改自周立功软件包)#include <reg51.h>#include <intrins.h>#define uchar unsigned char /*宏定义*/#define uint unsigned intextern void Delay1us(unsigned char );sbit SDA=P1^6; /*模拟I2C数据传送位*/sbit SCL=P1^7; /*模拟I2C时钟控制位*/bit ack; /*应答标志位*//************************************************************** *****起动总线函数函数原型: void Start_I2c();功能: 启动I2C总线,即发送I2C起始条件.*************************************************************** *****/void Start_I2c(){SDA=1; /*发送起始条件的数据信号*/Delay1us(1);SCL=1;Delay1us(5); /*起始条件建立时间大于4.7us,延时*/SDA=0; /*发送起始信号*/Delay1us(5); /* 起始条件锁定时间大于4μs*/SCL=0; /*钳住I2C总线,准备发送或接收数据 */Delay1us(2);}/************************************************************** *****结束总线函数函数原型: void Stop_I2c();功能: 结束I2C总线,即发送I2C结束条件.*************************************************************** *****/void Stop_I2c(){SDA=0; /*发送结束条件的数据信号*/Delay1us(1); /*发送结束条件的时钟信号*/SCL=1; /*结束条件建立时间大于4us*/Delay1us(5);SDA=1; /*发送I2C总线结束信号*/Delay1us(4);}/*******************************************************************字节数据发送函数函数原型: void SendByte(uchar c);功能: 将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对此状态位进行操作.(不应答或非应答都使ack=0)发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
Windows下I2C总线的GPIO模拟
Windows下I2C总线的GPIO模拟作者:邹应双来源:《电脑知识与技术》2017年第01期摘要:简要介绍了I2C总线操作和基于Windows内核模式驱动的用户态I/O端口访问,分析了Windows平台下GPIO管脚模拟I2C总线的可行性,讲解了编程实现过程,连接I2C接口的安全芯片进行了验证。
关键词:I2C总线;GPIO管脚;Windows;内核模式驱动中图分类号:TP311 文献标识码:A 文章编号:1009-3044(2017)01-0100-04Abstract: I2C bus operations and user-mode I/O port access using Windows kernel mode driver are briefly introduced in this paper. And a feasibility analysis on simulating I2C bus with GPIO pins under Windows is made. Then we do a programming impelmentation to the simulating method, and verify the software by accessing an I2C-interfaced security chip.Key words: I2C bus; GPIO pins; Windows; kernel mode driver1 背景I2C总线是Philips公司推出的两线式串行总线,用于嵌入式系统连接各种低速外围设备,如RTC、EEPROM、传感器、安全芯片等。
许多单片机、嵌入式芯片等都带有I2C主控器,其采用的操作系统如嵌入式Linux等均带有I2C驱动程序,编程中可直接使用。
对于不含I2C 主控器的芯片,为了满足定制系统设计需求,一般也有大量的GPIO管脚,可用于软件模拟I2C总线。
STM32用GPIO模拟IIC(I2C)通讯C语言源码 实测可用
/******************************************************************************
*
* Function Name : I2C_NoAck
* Description : Master Send No Acknowledge Single
SDA_IN();//SDA 设置为输入
for(i=0;i<8;i++ )
{
IIC_SCL=0;
Delay_us(I2C_Delayus);
IIC_SCL=1;
receive<<=1;
if(READ_SDA)receive++;
Delay_us(I2C_Delayus);
}
return receive;
IIC_SDA=(dat&0x80)>>7; dat<<=1; Delay_us(I2C_Delayus); //对 TEA5767 这三个延时都是必须的 IIC_SCL=1; Delay_us(I2C_Delayus); IIC_SCL=0; Delay_us(I2C_Delayus); } IIC_RecvACK(); #endif } //************************************** //从 IIC 总线接收一个字节数据 //************************************** u8 IIC_RecvByte(void) { #ifdef BMI160 u8 i=8; u8 ReceiveByte=0;
if(!IIC_RecvACK()){IIC_Stop();return FALSE;} IIC_SendByte((u8) REG_Address); //设置低起始地址 IIC_RecvACK(); IIC_Start(); IIC_SendByte(SlaveAddress+1); IIC_RecvACK();
stm8s使用IO口模拟I2C
stm8s使⽤IO⼝模拟I2C刚⼊职不久,下⾯是使⽤stm8s005k6写的eeprom驱动程序。
EEPROM型号为ST公司的M24C256.#include "bsp_i2c.h"/* 在stm8平台下移植,只需要改下⾯的宏定义即可 */#define PORT_I2C_SCL GPIOC#define PIN_I2C_SCL GPIO_PIN_1#define PORT_I2C_SDA GPIOC#define PIN_I2C_SDA GPIO_PIN_2static void i2c_Delay(void);static void i2c_PinModeOutput(void);static void i2c_PinModeInput(void);static void i2c_SCL(uint8_t stat);static void i2c_SDA(uint8_t stat);static uint8_t i2c_ReadSDA(void);/** 函数名: i2c_InitGpio* 功能说明: 初始化IIC接⼝* 形参: ⽆* 返回值: ⽆*/void i2c_InitGpio(void){GPIO_Init(PORT_I2C_SCL, PIN_I2C_SCL, GPIO_MODE_OUT_PP_LOW_FAST);GPIO_Init(PORT_I2C_SDA, PIN_I2C_SDA, GPIO_MODE_OUT_PP_LOW_FAST);i2c_Stop();}/** 函数名: i2c_Delay* 功能说明: 延时函数* 形参: ⽆* 返回值: ⽆*/static void i2c_Delay(void){uint8_t time = 10;while (time--);}/** 函数名: i2c_PinModeOutput* 功能说明: 将SDA线的端⼝设置为输出* 形参: ⽆* 返回值: ⽆*/static void i2c_PinModeOutput(void){GPIO_Init(PORT_I2C_SDA, PIN_I2C_SDA, GPIO_MODE_OUT_PP_LOW_FAST);}/** 函数名: i2c_PinModeOutput* 功能说明: 将SDA线的端⼝设置为输⼊* 形参: ⽆* 返回值: ⽆*/static void i2c_PinModeInput(void){GPIO_Init(PORT_I2C_SDA, PIN_I2C_SDA, GPIO_MODE_IN_FL_NO_IT);}/** 函数名: i2c_SCL* 功能说明: 控制SCL线电平状态* 形参: stat:0 输出低电平,1 输出⾼电平* 返回值: ⽆*/static void i2c_SCL(uint8_t stat){if (stat){GPIO_WriteHigh(PORT_I2C_SCL, PIN_I2C_SCL);}else{GPIO_WriteLow(PORT_I2C_SCL, PIN_I2C_SCL);}}/** 函数名: i2c_SDA* 功能说明: 控制SDA线电平状态* 形参: stat:0 输出低电平,1 输出⾼电平* 返回值: ⽆*/static void i2c_SDA(uint8_t stat){if (stat){GPIO_WriteHigh(PORT_I2C_SDA, PIN_I2C_SDA);}else{GPIO_WriteLow(PORT_I2C_SDA, PIN_I2C_SDA);}}/** 函数名: i2c_ReadSDA* 功能说明: 读取SDA线电平状态* 形参: ⽆* 返回值: 0 或 1*/static uint8_t i2c_ReadSDA(void){if (GPIO_ReadInputPin(PORT_I2C_SDA, PIN_I2C_SDA)) {return1;}else{return0;}}/** 函数名: i2c_Start* 功能说明: IIC总线起始信号* 形参: ⽆* 返回值: ⽆*/void i2c_Start(void){i2c_PinModeOutput();i2c_SDA(1);i2c_Delay();i2c_SCL(1);i2c_Delay();i2c_SDA(0);i2c_Delay();i2c_SCL(0);i2c_Delay();}/** 函数名: i2c_Stop* 功能说明: IIC总线停⽌信号* 形参: ⽆* 返回值: ⽆*/void i2c_Stop(void){i2c_PinModeOutput();i2c_SCL(0);i2c_SDA(0);i2c_Delay();i2c_SCL(1);i2c_Delay();i2c_SDA(1);i2c_Delay();}/** 函数名: i2c_WriteByte* 功能说明: IIC总线写数据* 形参: _ucByte:写⼊的⼀个字节数据* 返回值: ⽆*/void i2c_WriteByte(uint8_t _ucByte){uint8_t i;i2c_PinModeOutput();i2c_SCL(0);i2c_Delay();for (i = 0; i < 8; i++){if (_ucByte & 0x80){i2c_SDA(1);}else{i2c_SDA(0);}_ucByte = _ucByte << 1;i2c_SCL(1);i2c_Delay();i2c_SCL(0);i2c_Delay();}i2c_SDA(1);}/** 函数名: i2c_ReadByte* 功能说明: IIC总线读数据* 形参: ⽆* 返回值: recv:读取的⼀个字节数据*/uint8_t i2c_ReadByte(void){uint8_t i;uint8_t recv = 0;i2c_PinModeOutput();i2c_SDA(1);i2c_Delay();i2c_PinModeInput();for (i = 0; i < 8; i++){recv = recv << 1;i2c_SCL(1);i2c_Delay();if (i2c_ReadSDA()){recv |= 0x01;}else{recv |= 0x00;}i2c_SCL(0);i2c_Delay();}return recv;}/** 函数名: i2c_Ack* 功能说明: IIC总线主机主动应答* 形参: ⽆* 返回值: ⽆*/void i2c_Ack(void){i2c_PinModeOutput();i2c_SCL(0);i2c_SDA(0);i2c_Delay();i2c_SCL(1);i2c_Delay();i2c_SCL(0);}/** 函数名: i2c_NAck* 功能说明: IIC总线主机主动⾮应答* 形参: ⽆* 返回值: ⽆*/void i2c_NAck(void){i2c_PinModeOutput();i2c_SCL(0);i2c_SDA(1);i2c_Delay();i2c_SCL(1);i2c_Delay();i2c_SCL(0);}/** 函数名: i2c_CheckAck* 功能说明: IIC总线检测应答信号* 形参: ⽆* 返回值: 0 应答信号,1 ⾮应答信号*/uint8_t i2c_CheckAck(void){uint8_t time = 0;i2c_PinModeOutput();i2c_SDA(1);i2c_Delay();i2c_SCL(1);i2c_Delay();i2c_PinModeInput();while (i2c_ReadSDA()){time++;if (time >= 100){return1;}}i2c_SCL(0);return0;}bsp_i2c.c#ifndef __BSP_I2C_H__#define __BSP_I2C_H__#include "stm8s.h"#define I2C_WR ((uint8_t) 0) /* 写控制bit */ #define I2C_RD ((uint8_t) 1) /* 读控制bit */ #define ACK ((uint8_t) 0)#define NOACK ((uint8_t) 1)void i2c_InitGpio(void);void i2c_Start(void);void i2c_Stop(void);void i2c_WriteByte(uint8_t _ucByte);uint8_t i2c_ReadByte(void);void i2c_Ack(void);void i2c_NAck(void);uint8_t i2c_CheckAck(void);#endif /* __BSP_I2C_H__ */bsp_i2c.h#include "m24256_driver.h"#include "bsp_i2c.h"#include "modbus_driver.h"//uint8_t g_ucIsEEPROMBusy;/** 函数名: M24256_Init* 功能说明: 初始化* 形参: ⽆* 返回值: ⽆*/void M24256_Init(void){i2c_InitGpio();}/** 函数名: M24256_WriteByte* 功能说明: 写⼀个字节* 形参: _usAddress:地址* _ucByte:数据* 返回值: ⽆*/uint8_t M24256_WriteByte(uint16_t _usAddress, uint8_t _ucByte) {uint16_t i;for (i = 0; i < 3000; i++){i2c_Start();i2c_WriteByte(EE_DEV_ADDR | I2C_WR); /* 选中器件 + 写 */ if (i2c_CheckAck() == ACK){break;}}if (i >= 3000){i2c_Stop();return0;}/* 发送地址 */i2c_WriteByte((_usAddress & 0xFF00) >> 8);if (i2c_CheckAck() == NOACK){i2c_Stop();return2;}i2c_WriteByte(_usAddress & 0x00FF);if (i2c_CheckAck() == NOACK){i2c_Stop();return3;}/* 读数据 */i2c_WriteByte(_ucByte);if (i2c_CheckAck() == NOACK){i2c_Stop();return4;}i2c_Stop();/** 函数名: M24256_ReadByte* 功能说明: 读⼀个字节* 形参: _usAddress:地址* 返回值: recv:读取到的⼀个字节数据*/uint8_t M24256_ReadByte(uint16_t _usAddress){uint8_t recv = 0;uint16_t i;for (i = 0; i < 3000; i++){i2c_Start();i2c_WriteByte(EE_DEV_ADDR | I2C_WR); /* 选中器件 + 写 */if (i2c_CheckAck() == ACK){break;}}if (i >= 3000){i2c_Stop();return0;}/* 发送地址 */i2c_WriteByte((_usAddress & 0xFF00) >> 8);if (i2c_CheckAck() == NOACK){i2c_Stop();return0;}i2c_WriteByte(_usAddress & 0x00FF);if (i2c_CheckAck() == NOACK){i2c_Stop();return0;}i2c_Start();i2c_WriteByte(EE_DEV_ADDR | I2C_RD); /* 选中器件 + 读 */if (i2c_CheckAck() == NOACK){i2c_Stop();return0;}recv = i2c_ReadByte();i2c_NAck();i2c_Stop();return recv;}/** 函数名: M24256_ReadBlock* 功能说明: 从串⾏EEPROM指定地址处开始读取若⼲数据* 形参: _usAddress : 起始地址* _usSize : 数据长度,单位为字节* _pReadBuf : 存放读到的数据的缓冲区指针* 返回值: 0 表⽰失败,1表⽰成功*/unsigned char M24256_ReadBlock(unsigned char *_pReadBuf, unsigned short _usSize, unsigned short _usAddress) {uint16_t i;for (i = 0; i < 3000; i++){i2c_Start();i2c_WriteByte(EE_DEV_ADDR | I2C_WR); /* 选中器件 + 写 */if (i2c_CheckAck() == ACK){break;}}if (i >= 3000){i2c_Stop();/* 发送地址 */i2c_WriteByte((_usAddress & 0xFF00) >> 8);if (i2c_CheckAck() == NOACK){i2c_Stop();return0;}i2c_WriteByte(_usAddress &0x00FF);if (i2c_CheckAck() == NOACK){i2c_Stop();return0;}i2c_Start();i2c_WriteByte(EE_DEV_ADDR | I2C_RD); /* 选中器件 + 读 */if (i2c_CheckAck() == NOACK){i2c_Stop();return0;}/* 循环读取数据 */for (i = 0; i < _usSize; i++){_pReadBuf[i] = i2c_ReadByte();if (i != _usSize - 1){i2c_Ack();}else{i2c_NAck(); /* 读完最后⼀个字节,主机发送⾮应答 */}}i2c_Stop();return1;}/** 函数名: M24256_WriteBlock* 功能说明: 向串⾏EEPROM指定地址写⼊若⼲数据,采⽤页写操作提⾼写⼊效率* 形参: _usAddress : 起始地址* _usSize : 数据长度,单位为字节* _pWriteBuf : 存放读到的数据的缓冲区指针* 返回值: 0 表⽰失败,1表⽰成功*/unsigned char M24256_WriteBlock(unsigned char *_pWriteBuf, unsigned short _usSize, unsigned short _usAddress) {uint16_t i, m;uint16_t usAddr;usAddr = _usAddress;for (i = 0; i < _usSize; i++){if ((i == 0) || (usAddr & (EE_PAGE_SIZE - 1)) == 0){i2c_Stop();/* 重复发送起始信号,eeprom要重新开始写要等待10ms左右 */for (m = 0; m < 3000; m++){i2c_Start();i2c_WriteByte(EE_DEV_ADDR | I2C_WR);if (i2c_CheckAck() == ACK){break;}}if (m >= 3000){i2c_Stop(); /* 写eeprom超时 */return0;}/* 发送地址 */i2c_WriteByte((usAddr & 0xFF00) >> 8);if (i2c_CheckAck() == NOACK){i2c_Stop();return0;}i2c_WriteByte(usAddr & 0x00FF);if (i2c_CheckAck() == NOACK){i2c_Stop();return0;}}/* 写⼊数据 */i2c_WriteByte(_pWriteBuf[i]);if (i2c_CheckAck() == NOACK){i2c_Stop();return0;}usAddr++;}i2c_Stop();return1;}bsp_eeprom.c#ifndef __M24256_DRIVER_H__#define __M24256_DRIVER_H__#include "stm8s.h"#define EE_MODEL_NAME "M24256"#define EE_DEV_ADDR 0xA0 /* 设备地址 */#define EE_PAGE_SIZE 64 /* 页⾯⼤⼩(字节) */#define EE_SIZE (32*1024) /* 总容量(字节) */#define EE_ADDR_BYTES 1 /* 地址字节个数 */extern unsigned char g_ucIsEEPROMBusy;void M24256_Init(void);uint8_t M24256_WriteByte(uint16_t _usAddress, uint8_t _ucByte);uint8_t M24256_ReadByte(uint16_t _usAddress);unsigned char M24256_ReadBlock(unsigned char *_pReadBuf, unsigned short _usSize, unsigned short _usAddress); unsigned char M24256_WriteBlock(unsigned char *_pWriteBuf, unsigned short _usSize, unsigned short _usAddress); void ee_Test(void);#endif /* __M24256_DRIVER_H__ */bsp_eeprom.h。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
GPIO模拟I2C应用设计说明书
1简介
1.1目的
介绍I2C的特性,工作原理以及通过GPIO(GeneralPurpose Input /Output)模拟I2C总线的时序实现数据传输;该文档描述的设计思想可供GPIO驱动开发者进行设计参考。
本文以Hi3510为例,通过具体的应用实例来描述GPIO模拟I2C实现数据传输,本文的读者假定是对GPIO的特点以及工作方式等非常熟悉,涉及到GPIO的内容请参考相关的文档。
2I2C
2.1概述
I2C总线(The Inter-Integrated Circuit)是一种通用的串行总线,是用于IC器件之间连接的二线制总线。
他通过串行数据或者地址线(Serial Data Line,SDA)及串行时钟线(Serial ClockLine,SCL)两线在连接到总线上的器件之间传送信息,并根据地址识别每个器件。
一个或多个微控制器以及外围器件可以通过I2C总线接口非常方便的连接在一起构成系统。
这种总线结构的连线和连接引脚少,器件间总线简单。
结构紧凑,因此其构成系统的成本较低;并且在总线上增加器件不会影响系统的正常工作,所有的IC器件共用一套总线,因此其系统修改和可扩展性好。
即使有不同时钟速度的器件连接到总线上,时间同步机制也能够很方便地确定总线时钟,在Hi3510中,I2C仅支持Master功能,遵守I2C总线协议2.1版本,在Hi3510中可用于Video Encoder、Video Decoder、Digital Camera的控制接口。
2.2特点
I2C接口有以下特点:
I2C接口在I2C总线上可以作为接收器,也可以作为发送器,具体由数据的传输方向确定
支持标准传输模式和快速传输模式
提供TX FIFO 、RX FIFO,支持DMA数据传输
支持中断上报和初始化中断状态,屏蔽后中断状态的查询
2.3信号描述
本节描述了I2C单元的输入输出管脚信号,如下表所示:
2.4工作原理
I2C总线是由数据线SDA和时钟线SCL构成的串行总线,可发送和接收数据。
每个连接到总线的器件都可以通过惟一的地址与主机通讯,主机可以作为主机发送器或主机接收器。
是一个真正的多主机总线,如果两个或更多主机同时初始化,数据传输可以通过冲突检测和仲裁防止数据被破坏。
串行的8位双向数据传输位速率在标准模式下可达100kb/s,快速模式下可达400kb/s,高速模式下可达3.4Mb/s。
I2C总线在传送数据过程中共有3种特殊的电平变换情况,他们分别是:起始(start)、停止(stop)和响应(ack)。
当SCL为高电平时,SDA由高电平向低电平跳变,这个表示起始条件;当SCL是高电平时,SDA线由低电平向高电平跳变表示停止条件。
起始和停止条件一般由主机产生,总线在起始条件后被认为处于忙的状态,在停止条件的某段时间后总线被认为再次处于空闲状态。
响应信号是指从机在接收到8位数据后,向主机发出特定的低电平脉冲,表示已收到数据。
在响应的时钟脉冲期间,从机必须将SDA线拉低使他在这个时钟脉冲的高电平期间保持稳定的低电平,主机收到应答信号后,根据实际情况做出是否继续传递信号的判断。
若未收到应答信号,则判断为从机出现故障。
2.5操作时序
IIC总线运用主/从双向通讯。
主机和从机都可以工作于接收和发送状态。
总线必须由主机(通常为微控制器)控制,主机产生串行时钟(SCL)控制总线的传输方向,并产生起始和停止条件上。
SDA线上的数据状态仅在SCL为低电平的期间才能改变,SCL为高电平的期间,SDA状态的改变被用来表示起始和停止条件。
2.6操作时序图
操作时序如下图:
3模块移植
3.1模块概述
GPIO模拟I2C应用接口驱动模块主要提供模拟I2C接口的读和写。
●gpio_i2c_read:GPIO模拟I2C读取函数
●gpio_i2c_write:GPIO模拟I2C写入函数
3.2函数描述
3.2.1gpio_i2c_read
【目的】读取一个I2C设备的某个寄存器的值
【语法】
unsigned char gpio_i2c_read(unsigned char devaddress,unsigned char address);
【参数】
【返回值】
【需求】头文件:gpio_i2c.h
【注意】无
【相关问题】gpio_i2c_write
3.2.2gpio_i2c_write
【目的】往一个I2C设备的某个寄存器写入需要的值
【语法】
void gpio_i2c_write(unsigned char devaddress,unsigned char address,unsigned char data);
【参数】
【返回值】
【需求】头文件:gpio_i2c.h
【注意】无
【相关主题】gpio_i2c_read
3.3硬件框图
在本框图中,通过Hi3510的GPIO管脚与OV7725的I2C总线相连,实现对OV7725的控制。
3.4模块移植
首先该模块依赖linux-2.6.x内核,在用这前确保的linux的内核版本要基于linux2.6.x以上,否则可能编译不过。
操作步骤如下:
[root@localhost test]# tar zxvf gpio_i2c.tgz //解压
[root@localhost test]cd gpio_i2c
解压后进入模块目录gpio_i2c后,首先要修改Makefile,在其中有几个关键的部分,实际的内容以提供的Makefile为准。
例如Makefile内容如下:
如果要在你的系统中使用的话,注要修改以上三个(红色)的环境变量对应的值,这里以ARM系统为例,具体含义如下:
KDIR:这个环境变量代表你当前的内核的路径
CROSS_ARCH:交叉系统的体系,在这里为ARM。
CROSS_COMPILE:所使用的交叉工具链
以上三个参数的设置以实际的系统为依据,去修改相应的值。
其它的参数的含义请参见Makefile编写手册,在这里不再赘述。
修改完Makefile后,在当前shell下执行Make,即可生成对应的模块名如:gpio_i2c.ko,然后拷入实环境中的lib环境中。
3.5以OV7725为例:
通过调用gpio模拟I2C读取函数和写入函数实现DC(Digital Camera)的初始化。
static int ov7725_device_init(void)
{
unsigned char regvalue;
int loop1;
/* reset */
rst_ov7725();
gpio_i2c_write(I2C_OV7725, DC_COM7, 0x80);//I2C_OV7725为OV7725 设备的从地址。
for(loop1=0;loop1 < 5000;loop1++)
{
;
}
regvalue = gpio_I2C_read(I2C_OV7725, DC_COM7);
regvalue &=0x7f;
gpio_i2c_write(I2C_OV7725, DC_COM7, regvalue);
regvalue = gpio_I2C_read(I2C_OV7725,DC_PIDH);
loop1 = gpio_I2C_read(I2C_OV7725,DC_PIDL);
if((regvalue != PIDH) || (loop1 != PIDL))
{
printk("read Prodect ID Number MSB is %x\n",regvalue);
printk("read Prodect ID Number LSB is %x\n",loop1);
printk("check ov7725 ID error.\n");
return -EFAULT;
}
if(out_mode == 1)
ov7725_vga_init();
else
ov7725_qvga_init();
return 0;
}
实际过程中,请配合你的驱动进行开发。