大家好,我是麦鸽,在单片机开发中,片上Flash存储空间往往捉襟见肘。无论是传感器日志、固件升级包,还是配置参数,数据量的增长常常超出硬件资源的承载能力。
直接存储原始数据不仅占用空间,还可能影响系统响应速度。此时,无损压缩算法成为解决问题的关键——通过压缩数据再存储,可显著节省空间。
而在众多压缩方案中,基于LZSS算法的开源库heatshrink凭借其轻量化、低内存占用的特性,已经有1.4K的star了。
项目首页
项目地址:github.com/atomicobject/heatshrink
2 什么是LZSS算法?
LZSS(Lempel-Ziv-Storer-Szymanski)是LZ77算法的改进版本,其核心思想是通过滑动窗口技术实现重复字符串的高效编码。
在LZSS算法的数据编码里面有一个重要概念,就是:数据分组。
一个字节由8位组成,因此可以用一个字节来标记后面的至少8字节是否存在压缩编码,而不用x00x00的前缀来区分是否被压缩,从而节省了大量的x00x00前缀空间开销。
数据分组标记方式:
Data Bits
由此看见,这种数据分组的方式,最坏的情况下,只会每8个字节增加一个字节的额外空间开销,比起每个字节另外需要2个字节的空间开销而言,效率大幅提升。篇幅有限,这里只做简单介绍
3 heatshrink压缩库
heatshrink是基于LZSS算法优化的开源库,专为资源受限的单片机环境设计。其核心优势体现在以下几个方面:
1. 极低的内存占用- 运行时内存需求:仅需50-300字节的RAM,适用于RAM仅KB级的单片机(如STM32F0系列)。
- Flash占用:代码体积最小可压缩至1KB(AVR平台测试数据),几乎不增加固件体积。
- 配置灵活性:通过调整窗口大小(window_sz2)和前瞻缓冲区大小(lookahead_sz2),开发者可平衡压缩率与内存消耗。例如,设置window_sz2=10(窗口1024字节)和lookahead_sz2=4(前瞻16字节)是常见配置。
- 流式处理:支持分块压缩/解压,无需一次性加载全部数据,适合实时数据流场景。
- 状态机设计:通过heatshrink_encoder和heatshrink_decoder状态机管理压缩流程,减少CPU占用。
- 跨平台支持:纯C语言实现,兼容FreeRTOS、裸机系统及各类IDE(如Keil、IAR)。
- 简洁API:提供初始化、数据输入(sink)、处理(poll)和结束(finish)四类函数,集成仅需数行代码。
- 无动态内存分配:通过预编译选项HEATSHRINK_DYNAMIC_ALLOC=0,可完全避免动态内存申请,增强系统稳定性。
4 适用的场景传感器数据压缩存储
在环境监测设备中,传感器每小时产生1KB的温湿度数据。使用heatshrink压缩后,数据体积平均减少40%
OTA固件升级通过压缩固件文件,可减少无线传输的数据量。以STM32F4为例,压缩后的固件传输时间缩短30%,且解压过程仅需数毫秒。
配置参数管理将JSON或二进制格式的配置参数压缩存储,既节省空间,又能在读取时快速解压,避免解析延迟。
5 使用指南步骤1:获取代码可以通过git直接拉取代码,或者 公众号后台 回复【LZSS】
git clone https://github.com/atomicobject/heatshrink.git步骤2:配置
# 将heatshrink_encoder.c、heatshrink_decoder.c加入工程
在heatshrink_config.h中设置:
#define HEATSHRINK_DYNAMIC_ALLOC 0 // 禁用动态内存步骤3:示例
#define HEATSHRINK_WINDOW_BITS 10 // 窗口大小1024字节
#define HEATSHRINK_LOOKAHEAD_BITS 4 // 前瞻缓冲区16字节
// 压缩数据6 总结
heatshrink_encoder *enc = heatshrink_encoder_alloc();
uint8_t input[] = "原始数据";
uint8_t output[128];
size_t input_size = sizeof(input);
size_t output_size = 0;
// 分块处理
while (input_size > 0) {
heatshrink_encoder_sink(enc, input, input_size, &input_consumed);
heatshrink_encoder_poll(enc, output, sizeof(output), &output_byte_count);
// 写入Flash或发送数据
input += input_consumed;
input_size -= input_consumed;
}
heatshrink轻量、高效,无论是Flash空间优化,对于资源紧张但需要数据完整性的场景,都是很好的选择。通过合理配置参数,可最大化发挥其性能,为资源紧张的嵌入式系统提供更好的存储能力。