简介:本资源是一份面向嵌入式开发初学者与厨房秤类IoT设备开发者的技术实践包,聚焦TM7711高精度称重传感器在0.1克级测量场景下的噪声抑制问题。针对传感器原始数据跳变大、内码波动超5 LSB等典型现象,提供轻量、可移植的C语言滤波实现方案,适用于MCU资源受限的8/16位平台。压缩包仅含2个核心文件(1个.h头文件定义接口与参数,1个.c源文件实现滤波逻辑),总大小仅1KB,结构简洁,无依赖库,便于快速集成到Keil、IAR或GCC嵌入式工程中。已有5022人学习下载,读者可直接获取已验证的滤波算法框架,包含滑动平均或加权平均等适配称重特性的稳定策略、参数调优注释及内码→克重转换参考逻辑,显著降低高精度称重系统开发中的信号处理调试门槛。
1. 项目概述:从厨房秤到高精度信号处理的挑战
最近在整理一个老项目,翻出来一个关于TM7711高精度厨房秤滤波算法的C语言实现。这玩意儿乍一看就是个厨房秤,但里面涉及到的信号处理、模数转换和软件滤波,其实在很多嵌入式测量场景里都能用上,比如电子天平、压力传感器、甚至是某些DIY的精密测量设备。TM7711这个芯片,本质上是一个24位Σ-Δ模数转换器(ADC),专门为桥式传感器设计,像称重传感器、压力传感器这些。它的核心卖点就是高分辨率,能把传感器微弱的模拟信号变化,转换成数字世界我们能处理的数值。
但高分辨率不等于高精度。厨房秤放在那里,数值可能自己在那跳,一会儿多0.1克,一会儿少0.1克。这背后的原因很复杂:电源的纹波、环境的电磁干扰、传感器自身的微小形变和热噪声,甚至你用手轻轻碰一下桌子,都会在ADC的输出数据里引入噪声。我们的目标,就是写一套C语言算法,把这些乱七八糟的噪声尽可能地滤掉,让秤稳定、准确地显示我们放上去的重量,尤其是要稳住那最后一位小数(0.1克)的跳动。
所以,这个项目.zip文件里的核心,绝不仅仅是读个ADC数据然后显示那么简单。它是一场与噪声的“战争”,我们需要在有限的单片机资源(比如常见的51、STM32、或者低功耗的MSP430)里,用巧妙的数学方法和程序逻辑,从充满毛刺的原始数据流中,提取出真实、稳定的重量信号。这涉及到对TM7711驱动、多种数字滤波器设计、以及称重特定逻辑(如去皮、零点跟踪、稳定判断)的深度整合。下面,我就把这个项目的里里外外拆解一遍,把思路、代码和踩过的坑都摊开来聊聊。
2. 核心需求与方案选型背后的逻辑
2.1 为什么是TM7711?芯片选型考量
在做低成本、高精度的称重方案时,ADC的选择是关键。TM7711之所以常见于厨房秤、珠宝秤,有几个硬核理由。首先,它是24位Σ-Δ架构。传统的逐次逼近型ADC在达到高分辨率时,对基准电压和模拟电路的要求极其苛刻,成本飙升。而Σ-Δ ADC通过过采样和噪声整形,把量化噪声推到高频段,再用数字滤波器轻松滤掉,从而用相对简单的模拟前端实现了高分辨率。TM7711在10Hz输出速率下,有效位数能轻松超过20位,这意味着对于满量程2mV/V的典型称重传感器,它可以分辨出极其微小的电压变化,对应到重量上就是0.1克甚至更小的分度值。
其次,它内置了可编程增益放大器(PGA),增益从1到128可调。称重传感器输出信号很小,通常是毫伏级别。PGA可以在芯片内部先将信号放大,再送给ADC进行转换,这样就降低了对后续运放电路的要求,简化了外围设计,也减少了引入外部噪声的环节。最后,它的接口是简单的SPI或类似的三线制,单片机用几根GPIO就能驱动,非常适合资源有限的嵌入式系统。
注意:TM7711有两个通道(A和B),厨房秤通常只用通道A接称重传感器。通道B有时会用来接温度传感器做补偿,但在基础应用中往往悬空或接地,编程时需注意正确配置通道选择寄存器。
2.2 滤波算法目标:稳定、快速、准确
我们的滤波算法需要达成三个有时互相矛盾的目标:
- 稳定:最终显示的重量值不能乱跳。在空秤或稳定负载时,最后一位数字(比如0.1g)应该几乎不动,或者只在正负1个数字内缓慢变化。
- 快速:放上物品后,重量值应该快速收敛到真实值,不能等好几秒才稳定。这关系到用户体验。
- 准确:滤除噪声的同时,不能扭曲真实的重量变化。比如放上一个物品的瞬间,算法要能快速响应,而不是被当成噪声滤掉。
基于这些目标,单纯的一种滤波器往往难以胜任。比如,一个很深的移动平均滤波可以让显示非常稳定,但响应会变得极其迟钝,放上东西后数字像蜗牛一样慢慢爬升,用户体验很差。反之,如果只用一次采样值,响应最快,但显示会跳得让人眼花缭乱。因此,分层滤波或复合滤波策略是必然选择。我们需要将“抑噪”和“保真”分阶段处理。
2.3 方案选型:从基础到进阶的滤波策略
在嵌入式称重领域,经过实践检验的常见方案组合如下:
基础层:硬件与驱动层抑噪
- 均值滤波:这是第一道防线。连续读取N次TM7711的原始ADC值(比如N=10),然后取算术平均值。这能有效抑制高频随机噪声。N的大小需要在速度和稳定性间权衡。
- 中值滤波:在均值之前,可以先对一组采样值进行中值滤波,剔除偶然出现的、幅度巨大的脉冲干扰(比如电磁干扰毛刺),防止它们污染均值。
核心层:软件数字滤波器
- 一阶滞后滤波(低通滤波):这是最常用、最有效的软件滤波器之一,公式为
Y(n) = α * X(n) + (1-α) * Y(n-1)。其中X(n)是当前输入(经过基础层处理的值),Y(n)是当前输出,Y(n-1)是上一次输出,α是滤波系数(0<α<1)。这个滤波器的物理意义很好理解:当前输出是当前输入和上一次输出的加权平均。α越接近1,响应越快,但滤波效果弱;α越接近0,滤波效果越强,响应越慢。它计算量极小,非常适合单片机。 - 滑动平均滤波:维护一个固定长度的队列,每次新的数据进来,剔除最老的数据,计算队列中所有数据的平均值。它对周期性干扰有良好抑制,但会引入固定的延迟,且需要占用存储队列的内存。
- 一阶滞后滤波(低通滤波):这是最常用、最有效的软件滤波器之一,公式为
应用层:称重特定逻辑
- 动态阈值与稳定判断:这是让显示“不跳”的关键。算法需要实时计算最近一段时间内重量值的变化幅度(比如标准差或最大值与最小值之差)。当这个变化幅度低于一个预设的“稳定阈值”时,才认为秤已经稳定,此时显示的数字才可以被更新到最终显示值上。否则,显示一个“正在稳定”的中间值或保持原值。
- 零点跟踪:空秤的零点会随着温度、时间漂移。算法需要能在长时间空秤且稳定的情况下,缓慢地调整零点参考值,防止因为零点漂移导致空秤不归零。
- 去皮处理:去皮操作不仅仅是显示置零,在算法内部,它意味着将当前的稳定重量值作为一个偏移量保存下来,后续所有测量值都减去这个偏移量。滤波算法需要能正确处理去皮瞬间的数据跳变。
在本项目中,我最终采用的是一种“中值+均值+一阶滞后+动态稳定判断”的组合拳方案。下面我们进入具体的实现细节。
3. 核心模块实现与代码解析
3.1 TM7711驱动编写要点
驱动TM7711,本质上就是模拟它的通信时序来读写寄存器。它有两种模式:一种是简单的三线制(数据输入DIN, 数据输出DOUT, 时钟SCK),另一种是标准的SPI。这里以三线制为例,讲解关键点。
首先,是初始化和配置。上电后,TM7711需要一段时间稳定(通常几十毫秒)。然后,我们要通过写入配置寄存器来设置增益、通道和输出速率。例如,设置通道A、增益128、输出速率10Hz。
// 假设引脚定义 #define TM7711_SCK_GPIO_PIN ... #define TM7711_DOUT_GPIO_PIN ... #define TM7711_DIN_GPIO_PIN ... // 向TM7711写入一个字节(24位数据,分3次写入8位) static void TM7711_WriteByte(uint8_t data) { for(uint8_t i = 0; i < 8; i++) { if(data & 0x80) { GPIO_SetBits(TM7711_DIN_GPIO_PORT, TM7711_DIN_GPIO_PIN); } else { GPIO_ResetBits(TM7711_DIN_GPIO_PORT, TM7711_DIN_GPIO_PIN); } // 产生一个时钟上升沿,数据被锁存 GPIO_SetBits(TM7711_SCK_GPIO_PORT, TM7711_SCK_GPIO_PIN); Delay_us(1); // 短暂延时,满足时序要求 GPIO_ResetBits(TM7711_SCK_GPIO_PORT, TM7711_SCK_GPIO_PIN); Delay_us(1); data <<= 1; } } // 从TM7711读取24位数据 static int32_t TM7711_ReadData(void) { int32_t value = 0; uint8_t i; // 等待DOUT引脚变低,表示数据准备就绪 while(GPIO_ReadInputDataBit(TM7711_DOUT_GPIO_PORT, TM7711_DOUT_GPIO_PIN) == 1); for(i = 0; i < 24; i++) { GPIO_SetBits(TM7711_SCK_GPIO_PORT, TM7711_SCK_GPIO_PIN); Delay_us(1); value <<= 1; // 先左移,再读位 if(GPIO_ReadInputDataBit(TM7711_DOUT_GPIO_PORT, TM7711_DOUT_GPIO_PIN)) { value |= 0x01; } GPIO_ResetBits(TM7711_SCK_GPIO_PORT, TM7711_SCK_GPIO_PIN); Delay_us(1); } // 再额外产生一个时钟上升沿,为下一次转换启动做准备(根据数据手册) GPIO_SetBits(TM7711_SCK_GPIO_PORT, TM7711_SCK_GPIO_PIN); Delay_us(1); GPIO_ResetBits(TM7711_SCK_GPIO_PORT, TM7711_SCK_GPIO_PIN); Delay_us(1); // TM7711输出的是24位有符号补码,需要扩展到32位 if(value & 0x00800000) { // 检查第24位(符号位) value |= 0xFF000000; // 如果是负数,高8位补1 } return value; }实操心得:
Delay_us(1)的精度很重要。如果单片机主频不高,或者有中断干扰,这个延时可能不准确,导致通信失败。一个更稳健的做法是用循环空指令实现精确延时,或者直接使用硬件SPI接口(如果芯片支持)。另外,一定要仔细看数据手册里关于“数据就绪”(DOUT变低)和“启动下一次转换”的时序要求,不同厂家的7711芯片可能略有差异。
3.2 分层滤波算法的C语言实现
接下来是重头戏,滤波算法的具体实现。我们定义一个结构体来管理滤波器的状态和参数。
typedef struct { // 基础采样缓冲区(用于中值/均值滤波) int32_t raw_sample_buf[RAW_SAMPLE_NUM]; // RAW_SAMPLE_NUM 例如 10 uint8_t raw_sample_index; // 一阶滞后滤波参数与状态 int32_t filtered_value; // Y(n-1), 也是最终的滤波输出 float alpha; // 滤波系数,例如 0.2 // 稳定判断相关 int32_t stable_value; // 当前认定的稳定值(用于显示) int32_t last_stable_value; int32_t variance_threshold; // 稳定判断阈值,单位是ADC码值 uint32_t stable_counter; // 稳定计数器 } WeightFilter_t; // 初始化滤波器 void Filter_Init(WeightFilter_t *filter, float alpha, int32_t init_value, int32_t var_thresh) { memset(filter, 0, sizeof(WeightFilter_t)); for(int i=0; i<RAW_SAMPLE_NUM; i++) { filter->raw_sample_buf[i] = init_value; } filter->filtered_value = init_value; filter->stable_value = init_value; filter->alpha = alpha; filter->variance_threshold = var_thresh; } // 核心滤波与稳定判断函数 int32_t Filter_Process(WeightFilter_t *filter, int32_t new_raw_adc) { int32_t temp_value; int32_t base_value; // 1. 基础层:中值滤波(这里简化为去掉最大最小值后求平均,替代严格中值以节省排序时间) filter->raw_sample_buf[filter->raw_sample_index] = new_raw_adc; filter->raw_sample_index = (filter->raw_sample_index + 1) % RAW_SAMPLE_NUM; // 计算缓冲区中数据的简单均值(可优化为去掉头尾极值) int64_t sum = 0; for(int i=0; i<RAW_SAMPLE_NUM; i++) { sum += filter->raw_sample_buf[i]; } base_value = (int32_t)(sum / RAW_SAMPLE_NUM); // 2. 核心层:一阶滞后滤波 // Y(n) = α * X(n) + (1-α) * Y(n-1) // 为避免浮点运算,使用定点数技巧:alpha = 0.2 = 20 / 100 temp_value = (int32_t)(filter->alpha * base_value + (1.0 - filter->alpha) * filter->filtered_value); // 或者使用整数运算:temp_value = (base_value * 2 + filter->filtered_value * 8) / 10; (当alpha=0.2时) filter->filtered_value = temp_value; // 更新内部状态 // 3. 应用层:动态稳定判断 int32_t diff = abs(temp_value - filter->last_stable_value); if(diff < filter->variance_threshold) { filter->stable_counter++; if(filter->stable_counter >= STABLE_COUNT_LIMIT) { // 例如连续5次稳定 filter->stable_value = temp_value; // 更新显示用的稳定值 filter->stable_counter = STABLE_COUNT_LIMIT; // 防止溢出 } } else { // 变化超过阈值,认为不稳定,重置计数器 filter->stable_counter = 0; filter->last_stable_value = temp_value; // 更新为新的比较基准 } // 返回当前用于显示的值(稳定值或上一次的稳定值) return filter->stable_value; }这个Filter_Process函数需要被周期性调用,调用频率最好与TM7711的数据输出率匹配(如10Hz)。每次调用,它都会吸入一个新的原始ADC值,经过层层处理后,返回一个趋于稳定的重量ADC码值。
3.3 标定与重量转换
滤波后的ADC码值还不是重量。我们需要通过标定,建立ADC码值和实际重量的线性关系。通常采用两点标定法:记录空秤时的ADC码值(零点adc_zero)和放置一个已知标准砝码(如500克)时的ADC码值(adc_500g)。
// 标定参数 int32_t adc_zero = 0; // 零点ADC值 int32_t adc_cal = 0; // 标定点ADC值(如500克时) float weight_per_adc = 0.0; // 每个ADC码对应的重量(克/码) // 标定函数(在特定界面下调用) void Calibrate(WeightFilter_t *filter, float known_weight_grams) { // 1. 清空秤盘,长按“去皮”进入零点标定模式 // 等待稳定后,读取稳定的 filtered_value 作为 adc_zero adc_zero = filter->stable_value; // 2. 放上已知重量的砝码,按“确认” // 等待稳定后,读取稳定的 filtered_value 作为 adc_cal adc_cal = filter->stable_value; // 3. 计算系数 if(adc_cal != adc_zero) { weight_per_adc = known_weight_grams / (adc_cal - adc_zero); } } // 将滤波后的ADC值转换为重量(克) float ConvertToWeight(int32_t filtered_adc) { float weight = (filtered_adc - adc_zero) * weight_per_adc; // 可以在这里做四舍五入到0.1克的操作 weight = ((int)(weight * 10 + 0.5)) / 10.0; return weight; }注意事项:标定过程本身也需要在非常稳定的环境下进行。标定时使用的滤波稳定阈值可以设置得比日常使用更严格,以确保标定数据的准确性。
weight_per_adc这个系数最好保存在单片机的非易失性存储器(如Flash或EEPROM)中,下次上电直接读取。
4. 参数调优与性能平衡的艺术
算法框架搭好了,但里面的参数(RAW_SAMPLE_NUM,alpha,variance_threshold,STABLE_COUNT_LIMIT)直接决定了秤的“性格”。调参是个细致活,需要反复实测。
4.1 滤波系数α的选择:响应速度 vs 平滑度
alpha是一阶滞后滤波器的灵魂。它的取值需要在响应速度和平滑度之间做权衡。
- α较大(如0.5):系统对重量变化的响应非常迅速,放上东西后显示值“嗖”一下就上去了。但副作用是,在稳定状态下,显示值的最后一位数字可能还会有可见的、缓慢的波动。这适合需要快速读数的场合,但对极致稳定不友好。
- α较小(如0.05):滤波效果极强,稳定时显示数字几乎像钉死一样不动。但放上物品后,显示值会非常缓慢地逼近真实值,用户会觉得“这秤反应好慢”。
- 折中方案:在实际项目中,我常常采用“动态α”策略。当检测到重量发生剧烈变化(
diff很大)时,临时调高alpha(比如到0.4),让系统快速跟踪。当重量变化进入稳定阈值范围内时,再将alpha切换回一个较小的值(如0.1),实现高平滑度。这相当于一个非线性滤波器。
// 动态alpha的简单示例 float dynamic_alpha; int32_t diff = abs(new_raw_adc - filter->filtered_value); // 计算新数据与当前滤波值的差 if(diff > BIG_CHANGE_THRESHOLD) { dynamic_alpha = 0.4f; // 快速跟踪模式 } else if(diff > filter->variance_threshold) { dynamic_alpha = 0.2f; // 常规跟踪模式 } else { dynamic_alpha = 0.05f; // 高稳定模式 } // 使用 dynamic_alpha 进行一阶滞后滤波计算4.2 稳定阈值与计数器的设定
variance_threshold(稳定阈值)和STABLE_COUNT_LIMIT(稳定计数限制)共同决定了“何时显示才算稳定”。
- 阈值太小:系统过于“敏感”,很难达到稳定条件,导致显示值迟迟不更新,或者在不该更新的时候(仍有微小波动)更新,造成最后一位数字偶尔跳动。
- 阈值太大:系统过于“迟钝”,可能把一些真实的微小重量变化(比如缓慢放置物品)也误判为稳定,导致显示值提前“定格”,与实际重量有偏差。
- 计数器的作用:要求连续多次满足阈值条件才判定稳定,这提供了抗干扰的冗余度。比如,一个偶然的干扰毛刺导致一次
diff超限,但计数器会清零,不会立即更新稳定值,从而避免了显示跳动。
一个实用的调试方法是:让秤空载,运行一段时间,观察filtered_value波动的最大范围(峰值)。将variance_threshold设置为这个波动范围的2到3倍。STABLE_COUNT_LIMIT通常设置为3到10,数值越大,判定越严格,稳定显示越“迟钝”。
4.3 零点跟踪与防误触发
零点跟踪是为了应对传感器的热漂移和蠕变。但实现时必须非常小心,否则可能把用户缓慢放置的轻小物品也“跟踪”掉。
安全的零点跟踪逻辑:
- 只有在重量值长时间处于“空秤区间”内(比如绝对值小于10个ADC码值),且系统判定为稳定时,才允许进行零点跟踪。
- 跟踪速度必须非常缓慢。例如,每次采样周期只将零点
adc_zero向当前filtered_value调整非常小的一个步长(如1/100的差值),或者每分钟只调整一次。 - 一旦检测到重量明显超出“空秤区间”,立即停止零点跟踪,并锁定当前的零点值,直到重量再次长时间归零。
// 简易零点跟踪示例(需在主循环中慢速调用) void SlowZeroTracking(WeightFilter_t *filter) { static uint32_t zero_track_timer = 0; const uint32_t TRACK_INTERVAL_MS = 60000; // 每分钟跟踪一次 const int32_t ZERO_DEAD_ZONE = 10; // 空秤死区,单位ADC码 if(GetSystemTick() - zero_track_timer > TRACK_INTERVAL_MS) { zero_track_timer = GetSystemTick(); int32_t current_stable_adc = filter->stable_value; // 判断是否处于空秤且稳定状态 if(abs(current_stable_adc - adc_zero) < ZERO_DEAD_ZONE && filter->stable_counter >= STABLE_COUNT_LIMIT) { // 缓慢调整零点,每次调整1% adc_zero = adc_zero + (int32_t)((current_stable_adc - adc_zero) * 0.01); // 保存新的adc_zero到EEPROM(需要节拍操作) } } }5. 常见问题排查与调试技巧
在实际制作和调试过程中,你肯定会遇到各种问题。下面是一些典型问题及其排查思路。
5.1 问题一:显示值乱跳,完全不稳定
- 可能原因1:电源噪声。这是最常见的问题。TM7711对电源非常敏感。使用线性稳压电源(如LM1117-3.3)而不是开关电源,在芯片的电源引脚就近放置一个10μF的钽电容和一个0.1μF的陶瓷电容。
- 排查:用示波器观察TM7711的AVDD引脚(模拟电源),看纹波是否过大(应小于几毫伏)。如果没有示波器,可以尝试用电池供电,看是否改善。
- 可能原因2:传感器或连接问题。称重传感器的四根线(激励+、激励-、信号+、信号-)接触不良,或者传感器本身损坏。
- 排查:测量传感器桥路的阻值(通常每个桥臂350欧姆左右)。检查接线是否牢固。尝试轻轻敲击传感器,看ADC值是否有剧烈变化。
- 可能原因3:参考电压不稳。TM7711需要非常稳定的参考电压。如果使用芯片内部的参考源,要确保其稳定。如果使用外部参考,同样需要干净、低噪声的电源。
- 可能原因4:数字信号干扰。SCK和DOUT等数字信号线如果离传感器模拟信号线太近,可能耦合噪声。尽量分开走线,或使用屏蔽线。
5.2 问题二:响应速度太慢,放上东西后数字爬升慢
- 可能原因1:滤波过重。
alpha值太小,或者RAW_SAMPLE_NUM太大,STABLE_COUNT_LIMIT太大。 - 排查与解决:尝试逐步增大
alpha(如从0.05调到0.2),减少RAW_SAMPLE_NUM(如从10减到5)。考虑引入前面提到的“动态α”策略。 - 可能原因2:TM7711输出速率设置过低。TM7711的输出速率是可配置的(如10Hz, 40Hz, 640Hz)。速率越低,每次转换时间越长,数据更新自然慢。
- 排查:检查初始化代码中,配置寄存器是否将输出速率设为了较低的10Hz。在满足噪声要求的前提下,可以尝试提高到40Hz。注意,提高速率可能会增加噪声,需要重新调整滤波参数。
5.3 问题三:去皮后,空秤不回零,或有微小底数
- 可能原因1:零点跟踪过于激进或逻辑有误。可能在去皮操作后,零点跟踪逻辑立即开始工作,错误地跟踪了一个非零值。
- 排查:检查零点跟踪的触发条件。确保去皮操作后,立即将零点跟踪功能暂时禁用一段时间(比如10秒),或者将当前去皮后的状态设置为新的、临时的“零参考点”,零点跟踪基于这个新参考点进行,而不是原始的
adc_zero。 - 可能原因2:机械结构应力。去皮后,秤盘或传感器可能因为机械结构存在微小应力,导致ADC码值并非绝对的零点。
- 排查:这是物理限制。可以在软件中设置一个“零区范围”,当重量绝对值小于某个很小值时(比如对应0.5克),直接显示为0。这就是很多商用秤的“自动归零”功能。
5.4 问题四:标定后线性度不好,不同重量段误差大
- 可能原因1:传感器非线性。廉价的称重传感器在满量程的两端可能存在非线性。
- 解决:两点标定只能保证零点和标定点的准确。如果要求高,可以采用多点标定(如0g, 100g, 500g, 满量程),并采用查表法或线性插值法进行转换。对于厨房秤,两点标定通常足够。
- 可能原因2:标定过程不稳定。标定时,秤没有放稳,或者环境有振动、气流。
- 解决:标定必须在绝对稳定的台面上进行,避开风扇、空调出风口,等待显示值完全稳定后再进行确认操作。
5.5 调试技巧:利用串口打印数据曲线
最有效的调试手段之一,就是把关键数据通过串口发送到电脑,用串口绘图工具(如Serial Plotter, CoolTerm,或者自己写个Python脚本)画出来看。
你可以同时打印:
new_raw_adc(原始ADC值):观察噪声的原始形态。filtered_value(一阶滤波后):观察滤波器的平滑效果。stable_value(稳定值):观察稳定判断逻辑是否正确触发。diff(变化量):观察是否超过了设定的阈值。
通过图形,你可以直观地看到放上物品、取下物品、稳定、跳变等各个阶段,数据是如何变化的,从而精准地调整alpha、variance_threshold等参数。这比盲目修改代码、反复烧录测试要高效得多。
最后,分享一个我个人的体会:高精度滤波没有“银弹”参数。一套参数在一台秤上表现完美,换一个传感器、换一个电源、甚至换一个安装外壳,可能就需要重新微调。核心在于理解每个参数和模块对系统动态特性的影响(是影响响应速度,还是影响稳定精度),然后掌握基于数据观察的调试方法。这个TM7711的项目,本质上是一个经典的嵌入式信号处理案例,把这些思路吃透了,以后做压力测量、温度采集、声音信号处理等等,都会触类旁通。
本文还有配套的精品资源,点击获取