现在有I2C显卡接口有几种,麻烦告知哪个是SCL, SDA和GND (红框里面的是I2C显卡接口有几种)

i2c 驱动编程接口
1、通信接口
i2c发送或者接收一次数据都以数据包 struct i2c_msg 封装
struct i2c_msg {&
&&& __u16&&&& // 从机地址&
&&& __u16&&& // 标志&
#define I2C_M_TEN&& 0x0010& // 十位地址标志&
#define I2C_M_RD&&& 0x0001& // 接收数据标志&
&&& __u16&&&&& // 数据长度&
&&& __u8 *&&&&& // 数据指针&
其中addr为从机地址;flags则是这次通信的标志,发送数据为0,接收数据则为 I2C_M_RD;len为此次通信的数据字节数;buf 为发送或接收数据的指针。在设备驱动中我们通常调用 i2c-core 定义的接口 i2c_master_send 和 i2c_master_recv 来发送或接收一次数据。
int i2c_master_send(struct i2c_client *client,const char *buf ,int count)&
&&& struct i2c_adapter *adap=client-&& // 获取adapter信息&
&&& struct i2c_&&&&&&&&&&&&&&&&&&&&&&& // 定义一个临时的数据包&
&&& msg.addr = client-&&&&&&&&&&&&&&&&&&& // 将从机地址写入数据包&
&&& msg.flags = client-&flags & I2C_M_TEN;&&&& // 将从机标志并入数据包&
&&& msg.len =&&&&&&&&&&&&&&&&&&&&&&&&&& // 将此次发送的数据字节数写入数据包&
&&& msg.buf = (char *)&&&&&&&&&&&&&&&&&&&& // 将发送数据指针写入数据包&
&&& ret = i2c_transfer(adap, &msg, 1);&&&&&&&& // 调用平台接口发送数据&
&&& /* If everything went ok (i.e. 1 msg transmitted), return #bytes
&&&&&& transmitted, else error code. */&
&&& return (ret == 1) ? count :&&&&&&&&&& // 如果发送成功就返回字节数&
EXPORT_SYMBOL(i2c_master_send);&
i2c_master_send 接口的三个参数:client 为此次与主机通信的从机,buf 为发送的数据指针,count 为发送数据的字节数。
int i2c_master_recv(struct i2c_client *client, char *buf ,int count)&
&&& struct i2c_adapter *adap=client-&& // 获取adapter信息&
&&& struct i2c_&&&&&&&&&&&&&&&&&&&&&&& // 定义一个临时的数据包&
&&& msg.addr = client-&&&&&&&&&&&&&&&&&&& // 将从机地址写入数据包&
&&& msg.flags = client-&flags & I2C_M_TEN;&&&& // 将从机标志并入数据包&
&&& msg.flags |= I2C_M_RD;&&&&&&&&&&&&&&&&&&&& // 将此次通信的标志并入数据包&
&&& msg.len =&&&&&&&&&&&&&&&&&&&&&&&&&& // 将此次接收的数据字节数写入数据包&
&&& msg.buf =&
&&& ret = i2c_transfer(adap, &msg, 1);&&&&&&&& // 调用平台接口接收数据&
&&& /* If everything went ok (i.e. 1 msg transmitted), return #bytes
&&&&&& transmitted, else error code. */&
&&& return (ret == 1) ? count :&&&&&&&&&& // 如果接收成功就返回字节数&
EXPORT_SYMBOL(i2c_master_recv);&
i2c_master_recv 接口的三个参数:client 为此次与主机通信的从机,buf 为接收的数据指针,count 为接收数据的字节数。我们看一下 i2c_transfer 接口的参数说明:
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num);&
其中 adap 为此次主机与从机通信的适配器;msgs 为通信的数据包,这里可以是单个或多个数据包;num 用于指定数据包的个数,如果大于1则表明将进行不止一次的通信。通信一次就需要寻址一次,如果需要多次通信就需要多次寻址,前面2个接口都是进行一次通信,所以 num 为1;有的情况下我们要读一个寄存器的值,就需要先向从机发送一个寄存器地址然后再接收数据,这样如果想自己封装一个接口就需要将 num 设置为2。接口的返回值如果失败则为负数,如果成功则返回传输的数据包个数。比如读一个寄存器的接口可以按照如下方式封装:
static int read_reg(struct i2c_client *client, unsigned char reg, unsigned char *data)&
&&& struct i2c_msg msgs[] = {&
&&&&&&& {&
&&&&&&&&&&& .addr&& = client-&addr,&
&&&&&&&&&&& .flags& = 0,&
&&&&&&&&&&& .len&&& = 1,&
&&&&&&&&&&& .buf&&& = &reg,& // 寄存器地址&
&&&&&&& },&
&&&&&&& {&
&&&&&&&&&&& .addr&& = client-&addr,&
&&&&&&&&&&& .flags& = I2C_M_RD,&
&&&&&&&&&&& .len&&& = 1,&
&&&&&&&&&&& .buf&&& = data,& // 寄存器的值&
&&&&&&& },&
&&& ret = i2c_transfer(client-&adapter, msgs, 2);& // 这里 num = 2,通信成功 ret = 2&
&&& if (ret & 0)&
&&&&&&& tp_err(&%s error: %d\n&, __func__, ret);&
还可调用前面所述的接口封装:
static unsigned char read_reg(struct i2c_client *client, unsigned char reg)&
&&& i2c_master_send(client, &reg, 1);& // 发送寄存器地址&
&&& i2c_master_recv(client, &buf, 1);& // 接收寄存器的值&
&&& return&&
2、reset 接口
最近因为平台的i2c总线经常发生死锁,用逻辑分析仪检测发现通常为SDA和SCL都被拉低,于是在i2c-core中加入了reset机制,总体思路如下:
(1)在i2c.driver和i2c.adapter的结构中加入reset接口,即每一个i2c设备都可以注册reset函数,每条i2c总线都有相应的reset接口
(2)当发生死锁时,首先根据i2c-timeout的信息获取当前通信的设备地址和总线编号,然后依次执行当前总线下所有i2c设备的reset函数,再尝试发送是否成功;如果总线仍然处于死锁状态则执行i2c.adapter的reset函数;如果总线还是处于死锁状态就重启机器;总共3层reset机制
(3)i2c.driver的reset函数一般操作设备的reset pin或者电源(需要根据硬件设计进行相应操作)
(4)i2c.adapter的reset函数首选进行SCL的模拟解锁方案,然后再是操作整个总线上设备的电源(需要根据硬件设计进行相应操作)
(5)重启是最后的一层机制,此时无法恢复设备的正常使用就只能重启了
因为i2c.adapter层的需要,在i2c-core中加入了遍历当前总线所有设备并执行设备reset函数的接口i2c_reset_device:
&* i2c_reset_device - reset I2C device when bus dead
&* @adapter: the adapter being reset
&* @addr: the device address
static int __i2c_reset_device(struct device *dev, void *addrp)&
&&& struct i2c_client *client = to_i2c_client(dev);&
&&& int addr = *(int *)&
&&& if (client && client-&driver && client-&driver-&reset)&
&&&&&&& return client-&driver-&reset();&
&&& return 0;&
int i2c_reset_device(struct i2c_adapter *adapter, int addr)&
&&& return device_for_each_child(&adapter-&dev, &addr, __i2c_reset_device);&
EXPORT_SYMBOL(i2c_reset_device);&
需要注意的是i2c.driver的reset函数返回值需要为0,不然device_for_each_child不会继续后面的遍历。用GPIO模拟SCL解锁的参考代码如下:
static int i2c_reset_adapter(void)&
&&& int counter = 0;&
&&& gpio_request(I2C_BUS_DATA, &gpioxx&);&
&&& gpio_request(I2C_BUS_CLK, &gpioxx&);&
&&& /* try to recover I2C bus */&
&&& gpio_direction_input(I2C_BUS_DATA);&
&&& if (!__gpio_get_value(I2C_BUS_DATA)) {&
&&&&&&& while((!__gpio_get_value(I2C_BUS_DATA)) && ++counter & 10)&
&&&&&&& {&
&&&&&&&&&&& udelay(5);&
&&&&&&&&&&& gpio_direction_output(I2C_BUS_CLK, 1);&
&&&&&&&&&&& udelay(5);&
&&&&&&&&&&& gpio_direction_output(I2C_BUS_CLK, 0);&
&&&&&&& }&
&&&&&&& i2c_err(&try to recover i2c bus, retry times are %d\n&,counter);&
&&&&&&& if (counter & 10) {&
&&&&&&&&&&& udelay(5);&
&&&&&&&&&&& gpio_direction_output(I2C_BUS_DATA, 0);&
&&&&&&&&&&& udelay(5);&
&&&&&&&&&&& gpio_direction_output(I2C_BUS_CLK, 1);&
&&&&&&&&&&& udelay(5);&
&&&&&&&&&&& gpio_direction_output(I2C_BUS_DATA, 1);&
&&&&&&&&&&& msleep(10);&
&&&&&&& } else {&
&&&&&&&&&&& i2c_err(&try to recover i2c bus failed!\n&);&
&&&&&&& }&
&&& gpio_free(I2C_BUS_DATA);&
&&& gpio_free(I2C_BUS_CLK);&
&&& return 0;&下次自动登录
现在的位置:
& 综合 & 正文
i2c 驱动编程接口 i2c_master_send 和 i2c_master_recv i2c_transfer
1、通信接口i2c发送或者接收一次数据都以数据包 struct i2c_msg 封装[cpp] struct i2c_msg {
// 从机地址
// 标志 #define I2C_M_TEN
// 十位地址标志 #define I2C_M_RD
// 接收数据标志
// 数据长度
// 数据指针 }; 其中addr为从机地址;flags则是这次通信的标志,发送数据为0,接收数据则为 I2C_M_RD;len为此次通信的数据字节数;buf 为发送或接收数据的指针。在设备驱动中我们通常调用 i2c-core 定义的接口 i2c_master_send 和 i2c_master_recv 来发送或接收一次数据。[cpp]int i2c_master_send(struct i2c_client *client,const char *buf ,int count) {
struct i2c_adapter *adap=client-&
// 获取adapter信息
struct i2c_
// 定义一个临时的数据包
msg.addr = client-&
// 将从机地址写入数据包
msg.flags = client-&flags & I2C_M_TEN;
// 将从机标志并入数据包
// 将此次发送的数据字节数写入数据包
msg.buf = (char *)
// 将发送数据指针写入数据包
ret = i2c_transfer(adap, &msg, 1);
// 调用平台接口发送数据
/* If everything went ok (i.e. 1 msg transmitted), return #bytes
transmitted, else error code. */
return (ret == 1) ? count :
// 如果发送成功就返回字节数 } EXPORT_SYMBOL(i2c_master_send); i2c_master_send 接口的三个参数:client 为此次与主机通信的从机,buf 为发送的数据指针,count 为发送数据的字节数。[cpp] int i2c_master_recv(struct i2c_client *client, char *buf ,int count) {
struct i2c_adapter *adap=client-&
// 获取adapter信息
struct i2c_
// 定义一个临时的数据包
msg.addr = client-&
// 将从机地址写入数据包
msg.flags = client-&flags & I2C_M_TEN;
// 将从机标志并入数据包
msg.flags |= I2C_M_RD;
// 将此次通信的标志并入数据包
// 将此次接收的数据字节数写入数据包
ret = i2c_transfer(adap, &msg, 1);
// 调用平台接口接收数据
/* If everything went ok (i.e. 1 msg transmitted), return #bytes
transmitted, else error code. */
return (ret == 1) ? count :
// 如果接收成功就返回字节数 } EXPORT_SYMBOL(i2c_master_recv); i2c_master_recv 接口的三个参数:client 为此次与主机通信的从机,buf 为接收的数据指针,count 为接收数据的字节数。我们看一下 i2c_transfer 接口的参数说明:[cppint i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num); 其中 adap 为此次主机与从机通信的适配器;msgs 为通信的数据包,这里可以是单个或多个数据包;num 用于指定数据包的个数,如果大于1则表明将进行不止一次的通信。通信一次就需要寻址一次,如果需要多次通信就需要多次寻址,前面2个接口都是进行一次通信,所以 num 为1;有的情况下我们要读一个寄存器的值,就需要先向从机发送一个寄存器地址然后再接收数据,这样如果想自己封装一个接口就需要将
num 设置为2。接口的返回值如果失败则为负数,如果成功则返回传输的数据包个数。比如读一个寄存器的接口可以按照如下方式封装:[cpp] static int read_reg(struct i2c_client *client, unsigned char reg, unsigned char *data) {
struct i2c_msg msgs[] = {
= client-&addr,
// 寄存器地址
= client-&addr,
= I2C_M_RD,
// 寄存器的值
ret = i2c_transfer(client-&adapter, msgs, 2);
// 这里 num = 2,通信成功 ret = 2
if (ret & 0)
tp_err("%s error: %d\n", __func__, ret);
} 还可调用前面所述的接口封装:[cpp] static unsigned char read_reg(struct i2c_client *client, unsigned char reg) {
i2c_master_send(client, &reg, 1);
// 发送寄存器地址
i2c_master_recv(client, &buf, 1);
// 接收寄存器的值
} 2、reset 接口最近因为平台的i2c总线经常发生死锁,用逻辑分析仪检测发现通常为SDA和SCL都被拉低,于是在i2c-core中加入了reset机制,总体思路如下:(1)在i2c.driver和i2c.adapter的结构中加入reset接口,即每一个i2c设备都可以注册reset函数,每条i2c总线都有相应的reset接口(2)当发生死锁时,首先根据i2c-timeout的信息获取当前通信的设备地址和总线编号,然后依次执行当前总线下所有i2c设备的reset函数,再尝试发送是否成功;如果总线仍然处于死锁状态则执行i2c.adapter的reset函数;如果总线还是处于死锁状态就重启机器;总共3层reset机制(3)i2c.driver的reset函数一般操作设备的reset pin或者电源(需要根据硬件设计进行相应操作)(4)i2c.adapter的reset函数首选进行SCL的模拟解锁方案,然后再是操作整个总线上设备的电源(需要根据硬件设计进行相应操作)(5)重启是最后的一层机制,此时无法恢复设备的正常使用就只能重启了因为i2c.adapter层的需要,在i2c-core中加入了遍历当前总线所有设备并执行设备reset函数的接口i2c_reset_device:[cpp]/** * i2c_reset_device - reset I2C device when bus dead * @adapter: the adapter being reset * @addr: the device address */ static int __i2c_reset_device(struct device *dev, void *addrp) {
struct i2c_client *client = to_i2c_client(dev);
int addr = *(int *)
if (client && client-&driver && client-&driver-&reset)
return client-&driver-&reset();
return 0; }
int i2c_reset_device(struct i2c_adapter *adapter, int addr) {
return device_for_each_child(&adapter-&dev, &addr, __i2c_reset_device); } EXPORT_SYMBOL(i2c_reset_device); 需要注意的是i2c.driver的reset函数返回值需要为0,不然device_for_each_child不会继续后面的遍历。用GPIO模拟SCL解锁的参考代码如下:[cpp] static int i2c_reset_adapter(void) {
int counter = 0;
gpio_request(I2C_BUS_DATA, "gpioxx");
gpio_request(I2C_BUS_CLK, "gpioxx");
/* try to recover I2C bus */
gpio_direction_input(I2C_BUS_DATA);
if (!__gpio_get_value(I2C_BUS_DATA)) {
while((!__gpio_get_value(I2C_BUS_DATA)) && ++counter & 10)
udelay(5);
gpio_direction_output(I2C_BUS_CLK, 1);
udelay(5);
gpio_direction_output(I2C_BUS_CLK, 0);
i2c_err("try to recover i2c bus, retry times are %d\n",counter);
if (counter & 10) {
udelay(5);
gpio_direction_output(I2C_BUS_DATA, 0);
udelay(5);
gpio_direction_output(I2C_BUS_CLK, 1);
udelay(5);
gpio_direction_output(I2C_BUS_DATA, 1);
msleep(10);
i2c_err("try to recover i2c bus failed!\n");
gpio_free(I2C_BUS_DATA);
gpio_free(I2C_BUS_CLK);
return 0; }
&&&&推荐文章:
【上篇】【下篇】5011人阅读
3D打印机(3)
我的硬件是atmega2560的芯片。由于需求使用了LCD2004。虽然板子上也有硬件的SDA(20)和SCL(21)引脚。但是由于各种原因我只能使用被指定的45和47引脚。&
我尝试了更改arduino库里的设置。像Boards.h和pins_arduino.h什么的有关SDA和SCL引脚的定义,改了全都无效的。而且还在国内的网站上竟然找到了一个说是改变pins_arduino.h里面对SDA和SCL的定义就行了。我试过了,如果不是软件模拟I2C并且包含了pins_arduino.h头文件使用’SDA’和’SCL’宏,是无效的。他也没说是软模。&
后来只能翻墙找资料了。都说硬件的IIC引脚是改不了的。其他引脚只能通过软件来模拟硬件的SDA和SCL。国外有牛人做了个软件模拟I2C的。要说模拟I2C并不稀奇。但是他模拟的是和arduino库里面的Wire.h相关接口几乎是一样的。最起码重要的接口是相同。
而我们使用的LCD库都是引用的硬件SDA和SCL。所以就用到了Wire.h。而Wire.h又使用的是twi.h包含的函数。无奈如果你会改寄存器我想不是不可以尝试改一下这蛋疼的玩意儿。&
而这个软模IIC可以使用任何IO口。标称是这样的哈,我也没有试过所有的IO。最起码让你换大部分的IO任意两个脚作为SDA\SCL使用应该是可行的。
我下载过的所有IIC的库代码如有需要的可以下载看看:
我改过的支持LCD1602和LCD2004的软模IIC文件下载地址:(只要把MYSDA和MYSCL在头文件改掉为自定义就行了。并且一个SoftI2CMaster.h/.cpp就可以取代arduino库里面的Wire.h/.c和twi.h/.c两个文件。对于LCD来说稍微改动一下就完事儿了)。
未改过的LCD库文件:&(使用的是库Wire.h)
改动截图:
LiquidCrystal_I2C.cpp开头
LiquidCrystal_I2C.h最末尾
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:15937次
排名:千里之外
(window.slotbydup = window.slotbydup || []).push({
id: '4740881',
container: s,
size: '200,200',
display: 'inlay-fix'价格:面议
型号:VK0144
关键词:LCD液晶驱动器,液晶显示驱动芯片
在线联系:
产品别名 超低功耗,原厂直销,工程服务,技术支持
面向地区 深圳
型号 VK0144
VK0144是字段式液晶显示驱动芯片超低功耗I2C串行接口(SCL,SDA 产品型号:VK0144
产品品牌:VINKA
产品年份:新年份
封装形式:QFN48L/TSSOP48
联 系 人:许先生
联 系 QQ:
联系手机:
工程服务,技术支持,价格最具优势!
VK0144是一款性能优越的液晶段码显示驱动器,由于其驱动段位多达144段和超低功耗的工艺设计特点。还具有性能稳定和低价格优势、供货稳定,目前被业界广泛应用在众多的仪器仪表的产品上。比如手持式仪表、费率表、工控仪表、医疗仪器、专用测量仪表头等等设备上使用。
■最大144段位输出
4条公共线(COM0-COM3)36条段线(SEG0-SEG35) 内置144位显示内存映射
■多种驱动模式1/2,1/3 Bias 1/4 Duty
■内置时钟振荡电路、复位电路
■IIC总线接口
■低功耗工艺设计、带休眠功能
  工作电压范围: 2.5-5.5V
  低功耗模式下,实测工作电流:≈5.5uA (典型值所有段全显示时)
  关闭显示时,实测休眠电流:0.1uA (典型值屏无显示)
■TSSOP-48双列贴片48脚封装(脚心间距0.5mm)
■符合环保要求
高品质产品设计!
○应用推荐
  电表、水表、气表、热表、各种计量专用表头。
■手持式仪表:
  万用表、电子称、医疗仪器、等各种手持式仪表和计量器。
■各种需要较多段液晶显示的仪器仪表显示屏。
■特别适合应用于电池供电或对功耗敏感的产品上使用;使产品的电池更耐用、寿命更持久。
■无液晶驱动的低功耗型单片机+MCP144组合应用:MSP430、STM32L、EFM32、MAXQ等系列低功耗设计应用。
■代替其他应用
相比HT1621器件功耗低15-30倍,段码多16段,体积更薄更小;有足够更换理由。
■推荐应用领域 
工控、医疗、物联网、白色家电、环境监测等领域。
○典型电路
上图VK0144的SEG0~31、COM0~3是连接至LCD片(128段)相应的引脚上。
○手册下载
手册、封装库文档将不定期更新,请留意下载最新版本。
VK0144中文手册VK0144测试参考手册   VK0144应用指南VK0144 SCH/PCB封装库
VK0144驱动程序移植指南 注:关于VK0144驱动源程序请购买样片的用户联系淘宝店长或者联系我们索取。
电池供电的低功耗设计杂谈HT1621与VK0144性价比较 液晶独立驱动器与集成驱动各有优势
○帮助设计
■MC128DM2评估模块、VK0144+MSP430F1232演示板,使工程师快速测试和体验。
■提供Altium Designer版的SCH、PCB封装库、3D模型文件和参考电路图源文件。帮助工程师快速地导入到设计中。
■提供演示驱动源程序参考。简单易用易移植的C代码例程,中文注解;全中文资料文档支持。
○供货信VK0144器件已批量供货,器件3K参考价≤2.10(RMB)/片(税前)。
 注:①为防止购买到假、仿伪劣产品,建议用户直联系我们采购或指定受权代理网点购买。
②大批量用户请提前4周订货,详情请与我们联系洽商。
联系我时请务必告知是在黄页88网看到的!
4年主营:lcd液晶显示驱动ic,led液晶显示驱动ic,驱动ic全系列———— 认证资质 ————
个人 营业执照 手机 微信 邮箱
没有个人认证 没有企业认证 手机认证已通过 微信认证已通过 没有邮箱认证
单片机VIP推荐信息
相关推荐产品
咨询主题:价格发货与交货商品参数其它 *咨询详情: *联系人: *手机号码: QQ号:
深圳半球电子科技有限公司为你提供的“VK0144是字段式液晶显示驱动芯片超低功耗I2C串行接口(SCL,SDA”详细介绍,包括LCD液晶驱动器价格、型号、图片、厂家等信息。如有需要,请拨打电话:。不是你想要的产品?,让供应商主动联系你。
“VK0144是字段式液晶显示驱动芯片超低功耗I2C串行接口(SCL,SDA”信息由发布人自行提供,其真实性、合法性由发布人负责。交易汇款需谨慎,请注意调查核实。

我要回帖

更多关于 雷电3接口有什么用 的文章

 

随机推荐