首页/新闻资讯/正文详情

Audio学习9(AudioFlinger/HAL)

发布时间:2026/11/4 23:04:10 来源:云帆数科 栏目:资讯中心
Audio学习9(AudioFlinger/HAL)
1 环境这次主要是看看audio在安卓平台的实现用是瑞芯微RK3568开发板。本来是想还是用之前的WM8960模块但是很无语发现它板子上的I2S接口并没有引出来。引出的口只有I2CSPI还有UART。和之前用的WM8960比较一下参数RK809-5WM8960芯片定位PMIC Audio Codec独立 Audio CodecADC24-bit 立体声24-bit 立体声DAC24-bit 立体声24-bit 立体声最高采样率192kHz48kHzI2S支持支持PLL内置内置麦克风输入单端/差分多路输入支持伪差分MICBIAS支持麦克风输入具体偏置配置看电路集成低噪声 MICBIASALC支持支持Noise Gate支持支持耳机功放Class-ABReal GroundClass-AB 耳机驱动扬声器功放Class-D最高约1.3W双声道 Class-D每声道1W8Ω、5V控制接口I2CI2C封装QFN687×7mmQFN5×5mm看来功能基本上都差不多RK809甚至采样率还更好。不过WM8960 是专门设计的音频 Codec在模拟输入、音频路由、增益控制和音频应用灵活性方面可能更好点。算了将就平台本来的audio去看吧不折腾了。2 整体架构关于安卓的整体音频架构之前写过一篇Android音频系统_android uac-CSDN博客不过之前没有实际用版本验证。下面这个图是流传很广的安卓音频架构的图。不过用AI跑了一下这个图估计已经是上古时代的了。整体应该还是有不少的变化。其实新的架构如下App (Java/Native)-AudioFlinger (系统服务audioserver)-Binder IPC-android.hardware.audio.service(供应商 HAL 进程)-ALSA 驱动 (/dev/snd/*)-硬件音频 Codec / DAC / 喇叭改动是原图这块板的实际情况AudioFlinger、AudioPolicyService 放在Media Server中已拆分到audioserver板上mediaserver仍存在但不再包办这些音频服务HAL 画成简单的一层调用板上有独立的android.hardware.audio.service进程对外提供HIDL 7.0接口内核写成 ALSAOSSCustom Driver本板模拟音频走ALSAASoC包含 I2S 控制器驱动、RK809 Codec 驱动及声卡连接配置框中的源码路径有些已经变化例如 AudioTrack、AudioRecord 等客户端代码主要在frameworks/av/media/libaudioclient新的核心就是两个AudioServer和android.hardware.audio.service。一个是上层服务一个是HAL。3 底层3.1 驱动这次还是用板子实际来看吧。先用AI把这个板子上的音频链路跑了一遍。目前在电路上实际接了一个喇叭一个麦克风一个耳机插座。RK3568 与 RK809之间的接口信号作用MCLK音频主时钟SCLKBCLK音频位时钟LRCK左右声道帧同步时钟RK3568 SDO0 → RK809 SDI播放数据RK809 SDO → RK3568 SDI0录音数据此外RK3568 通过 I²C0、地址 0x20 控制 RK809设置供电、音频通路、增益和静音等。I²C 负责配置I2S 负责传声音数据。目前在系统中已经有了三个底层声卡声卡编号声卡实际用途0rockchip,rk809-codec板载麦克风、耳机、喇叭支持录音和播放1rockchip,btI2S3 接蓝牙模块的 SCOPCM 语音链路2rockchip,hdmiHDMI 音频输出3.2 tinyalsaAndroid这边底层和一般Linux基本没太大区别。不过ALSA的界面是阉割了给了一个青春版tinyalsa很多功能混音、重采样、设备选择和音频路由等功能收到自己的上层去处理了。功能alsa-lib 可以提供的机制Android 通常由谁负责多个应用同时播放、混音dmix等插件AudioFlinger格式、采样率转换plug、rate 等插件音频框架及相应处理模块选择输出设备设备名、配置及插件机制AudioPolicyHAL读写 PCM、操作 MixerALSA 接口TinyALSATinyALSA常见命令工具全称 / 作用对标 amixer核心用途参数要点tinymixtiny mixer 控制amixer查看 / 设置 mixer 控件路由、增益、开关-D声卡号-a列出枚举全部值get看当前值直接带名字和值 设置tinyplaytiny player播放 wav放音测试验证播放通路-D声卡-pperiod-nbuffer只支持 wavtinycaptiny capturearecord录音采集验证录音通路-D-r采样率-c声道-b位深-pperiod-T时长 (秒)tinypcminfotiny pcm info—查看声卡 PCM 支持能力格式 / 采样率-D-p查 playback-c查 capture常用命令组合场景命令序列备注✅ 板载麦录音推荐模板tinymix Playback Path OFFtinymix Capture MIC Path MAIN MICtinycap /sdcard/main_mic.wav -T 8关闭播放通路避免回授啸叫录制 8 秒✅ 带麦耳机录音4 段耳机tinymix Playback Path HPtinymix Capture MIC Path HP MICtinycap /sdcard/hp_mic.wav -T 8耳机听 耳机麦收音✅ 喇叭外放播放tinymix Playback Path SPKtinyplay /sdcard/test.wav喇叭出声✅ 无麦耳机播放3 节耳机tinymix Playback Path HP_NO_MICtinyplay /sdcard/test.wav只有听没有麦克风✅ 带麦耳机播放4 段耳机tinymix Playback Path HPtinyplay /sdcard/test.wav耳机播放后续可以切 HP MIC 录音✅ 关闭全部音频通路tinymix Playback Path OFFtinymix Capture MIC Path MIC OFF调试收尾切断通路✅ 自定义参数录音模板tinymix Capture MIC Path MAIN MICtinycap /sdcard/rec.wav -D 0 -r 48000 -c 2 -b 16 -p 1024 -T 1048k、立体声、16bit、period1024 帧录 10s这些命令可以直接操作底层硬件但是需要root权限一般的app不能直接访问。需要上层接口。4 android.hardware.audio.serviceandroid.hardware.audio.service 是 Android 系统中负责音频硬件抽象层Audio HAL的核心服务进程。它是 Android 高层软件栈如 AudioFlinger、Java 音频 API与底层 Linux 内核音频驱动ALSA / SoC 声音驱动之间的“桥梁和翻译官”。作用是音频设备的控制与路由 管理扬声器Speaker、听筒Earpiece、麦克风、蓝牙耳机、USB 声卡等硬件的开关、音量调节、音频路径切换Routing。数据流管理Stream Management 负责创建和维护音频输入流IStreamIn录音和输出流IStreamOut播放。通过共享内存Shared Memory / FMQ 快速消息队列高效接收来自AudioFlinger的 PCM 音频数据包。对接底层 ALSA 驱动 HAL 进程内部最终会调用 Linux 标准的alsa-lib如snd_pcm_writei将 PCM 数据写入内核的声卡驱动缓冲区完成物理发声。工作HAL 实际要处理的内容选设备Android 要从耳机输出具体应该打开哪张声卡、哪个 PCM 设备配置音频流使用什么采样率、位深、声道数硬件是否支持配置缓冲区每次传多少帧、准备几块缓冲区兼顾延迟和稳定性打开硬件通路设置 Mixer打开 PCM处理打开失败的情况持续传输数据将上层送来的 PCM 写入声卡录音时反向读取必要的数据转换例如你这份 RK 实现中的部分重采样处理处理状态变化暂停后进入待机、恢复时重新打开切换输出时关闭或重建相应通路向上报告状态缓冲区大小、延迟、播放位置等让 Android 安排后续数据并维持音画同步4.1 Android定义代码位置在/data/rk3568/android12_sdk/hardware/interfaces/audio/common/all-versions/default/service/hardware/interfaces/应该所有的HAL接口定义都在这边。服务的定义service.cpp如下/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG audiohalservice #include string #include vector #include binder/ProcessState.h #include cutils/properties.h #include hidl/HidlTransportSupport.h #include hidl/LegacySupport.h #include hwbinder/ProcessState.h using namespace android::hardware; using android::OK; using InterfacesList std::vectorstd::string; /** Try to register the provided factories in the provided order. * If any registers successfully, do not register any other and return true. * If all fail, return false. */ template class Iter static bool registerPassthroughServiceImplementations(Iter first, Iter last) { for (; first ! last; first) { if (registerPassthroughServiceImplementation(*first) OK) { return true; } } return false; } int main(int /* argc */, char* /* argv */ []) { ::android::ProcessState::initWithDriver(/dev/vndbinder); // start a threadpool for vndbinder interactions ::android::ProcessState::self()-startThreadPool(); const int32_t defaultValue -1; int32_t value property_get_int32(persist.vendor.audio.service.hwbinder.size_kbyte, defaultValue); if (value ! defaultValue) { ALOGD(Configuring hwbinder with mmap size %d KBytes, value); ProcessState::initWithMmapSize(static_castsize_t(value) * 1024); } configureRpcThreadpool(16, true /*callerWillJoin*/); // Automatic formatting tries to compact the lines, making them less readable // clang-format off const std::vectorInterfacesList mandatoryInterfaces { { Audio Core API, android.hardware.audio7.0::IDevicesFactory, android.hardware.audio6.0::IDevicesFactory, android.hardware.audio5.0::IDevicesFactory, android.hardware.audio4.0::IDevicesFactory, }, { Audio Effect API, android.hardware.audio.effect7.0::IEffectsFactory, android.hardware.audio.effect6.0::IEffectsFactory, android.hardware.audio.effect5.0::IEffectsFactory, android.hardware.audio.effect4.0::IEffectsFactory, } }; const std::vectorInterfacesList optionalInterfaces { { Soundtrigger API, android.hardware.soundtrigger2.3::ISoundTriggerHw, android.hardware.soundtrigger2.2::ISoundTriggerHw, android.hardware.soundtrigger2.1::ISoundTriggerHw, android.hardware.soundtrigger2.0::ISoundTriggerHw, }, { Bluetooth Audio API, android.hardware.bluetooth.audio2.1::IBluetoothAudioProvidersFactory, android.hardware.bluetooth.audio2.0::IBluetoothAudioProvidersFactory, }, // remove the old HIDL when Bluetooth Audio Hal V2 has offloading supported { Bluetooth Audio Offload API, android.hardware.bluetooth.a2dp1.0::IBluetoothAudioOffload } }; // clang-format on for (const auto listIter : mandatoryInterfaces) { auto iter listIter.begin(); const std::string interfaceFamilyName *iter; LOG_ALWAYS_FATAL_IF(!registerPassthroughServiceImplementations(iter, listIter.end()), Could not register %s, interfaceFamilyName.c_str()); } for (const auto listIter : optionalInterfaces) { auto iter listIter.begin(); const std::string interfaceFamilyName *iter; ALOGW_IF(!registerPassthroughServiceImplementations(iter, listIter.end()), Could not register %s, interfaceFamilyName.c_str()); } joinRpcThreadpool(); }服务启动配置android.hardware.audio.service.rcservice vendor.audio-hal /vendor/bin/hw/android.hardware.audio.service class hal user audioserver # media gid needed for /dev/fm (radio) and for /data/misc/media (tee) group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct wakelock context_hub capabilities BLOCK_SUSPEND ioprio rt 4 task_profiles ProcessCapacityHigh HighPerformance onrestart restart audioserver当前这块板向 Android 音频框架提供的是 HIDL 7.0主要接口如下接口主要职责代表方法IDevicesFactory服务入口打开音频设备openDevice()、openPrimaryDevice()IDevice设备级控制、创建录放音流及连接通路openOutputStream()、openInputStream()、setMicMute()、createAudioPatch()、setConnectedState()IPrimaryDevice继承IDevice增加主音频设备、通话及蓝牙相关控制setMode()、setVoiceVolume()、setBtScoWidebandEnabled()IStream输入、输出流共用的配置和生命周期接口getAudioProperties()、setAudioProperties()、standby()、close()IStreamOut播放流、输出延迟、播放进度及暂停等控制prepareForWriting()、getLatency()、getPresentationPosition()、pause()、drain()IStreamIn录音流、采集进度及麦克风信息prepareForReading()、getCapturePosition()、getActiveMicrophones()IStreamOutCallback播放流异步通知onWriteReady()、onDrainReady()、onError()IStreamOutEventCallback输出流事件通知onCodecFormatChanged()IEffectsFactory枚举、查询和创建音效实例getAllDescriptors()、getDescriptor()、createEffect()IEffect配置和运行具体音效setConfig()、enable()、disable()、setParameter()、prepareForProcessing()4.2 RK适配所有的适配代码在hardware/rockchip/音频代码在主要的工作是/data/rk3568/android12_sdk/hardware/rockchip/audio/tinyalsa_hal/├── audio_hw.c 声卡识别、HDMI/蓝牙/采集特殊处理├── alsa_route.c 应用通路配置└── codec_config/ 不同 Codec 的控件配置表5 AudioServeraudioserver是 Android 音频的集中管理进程主要负责音频流、混音、设备路由和硬件访问。它里面最核心的是 AudioFlinger 和 AudioPolicyService。整体功能上和才写过的Linux的PipeWire差不多。5.1 功能和实现功能如下功能主要负责者具体作用创建播放、录音通道AudioFlinger为 App 的 AudioTrackAudioRecord 创建服务端音轨和录音通道多路混音AudioFlinger将音乐、通知、导航等多个音轨混合输出音量、静音及必要的格式转换AudioFlinger应用各音轨音量按输出要求进行必要的重采样、声道等处理音效处理AudioFlinger 及音效实现组织音效链例如均衡器、录音预处理实际支持取决于设备选择设备和通路AudioPolicyServiceAudioPolicyManager决定使用耳机、喇叭、蓝牙或 HDMI以及使用哪个输入输出流协调并发使用音频策略AudioFlinger根据策略处理多个应用、录放音及特殊音频模式的资源使用管理流的运行状态AudioFlinger启动、待机、关闭和资源回收管理播放采集线程与缓冲区访问 Audio HAL经libaudiohal打开硬件音频流、读写数据、设置参数、查询延迟和播放位置理论上其实app可以直接访问HAL。但 谷歌把它集中到audioserver是为了让多个应用安全、有序地共享音频硬件。正常第三方 App 也没有直接访问音频 HAL 的权限。场景如果各 App 直接操作 HALaudioserver提供的协调音乐和导航同时发声争用硬件流或各自重复实现混音AudioFlinger 统一混音不同格式、采样率的声音每个 App 自己匹配硬件要求统一处理必要的转换耳机插入或拔出多个 App 各自切换容易冲突根据音频策略协调路由一个 App 卡住或退出可能留下占用的资源统一管理和回收音频流通话、录音、媒体同时工作各 App 难以协调全局状态配合系统策略管理并发和权限代码在/frameworks/av/media/audioserver/具体实现在其它地方# AudioFlinger音频流、混音、录放音线程frameworks/av/services/audioflinger/AudioFlinger.cpp# 音频策略服务对外提供策略接口frameworks/av/services/audiopolicy/service/AudioPolicyService.cpp# 默认策略实现设备选择、路由等决策frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp一般情况下audioserver使用AOSP原生的即可不用怎么修改。5.2 App调用使用AudioTrack这套库就可以直接调用audioserver。用的是JNI/Binder。例子import android.media.AudioAttributes; import android.media.AudioFormat; import android.media.AudioTrack; private void playTone() { new Thread(() - { int sampleRate 48000; short[] pcm new short[sampleRate]; // 单声道1 秒 for (int i 0; i pcm.length; i) { pcm[i] (short) ( Math.sin(2 * Math.PI * 440 * i / sampleRate) * 2000 ); } AudioTrack track new AudioTrack.Builder() .setAudioAttributes(new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_MEDIA) .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .build()) .setAudioFormat(new AudioFormat.Builder() .setSampleRate(sampleRate) .setEncoding(AudioFormat.ENCODING_PCM_16BIT) .setChannelMask(AudioFormat.CHANNEL_OUT_MONO) .build()) .setTransferMode(AudioTrack.MODE_STATIC) .setBufferSizeInBytes(pcm.length * 2) .build(); try { track.write(pcm, 0, pcm.length); track.play(); while (track.getPlaybackHeadPosition() pcm.length) { Thread.sleep(10); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally { track.release(); } }).start(); }

相关推荐

企业智能体搭建攻略:从0到1实战指南,小白也能收藏学!
企业智能体搭建攻略:从0到1实战指南,小白也能收藏学!

本文以攻略形式,系统解析企业智能体的总体架构。首先定义企业智能体概念,区别于传统聊天机器人;接着详解四层总体架构(交互、认知、决策、执行层及数据知识与治理安全两条轨道);分析能力成熟度四级演进&… · 2026/11/4 23:03:08

2026年计算机小白如何抓住AI风口,避开断掉的阶梯?
2026年计算机小白如何抓住AI风口,避开断掉的阶梯?

文章分析了AI技术对程序员行业的影响,指出初级程序员岗位因AI辅助编程而需求下降,但智能体/Agent开发、具身智能等领域需求激增。建议计算机小白应关注AI落地应用开发,注重实践项目,并根据自身情况选择合适的职业方向,… · 2026/11/4 23:03:08

小白程序员必看:从入门到精通大模型Agent的进阶之路
小白程序员必看:从入门到精通大模型Agent的进阶之路

本文指出,许多学习Agent的人容易在将Demo投入生产环境时遇到困难。多数教程仅涉及API调用,而忽略了工程化阶段的挑战,如状态管理、持久化和可观测性。文章建议通过“手搓”Agent框架来加深理解,并强调掌握底层架构的重要性。文章还… · 2026/11/4 23:03:08

Opus 5.5与GPT-6 Astra/Sol同夜对决:大模型选型与API接入实战解析
Opus 5.5与GPT-6 Astra/Sol同夜对决:大模型选型与API接入实战解析

凌晨两点,我端着咖啡同时刷着两边的最新动态,一边是Anthropic的Opus 5.5性能数据,一边是OpenAI的GPT-6系列悄悄挂上了API列表。同夜上新这种操作,放以前还能说是巧合,放到今天我只能理解为正面交锋。这轮发布里最有意思… · 2026/11/4 23:47:59

Oracle 19c RAC on Linux安装手册:OS基线、SCAN解析与ASM绑盘
Oracle 19c RAC on Linux安装手册:OS基线、SCAN解析与ASM绑盘

简介:《Oracle 19c RAC on Linux 7.6 安装手册》面向需要在 Red Hat Enterprise Linux 7.6 上搭建 19c RAC 的数据库工程师与运维人员,重点解决 GNS 配置 SCAN、Flex ASM 使用以及集群模式选型三类实际问题,适合具备一定 Linux 与 Oracle 基础… · 2026/11/4 23:47:59

HarmonyOS 7系统级AI:从硬件抽象层到用户感知的全栈实现
HarmonyOS 7系统级AI:从硬件抽象层到用户感知的全栈实现

1. 这不是“加个AI App”,而是手机操作系统级的基因重组HarmonyOS 7把AI做进系统底层,这事听起来像营销话术,但实际拆开看,它根本不是在桌面上多装一个“小艺AI助手”App那么简单。我去年参与过两个国产OS的AI模块适配项目&#x… · 2026/11/4 23:47:59

Oracle 19c函数语义字典:NULL处理、隐式转换与索引失效避坑
Oracle 19c函数语义字典:NULL处理、隐式转换与索引失效避坑

简介:面向Oracle数据库开发者与DBA的官方《SQL Language Reference》19c版参考文档,集中解决日常SQL编写中函数查阅、语法确认与版本差异核对的问题,适合已有一定SQL基础、需要随手查证的中高级使用者。压缩包内仅有1个PDF文件,约… · 2026/11/4 23:47:59

物联网移动终端轨迹异常检测:双层聚类DCTOD复现与工程避坑
物联网移动终端轨迹异常检测:双层聚类DCTOD复现与工程避坑

简介:这份资源是李健等人在《计算机应用研究》网络首发的论文PDF,面向物联网、移动计算与轨迹数据挖掘方向的研究生、算法工程师与安全分析人员,聚焦移动终端轨迹数据量大且分布不均时异常检测效率偏低的难题。论文提出双层聚类的用户轨迹异常… · 2026/11/4 23:47:59

ZCode开源拆解:AI编程助手98.6%缓存命中率如何实现?
ZCode开源拆解:AI编程助手98.6%缓存命中率如何实现?

ZCode 开源了。刚看到这个消息,我第一反应不是去追功能对比,而是直接翻它的源码,把缓存相关的模块从头到尾看了一遍。原因很简单:之前 ZCode 对外宣称 98.6% 缓存命中率,这个数字放在一般的 Web 系统里不算稀奇&#x… · 2026/11/4 23:45:50

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 3:16:49

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 6:59:29

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 7:02:38

AI辅助技术栈评估:提升研发决策效率60%
AI辅助技术栈评估:提升研发决策效率60%

1. 项目背景与核心价值技术决策一直是研发团队面临的重大挑战。随着技术生态的快速演进,技术栈的选择、维护和迭代变得愈发复杂。我们团队在过去两年里,先后经历了三次重大技术栈迁移,每次都需要投入大量人力进行技术评估和风险分析。直到去年… · 2026/11/4 0:00:17

从生成Token到直接决策:Jev如何重塑AI Agent工程实践
从生成Token到直接决策:Jev如何重塑AI Agent工程实践

1. 从"生成文字"到"拍板决策":Jev 到底在解决什么问题大多数人第一次接触大模型,脑子里建立的模型是"输入问题、输出文字"。你问它今天天气怎么样,它给你一段描述;你让它写个周报,它给你… · 2026/11/4 0:00:17

32G统一内存跑大模型:内存账、TPS实测与端云分流
32G统一内存跑大模型:内存账、TPS实测与端云分流

想在一台 32G 统一内存的小主机上把大模型跑成"日常可用",这件事我前后折腾了小半年。标题里说的这台 Mac mini M6,是我们这次讨论的目标平台,具体到手规格以实物为准;但下面这套推算方法和实测思路,对任何统… · 2026/11/4 0:00:17

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 3:16:49

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 6:59:29

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 7:02:38

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码