linux下I2C驱动发送IO时序,笔记四:linux下IO口模拟实现I2C协议

一、i2c总线是什么?

1、i2c总线是一种物理总线及实实在在的总线,通过板子pcb等图能看到。

2、i2c总线是一种主从结构。

3、i2c总线是一种通信协议。

4、i2c总线是两线制半双工串行总线:

两线制:数据线(SDA)——>数据传输、时钟线(SCL)——>同步

半双工:同时刻数据只能从一端到另一端传输,一条数据线;对比全双工,同时刻完成数据的收发,两条数据线。

串行:一个时钟周期发送一位数据,一条线;对比并行,一个时钟周期发送一个字节数据,8条线。

注意:从相同时钟频率看并行比串行传输速度快,在实际传输中,随着时钟频率越来越高,并行数据传输时是有干扰,串行的传输优势更大一些。

5、i2c总线接口线少,控制简单,通信速率高。以上可以体现。

二、i2c总线协议怎么实现?

1、首先看一下i2c总线的时序图。

3f288ee285423cc6e29fa526842ca321.png

分析上图可以分为四部分,在学习的过程中我们要化整为零,逐个击破,然后再整合起来,这样就达到了学习的目的。

a、起始信号:时钟线为高电平时,数据线从高到低的变化;

b、数据传输:I2C为电平出发方式(数据先发高位,再发地位)

注:数据线上的数据必须在时钟线的高电平周期保持稳定,数据线上的电平状态在时钟线为低电平时才可以改变。

c、应答信号:接收端收到数据,发送一应答信号,低电平表示OK,高电平表示no。

d、 终止信号:时钟线为高电平时,数据线从低到高变化。

2、通过时序图完成模拟时序。

(起始、终止、发送应答、接收应答、发送数据位、接收数据位)

例子代码:

#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口)

157241c8f0bc7b3201b7b3b2261e2de5.png

3、设置I/O口功能。

4、打开mma8653芯片资料。

(查看i2c时序图,根据芯片的时序图,完成发送数据、接收数据的接口)

3f425716be1a11b82a5999b29b0a346b.png

3b85ea6d5e66671bc8c4c8781afdff74.png

例子代码:

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.

", __LINE__);

return -1;

}

demo_i2c_send_byte(reg);

if(demo_i2c_recv_ack()) {

printk(KERN_WARNING "%d,get a nack.

", __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.

", __LINE__);

return -1;

}

for(i=0; i

5、配置初始化mma8653芯片:active(0x2A)

检查chip_id(0x0D)

读取坐标信息。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值