Skip to content

Latest commit

 

History

History
242 lines (161 loc) · 10.8 KB

11-IIC驱动.rst

File metadata and controls

242 lines (161 loc) · 10.8 KB

IIC驱动模块

硬件特性

简介

I2C(inter-Integrated-Circuit,简写为 I2C)总线是一种双线制、双向串行通信协 议总线,适合多个芯片或板上设备之间短距离、传输速率不高、数据量较少的通信场景。

时钟

IIC时钟来源于PCLK,PCLK由SYSCLK分频得到,而SYSCLK来自HCLK的分频,HCLK来自SYSCLK或SYSCLK的特殊分频,SYSCLK可选PLL、HOSC、LOSC三者之一。下图为M400单片机中与IIC相关的时钟结构图。

图示 1: IIC时钟来源

备注:M400的典型SYSCLK为200M。XHOSC为外部晶振,M400开发板MCU_dev V1.0使用的XHOSC为30MHz。

输入输出引脚

外部输出引脚EXOUT

IIC模块外部输出引脚主要为SDA和SCL。

表格 2.1: IIC输出引脚功能IO复用表

外部输入引脚EXIN

同外部输出引脚。

IIC模块功能

参考IIC的硬件特性,IIC驱动支持以下功能

1.支持主机可编程生成起始位、停止位、重复起始位、响应位、等待状态

2.支持主机速率软件编程

3.支持主发、主收模式

4.支持从机起始位、停止位、重复起始位监测,总线忙状态监测

5.支持主机和从机模式下 7 位、10 位地址、广播呼叫地址

6.在主机和从机模式下,支持中断与状态查询 7.支持对 SCL/SDA 信号进行去毛刺处理

硬件中断

IIC驱动函数中比较重要的是IIC中断的产生与处理,可以通过IIC的配置寄存器I2C_CFG打开数据传输过程中的各种中断,然后数据实际的传输过程中,根据产生的各种中断,来进行相应的逻辑处理。

关键数据结构

编程接口

IIC的总体设计是沿用ulinx系统中的IIC驱动框架,通过在伪文件系统注册生成字符设备的方式供用户层使用.

应用层编程接口

open接口

上层应用使用open函数开启IIC设备时底层驱动会完成硬件的初始化,然后把IIC设备绑定到文件IO操作的标准函数中,之后就可以向访问文件一样操作IIC设备。IIC设备open流程如下:

IOCTL接口

IIC驱动暂时不支持IOCTL设置参数

write接口

上层应用通过write接口向板载的IIC从设备EEPROM写入数据

lseek接口

lseek接口用来指定当前文件指针的位置,比如读取了一页的数据之后,那文件指针就需要移动一页。

read接口

read接口用来从eeprom中读取数据,先按照整页读取,整页读取之后,余下不足一页的数据直接读取。

驱动层接口

驱动功能

发送start信号

向寄存器I2C_CMD的bit0写人1来产生start信号,从而开启IIC数据传输,写入start之后,还需要写入EEPROM从设备器件的地址,对EEPROM进行寻址。

IIC总线初始化

初始化主要是由taishan400_i2c_init完成,主要是初始化相关的引脚,注册中断处理函数,初始化时钟。

IIC数据传输流程处理

主要是通过taishan400_i2c_process函数来进行数据传说过程中的流程处理,主要的功能就是方便和驱动上半部分进行交互。

驱动中断

在数据处理函数中调用taishan400_i2c_sendstar向总线上面发送start函数之后,如果start正确发送到了总线上面之后会产生开始条件中断标志,程序跳转到中断处理函数中,在中断处理函数中先清除开始中断标志位,由于在taishan400_i2c_sendstar中同时也向总线上面发送了EEPROM的器件地址,如果正确发送,会产生字节传输完成的中断,这时如果需要传输的字节数priv->dcnt不为0,而且上半部分读写标志位表示写操作,则会进入写数据的流程,在写数据流程中先清除上一个字节传输完成的中断标志位,然后将数据缓冲区指针priv->ptr的第一个字节写入I2C的数据寄存器,数据寄存器中的数据会自动被发送到I2C总线上面去,之后待发送数据字节数priv->dcnt减一,priv->ptr指针移动到下一个需要传输的字节处,由此完成一个字节的写入,之后程序跳出中断处理函数,等待一个字节的数据发送完成,发送完成之后会再次进入中断处理函数,重复同样的发送流程,数据读取同理。在完成所有数据字节传输之后(即priv->dcnt==0),会向I2C总线发送stop信号,发送成功之后会停止I2C通信。

IIC驱动设计

驱动框架

设备注册流程

board_app_initialize初始化时会调用ee24xx_initialize,把I2C0和EEPROM进行绑定,同时会把EEPROM注册为字符设备,在文件系统中会生成一个/dev/at24文件,然后通过register_driver函数把/dev/at24与文件IO基本操作进行关联,方便应用程序通过文件IO访问/dev/at24。

设备使用流程

上层应用使用open函数开启IIC设备时 底层驱动会完成硬件的初始化,然后把IIC设备绑定到文件IO操作的标准函数中,之后就可以向访问文件一样操作IIC设备。IIC从设备EEPROMopen流程如下:

详细设计

软件框架设计

操作函数集

在IIC驱动中,实现了一些内置的数据结构来描述IIC相关的配置参数信息。

static const struct taishan400_i2c_config_s taishan400_i2c0_config =
{
   .base          = TAISHAN400_I2C_BASE_ADDR,
  .clk_bit       = TAISHAN400_PCLK0_EN_I2C0,
  .reset_bit     = TAISHAN400_I2C0_SOFT_RESET,
  .scl_pin       = TAISHAN400_GPIO_I2C0_SCL,
  .sda_pin       = TAISHAN400_GPIO_I2C0_SDA,
#ifndef CONFIG_I2C_POLLED
  .ev_irq        = TAISHAN400_IRQ_I2C0,
  .er_irq        = TAISHAN400_IRQ_I2C0
#endif
};

static struct taishan400_i2c_priv_s taishan400_i2c0_priv =
{
  .config        = &taishan400_i2c0_config,
  .refs          = 0,
  .intstate      = INTSTATE_IDLE,
  .msgc          = 0,
  .msgv          = NULL,
  .ptr           = NULL,
  .frequency     = 0,
  .dcnt          = 0,
  .flags         = 0,
  .status        = 0,
#ifdef CONFIG_PM
  .pm_cb.prepare = taishan400_i2c_pm_prepare,
#endif
};

中断处理

在数据处理函数中调用taishan400_i2c_sendstar向总线上面发送start函数之后,如果start正确发送到了总线上面之后会产生开始条件中断标志,程序跳转到中断处理函数中,在中断处理函数中先清除开始中断标志位,由于在taishan400_i2c_sendstar中同时也向总线上面发送了EEPROM的器件地址,如果正确发送,会产生字节传输完成的中断,这时如果需要传输的字节数priv->dcnt不为0,而且上半部分读写标志位表示写操作,则会进入写数据的流程,在写数据流程中先清除上一个字节传输完成的中断标志位,然后将数据缓冲区指针priv->ptr的第一个字节写入I2C的数据寄存器,数据寄存器中的数据会自动被发送到I2C总线上面去,之后待发送数据字节数priv->dcnt减一,priv->ptr指针移动到下一个需要传输的字节处,由此完成一个字节的写入,之后程序跳出中断处理函数,等待一个字节的数据发送完成,发送完成之后会再次进入中断处理函数,重复同样的发送流程,数据读取同理。在完成所有数据字节传输之后(即priv->dcnt==0),会向I2C总线发送stop信号,发送成功之后会停止I2C通信。

功能实现

IIC总线初始化

初始化主要是由taishan400_i2c_init完成,主要是初始化相关的引脚,注册中断处理函数,初始化时钟。

I2C设备绑定

board_app_initialize初始化时会调用ee24xx_initialize,把I2C0和EEPROM进行绑定,同时会把EEPROM注册为字符设备,在文件系统中会生成一个/dev/at24文件,然后通过register_driver函数把/dev/at24与文件IO基本操作进行关联,方便应用程序通过文件IO访问/dev/at24。

数据处理函数

I2C驱动下半部分和上半部分进行数据交互的处理函数主要为taishan400_i2c_transfer函数,该函数中调用了taishan400_i2c_process函数,process函数先使能中断,然后调用taishan400_i2c_sendstart向总线上面发送I2C开始信号(scl时钟信号线由高电平向低电平跳变),发送开始信号之后再发送EEPROM的器件地址0xa0(发送了开始信号和EEPROM器件地址之后,进入等待状态等待一些中断产生。处理完中断之后会进行一些错误状态的判断并进行处理,比如数据溢出,从设备响应失败等状态。

中断处理函数

在数据处理函数中调用taishan400_i2c_sendstar向总线上面发送start函数之后,如果start正确发送到了总线上面之后会产生开始条件中断标志,程序跳转到中断处理函数中,在中断处理函数中先清除开始中断标志位,由于在taishan400_i2c_sendstar中同时也向总线上面发送了EEPROM的器件地址,如果正确发送,会产生字节传输完成的中断,这时如果需要传输的字节数priv->dcnt不为0,而且上半部分读写标志位表示写操作,则会进入写数据的流程,在写数据流程中先清除上一个字节传输完成的中断标志位,然后将数据缓冲区指针priv->ptr的第一个字节写入I2C的数据寄存器,数据寄存器中的数据会自动被发送到I2C总线上面去,之后待发送数据字节数priv->dcnt减一,priv->ptr指针移动到下一个需要传输的字节处,由此完成一个字节的写入,之后程序跳出中断处理函数,等待一个字节的数据发送完成,发送完成之后会再次进入中断处理函数,重复同样的发送流程,数据读取同理。在完成所有数据字节传输之后(即priv->dcnt==0),会向I2C总线发送stop信号,发送成功之后会停止I2C通信。

GPIO设置(根据具体情况)

编程示例

编程示例需要涵盖各个相应的功能