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协议的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HTML与CSS面试题
- 下一篇: linux 关联数组,linux 普通数