I2C简单实验之LT6911UXC读取ChipID

近期有点全身心投入到了嵌入式驱动的开发意思了,起早贪黑的学习。不过也是,人生的路都是在不断地学习中度过的。对于干了几年的硬件工程师而言,不说硬件是不是很牛了,就是想换换脑子,整天三极管、电阻、电容的,确实让人乏味。思来想去,硬件是软件的基座,驱动是软件沟通硬件的桥梁。倒不如自己整点知识,也方便自己以后调试硬件不是,再说了从软件角度去理解硬件思维,会有很多不同的收获不是。

​ 奋战了一个月,倒是把驱动的基本框架了解七七八八了,兴致使然,图像采集感觉还不错,公司有产品当开发板,也是省下了大部分的学习成本。

​ 硬件基本结构就是:SOC平台为瑞芯微,视频桥接芯片是LT6911UXC,千兆网络接口和基本的电源电路,还有的最小核心板组成就不多说了。

​ 总归是要初始化和调试LT6911UXC的,那么最基础的当然是通过固定的总线去访问和配置其寄存器了,而大多这类芯片都是用的I2C,LT6911UXC也不例外。于是重点看了下I2C总线的驱动实现框架。那么就在已有的基本驱动框架下实验下了

一、基本的驱动框架

#include <linux/init.h>
#include <linux/module.h>
static int lt6911_driver_init(void)
{
    return 0;
}

static void lt6911_driver_exit(void)
{
}

module_init(lt6911_driver_init);
module_exit(lt6911_driver_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("LY");
MODULE_VERSION("V1.0");

二、 增加I2C的框架

1. 添加一个I2C设备

这一步是通过i2c_add_driver(driver)这个API函数实现的,那么就在驱动加载的时候使用这个函数

static int lt6911_driver_init(void)
{
    int ret;
    printk("==>this is lt6911_driver_init\n");
    ret= i2c_add_driver(&lt6911_driver);
    if(ret<0){
        printk("==>lt6911 i2c driver add error\n");
        return 0;
    }

    return 0;
}

那么要按照以上的实现方式,必须要先实现一个I2C设备,这个设备是通过i2c_driver这个结构体实现的

struct i2c_driver lt6911_driver={
    .probe=lt6911_driver_probe,
    .remove=lt6911_driver_remove,
    .driver={
        .owner=THIS_MODULE,
        .name="lt6911uxc",          //没有设备树使用的匹配名
        .of_match_table=lt6911_id   //使用设备树匹配的设备列表
    },
	.id_table=lt6911_id_table       //无论使不使用设备树,这里必须实现
};

2. 实现两个函数

从上一步的i2c_driver设备结构体可以看出,需要实现probe和remove函数。probe函数是当I2C设备正确挂载后所执行的函数,remove函数是I2C设备卸载时所执行的函数。

probe函数
int lt6911_driver_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
    printk("==>this is lt6911_driver_probe\n");
    return 0;
}
remove函数
int lt6911_driver_remove(struct i2c_client *client)
{
    printk("==>this is lt6911_driver_remove\n");
    return 0;
}

3. 在设备树中对应的I2C下添加此设备信息

上面两步完成后,编译驱动为KO文件,通过insmod是可以加载此驱动的,但是会发现加载后只会执行到init这一步。那是因为我们没有在设备树中添加相应设备信息。我的板卡是挂在了I2C2上的,于是就进行下面操作

&i2c2{
	status = "okay";
	clock-frequency = <100000>;
	lt6911uxc:lt6911uxc@56{
        compatible = "lt6911uxc";
		status = "okay";
        reg = <0x56>;      //设备的芯片地址,手册都会说明             
		interrupt-parent = <&gpio3>;
		interrupts = <RK_PA5 IRQ_TYPE_LEVEL_LOW>;
		rst-gpio =  <&gpio4 RK_PA1 GPIO_ACTIVE_LOW>;

		pinctrl-names="default";
		pinctrl-0=<&lt6911_rstn_gpio>;
	};
	
};

然后重新编译内核,烧录开发板。再此进行加载KO文件,发现可以打印probe函数中设置的打印语句了

4. 实现最简单的读取Chip ID

框架都搭建完成,接下来当然是与芯片交流一下了,阅读了下LT6911UXC相关手册,要想读取寄存器的数据还得改变它的I2C工作模式和切换bank.原因是其内部集成了MCU,而这个MCU也是通过这个I2C在内部已经连接了LT6911UXC处理核心。

在这里插入图片描述

那么就要实现i2c的write和read函数了。驱动程序中I2C的读写都是以包的形式发送和接收的,所以我们先封包。封包使用的结构体是struct i2c_msg,最终的读写函数实现如下

static void lt6911_i2c_write( u16 reg, u8 *values, u32 n)
{
   	struct i2c_msg msgs[2];
	int err, i;
	u8 data[8];
	u8 bank = reg >> 8;
	u8 reg_addr = reg & 0xFF;
	u8 buf[2] = {0xFF, bank};

	data[0] = reg_addr;
	for (i = 0; i < n; i++)
		data[i + 1] = values[i];

	/* write bank */
	msgs[0].addr = lt6911_client->addr;
	msgs[0].flags = 0;
	msgs[0].len = 2;
	msgs[0].buf = buf;

	/* write reg data */
	msgs[1].addr = lt6911_client->addr;
	msgs[1].flags = 0;
	msgs[1].len = 1 + n;
	msgs[1].buf = data;

	err = i2c_transfer(lt6911_client->adapter, msgs, ARRAY_SIZE(msgs));
    if(err < 0){
         printk("==>transfer error %d\n",err);
    }
}
static int lt6911_i2c_read(u16 reg,u8 *values, u32 n)
{
    
    int ret;
    u8 bank = reg >> 8;
	u8 reg_addr = reg & 0xFF;
    u8 bank_buff[2]={0xff,bank};
    struct i2c_msg msgs[]={
        [0]={
            .addr=lt6911_client->addr,
            .flags=0,
            .len=2,
            .buf=bank_buff,
        
        },
        [1]={
            .addr=lt6911_client->addr,
            .flags=0,
            .len=sizeof(reg_addr),
            .buf=&reg_addr,
        
        },
        [2]={
            .addr=lt6911_client->addr,
            .flags=1,
            .len=sizeof(values),
            .buf=values,           
        }
    };
    ret = i2c_transfer(lt6911_client->adapter, msgs, ARRAY_SIZE(msgs));
    if(ret < 0){
         printk("==>transfer error %d\n",ret);
         return ret;
    }
    return 0;
}

读写函数实现没问题了,那么就在init函数中添加调用就可以了

    lt6911_i2c_write( 0x80ee, &i2c_enable, 1);
    lt6911_i2c_read(0x8100,&rdata,1);
    printk("==>lt6911_id is %#x\n",rdata);

编译后,再次加载KO文件,发现在写函数中i2c_transfer函数返回值为-6,意思是NO ACK。怎么回事呢,经过询问最近比较火热的Chatgpt,它告诉我了个答案
在这里插入图片描述

也就是我们给了设备地址,但是这个函数会将设备地址左移后然后增加读写位,才是真正的发送的地址。而通过开发板命令行中使用I2C工具(命令:i2cdump -y -f 2 0x56)来读取设备寄存器,通过逻辑分析仪抓取后得到

在这里插入图片描述

0x56左移一位再加上写标志位,确实是0xAC啊,经过资料的一番查找,对于I2C设备地址,都是七位。而资料给的发送格式0x56是带有读写位的。那么去掉读写位,也就是将0x56右移一位,在最高位加一个零,就得到了0x2B,再次使用I2C工具试下

在这里插入图片描述

就这样成功了,翻阅了大量资料。对于一个初学者而言都是在不断地怀疑和比较中找到了答案。还是挺兴奋的。所以我们就要把设备树中的配置更改下

&i2c2{
	status = "okay";
	clock-frequency = <100000>;
	lt6911uxc:lt6911uxc@56{
        compatible = "lt6911uxc";
		status = "okay";
        reg = <0x2b>;      //设备的芯片地址,手册都会说明             
		interrupt-parent = <&gpio3>;
		interrupts = <RK_PA5 IRQ_TYPE_LEVEL_LOW>;
		rst-gpio =  <&gpio4 RK_PA1 GPIO_ACTIVE_LOW>;

		pinctrl-names="default";
		pinctrl-0=<&lt6911_rstn_gpio>;
	};
	
};

编译内核,烧录。读chipID成功

在这里插入图片描述

总结

i2c的读写最关键的就是设备地址了,驱动的框架是固定的。

学习就应该在怀疑中调试,在调试中比较,在比较中得到答案。我们都是站在巨人的肩膀上的,当自己出现问题时,最好是看看巨人都是怎么做的。

原文链接

  • 19
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: LT6911UxC是龙翔科技公司生产的一种无线网络芯片。该芯片集成了MAC层、PHY层、RF射频以及其他必要的电路,可以实现高性能的无线通信功能。由于该芯片较新,一般需要下载并安装相应的驱动程序才能正常运行。 安装LT6911UxC驱动的步骤如下: 1. 首先,打开龙翔科技公司的官方网站,找到LT6911UxC产品页面。 2. 在产品页面中,查找并下载相应的驱动程序。一般会有针对各种操作系统的不同版本驱动程序可供选择。 3. 下载完驱动程序后,双击打开,并按照提示完成安装过程。通常安装过程只需简单地点击“下一步”即可。 4. 安装完成后,重启计算机。这将使驱动程序生效。 5. 在计算机重新启动之后,就可以开始使用LT6911UxC芯片进行无线网络通信了。 需要注意的是,安装驱动程序前,要确保计算机的操作系统与驱动程序的要求相匹配。如果操作系统不兼容,则可能需要更新操作系统或选择其他版本的驱动程序。 总之,安装LT6911UxC驱动程序是使该无线网络芯片正常工作的关键步骤。通过以上步骤,用户可以成功安装和使用LT6911UxC芯片来进行无线网络通信。 ### 回答2: LT6911UXC是一款用于驱动液晶显示器的芯片。该芯片可以通过接口与计算机或其他设备连接,并通过控制信号来驱动液晶显示器的工作。 LT6911UXC芯片具有较高的集成度和性能优势。它支持常用的显示模式,如VGA、HDMI和DVI,并能够实现高分辨率的显示效果。此外,它还支持自动信号检测和自动调节功能,可以根据输入信号的特性自动调节输出信号,以达到最佳的显示效果。 在使用LT6911UXC芯片时,首先需要将其正确连接到液晶显示器和计算机或其他设备。然后,根据具体的应用需求,编写相应的驱动程序或使用现有的驱动程序,将数据发送给LT6911UXC芯片,控制其输出信号以实现液晶显示器的正常显示。 作为一款专门用于液晶显示器驱动的芯片,LT6911UXC不仅广泛应用于电脑显示器,还可以用于监视器、电视等各类液晶显示设备上。它在增强图像显示效果、提高显示质量方面有着重要作用。 总之,LT6911UXC驱动是用于控制液晶显示器工作的芯片,可以通过编写驱动程序或使用现有的驱动程序来实现对其输出信号的控制,从而实现液晶显示器的正常工作。 ### 回答3: lt6911uxc是一款型号为lt(Linear Technology)6911uxc的驱动芯片。这款芯片是一种高性能于半导体驱动电路,用于驱动功率半导体器件,如功率MOSFET或IGBT等。 lt6911uxc具有多种特性和功能。首先,它能够提供高速响应和快速开关速度,可以满足各种应用需求。其次,lt6911uxc具有低电压和低电流操作特性,能够有效降低功耗和发热。此外,它还具有低输入/输出电容和低电压门极电荷特性,可以提供高效的电路输出。 lt6911uxc的驱动能力也值得注意。它具有高峰值电流输出,可以快速驱动功率半导体器件的开关。此外,它还具有低输出阻抗和高驱动电流能力,可以提供稳定的输出信号。 此外,lt6911uxc还具有过流保护和过热保护功能,可以有效保护芯片和周边电路的安全运行。这些保护功能对于长时间运行和高负载应用非常重要。 总而言之,lt6911uxc是一款高性能、低功耗、高驱动能力的驱动芯片。它具有多种特点和功能,适用于各种功率半导体器件的驱动应用。无论是在工业控制、汽车电子、医疗设备还是其他领域,lt6911uxc都可以提供可靠和高效的驱动支持。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

湮雨塵飛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值