微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > I2C总线驱动程序

I2C总线驱动程序

时间:11-21 来源:互联网 点击:

nr"); }

switch (s3c2440_i2c_xfer_data.state)

{

case STATE_START : // 发出S和设备地址后,产生中断 //

{

PRINTK("Start\n");

// 如果没有ACK, 返回错误 //

if (iicSt & S3C2410_IICSTAT_LASTBIT)

{

s3c2440_i2c_stop(-ENODEV);

break;

}

if (isLastMsg() && isEndData())

{

s3c2440_i2c_stop(0);

break;

}

// 进入下一个状态 //

if (s3c2440_i2c_xfer_data.msgs->flags & I2C_M_RD) // 读 //

{

s3c2440_i2c_xfer_data.state = STATE_READ;

goto next_read;

}

else

{

s3c2440_i2c_xfer_data.state = STATE_WRITE;

}

}

case STATE_WRITE:

{

PRINTK("STATE_WRITE\n");

// 如果没有ACK, 返回错误 //

if (iicSt & S3C2410_IICSTAT_LASTBIT)

{

s3c2440_i2c_stop(-ENODEV);

break;

}

if (!isEndData()) // 如果当前msg还有数据要发送 //

{

s3c2440_i2c_regs->iicds = s3c2440_i2c_xfer_data.msgs->buf[s3c2440_i2c_xfer_data.cur_ptr];

s3c2440_i2c_xfer_data.cur_ptr++;

// 将数据写入IICDS后,需要一段时间才能出现在SDA线上

ndelay(50);

s3c2440_i2c_regs->iiccon = 0xaf; // 恢复I2C传输

break;

}

else if (!isLastMsg())

{

// 开始处理下一个消息 //

s3c2440_i2c_xfer_data.msgs++;

s3c2440_i2c_xfer_data.cur_msg++;

s3c2440_i2c_xfer_data.cur_ptr = 0;

s3c2440_i2c_xfer_data.state = STATE_START;

// 发出START信号和发出设备地址 //

s3c2440_i2c_start();

break;

}

else

{

// 是最后一个消息的最后一个数据 //

s3c2440_i2c_stop(0);

break;

}

break;

}

case STATE_READ:

{

PRINTK("STATE_READ\n");

// 读出数据 //

s3c2440_i2c_xfer_data.msgs->buf[s3c2440_i2c_xfer_data.cur_ptr] = s3c2440_i2c_regs->iicds;

s3c2440_i2c_xfer_data.cur_ptr++;

next_read:

if (!isEndData()) // 如果数据没读完, 继续发起读操作 //

{

if (isLastData()) // 如果即将读的数据是最后一个, 不发ack //

{

s3c2440_i2c_regs->iiccon = 0x2f; // 恢复I2C传输,接收到下一数据时无ACK

}

else

{

s3c2440_i2c_regs->iiccon = 0xaf; // 恢复I2C传输,接收到下一数据时发出ACK

}

break;

}

else if (!isLastMsg())

{

// 开始处理下一个消息 //

s3c2440_i2c_xfer_data.msgs++;

s3c2440_i2c_xfer_data.cur_msg++;

s3c2440_i2c_xfer_data.cur_ptr = 0;

s3c2440_i2c_xfer_data.state = STATE_START;

// 发出START信号和发出设备地址 //

s3c2440_i2c_start();

break;

}

else

{

// 是最后一个消息的最后一个数据 //

s3c2440_i2c_stop(0);

break;

}

break;

}

default: break;

}

// 清中断 //

s3c2440_i2c_regs->iiccon &= ~(S3C2410_IICCON_IRQPEND);

return IRQ_HANDLED;

}

//

* I2C初始化

//

static void s3c2440_i2c_init(void)

{

struct clk *clk;

clk = clk_get(NULL, "i2c");

clk_enable(clk);

// 选择引脚功能:GPE15:IICSDA, GPE14:IICSCL

s3c_gpio_cfgpin(S3C2410_GPE(14), S3C2410_GPE14_IICSCL);

s3c_gpio_cfgpin(S3C2410_GPE(15), S3C2410_GPE15_IICSDA);

// bit[7] = 1, 使能ACK

* bit[6] = 0, IICCLK = PCLK/16

* bit[5] = 1, 使能中断

* bit[3:0] = 0xf, Tx clock = IICCLK/16

* PCLK = 50MHz, IICCLK = 3.125MHz, Tx Clock = 0.195MHz

//

s3c2440_i2c_regs->iiccon = (1<7) | (0<6) | (1<5) | (0xf); // 0xaf

s3c2440_i2c_regs->iicadd = 0x10; // S3C24xx slave address = [7:1]

s3c2440_i2c_regs->iicstat = 0x10; // I2C串行输出使能(Rx/Tx)

}

static int i2c_bus_s3c2440_init(void)

{

// 2. 硬件相关的设置 //

s3c2440_i2c_regs = ioremap(0x54000000, sizeof(struct s3c2440_i2c_regs));

s3c2440_i2c_init();

request_irq(IRQ_IIC, s3c2440_i2c_xfer_irq, 0, "s3c2440-i2c", NULL);

init_waitqueue_head(&s3c2440_i2c_xfer_data.wait);

// 3. 注册i2c_adapter //

i2c_add_adapter(&s3c2440_i2c_adapter);

return 0;

}

static void

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top