日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

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

發布時間:2023/12/20 linux 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux下I2C驱动发送IO时序,笔记四:linux下IO口模拟实现I2C协议 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、i2c總線是什么?

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、通過時序圖完成模擬時序。

(起始、終止、發送應答、接收應答、發送數據位、接收數據位)

例子代碼:

#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.

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

讀取坐標信息。

總結

以上是生活随笔為你收集整理的linux下I2C驱动发送IO时序,笔记四:linux下IO口模拟实现I2C协议的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。