首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >RK3576开发板I2C驱动实战教程,HYM8563 RTC时钟芯片为例

RK3576开发板I2C驱动实战教程,HYM8563 RTC时钟芯片为例

原创
作者头像
Industio_触觉智能
修改2026-07-06 13:47:53
修改2026-07-06 13:47:53
40
举报
文章被收录于专栏:Linux嵌入式Linux嵌入式

本文基于触觉智能RK3576开发板(Purple Pi OH2)讲解与调试,聚焦I2C驱动开发核心知识点,以HYM8563 RTC芯片为例,从协议原理到驱动源码全维度解析。

一、I2C 基本概念 1.1 什么是 I2C? I2C(Inter-Integrated Circuit)是一种两线串行总线协议,由 Philips(现 NXP)在 1980 年代发明,广泛用于连接低速外设: •SDA(Serial Data):数据线,双向传输,开漏输出 •SCL(Serial Clock):时钟线,由主设备产生,开漏输出 •外部需接上拉电阻(典型 4.7kΩ)将总线拉高 1.2 I2C 总线特点 特性说明线数2 根(SDA + SCL),节省 PCB 空间设备数量最多 127 个(7 位地址)或 1023 个(10 位地址)速率标准模式 100 kHz,快速模式 400 kHz,高速模式 3.4 MHz通信方式主从架构,主设备(Master)发起通信并产生时钟数据传输MSB 优先,每个字节后跟一个 ACK/NACK 位 1.3 I2C 与 SPI 的简要对比 特性I2CSPI引脚数2(SDA + SCL)3+N(SCK + MOSI + MISO + N×CS)速率~100 kHz–3.4 MHz~MHz–几十 MHz寻址软件寻址(7/10 位地址)硬件片选(每个设备一根 CS)多主支持支持(冲突检测)不支持功耗较低(开漏+上拉)较高(推挽输出)适合场景低复杂度、节省引脚的外设高速、大批量数据传输 1.4 RK3576 I2C 资源 RK3576 提供 10 路 I2C 控制器(I2C0 ~ I2C9),每个控制器可通过 pinctrl 选择多个引脚复用(mux)选项: i2c0 = &i2c0;   // 通常用于 PMIC (RK806) i2c1 = &i2c1;   // 通用 i2c2 = &i2c2;   // 本教程使用:RTC (hym8563) i2c3 = &i2c3;   // Audio Codec ... i2c9 = &i2c9; 二、I2C 通信协议 2.1 I2C 协议交互流程 I2C 总线上一次完整的数据传输遵循以下流程: 起始条件(S) → 7位从机地址 → R/W位 → ACK → 8位数据 → ACK → 停止条件(P) 以下是主设备与从设备之间的完整协议交互序列图(含起始条件、地址发送、数据读写、应答和停止条件): 📷 协议时序参数表: 阶段时钟周期数说明S (起始条件)0SCL=High,SDA 下降沿7位地址7 个 SCLMSB (A6) 先发,LSB (A0) 最后R/W 位1 个 SCL0 = 写操作,1 = 读操作ACK1 个 SCL(第9个)从机拉低 SDA 应答数据字节8 个 SCL数据位 D7~D0,MSB 先发P (停止条件)0SCL=High,SDA 上升沿 数据帧结构 — I2C 总线上一个完整数据帧的比特布局(共 19 个 SCL 时钟周期): ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐ │ S │A6 │A5 │A4 │A3 │A2 │A1 │A0 │R/W│ACK│D7 │D6 │D5 │D4 │D3 │D2 │D1 │D0 │ P │ │ ↓ │◄──────── 从机地址7bit ────────►│   │◄──────── 数据8bit────────────►│ ↑ │ └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘   S     ▲──── SCL 时钟采样 SDA ────▲                                     P 起始          每个时钟1位数据          停止 条件                                   条件 2.2 起始条件与停止条件 这是 I2C 总线最核心的时序特征 — SDA 在 SCL 高电平时跳变,此信号在数据传输阶段被严格禁止。以下是两个关键边沿的序列图: 📷 规则:在数据传输阶段(S 和 P 之间),SDA 只能在 SCL 低电平时变化,SCL 高电平时 SDA 必须保持稳定 — 这是 I2C 协议的根本规则。 2.3 数据有效性规则 以下是 SCL 与 SDA 配合关系的序列图: 📷 2.4 应答机制(ACK/NACK) 每个字节传输完成后,接收方必须在第 9 个 SCL 时钟周期驱动 SDA 发送应答位。以下是应答机制的序列图: 📷 应答SDA 电平发送方含义ACKLow接收方驱动接收成功,继续发送下一字节NACKHigh上拉电阻拉高接收失败或传输结束 2.5 I2C 设备地址 I2C 7 位地址由芯片厂商分配(高位)和硬件引脚电平(低位)共同决定,在总线上地址左移 1 位后附加 R/W 位发送: 7'h51 (HYM8563) → 左移1位 → 0xA2 (写) / 0xA3 (读)    bit:  6   5   4   3   2   1   0   R/W         1   0   1   0   0   0   1   0/1         └──────── 0xA2 (写) / 0xA3 (读) 设备7位地址写地址(<<1)典型用途HYM8563 RTC0x510xA2本教程 RTC 芯片PCF8563 RTC0x510xA2NXP 兼容 RTCEEPROM (AT24Cxx)0x500xA0存储ES8316 Audio Codec0x180x30音频编解码RK806 PMIC0x230x46电源管理 三、HYM8563 RTC 硬件原理 3.1 HYM8563 芯片简介 HYM8563 是 Haoyu Microelectronics 生产的低功耗 RTC(实时时钟)芯片,与 NXP PCF8563 兼容,通过 I2C 接口与主控通信。 关键特性: •I2C 总线接口(最大 400 kHz) •计时精度依赖外部 32768 Hz 晶振 •内置秒、分、时、日、星期、月、年计数(BCD 格式) •具有闹钟(Alarm)和定时器(Timer)功能 •可编程 CLKOUT 引脚输出时钟(32768 / 1024 / 32 / 1 Hz) •低功耗:典型 0.25 μA(VDD=3.0V,定时器关闭) •宽电压:1.0V ~ 5.5V 3.2 引脚定义与典型电路 应用电路: 📷 3.3 寄存器映射表(核心) HYM8563 内部寄存器共 16 个(0x00 ~ 0x0f),其中时间寄存器从 0x02 开始,全部采用 BCD 编码: 地址名称Bit 7Bit 6Bit 5Bit 4Bit 3Bit 2Bit 1Bit 0取值范围0x00CTL1TEST—STOP—TESTC————0x01CTL2——TI/TPAFTFAIETIE——0x02SECVL秒(BCD 十位) 秒(BCD 个位) 00–59 0x03MIN—分(BCD 十位) 分(BCD 个位) 00–59 0x04HOUR——时(BCD 十位) 时(BCD 个位) 00–23 0x05DAY——日(BCD 十位) 日(BCD 个位) 01–31 0x06WEEKDAY—————星期 00–06 0x07MONTHC——月(BCD 十位) 月(BCD 个位)01–12 0x08YEAR年(BCD 千位+百位) 年(BCD 十位) 年(BCD 个位)00–99 0x09ALM_MINAE—闹钟分(BCD) 00–59 0x0AALM_HOURAE——闹钟时(BCD) 00–23 0x0BALM_DAYAE——闹钟日(BCD) 01–31 0x0CALM_WEEKAE———闹钟星期 00–06 0x0DCLKOUTOE————FD1FD0——0x0ETMR_CTLTE————TD1TD0——0x0FTMR_CNT定时器倒计数值 0–255 关键位说明: 位所在寄存器功能STOP (Bit 5)CTL1 (0x00)1 = RTC 停止计数,0 = 正常运行VL (Bit 7)SEC (0x02)0 = 时间有效,1 = 时间无效(掉电或晶振停振)C (Bit 7)MONTH (0x07)世纪位— 但驱动实测不可靠,内核限制为 2000–2099AE (Bit 7)ALM_* (0x09~0x0C)1 = 该闹钟字段不参与匹配(即忽略此项)OE (Bit 7)CLKOUT (0x0D)1 = 使能 CLKOUT 输出FD[1:0]CLKOUT (0x0D)00=32768Hz, 01=1024Hz, 10=32Hz, 11=1HzTE (Bit 7)TMR_CTL (0x0E)1 = 使能定时器TD[1:0]TMR_CTL (0x0E)定时器时钟源选择 3.4 BCD 编码说明 时间寄存器使用 BCD(Binary-Coded Decimal)编码,即每个十进制数字用 4 位二进制表示,驱动中使用bcd2bin() / bin2bcd() 完成转换: BCD 编码示例:时间 12:34:56   秒(0x56) = 0101 0110 → 高4位(5) + 低4位(6) = 56 秒   分(0x34) = 0011 0100 → 高4位(3) + 低4位(4) = 34 分   时(0x12) = 0001 0010 → 高4位(1) + 低4位(2) = 12 时 驱动中的 BCD 转换函数(定义在 linux/bcd.h):   bcd2bin(0x56) = 5*10 + 6 = 56          // BCD → 整数   bin2bcd(34)   = (3<<4) | 4 = 0x34       // 整数 → BCD 四、I2C 设备树配置 4.1 使能 I2C 控制器并添加 RTC 设备 在设备树文件(如ido-evb7609-v1a.dtsi)中配置 I2C2 控制器及 HYM8563 子设备: /* I2C2 - 挂载 HYM8563 RTC */ &i2c2 {     status = "okay";     pinctrl-names = "default";     pinctrl-0 = <&i2c2m0_xfer>;     hym8563: hym8563@51 {         compatible = "haoyu,hym8563";       // 驱动匹配的关键字符串         reg = <0x51>;                       // I2C 7 位从机地址 (7'h51)         #clock-cells = <0>;                 // 可作为时钟提供者         clock-frequency = <32768>;          // CLKOUT 输出频率         clock-output-names = "hym8563";     // 时钟输出名称         interrupt-parent = <&gpio0>;        // 中断控制器         interrupts = <RK_PC5 IRQ_TYPE_LEVEL_LOW>;  // 中断引脚与触发方式         wakeup-source;                      // 支持系统唤醒     }; }; 各属性详解: 属性作用说明compatible驱动匹配内核据此查找of_device_id 表中匹配的驱动regI2C 地址7 位地址左对齐写入,0x51 即器件地址#clock-cells时钟接口0 表示直接输出固定频率时钟clock-frequency输出频率仅描述信息,实际由 CLKOUT 寄存器控制interrupts中断配置指定 INT 引脚对应的 GPIO 和触发类型wakeup-source唤醒标记系统 Suspend 时 RTC 闹钟可唤醒 SoC 4.2 pinctrl 引脚复用配置 I2C2 的 SDA/SCL 引脚可以复用到不同的 GPIO 组,需要根据实际硬件原理图选择对应的 mux: &pinctrl { i2c2 { /* I2C2 M0 组:SCL = GPIO1_B4, SDA = GPIO1_B3 */ i2c2m0_xfer: i2c2m0-xfer { rockchip,pins = <1 RK_PB4 9 &pcfg_pull_none>, /* i2c2_scl_m0 */ <1 RK_PB3 9 &pcfg_pull_none>; /* i2c2_sda_m0 */ }; /* I2C2 M1 组:备用引脚(如需要) */ i2c2m1_xfer: i2c2m1-xfer { rockchip,pins = <1 RK_PB4 10 &pcfg_pull_none>, /* i2c2_scl_m1 */ <1 RK_PB3 10 &pcfg_pull_none>; /* i2c2_sda_m1 */ }; }; }; pinctrl 字段说明: •<1 RK_PB4 9 &pcfg_pull_none> = <bank(1) pin(GPIO1_B4) function(9) pull-config(无上拉)> •每个 SoC 的 function 编号不同,需参考 RK3576 TRM(Technical Reference Manual) 的 GPIO 复用表格 4.3 查看当前引脚复用状态 # 查看 GPIO1_B3 (I2C2_SDA) 当前功能 cat /sys/kernel/debug/pinctrl/pinctrl-handles | grep i2c2 # 或者检查 pinctrl 设置 cat /sys/kernel/debug/gpio | grep i2c 五、hym8563 驱动源码分析 5.1 驱动文件概览 源文件:kernel-6.1/drivers/rtc/rtc-hym8563.c(643 行) 编译配置: // Kconfig config RTC_DRV_HYM8563 tristate "Haoyu Microelectronics HYM8563" depends on OF help Say Y to enable support for the HYM8563 I2C RTC chip. // Makefile obj-$(CONFIG_RTC_DRV_HYM8563) += rtc-hym8563.o 5.2 数据结构与寄存器定义 struct hym8563 { struct i2c_client *client; // I2C 客户端(关联设备和适配器) struct rtc_device *rtc; // RTC 核心框架设备 #ifdef CONFIG_COMMON_CLK struct clk_hw clkout_hw; // CLKOUT 时钟提供者 #endif int alarm_or_timer_irq; // 0=闹钟模式, 1=定时器模式 int alarm_tm_sec; // 闹钟秒数(定时器模式用) }; 寄存器宏定义(驱动中命名对应数据手册): 宏值对应寄存器HYM8563_CTL10x00控制寄存器 1HYM8563_CTL20x01控制寄存器 2HYM8563_SEC0x02秒寄存器(含 VL 位)HYM8563_MIN0x03分钟寄存器HYM8563_HOUR0x04小时寄存器HYM8563_DAY0x05日寄存器HYM8563_WEEKDAY0x06星期寄存器HYM8563_MONTH0x07月寄存器(含 C 世纪位)HYM8563_YEAR0x08年寄存器HYM8563_ALM_MIN0x09闹钟分钟HYM8563_CLKOUT0x0D时钟输出控制HYM8563_TMR_CTL0x0E定时器控制HYM8563_TMR_CNT0x0F定时器计数值 5.3 核心函数分析:读取时间 static int hym8563_rtc_read_time(struct device *dev, struct rtc_time *tm) { struct i2c_client *client = to_i2c_client(dev); u8 buf[7]; int ret; // ---- I2C 通信:一次读取 7 个时间寄存器 (SEC ~ YEAR) ---- // SMBus 协议:发送寄存器地址 0x02 → 连续读取 7 个字节 ret = i2c_smbus_read_i2c_block_data(client, HYM8563_SEC, 7, buf); if (ret < 0) return ret; // ---- BCD 解码:将 BCD 格式转为内核 tm 结构体 ---- tm->tm_sec = bcd2bin(buf[0] & HYM8563_SEC_MASK); // buf[0]=SEC tm->tm_min = bcd2bin(buf[1] & HYM8563_MIN_MASK); // buf[1]=MIN tm->tm_hour = bcd2bin(buf[2] & HYM8563_HOUR_MASK); // buf[2]=HOUR tm->tm_mday = bcd2bin(buf[3] & HYM8563_DAY_MASK); // buf[3]=DAY tm->tm_wday = bcd2bin(buf[4] & HYM8563_WEEKDAY_MASK); // buf[4]=WEEKDAY, 0=周日 tm->tm_mon = bcd2bin(buf[5] & HYM8563_MONTH_MASK) - 1; // buf[5]=MONTH, -1=0基 tm->tm_year = bcd2bin(buf[6]) + 100; // buf[6]=YEAR, +100=2000基 return 0; } I2C 读写复合时序(i2c_smbus_read_i2c_block_data 的实际总线波形): 📷 数据结构转换关系: 📷 5.4 核心函数分析:写入时间 static int hym8563_rtc_set_time(struct device *dev, struct rtc_time *tm) { struct i2c_client *client = to_i2c_client(dev); u8 buf[7]; int ret; // ---- 年份范围检查 ---- // 硬件世纪位不可靠,驱动限制:2000–2099 if (tm->tm_year < 100 || tm->tm_year >= 200) return -EINVAL; // ---- BCD 编码:将 tm 结构体转为 BCD 格式 ---- buf[0] = bin2bcd(tm->tm_sec); buf[1] = bin2bcd(tm->tm_min); buf[2] = bin2bcd(tm->tm_hour); buf[3] = bin2bcd(tm->tm_mday); buf[4] = bin2bcd(tm->tm_wday); buf[5] = bin2bcd(tm->tm_mon + 1); // +1: 0基→1基 buf[6] = bin2bcd(tm->tm_year - 100); // -100: 2000基→0基 // ---- 写入时序:STOP → 写时间 → 清除STOP ---- // ① 先设置 STOP 位,暂停 RTC 计数(防止写入过程中时间变化) ret = i2c_smbus_write_byte_data(client, HYM8563_CTL1, HYM8563_CTL1_STOP); if (ret < 0) return ret; // ② 一次性写入 7 个时间寄存器 ret = i2c_smbus_write_i2c_block_data(client, HYM8563_SEC, 7, buf); if (ret < 0) return ret; // ③ 清除 STOP 位,RTC 恢复计数(从新设定的时间开始) ret = i2c_smbus_write_byte_data(client, HYM8563_CTL1, 0); if (ret < 0) return ret; return 0; } 写入时序要点 — 为什么需要先暂停 RTC? 📷 5.5 Probe 函数分析 static int hym8563_probe(struct i2c_client *client) { struct hym8563 *hym8563; int ret; struct rtc_time tm_read, tm = { .tm_wday = 0, .tm_year = 121, // 2021年 .tm_mon = 0, // 1月 .tm_mday = 1, .tm_hour = 12, .tm_min = 0, .tm_sec = 0, }; // ① 分配私有数据结构 hym8563 = devm_kzalloc(&client->dev, sizeof(*hym8563), GFP_KERNEL); if (!hym8563) return -ENOMEM; // ② 分配 RTC 核心设备 hym8563->rtc = devm_rtc_allocate_device(&client->dev); if (IS_ERR(hym8563->rtc)) return PTR_ERR(hym8563->rtc); hym8563->client = client; i2c_set_clientdata(client, hym8563); // ③ 初始化硬件:清除STOP/中断/标志位 ret = hym8563_init_device(client); if (ret) { dev_err(&client->dev, "could not init device, %d\n", ret); return ret; } // ④ 注册中断(仅当 DT 中配置了 interrupt 时才执行) if (client->irq > 0) { ret = devm_request_threaded_irq(&client->dev, client->irq, NULL, hym8563_irq, IRQF_TRIGGER_LOW | IRQF_ONESHOT, client->name, hym8563); // ... 错误处理 ... } // ⑤ 检查 VL 位 — 判断 RTC 时间是否有效 ret = i2c_smbus_read_byte_data(client, HYM8563_SEC); dev_info(&client->dev, "rtc information is %s\n", (ret & HYM8563_SEC_VL) ? "invalid" : "valid"); // ⑥ 如果时间无效或超出范围,重置为默认时间 (2021-01-01 12:00:00) hym8563_rtc_read_time(&client->dev, &tm_read); if ((ret & HYM8563_SEC_VL) || (tm_read.tm_year < 70) || (tm_read.tm_year > 200) || (rtc_valid_tm(&tm_read) != 0)) hym8563_rtc_set_time(&client->dev, &tm); // ⑦ 注册 RTC 设备到 Linux RTC 核心框架 hym8563->rtc->ops = &hym8563_rtc_ops; clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, hym8563->rtc->features); return devm_rtc_register_device(hym8563->rtc); } Probe 完整流程图: 📷 5.6 初始化设备分析 static int hym8563_init_device(struct i2c_client *client) { int ret; ret = i2c_smbus_read_byte_data(client, HYM8563_CTL1); // ... error check ... // 清除 STOP 位(如果 RTC 之前被停止过) ret = i2c_smbus_write_byte_data(client, HYM8563_CTL1, 0); if (ret < 0) return ret; ret = i2c_smbus_read_byte_data(client, HYM8563_CTL2); if (ret < 0) return ret; // 禁用闹钟中断 (AIE) 和定时器中断 (TIE) ret &= ~HYM8563_CTL2_AIE; ret &= ~HYM8563_CTL2_TIE; // 清除任何待处理的闹钟/定时器标志 if (ret & HYM8563_CTL2_AF) ret &= ~HYM8563_CTL2_AF; if (ret & HYM8563_CTL2_TF) ret &= ~HYM8563_CTL2_TF; // 复位定时器(写回配置) i2c_smbus_write_byte_data(client, HYM8563_TMR_CNT, 0); i2c_smbus_write_byte_data(client, HYM8563_TMR_CTL, HYM8563_TMR_CFG); // HYM8563_TMR_CFG = TE(使能) | 01(时钟源=64Hz) // ↑每 1/64 秒减1 return i2c_smbus_write_byte_data(client, HYM8563_CTL2, ret); } 5.7 中断处理分析 static irqreturn_t hym8563_irq(int irq, void *dev_id) { struct hym8563 *hym8563 = (struct hym8563 *)dev_id; struct i2c_client *client = hym8563->client; int data, ret; rtc_lock(hym8563->rtc); // 读取 CTL2,获取中断状态 data = i2c_smbus_read_byte_data(client, HYM8563_CTL2); // 清除闹钟标志 (AF) 和定时器标志 (TF) data &= ~HYM8563_CTL2_AF; data &= ~HYM8563_CTL2_TF; // 复位定时器计数器 i2c_smbus_write_byte_data(client, HYM8563_TMR_CNT, 0); // 写回清除后的 CTL2 ret = i2c_smbus_write_byte_data(client, HYM8563_CTL2, data); out: rtc_unlock(hym8563->rtc); return IRQ_HANDLED; } // 中断注册参数: // IRQF_TRIGGER_LOW — INT 引脚为低电平触发 // IRQF_ONESHOT — 线程化中断,中断线在handler运行期间保持屏蔽 5.8 闹钟与定时器双模式 这是一个巧妙的设计:HYM8563 硬件同时支持闹钟(Alarm)和定时器(Timer),驱动根据唤醒间隔自动选择: static int hym8563_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) { // ... interval = alarm - now; // 计算到闹钟的秒数 if (interval < HYM8563_TMR_MAXCNT) { // < 255 秒 // ---- 定时器模式(1秒精度) ---- // 使用硬件定时器做短间隔唤醒 // 精度高,但最长只能 255 秒 hym8563->alarm_or_timer_irq = 1; i2c_smbus_write_byte_data(client, HYM8563_TMR_CNT, (u8)interval); } else { // ---- 闹钟模式(分钟精度) ---- // 使用硬件闹钟做长间隔唤醒 // 没有秒级精度(tm_sec 被强制设为 0) // 但可以设置任意未来的时间 hym8563->alarm_or_timer_irq = 0; alm_tm->tm_sec = 0; // 秒强制归零 } // ... } 双模式选择流程图: 📷 5.9 CLKOUT 时钟提供者 HYM8563 的 CLKOUT 引脚可以输出 32768/1024/32/1 Hz 的方波,驱动通过 Common Clock Framework 注册为时钟提供者: #ifdef CONFIG_COMMON_CLK static int clkout_rates[] = { 32768, // FD[1:0] = 00 1024, // FD[1:0] = 01 32, // FD[1:0] = 10 1, // FD[1:0] = 11 }; static int hym8563_clkout_control(struct clk_hw *hw, bool enable) { // 读 CLKOUT 寄存器 → 设置/清除 OE 位 → 写回 int ret = i2c_smbus_read_byte_data(client, HYM8563_CLKOUT); if (enable) ret |= HYM8563_CLKOUT_ENABLE; else ret &= ~HYM8563_CLKOUT_ENABLE; return i2c_smbus_write_byte_data(client, HYM8563_CLKOUT, ret); } // 驱动标记为 CLK_IS_CRITICAL — 防止系统关闭 CLKOUT // 某些 SoC 依赖此时钟源,关闭会导致系统问题 init.flags = CLK_IS_CRITICAL; #endif 5.10 I2C 驱动注册 // 设备树匹配表 — 与 dts 中的 compatible 关联 static const struct of_device_id hym8563_dt_idtable[] = { { .compatible = "haoyu,hym8563" }, {}, }; MODULE_DEVICE_TABLE(of, hym8563_dt_idtable); // I2C 设备 ID 表(用于非设备树平台) static const struct i2c_device_id hym8563_id[] = { { "hym8563", 0 }, {}, }; MODULE_DEVICE_TABLE(i2c, hym8563_id); // I2C 驱动结构体 static struct i2c_driver hym8563_driver = { .driver = { .name = "hym8563", .of_match_table = hym8563_dt_idtable, }, .probe = hym8563_probe, .id_table = hym8563_id, }; module_i2c_driver(hym8563_driver); MODULE_DESCRIPTION("Haoyu HYM8563 RTC driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Haoyu Microelectronics"); 本文完整覆盖了I2C协议原理、HYM8563硬件设计、设备树配置及驱动源码核心逻辑,是嵌入式开发者学习I2C驱动开发的实用参考。基于Purple Pi OH2开发板的实战,所有代码和配置可直接落地调试。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档