笔记四:linux下IO口模拟实现I2C协议
2017-10-25 17:25
926 查看
一、i2c总线是什么?
1、i2c总线是一种物理总线及实实在在的总线,通过板子pcb等图能看到。
2、i2c总线是一种主从结构。
3、i2c总线是一种通信协议。
4、i2c总线是两线制半双工串行总线:
两线制:数据线(SDA)——>数据传输、时钟线(SCL)——>同步
半双工:同时刻数据只能从一端到另一端传输,一条数据线;对比全双工,同时刻完成数据的收发,两条数据线。
串行:一个时钟周期发送一位数据,一条线;对比并行,一个时钟周期发送一个字节数据,8条线。
注意:从相同时钟频率看并行比串行传输速度快,在实际传输中,随着时钟频率越来越高,并行数据传输时是有干扰,串行的传输优势更大一些。
5、i2c总线接口线少,控制简单,通信速率高。以上可以体现。
二、i2c总线协议怎么实现?
1、首先看一下i2c总线的时序图。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201710/b067face89dce192fe654bf4e57b9f7f)
分析上图可以分为四部分,在学习的过程中我们要化整为零,逐个击破,然后再整合起来,这样就达到了学习的目的。
a、起始信号:时钟线为高电平时,数据线从高到低的变化;
b、数据传输:I2C为电平出发方式(数据先发高位,再发地位)
注:数据线上的数据必须在时钟线的高电平周期保持稳定,数据线上的电平状态在时钟线为低电平时才可以改变。
c、应答信号:接收端收到数据,发送一应答信号,低电平表示OK,高电平表示no。
d、 终止信号:时钟线为高电平时,数据线从低到高变化。
2、通过时序图完成模拟时序。
(起始、终止、发送应
4000
答、接收应答、发送数据位、接收数据位)
例子代码:
三、i2c总线使用?
无外乎就是通过i2c总线协议进行数据收发!
1、这里我们用mma8653三轴重力加速度传感器来验证我们写的模拟时序
2、查看mma8653在咱们板子的位置以及所用的I/O口。
(查看底板-->查看核心板-->得到所用I/O口)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201710/157241c8f0bc7b3201b7b3b2261e2de5)
3、设置I/O口功能。
4、打开mma8653芯片资料。
(查看i2c时序图,根据芯片的时序图,完成发送数据、接收数据的接口)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201710/3f425716be1a11b82a5999b29b0a346b)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201710/3b85ea6d5e66671bc8c4c8781afdff74)
例子代码:
5、配置初始化mma8653芯片:active(0x2A)
检查chip_id(0x0D)
读取坐标信息。
1、i2c总线是一种物理总线及实实在在的总线,通过板子pcb等图能看到。
2、i2c总线是一种主从结构。
3、i2c总线是一种通信协议。
4、i2c总线是两线制半双工串行总线:
两线制:数据线(SDA)——>数据传输、时钟线(SCL)——>同步
半双工:同时刻数据只能从一端到另一端传输,一条数据线;对比全双工,同时刻完成数据的收发,两条数据线。
串行:一个时钟周期发送一位数据,一条线;对比并行,一个时钟周期发送一个字节数据,8条线。
注意:从相同时钟频率看并行比串行传输速度快,在实际传输中,随着时钟频率越来越高,并行数据传输时是有干扰,串行的传输优势更大一些。
5、i2c总线接口线少,控制简单,通信速率高。以上可以体现。
二、i2c总线协议怎么实现?
1、首先看一下i2c总线的时序图。
分析上图可以分为四部分,在学习的过程中我们要化整为零,逐个击破,然后再整合起来,这样就达到了学习的目的。
a、起始信号:时钟线为高电平时,数据线从高到低的变化;
b、数据传输:I2C为电平出发方式(数据先发高位,再发地位)
注:数据线上的数据必须在时钟线的高电平周期保持稳定,数据线上的电平状态在时钟线为低电平时才可以改变。
c、应答信号:接收端收到数据,发送一应答信号,低电平表示OK,高电平表示no。
d、 终止信号:时钟线为高电平时,数据线从低到高变化。
2、通过时序图完成模拟时序。
(起始、终止、发送应
4000
答、接收应答、发送数据位、接收数据位)
例子代码:
#define SCL (PAD_GPIO_D+6) #define SDA (PAD_GPIO_D+7) #define out_scl() nxp_soc_gpio_set_io_dir(SCL, 1) //代替s3c_gpio_cfgpin #define out_sda() nxp_soc_gpio_set_io_dir(SDA, 1) #define in_sda() nxp_soc_gpio_set_io_dir(SDA, 0) #define low_scl() nxp_soc_gpio_set_out_value(SCL, 0) #define high_scl() nxp_soc_gpio_set_out_value(SCL, 1) #define low_sda() nxp_soc_gpio_set_out_value(SDA, 0) #define high_sda() nxp_soc_gpio_set_out_value(SDA, 1) #define demo_delay() udelay(6) #define demo_i2c_get_data() nxp_soc_gpio_get_in_value(SDA) #define I2C_W 0 #define I2C_R 1 #define SLAVE_ADDR 0x1D
static void demo_i2c_send_byte(unsigned char data) { int i = 0; out_scl(); out_sda(); low_scl(); for(i=0;i<8;i++) { if(data & (0x80>>i)) high_sda(); else low_sda(); demo_delay(); high_scl(); demo_delay(); low_scl(); } } static unsigned char demo_i2c_recv_byte(void) { int i = 0; unsigned char data = 0; out_scl(); in_sda(); low_scl(); for(i=0;i<8;i++) { demo_delay(); high_scl(); demo_delay(); data <<= 1;//循环8次,最终只左移了7次 data |= demo_i2c_get_data(); low_scl(); } return data; } static void demo_i2c_send_ack(unsigned char ack) { out_scl(); out_sda(); low_scl(); if(ack) high_sda(); else low_sda(); demo_delay(); high_scl(); demo_delay(); low_scl(); } static unsigned char demo_i2c_recv_ack(void) { unsigned char ack = 0; out_scl(); in_sda(); low_scl(); demo_delay(); high_scl(); demo_delay(); ack = demo_i2c_get_data(); low_scl(); return ack; } static void demo_i2c_start(void) { out_scl(); out_sda(); high_scl(); high_sda(); demo_delay(); low_sda(); demo_delay(); low_scl(); } static void demo_i2c_stop(void) { out_scl(); out_sda(); high_scl(); low_sda(); demo_delay(); high_sda(); demo_delay(); low_scl(); }
三、i2c总线使用?
无外乎就是通过i2c总线协议进行数据收发!
1、这里我们用mma8653三轴重力加速度传感器来验证我们写的模拟时序
2、查看mma8653在咱们板子的位置以及所用的I/O口。
(查看底板-->查看核心板-->得到所用I/O口)
3、设置I/O口功能。
4、打开mma8653芯片资料。
(查看i2c时序图,根据芯片的时序图,完成发送数据、接收数据的接口)
例子代码:
static int demo_i2c_read_buffer(unsigned char reg, unsigned char *buff, int len) { int i = 0; demo_i2c_start(); demo_i2c_send_byte((SLAVE_ADDR << 1) | I2C_W); if(demo_i2c_recv_ack()) { printk(KERN_WARNING "%d,get a nack.\n", __LINE__); return -1; } demo_i2c_send_byte(reg); if(demo_i2c_recv_ack()) { printk(KERN_WARNING "%d,get a nack.\n", __LINE__); return -1; } demo_i2c_start(); demo_i2c_send_byte((SLAVE_ADDR << 1) | I2C_R); if(demo_i2c_recv_ack()) { printk(KERN_WARNING "%d,get a nack.\n", __LINE__); return -1; } for(i=0; i<(len-1); i++) { buff[i] = demo_i2c_recv_byte(); demo_i2c_send_ack(0); } buff[i] = demo_i2c_recv_byte(); demo_i2c_send_ack(1); demo_i2c_stop(); return (i+1); } static int demo_i2c_write_buffer(unsigned char reg, unsigned char *buff, int len) { int i = 0; demo_i2c_start(); demo_i2c_send_byte((SLAVE_ADDR << 1) | I2C_W); if(demo_i2c_recv_ack()) { printk(KERN_WARNING "%d,get a nack.\n", __LINE__); return -1; } demo_i2c_send_byte(reg); if(demo_i2c_recv_ack()) { printk(KERN_WARNING "%d,get a nack.\n", __LINE__); return -1; } for(i=0; i<len; i++) { demo_i2c_send_byte(buff[i]); if(demo_i2c_recv_ack()) { printk(KERN_WARNING "%d,get a nack.\n", __LINE__); return -1; } } demo_i2c_stop(); return i; }
5、配置初始化mma8653芯片:active(0x2A)
检查chip_id(0x0D)
读取坐标信息。
相关文章推荐
- Arduino学习笔记3--用模拟IO口实现呼吸LED灯
- 学习笔记 --- LINUX I2C设备驱动的实现
- gec210 i2c程序io模拟方式实现
- linux2.4 GPIO模拟实现I2C数据传输-DS1302
- 普通IO口模拟实现I2C通信及应用解析
- linux下IO口模拟I2C的一些总结
- 学习笔记——51通过IO口模拟IIC实现AT24C02的读写
- C51IO口模拟I2C总线驱动AT24C16 (I2C协议部分)
- Linux下I2C设备驱动开发和实现
- MSP430FG439上实现IO模拟UART以及移植要点解析
- linux i2c驱动笔记
- MSP430FG439上实现IO模拟UART以及移植要点解析
- linux 文件IO和标准IO的一些实现细节
- Linux下I2C设备驱动开发和实现
- linux 2.6.11内核文件IO的系统调用实现分析--再续
- linux 2.6.11内核文件IO的系统调用实现分析(read,write)(转载)
- IO模拟I2C代码
- Linux下C编程入门笔记——文件IO操作
- Linux下I2C设备驱动开发和实现