当前位置: 首页 > article >正文

手把手教你为嵌入式设备编写一个简单的电池驱动(基于Linux Power Supply框架)

手把手教你为嵌入式设备编写一个简单的电池驱动基于Linux Power Supply框架当你拿到一款新的嵌入式设备尤其是带有电池的便携式产品时如何快速为其开发一个可靠的电池状态监控驱动Linux内核提供的Power Supply子系统正是为此而生。不同于传统的字符设备或块设备驱动电源管理驱动有其独特的架构和设计哲学。1. 开发环境准备与基础概念在开始编写驱动之前我们需要先搭建好开发环境并理解几个核心概念。嵌入式Linux驱动开发通常需要目标设备的交叉编译工具链与设备内核版本匹配的内核源码树电池管理IC的数据手册基本的硬件调试工具如逻辑分析仪、万用表等Power Supply子系统的核心思想是将各种电源设备电池、USB充电器、AC适配器等抽象为统一的软件接口。每个电源设备在内核中表现为一个power_supply结构体实例通过sysfs向用户空间暴露标准化的属性接口。典型的电池驱动需要关注以下属性enum power_supply_property { POWER_SUPPLY_PROP_STATUS, // 充电状态 POWER_SUPPLY_PROP_CAPACITY, // 剩余电量百分比 POWER_SUPPLY_PROP_VOLTAGE_NOW, // 当前电压 POWER_SUPPLY_PROP_TEMP, // 电池温度 // ...其他属性根据硬件支持情况添加 };提示在开始编码前务必仔细阅读电池管理IC的数据手册确定其支持的通信接口I2C/SPI/SMBus等和寄存器映射。2. 驱动框架搭建与初始化创建一个基础的Power Supply驱动需要遵循Linux设备驱动的标准模式。我们以Platform Driver为例#include linux/power_supply.h #include linux/platform_device.h struct my_battery { struct power_supply *psy; struct i2c_client *client; // 其他设备特定数据 }; static int my_battery_probe(struct platform_device *pdev) { struct my_battery *battery; struct power_supply_config psy_cfg {}; // 分配设备结构体 battery devm_kzalloc(pdev-dev, sizeof(*battery), GFP_KERNEL); if (!battery) return -ENOMEM; // 初始化power_supply描述 battery-psy_desc.name battery; battery-psy_desc.type POWER_SUPPLY_TYPE_BATTERY; battery-psy_desc.properties my_battery_props; battery-psy_desc.num_properties ARRAY_SIZE(my_battery_props); battery-psy_desc.get_property my_battery_get_property; // 注册power_supply设备 psy_cfg.drv_data battery; battery-psy devm_power_supply_register(pdev-dev, battery-psy_desc, psy_cfg); if (IS_ERR(battery-psy)) return PTR_ERR(battery-psy); // 初始化硬件接口如I2C battery-client i2c_get_client_device(...); platform_set_drvdata(pdev, battery); return 0; } static const struct of_device_id my_battery_of_match[] { { .compatible vendor,battery-ic }, {}, }; MODULE_DEVICE_TABLE(of, my_battery_of_match); static struct platform_driver my_battery_driver { .driver { .name my-battery, .of_match_table my_battery_of_match, }, .probe my_battery_probe, }; module_platform_driver(my_battery_driver);关键点解析power_supply_desc结构体定义了设备的基本属性和回调函数devm_power_supply_register是资源管理版本的注册函数设备树兼容性字符串应与硬件匹配3. 属性获取与硬件交互驱动最核心的部分是实现属性获取回调函数这需要与硬件实际交互static enum power_supply_property my_battery_props[] { POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_PROP_PRESENT, POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_CURRENT_NOW, POWER_SUPPLY_PROP_CAPACITY, POWER_SUPPLY_PROP_TEMP, }; static int my_battery_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) { struct my_battery *battery power_supply_get_drvdata(psy); int ret 0; switch (psp) { case POWER_SUPPLY_PROP_STATUS: val-intval read_battery_status(battery); break; case POWER_SUPPLY_PROP_CAPACITY: val-intval read_battery_soc(battery); break; case POWER_SUPPLY_PROP_VOLTAGE_NOW: val-intval read_battery_voltage(battery); break; // 其他属性处理... default: ret -EINVAL; break; } return ret; }硬件访问示例假设使用I2C接口static int read_battery_voltage(struct my_battery *battery) { u8 reg VOLTAGE_REGISTER; u16 raw_value; // 读取电压寄存器 int ret i2c_smbus_read_word_data(battery-client, reg); if (ret 0) return ret; raw_value (u16)ret; // 根据数据手册转换原始值为微伏 return (raw_value * 1000) / 2; // 示例转换公式 }注意实际硬件寄存器地址和转换公式需参考具体芯片手册。某些高级电池管理IC可能还需要解锁寄存器访问等额外步骤。4. 状态监控与事件通知电池状态需要持续监控常见实现方式有两种中断驱动利用硬件提供的中断引脚如低电量警报轮询方式定时器定期检查状态变化中断方式实现示例static irqreturn_t battery_irq_handler(int irq, void *dev_id) { struct my_battery *battery dev_id; // 读取中断状态寄存器确定事件类型 u8 status i2c_smbus_read_byte_data(battery-client, STATUS_REG); if (status LOW_BATTERY_BIT) { pr_info(Low battery warning!\n); } // 通知power supply子系统状态变化 power_supply_changed(battery-psy); return IRQ_HANDLED; }轮询方式实现示例static void battery_monitor_work(struct work_struct *work) { struct my_battery *battery container_of(work, struct my_battery, monitor_work.work); // 检查状态变化 int old_soc battery-last_soc; int new_soc read_battery_soc(battery); if (old_soc ! new_soc) { battery-last_soc new_soc; power_supply_changed(battery-psy); } // 重新调度工作队列例如每30秒检查一次 schedule_delayed_work(battery-monitor_work, msecs_to_jiffies(30000)); }调试技巧通过sysfs查看驱动状态cat /sys/class/power_supply/battery/status cat /sys/class/power_supply/battery/capacity使用内核日志观察驱动行为dmesg | grep battery模拟状态变化测试驱动响应echo 50 /sys/class/power_supply/battery/capacity5. 高级功能与优化基础功能实现后可以考虑添加以下增强功能温度补偿static int get_compensated_capacity(struct my_battery *battery, int raw_soc) { int temp read_battery_temp(battery); // 简单的线性温度补偿 if (temp 10) return raw_soc - (10 - temp); else if (temp 45) return raw_soc - (temp - 45); return raw_soc; }充电曲线优化static int calculate_time_to_full(struct my_battery *battery) { int current_ma read_battery_current(battery); int capacity_mah battery-design_capacity; int remaining_mah (capacity_mah * battery-soc) / 100; if (current_ma 0) // 不在充电状态 return -1; return (capacity_mah - remaining_mah) * 3600 / current_ma; }电源路径管理适用于同时有电池和外部电源的设备static void handle_power_source_change(struct my_battery *battery) { if (is_external_power_connected()) { // 切换到外部电源供电 set_charge_current(MAX_CHARGE_CURRENT); } else { // 切换到电池供电 set_charge_current(0); limit_power_consumption(); } power_supply_changed(battery-psy); }常见问题排查表问题现象可能原因解决方案sysfs属性不显示属性未在驱动中定义检查power_supply_property数组电量显示不更新未调用power_supply_changed在状态变化时触发通知读取值不正确寄存器解析错误验证数据手册和转换公式驱动加载失败设备树配置错误检查compatible字符串和资源定义6. 设备树配置与内核集成要让驱动正常工作通常需要配置设备树battery: battery55 { compatible vendor,battery-ic; reg 0x55; interrupt-parent gpio; interrupts 17 IRQ_TYPE_EDGE_FALLING; monitored-battery main_battery; // 电池参数 voltage-min-design-microvolt 3000000; voltage-max-design-microvolt 4200000; energy-full-design-microwatt-hours 10000000; };内核配置选项CONFIG_POWER_SUPPLYy CONFIG_BATTERY_MY_VENDORy # 你的驱动配置项在驱动中解析设备树参数static int parse_dt(struct device *dev, struct my_battery *battery) { struct device_node *np dev-of_node; if (!np) return -ENODEV; of_property_read_u32(np, voltage-min-design-microvolt, battery-min_voltage); of_property_read_u32(np, voltage-max-design-microvolt, battery-max_voltage); // 其他参数解析... return 0; }7. 用户空间交互与系统集成完整的电池解决方案还需要用户空间配合uevent通知 当驱动调用power_supply_changed()时内核会发送uevent用户空间服务如upower可以监听并处理这些事件。典型的uevent内容POWER_SUPPLY_NAMEbattery POWER_SUPPLY_STATUSCharging POWER_SUPPLY_CAPACITY85 POWER_SUPPLY_VOLTAGE_NOW4200000Android电源管理集成 Android系统通过BatteryService监听这些属性变化更新系统状态并触发相关广播。低电量处理策略static void check_low_battery(struct my_battery *battery) { if (battery-soc LOW_BATTERY_THRESHOLD) { // 触发低电量通知 battery-psy_desc.set_property my_battery_set_property; power_supply_changed(battery-psy); // 可以在这里限制设备性能以延长续航 if (battery-soc CRITICAL_BATTERY_THRESHOLD) { initiate_graceful_shutdown(); } } }在实际项目中电池驱动的稳定性至关重要。建议添加充分的错误处理和恢复机制比如I2C通信失败时的重试逻辑以及无效寄存器值的过滤处理。

相关文章:

手把手教你为嵌入式设备编写一个简单的电池驱动(基于Linux Power Supply框架)

手把手教你为嵌入式设备编写一个简单的电池驱动(基于Linux Power Supply框架) 当你拿到一款新的嵌入式设备,尤其是带有电池的便携式产品时,如何快速为其开发一个可靠的电池状态监控驱动?Linux内核提供的Power Supply子…...

OpenUserJS.org 快速上手指南:3大挑战与实用解决方案

OpenUserJS.org 快速上手指南:3大挑战与实用解决方案 【免费下载链接】OpenUserJS.org The home of FOSS user scripts. 项目地址: https://gitcode.com/gh_mirrors/op/OpenUserJS.org OpenUserJS.org 是一个开源的用户脚本托管平台,专为开发者提…...

从零到一:在NVIDIA Omniverse中构建你的首个USD机器人场景

1. 认识NVIDIA Omniverse与USD格式 第一次打开NVIDIA Omniverse时,我被它的界面震撼到了——这哪里是开发工具,分明是未来世界的入口啊!作为一个在机器人仿真领域摸爬滚打多年的老手,我必须说Omniverse彻底改变了我们构建3D场景的…...

芯片后端设计入门:搞懂LEF和DEF文件,别再让工具报PHYS-*错误了

芯片后端设计实战:LEF与DEF文件深度解析与排错指南 第一次打开EDA工具准备大展拳脚时,屏幕上突然跳出的"PHYS-4"错误提示就像一盆冷水浇下来——这种体验恐怕每个芯片后端工程师都记忆犹新。LEF和DEF文件作为物理设计流程中的"交通规则&q…...

鸣潮玩家必看:ok-ww如何用3个步骤彻底解放你的游戏时间

鸣潮玩家必看:ok-ww如何用3个步骤彻底解放你的游戏时间 【免费下载链接】ok-wuthering-waves 鸣潮 后台自动战斗 自动刷声骸 一键日常 Automation for Wuthering Waves 项目地址: https://gitcode.com/GitHub_Trending/ok/ok-wuthering-waves 你是否曾经计算…...

今天不看SITS2026这页PPT,明年招标书里将彻底消失“传统机器人”术语

第一章:SITS2026演讲:AGI与机器人结合 2026奇点智能技术大会(https://ml-summit.org) 核心范式转变 传统机器人系统依赖预编程行为树与模块化感知-决策-执行链路,而SITS2026展示的AGI驱动架构将大语言模型(LLM)与具身…...

托利多BCOM条码秤核心功能配置与实战调优指南

1. 网络配置:让条码秤稳定联网的实战技巧 第一次接触托利多BCOM条码秤时,最让我头疼的就是网络配置问题。记得有次在超市部署新秤,明明按照手册操作却始终连不上系统,后来才发现是子网掩码设置出了问题。下面这些实战经验&#xf…...

AGI能否逆转2℃升温路径?——2026奇点大会现场演示“气候-能源-政策”三重耦合仿真系统,结果震惊IPCC代表

第一章:AGI能否逆转2℃升温路径?——2026奇点大会现场演示“气候-能源-政策”三重耦合仿真系统,结果震惊IPCC代表 2026奇点智能技术大会(https://ml-summit.org) 在新加坡滨海湾金沙会议中心主会场,DeepClimate AGI平台首次实时…...

从投稿到接收:一份给Applied Soft Computing作者的完整Latex排版与提交保姆级教程

从投稿到接收:一份给Applied Soft Computing作者的完整LaTeX排版与提交保姆级教程 当你完成了一篇高质量的研究论文,准备向Applied Soft Computing投稿时,如何确保你的稿件在技术格式上完全符合期刊要求?这篇文章将带你走过从下载…...

军事AI伦理失守代价全测算,单次越界决策可能导致$2.8B国际追责与《日内瓦公约》升级修订,你准备好了吗?

第一章:AGI与军事应用的伦理边界 2026奇点智能技术大会(https://ml-summit.org) 通用人工智能(AGI)在军事系统中的深度集成正以前所未有的速度推进,但其自主决策能力与杀伤链闭环化趋势,已实质性挑战传统战争法与人类…...

3步掌握FanControl:实现Windows风扇精准控制的完整指南

3步掌握FanControl:实现Windows风扇精准控制的完整指南 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com/GitHub_Trending/f…...

AGI不是功能叠加,而是认知重编译:2026奇点大会发布的《产品智能成熟度评估矩阵v3.1》深度拆解

第一章:AGI不是功能叠加,而是认知重编译:2026奇点大会发布的《产品智能成熟度评估矩阵v3.1》深度拆解 2026奇点智能技术大会(https://ml-summit.org) 《产品智能成熟度评估矩阵v3.1》(简称PIMM v3.1)彻底摒弃了以“能…...

从VMAF到GAN:手把手教你搭建视频质量评估体系(附FFmpeg实战代码)

从VMAF到GAN:构建下一代视频质量评估体系的工程实践 视频质量评估一直是算法工程师面临的核心挑战。当用户抱怨"视频模糊"时,我们究竟该如何量化这种主观体验?传统PSNR指标与肉眼感知的差距可能高达30%,而VMAF的引入虽然…...

AGI系统性偏差检测实战指南(工业级质量门禁清单V2.3)

第一章:AGI系统性偏差检测的理论基石与工业级质量门禁演进 2026奇点智能技术大会(https://ml-summit.org) AGI系统性偏差并非孤立的模型输出异常,而是多层级认知架构中语义表征、推理路径与价值对齐机制在训练数据分布偏移、目标函数隐式假设及部署环境…...

AGI驱动的智能电网落地实战:7个已验证的能源调度模型,2025Q4起全面商用倒计时

第一章:2026奇点智能技术大会:AGI与能源管理 2026奇点智能技术大会(https://ml-summit.org) AGI驱动的实时能源调度范式 本届大会首次公开展示了基于通用人工智能架构的分布式能源协同调度系统(AEGIS)。该系统不再依赖预设规则或…...

深入解析Vivado AXI Quad SPI IP核:从寄存器配置到实战时序

1. AXI Quad SPI IP核基础入门 第一次接触Vivado中的AXI Quad SPI IP核时,我也被它复杂的寄存器配置搞得一头雾水。这个IP核本质上是一个通过AXI总线控制的SPI控制器,可以灵活配置为标准SPI、双线SPI或四线SPI模式。在实际项目中,我发现它特别…...

你的J-Link-OB驱动装对了吗?从驱动安装到MDK5/Keil配置的完整避坑流程

J-Link-OB驱动安装与MDK5配置全流程避坑指南 最近在调试STM32项目时,发现不少开发者卡在了J-Link-OB驱动安装和MDK5配置这个看似简单却暗藏玄机的环节。我自己也曾经因为一个驱动签名问题折腾了大半天,今天就把这些实战经验整理成完整的避坑手册。 1. 驱…...

专业PCB逆向分析利器:OpenBoardView深度实战指南

专业PCB逆向分析利器:OpenBoardView深度实战指南 【免费下载链接】OpenBoardView View .brd files 项目地址: https://gitcode.com/gh_mirrors/op/OpenBoardView OpenBoardView是一款专业的开源PCB文件查看器,专注于.brd电路板文件的逆向分析和可…...

TLK2711芯片的8B/10B编码与Comma发送详解:从原理到FPGA代码实现(附Verilog示例)

TLK2711芯片的8B/10B编码与Comma发送全解析:从原理到FPGA实现 高速串行通信领域,TLK2711作为TI的明星产品,其稳定性和性能一直备受工程师关注。但真正让这颗芯片发挥极致性能的关键,往往隐藏在那些看似简单的协议细节中——比如8B…...

WebPlotDigitizer完全指南:如何从图表图片中快速提取数值数据

WebPlotDigitizer完全指南:如何从图表图片中快速提取数值数据 【免费下载链接】WebPlotDigitizer Computer vision assisted tool to extract numerical data from plot images. 项目地址: https://gitcode.com/gh_mirrors/we/WebPlotDigitizer 你是否曾经面…...

环晶芯获数千万元天使轮融资,无损回收载板技术打破先进封装成本困局

【导语:环晶芯科技近期完成数千万元天使轮融资,该公司是国内首家提出临时键合载板无损回收复用方案的企业,其技术可降低先进封装辅料成本,市场前景广阔。】先进封装载板回收难题待解在先进封装中,为加工超薄晶圆或器件…...

从《未来编年史》到现实:聊聊火星移民、世界政府与‘灵性科技’的百年预言靠谱吗?

火星移民、全球治理与意识科技:未来预言的现实可行性拆解 当SpaceX的星舰原型机在得克萨斯州的试验场轰然升空时,埃隆马斯克那句"让人类成为多行星物种"的宣言再次引发热议。与此同时,Neuralink的脑机接口技术已在人体试验中取得进…...

开源多波束声呐数据集:从原始回波到AI识别的关键一步

1. 为什么原始声呐数据对AI研究如此重要? 我第一次接触水下目标识别项目时,发现一个奇怪现象:明明声呐设备采集的是原始回波数据,但几乎所有开源数据集提供的都是经过厂商软件处理后的扇形图像。这就像厨师做菜时,只能…...

TShock 5.1.2 配置精解:从安全防护到游戏体验的全方位调校指南

1. TShock 5.1.2 配置文件基础认知 初次接触TShock服务器的朋友,面对config.json里密密麻麻的参数难免会感到头疼。其实这个配置文件就像乐高积木的说明书,掌握关键模块就能搭建出理想的游戏环境。我刚开始管理服务器时,花了整整三天才摸清门…...

FPGA显示进阶:不用专用芯片,如何用IO口模拟HDMI驱动640x480显示器?

FPGA显示进阶:用IO口模拟HDMI驱动640x480显示器的技术解析 在资源受限或高度定制化的FPGA应用场景中,如何突破专用芯片的限制,直接利用FPGA的通用IO实现高清视频输出?本文将深入探讨一种基于LVDS和TMDS协议的"软核"HDMI…...

【环境解析】Android Studio 终端切换:从 cmd 到 PowerShell 引发的 gradlew 执行差异与适配

1. 当Android Studio终端突然罢工:从cmd到PowerShell的转变 最近升级Android Studio后,突然发现Terminal里熟悉的gradlew命令报错了?这不是你的问题,而是Android Studio悄悄把默认终端从cmd换成了PowerShell。这个变化看似微小&am…...

别再按分钟收剪辑费了:内容再利用才是更值钱的服务

很多创作者不是缺内容,是同一份内容浪费得太厉害。 我最近连续看这类项目,结论越来越清楚:一条长内容如果只能发一次,内容生产成本就永远下不来。 我不建议你把自己做成纯后期,真正能涨价的是‘一份内容,多次分发’。 一、我为什么判断这事能收钱 很多人看项目,只看热…...

OpCore Simplify黑苹果教程:10分钟搞定OpenCore EFI配置的终极方案

OpCore Simplify黑苹果教程:10分钟搞定OpenCore EFI配置的终极方案 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify 还在为复杂的黑苹果配置…...

IDR逆向工程实战:如何高效分析Delphi编译程序的结构与逻辑

IDR逆向工程实战:如何高效分析Delphi编译程序的结构与逻辑 【免费下载链接】IDR Interactive Delphi Reconstructor 项目地址: https://gitcode.com/gh_mirrors/id/IDR 在Windows逆向工程领域,Delphi编译的程序因其特殊的运行时信息(R…...

【多源融合】Sage-Husa自适应滤波:从理论推导到工程实践

1. Sage-Husa自适应滤波:从数学公式到工程落地 第一次接触Sage-Husa滤波时,我也被满屏的矩阵运算搞得头晕眼花。但当我真正把它用在无人机导航系统里,才发现这套算法的精妙之处——它能让滤波器在传感器性能波动时保持稳定输出。想象一下你的…...