linux平台上GPIO模拟I2C
来源:互联网 发布:网络机顶盒软件2017 编辑:程序博客网 时间:2024/05/21 10:48
GPIO模拟I2C是嵌入式中较为常用的一种应用。各个地方有各种不同的做法,按照我自己的个人理解,最好是把I2C的各种状态分割开来,比如起始条件终止条件,读数据和写数据,然后根据具体的使用场合组合起来。
这里需要注意两点:一是SCL的波形并不规律,不能将它理解为方波,它本身只是一段段独立的波形。二是每段操作时,之前和之后的SCL和SDA波形是可以忽略的;通常情况下I2C开始之前和I2C结束之后,两者都是有上拉的高电平,而在正常工作时两者不受控制的情况下都是默认低电平。三是I2C是要默认外部上拉的,但是不能有内部上拉也就是必须内部下拉,否则会出现I2C传输时的错误。
(1)基础宏定义#define GPIO_SCL S3C2410_GPF3#define GPIO_SDA S3C2410_GPF0#define GPIO_SDA_OUTP S3C2410_GPF0_OUTP //设定SDA输出#define GPIO_SDA_INP S3C2410_GPF0_INP //设定SDA输入#define GPIO_SCL_OUTP S3C2410_GPF3_OUTP //设定SCL输出void I2C_SCL_OUTP( void ){ s3c2410_gpio_cfgpin(GPIO_SCL,GPIO_SCL_OUTP);}void I2C_SCL_Output(u8 value){ if(value) { s3c2410_gpio_setpin(GPIO_SCL,value); } else { s3c2410_gpio_setpin(GPIO_SCL,value ); } } void I2C_SDA_Mode(u8 v_mode) //SDA输出方向{ if(v_mode) { s3c2410_gpio_cfgpin(GPIO_SDA, GPIO_SDA_OUTP); } else { s3c2410_gpio_cfgpin(GPIO_SDA, GPIO_SDA_INP); }}void I2C_SDA_Output(u8 value){ if(value) { s3c2410_gpio_setpin(GPIO_SDA,value); } else { s3c2410_gpio_setpin(GPIO_SDA,value ); }}u8 I2C_SDA_Read(void) //SDA读数据{ return s3c2410_gpio_getpin(GPIO_SDA); }(2)基础段void I2C_Init(void){ I2C_SDA_Output(1); I2C_SCL_Output(1); //默认拉高}void I2C_Wait(void){ u16 i; for(i=0;i<200;i++);}void I2C_Start(void) { I2C_SDA_Output(1); I2C_SCL_Output(1); I2C_Wait(); I2C_SDA_Output(0); I2C_Wait(); I2C_SCL_Output(0);}void I2C_Stop(void) { I2C_SDA_Output(0); I2C_Wait(); I2C_SCL_Output(1); I2C_Wait(); I2C_SDA_Output(1);}(3)读写单个字节的段u8 I2C_Send_Byte(u8 bytedata) { u8 i,ack; I2C_SDA_Mode(1); //SDA输出 I2C_SCL_OUTP(); for (i = 0; i < 8; i++) { if (bytedata & 0x80) { I2C_SDA_Output(1); } else { I2C_SDA_Output(0); } bytedata <<= 1; I2C_SCL_Output(1); udelay(3); I2C_SCL_Output(0); udelay(1); } I2C_SDA_Output(1); //release udelay(3); I2C_SDA_Mode(0); //设定SDA输入 I2C_SCL_Output(1); udelay(3); ack = I2C_SDA_Read(); //读应答 I2C_SDA_Mode(1); I2C_SCL_Output(0); udelay(3); return ack; }u8 I2C_Receive_Byte(void) { u8 i; u8 bytedata = 0x00; u8 temp; I2C_SDA_Mode(0); for ( i = 0; i < 8; i++) { I2C_SCL_Output(1); udelay(3); bytedata <<= 1; temp = I2C_SDA_Read(); printk("reda SDA'value is:%d/n",temp); if (temp) bytedata |= 0x01; printk(" bytedata is:%x/n",bytedata); I2C_SCL_Output(0); udelay(1); } I2C_SDA_Mode(1); return bytedata;}(4)读写单个字节的I2C应用函数u8 I2C_Byte_Write(u8 device_ID,u8 address,u8 bytedata){ u8 ack; printk("device_ID is:%x/n",device_ID); printk("address is:%x/n",address); printk("date is:%x/n",bytedata); I2C_Start(); ack=I2C_Send_Byte(device_ID); printk("ack is:%d/n",ack); if(ack) I2C_Stop(); I2C_Send_Byte(address); I2C_Send_Byte(bytedata); I2C_Stop(); I2C_Wait(); return 0;}u8 I2C_Byte_Read(u8 device_ID,u8 address){ u8 bytedata; I2C_Start(); I2C_Send_Byte(device_ID); I2C_Send_Byte(address); I2C_Start(); I2C_Send_Byte(device_ID+1); bytedata = I2C_Receive_Byte(); //读单个字节,不需要再发应答 I2C_Stop(); return bytedata;}(5)类似可以完成读写多个字节的函数,暂不补充。
==================================================================================================================================
==================================================================================================================================
第二种方式也可以用
#ifdef I2C_USE_GPIO#define GPIO_I2C_DEBUG#define GPIO_I2C_SDA_PIN GPIO_I2C1_SCA_PIN#define GPIO_I2C_SCA_PIN GPIO_I2C1_SDA_PIN#define GPIO_SDA_OUTP mt_set_gpio_dir(GPIO_I2C_SDA_PIN,GPIO_DIR_OUT) //设定SDA输出#define GPIO_SDA_INP mt_set_gpio_dir(GPIO_I2C_SDA_PIN,GPIO_DIR_IN) //设定SDA输入#define GPIO_SCL_OUTP mt_set_gpio_dir(GPIO_I2C_SCA_PIN,GPIO_DIR_OUT) //设定SCL输出#define I2C_SDA_Output(value) mt_set_gpio_out(GPIO_I2C_SDA_PIN,value)#define I2C_SCL_Output(value) mt_set_gpio_out(GPIO_I2C_SCA_PIN,value)#define DELAY_TIME 0xc0u8 I2C_SDA_Read(void) //SDA读数据{ return mt_get_gpio_in(GPIO_I2C_SDA_PIN); }void I2C_Init(void){ mt_set_gpio_mode(GPIO_I2C_SDA_PIN,GPIO_MODE_00);mt_set_gpio_mode(GPIO_I2C_SCA_PIN,GPIO_MODE_00);GPIO_SDA_OUTP;GPIO_SCL_OUTP; I2C_SDA_Output(1); I2C_SCL_Output(1); //默认拉高}#define I2C_START_TRANSMISSION \{ \volatile u8 idx; \GPIO_SCL_OUTP; \GPIO_SDA_OUTP; \I2C_SDA_Output(1); \for (idx = 0; idx < DELAY_TIME; idx++); \I2C_SCL_Output(1); \for (idx = 0; idx < DELAY_TIME; idx++); \I2C_SDA_Output(0); \for (idx = 0; idx < DELAY_TIME; idx++); \I2C_SCL_Output(0); \}#define I2C_STOP_TRANSMISSION \{ \volatile u8 idx; \GPIO_SCL_OUTP; \GPIO_SDA_OUTP; \I2C_SCL_Output(0); \I2C_SDA_Output(0); \for (idx = 0; idx < DELAY_TIME; idx++); \I2C_SCL_Output(1); \for (idx = 0; idx < DELAY_TIME; idx++); \I2C_SDA_Output(1); \}static kal_uint8 I2C_Send_Byte(kal_uint8 send_byte){volatile signed char i = 0;volatile kal_uint16 j = 0;kal_uint8 ack = 0;for (i = 7; i >= 0; i--){if (send_byte&(1 << i)){I2C_SDA_Output(1);}else{I2C_SDA_Output(0);}for (j = 0; j < DELAY_TIME; j++);I2C_SCL_Output(1);for (j = 0; j < DELAY_TIME; j++);GPIO_SDA_OUTP; /* only for delay */for (j = 0; j < DELAY_TIME; j++);I2C_SCL_Output(0);for (j = 0; j < DELAY_TIME; j++);}GPIO_SDA_INP;for (j = 0; j < DELAY_TIME; j++);I2C_SCL_Output(1);for (j = 0; j < DELAY_TIME; j++);ack = I2C_SDA_Read();for (j = 0; j < DELAY_TIME; j++);I2C_SCL_Output(0);for (j = 0; j < DELAY_TIME; j++);GPIO_SDA_OUTP;return ack;}static kal_uint8 I2C_Receive_Byte(void){volatile signed char i = 0;volatile kal_uint16 j = 0;kal_uint8 get_byte = 0;GPIO_SDA_INP;for (j = 0; j < DELAY_TIME; j++);for (i = 7; i >= 0; i--) { // data bit 7~0I2C_SCL_Output(1);for (j = 0; j < DELAY_TIME; j++);if (I2C_SDA_Read()) {get_byte |= (1 << i);}for (j = 0; j < DELAY_TIME; j++);I2C_SCL_Output(0);for (j = 0; j < DELAY_TIME; j++);}// don't care bit, 9th bitGPIO_SDA_OUTP;I2C_SDA_Output(1);for (j = 0; j < DELAY_TIME; j++);I2C_SCL_Output(1);for (j = 0; j < DELAY_TIME; j++);I2C_SCL_Output(0);return get_byte;} static kal_uint16 I2C_Receive_word(void){volatile signed char i = 0;volatile kal_uint32 j = 0;kal_uint16 get_byte = 0;for (i = 15; i >= 8; i--){GPIO_SDA_INP;for (j = 0; j < DELAY_TIME; j++);I2C_SCL_Output(1);for (j = 0; j < DELAY_TIME; j++);if (I2C_SDA_Read()) get_byte |= (1 << i);for (j = 0; j < DELAY_TIME; j++);I2C_SCL_Output(0);for (j = 0; j < DELAY_TIME; j++);}I2C_SDA_Output(0);GPIO_SDA_OUTP;for (j = 0;j < DELAY_TIME; j++);I2C_SCL_Output(1);for (j = 0;j < DELAY_TIME; j++);GPIO_SDA_OUTP; /* just for delay */for (j = 0;j < DELAY_TIME; j++);I2C_SCL_Output(0);for (j = 0;j < DELAY_TIME; j++);for (; i >= 0; i--){GPIO_SDA_INP;for (j = 0; j < DELAY_TIME; j++);I2C_SCL_Output(1);for (j = 0; j < DELAY_TIME; j++);if (I2C_SDA_Read()) get_byte |= (1 << i);for (j = 0; j < DELAY_TIME; j++);I2C_SCL_Output(0);for (j = 0; j < DELAY_TIME; j++);}I2C_SDA_Output(1);GPIO_SDA_OUTP;for (j = 0;j < DELAY_TIME; j++);I2C_SCL_Output(1);for (j = 0;j < DELAY_TIME; j++);GPIO_SDA_OUTP; /* just for delay */for (j = 0;j < DELAY_TIME; j++);I2C_SCL_Output(0);for (j = 0;j < DELAY_TIME; j++);return get_byte;}u8 I2C_Byte_Write(u8 * a_puBuff , u8 len , u8 i2c_addr){ kal_uint8 fail_try_no = 4;volatile signed char i = 0 ;u8 ack_flag = 0;while (--fail_try_no > 0){ack_flag = 0;I2C_START_TRANSMISSION;if (I2C_Send_Byte(i2c_addr)) continue; for(i = 0 ;i < len;i++){if (I2C_Send_Byte(a_puBuff[i])){ack_flag = 1;break;} }if(ack_flag)continue;break;}I2C_STOP_TRANSMISSION; return 0;}u8 I2C_Bytes_Read(u8 *a_puBuff, u8 reglen ,u8 *byteget,u8 bytelen,u8 i2c_addr){ kal_uint16 get_byte = 0xFFFF;kal_uint8 fail_try_no = 4;volatile kal_uint32 i = 0;u8 ack_flag = 0;while (--fail_try_no > 0){ack_flag = 0;I2C_START_TRANSMISSION;if (I2C_Send_Byte(i2c_addr)) continue;//send reg for(i = 0 ;i < reglen;i++){if (I2C_Send_Byte(a_puBuff[i])){ack_flag = 1;break;} }if(ack_flag)continue;I2C_START_TRANSMISSION;if (I2C_Send_Byte(i2c_addr | 1)) continue;if(bytelen == 1) byteget[0] = get_byte = I2C_Receive_Byte(); //读单个字节,不需要再发应答else if(bytelen > 1){ get_byte=I2C_Receive_word(); byteget[1] = get_byte & 0x00ff; byteget[0] = (get_byte & 0xff00) >> 8; }break;}I2C_STOP_TRANSMISSION;printk("----%s---read data %x---\n",__func__,get_byte);return get_byte;}int iWriteRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u16 i2cId){I2C_Byte_Write(a_pSendData,a_sizeSendData,i2cId);return 0;}int iReadRegI2C(u8 *a_pSendData , u16 a_sizeSendData, u8 * a_pRecvData, u16 a_sizeRecvData, u16 i2cId){I2C_Bytes_Read(a_pSendData,a_sizeSendData,a_pRecvData,a_sizeRecvData,i2cId); return 0;}#endif
- linux平台上GPIO模拟I2C
- linux平台上GPIO模拟I2C
- linux平台上GPIO模拟I2C && 安卓平台用户空间I2C读写工具
- linux gpio模拟i2c
- linux gpio模拟i2c
- Linux GPIO 模拟I2C
- Linux 内核gpio模拟I2C
- linux 内核GPIO 模拟 I2C
- ARM linux 内核gpio模拟I2C
- linux gpio模拟i2c的使用
- linux内核GPIO模拟I2C实例
- linux gpio模拟i2c的使用
- ARM Linux 内核gpio模拟I2C
- linux内核GPIO模拟I2C实例
- linux gpio模拟i2c的使用
- linux i2c-gpio 模拟i2c时序出现oops错误
- GPIO模拟I2C / I2C注意事项
- i2c 驱动gpio模拟i2c
- cscope的经典用法
- HTTP协议学习笔记
- iOS平台一套完善的Crash Report解决方案
- javassist 的简单使用
- visio2007或office 2007安装失败提示一个或多个受保护的windows文件导致office 2007安装失败
- linux平台上GPIO模拟I2C
- 文档在线预览(二)-使用JODConverter转换文档为PDF
- 一种快速治疗咳嗽的方法
- JQ选择器-知识总结
- Windbg简明教程
- 单例
- hadoop日常维护,备份、恢复、增加移除节点
- 北大oj—1664——放苹果
- flask下,实现简单博客4