尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
STM32二维码显示:从取模到上屏的完整方案
简介基于STM32ZET6红牛开发板的二维码显示工程完整演示了借助qrencode开源库在LCD屏上直接生成并显示二维码的实现过程项目初衷是替代上位机传图方案解决通讯设备图片内容大、操作不灵活的问题。资源面向需要为嵌入式设备增加二维码输出能力的开发者尤其适合关注二维码生成库选型、LCD驱动移植的STM32用户。压缩包共120个文件包括45个头文件、42个C源文件、32个汇编文件和1个MDK工程文件其中头文件与C文件覆盖外设驱动及qrencode移植代码汇编文件为STM32启动文件工程由MDK4.72编译通过整体仅679KB已有2451人学习下载。透过该工程可掌握qrinput等二维码输入接口在嵌入式侧的适配方式理解qrencode库精简移植的完整思路。同时可参考GLCD屏驱动、定时器、串口等外设驱动的封装手法为自制二维码显示功能或后续扩展提供直接参考。1. STM32二维码显示:先把取模思路理清,再上屏STM32二维码显示这件事,难点从来不在“显示”本身,而是在于“二维码从哪来”。很多第一次做串口屏或OLED二维码项目的开发者,第一反应是拍照、抠图、把二维码塞进SD卡——这其实绕了远路。最实用的做法是:在PC端把二维码内容生成好,转成0/1点阵,再取模成C数组,最后通过SPI或I2C刷到屏上。这么做的好处是MCU只负责搬运像素,不参与编码计算,一块STM32F103C8T6就能跑得动。适合的场景包括设备绑定二维码、门禁动态凭证、物流分拣信息牌、临时授权码展示等。如果你正卡在“二维码显示出来扫不出”或者“不知道从哪里入手”,这篇就是给你拆解决方案的。2. 生成二维码点阵:选版本、定容错,用脚本把内容变成0/1矩阵2.1 先分清静态码和动态码:生成策略完全不同拿到需求第一件事,不是找屏幕驱动,而是问一句:二维码内容是固定的,还是运行时才能确定的?固定内容比如设备编号、Wi-Fi配置信息、产品追溯链接,这种二维码一辈子不变。策略上直接在PC端一次性生成点阵,存成C数组烧进Flash。优点是稳定、省内存、零实时计算量;缺点是内容一改就要重新取模、重新编译。动态内容比如带时间戳的授权码、每次开机都不一样的随机凭证,MCU端在运行时才拿到完整字符串。这种情况下才需要讨论“要不要在STM32上实时生成二维码”。实时生成意味着要在单片机上跑完整的QR编码算法:数据分组、纠错码计算、掩码图案、模块布置。这对Flash和RAM都有要求。STM32F103C8T6有64KB Flash和20KB RAM,生成一个版本3或版本4的二维码(29×29或33×33)勉强可以做到,但要把容错级别压到L或M,而且不能同时开大缓冲区。所以我的取舍原则是:能离线取模就离线取模,只有内容必须动态变化时,才考虑MCU端生成。如果你做的是Demo或者课程设计,强烈建议先用静态点阵方案把整条链路跑通,再考虑要不要移植实时生成库。上来就搞动态生成,很容易在掩码和纠错编码上卡住半个月。2.2 Python生成二维码矩阵与参数选型离线取模的第一步,是用Python生成二维码矩阵。下面这段脚本用qrcode图像库生成一个纯0/1矩阵,并且去掉边框干扰,方便后面直接取模。import qrcode from qrcode.constants import ERROR_CORRECT_M, ERROR_CORRECT_L def generate_qr_matrix(content, version4, box_size1, border4): qr qrcode.QRCode( versionversion, error_correctionERROR_CORRECT_M, box_sizebox_size, borderborder, ) qr.add_data(content) qr.make(fitFalse) # 不自动调整版本,严格使用指定的version matrix qr.get_matrix() # 返回的是list[list[bool]] return matrix if __name__ __main__: content STM32-QR-DEMO-2025-001 qr_matrix generate_qr_matrix(content, version4) # 去除边框后再导出 inner [row[4:-4] for row in qr_matrix[4:-4]] for row in inner: print(.join(# if p else . for p in row))这里有几个参数要展开讲一下。version4意思是二维码版本号,版本越高容纳的数据越多,矩阵尺寸越大。版本4的纯矩阵是33×33,加上4格的安静区(quiet zone)后实际是41×41。box_size1表示矩阵里每个模块在图像上占1个像素,因为我们只要逻辑矩阵,不需要真彩色图,所以设成1就够了。border4是QR标准要求的安静区宽度,取模时这个区域必须保留,否则扫码枪会识别失败。fitFalse强制使用指定版本,如果加了fitTrue,qrcode库会自动升级版本,导致你准备好的显存缓冲区不够用。错误纠正级别也要注意。ERROR_CORRECT_M表示约15%的码字可被恢复,这是屏幕显示场景比较均衡的选择。如果你打算把二维码印在曲面上,或者屏幕上可能贴膜、有反光,建议用ERROR_CORRECT_H(约30%恢复能力),但代价是同样内容可能要多占一个版本,点阵尺寸变大。矩阵得到之后,下一步就是把它变成C语言能直接用的数组。这一步的坑比你想的多,核心在于“按位打包的扫描顺序必须跟屏幕显存布局一致”,我们放到下一章专门拆。3. 点阵转C数组:按位打包、反色与缩放,决定屏幕能不能正常显示3.1 为什么必须按位打包:显存布局决定取模方向很多人把二维码点阵直接做成二维数组:uint8_t qr[33][33],一个像素占用一个字节。这在小屏上太奢侈了。SSD1306 OLED的分辨率通常是128×64,显存一共1024字节,每个字节控制8个垂直排列的像素(一页8行)。如果你一个像素用一个字节,1024字节只能存1024个点,连2行二维码都放不下。所以必须按位打包:每8个像素压进1个字节,使其占用量缩小到原来的1/8。但“按位打包”并不是简单的从左到右、从上到下数8个点塞一个字节。它跟屏幕驱动IC的扫描方式强相关。SSD1306这类OLED的显存布局是“页-列-位”结构:列地址从0到127,页地址从0到7,每一页覆盖8行像素,字节的最低位(bit0)对应页内的第0行,bit1对应第1行,依次类推。取模时如果按照“行首优先”的常规思路打包,把一行8个像素凑成一个字节,那么显示到OLED上时,那一整行会被竖着拆开,结果必然是花屏或者镜像错位。正确做法是:按列扫描,把每个像素所在的位置换算到对应页的那一位。具体来说,对于坐标(x, y),它在显存里的字节地址是x (y / 8) * 128,该字节的第y % 8位就是这个像素。所以取模脚本要模拟这种“页”布局来输出字节,而不是简单地按行截取。ILI9341这类TFT彩屏则是另一种思路:它自带GRAM,显存地址是连续的行扫描,每个像素用RGB565两个字节。它的取模方向通常按行从左到右、从上到下逐点连续排列,每点需要2字节。这种屏不存在“按页打包”的问题,但存在“整帧缓冲太大”的问题,后面第4章会讲到怎么破。3.2 转换脚本:支持反色、缩放与三种扫描顺序下面这段脚本把上一章生成的矩阵转成C数组,同时支持最近邻缩放、反色和SSD1306页布局输出。def matrix_to_ssd1306_bytes(matrix, invertFalse, scale1): # 先做最近邻缩放 if scale 1: h len(matrix) w len(matrix[0]) new_h, new_w h * scale, w * scale scaled [[0]*new_w for _ in range(new_h)] for y in range(new_h): for x in range(new_w): scaled[y][x] matrix[y // scale][x // scale] else: scaled matrix h len(scaled) w len(scaled[0]) pages (h 7) // 8 buf_size pages * w buf [0] * buf_size for y in range(h): for x in range(w): bit 1 if scaled[y][x] else 0 if invert: bit 0 if bit else 1 page_index y // 8 bit_offset y % 8 buf[x page_index * w] | (bit bit_offset) return buf逻辑说明:先按scale做最近邻放大,因为版本4的矩阵只有33×33,直接上屏太小,通常要放大2到3倍。放大后按SSD1306的规则遍历每个像素:page_index y // 8决定这个点落在哪一页,bit_offset y % 8决定落在该页字节的第几位。最终数组的排列是“先遍历所有页的第0列,再遍历第1列……”,和SSD1306驱动里常见的buffer[x page * 128]索引方式正好对应。invertTrue时把0和1互换。白色二维码(黑背景白码)在OLED上很常见,因为OLED全亮面积越小功耗越低,反色后还能避免整屏大面积点亮。scale建议控制在2到4之间。STM32F103做128×64的屏,版本4二维码放大3倍后是99×99,刚好放得下,而且周围有29像素的边距,扫码识别很轻松。如果你用版本5(37×37),放大3倍就是111×111,剩下17像素边距,也能用,但再大就容易扫不到了。脚本输出后,在C端要定义成const uint8_t qr_image[],直接编进程序。这里有个小技巧:不要手动复制数组,让Python直接生成一个.c文件,再include进来,避免复制的时候漏掉大括号或者把某个0xFF改成0xFO。生成完数组后,先打印一批十六进制值人工核对一遍,再烧到板子里。4. 在STM32上点亮二维码:SPI驱动与画布刷新4.1 SSD1306显存与页寻址:小屏最常用的方案拿到C数组后,剩下的事情就是把它写进屏幕显存。以最常见的0.96寸SSD1306 OLED为例,它有两种接口:4线SPI和I2C。SPI更快,刷新更稳定,建议优先选SPI。如果板子只预留了I2C引脚,也不是不能用,但刷整屏时明显感觉到从上到下滚动刷新,因为I2C速率上限一般在400kHz。SSD1306写入显存有几个关键命令:设置列地址低位0x00-0x0F,列地址高位0x10-0x1F,页地址0xB0-0xB7,然后连续发送显存数据。每次写完一页,页地址会自动加1;当写到第7页后又会回到第0页。这种自动换页行为是很多人翻车的点:如果你的数组长度不是恰好等于一页的字节数,写完一页后没有转到下一页,继续往下发就会覆盖回第0页,表现为画面重复显示上半部分内容。初始化序列里还有个容易忽略的细节:SSD1306上电默认显示关闭,需要发送0xAF打开显示;如果忘了开,屏幕永远全黑。另外,内部电荷泵要显式开启,命令是0x8D加0x14。这两个命令漏掉任何一个,结果都是白屏或者暗屏。4.2 写一个通用的二维码绘制函数下面这段代码展示了怎么把取模好的数组画到OLED的画布缓冲里,然后整体刷新。#define OLED_WIDTH 128 #define OLED_PAGES 8 static uint8_t oled_buf[OLED_WIDTH * OLED_PAGES] {0}; // 在画布上绘制二维码,支持指定起始坐标 void qr_draw(uint8_t *qr_data, uint16_t qr_w, uint16_t qr_h, uint16_t x_off, uint16_t y_off, uint8_t invert) { uint16_t x, y; for (y 0; y qr_h; y) { for (x 0; x qr_w; x) { uint16_t src_bit (y / 8) * qr_w x; uint8_t pixel (qr_data[src_bit] (y % 8)) 0x01; if (invert) pixel ^ 1; uint16_t screen_x x_off x; uint16_t screen_y y_off y; if (screen_x OLED_WIDTH || screen_y 64) continue; uint16_t buf_index screen_x (screen_y / 8) * OLED_WIDTH; if (pixel) { oled_buf[buf_index] | (1 (screen_y % 8)); } else { oled_buf[buf_index] ~(1 (screen_y % 8)); } } } } void oled_flush(void) { // 通过SPI发送0xB0页地址,再连续发送128字节数据 for (uint8_t page 0; page 8; page) { oled_cmd(0xB0 page); oled_cmd(0x00); oled_cmd(0x10); for (uint16_t col 0; col OLED_WIDTH; col) { oled_data(oled_buf[col page * OLED_WIDTH]); } } }这里要解释一下索引算法。qr_data的排列方式和第3章脚本输出保持一致:每个字节存的是垂直方向8个像素。所以读取第(y, x)像素时,先算出它所在字节索引(y / 8) * qr_w x,再取出y % 8位,得到该像素的0/1值。这比二维数组省内存,但需要你牢牢记住打包顺序。写入画布时,screen_x (screen_y / 8) * OLED_WIDTH是目标字节索引,位偏移是screen_y % 8。用|和是因为画布上可能已经有其他图形,比如标题文字或边框,不能直接整字节覆盖。x_off和y_off用于居中。二维码放在屏幕正中央时,偏移量这样算:x_off (128 - qr_w) / 2,y_off (64 - qr_h) / 2。注意qr_h必须是8的倍数,否则最后一页会出现半个像素的锯齿。版本4放大3倍后是99像素,不是8的倍数,我的习惯是把上边距设为(64 - 99) / 2 -17?负值会裁掉顶部。所以推荐把放大倍数选成能让边长凑成8的整倍数:比如版本4(33×33)放大3倍后99,可以在底部补白到104?这样高度104,页数13页,超过8页,不行。更实际的做法是:如果屏幕高只有64,版本4放大2倍是66×66,正好放得下。所以小尺寸OLED上,版本4放大2倍最多,版本3(29×29)放大2倍是58×58,居中后上下各有3像素边距,效果更舒适。如果要放大3倍,得用128×128的OLED或LCD。4.3 大屏LCD怎么处理:局部刷新而不是整帧缓冲换到ILI9341这类320×240的TFT彩屏,情况又不一样。它的显存不在MCU里,而是在屏幕驱动IC内部,MCU可以通过SPI或并口直接写GRAM。一个320×240的RGB565帧需要153600字节,STM32F103的RAM根本放不下完整帧缓冲。所以不能照搬上面的oled_buf方案。常见做法是按区域刷新:每次写二维码时,计算二维码所在的矩形区域,设置GRAM窗口,然后把该区域的像素逐一写进去。ILI9341支持CASET和PASET命令设置窗口,设置后连续写入像素数据,写满窗口后自动回到起始位置。这样MCU只需要一个很小的行缓冲甚至不需要缓冲,直接把打包好的二维码按RGB565格式发送。颜色选择上,二维码的“黑位”用0x0000(纯黑),空白位用0xFFFF(纯白)。注意ILI9341的RGB565字节序通常是高字节在前,发送时要按0xFF, 0xF8这种顺序发,或者用SPI的16位模式直接发。很多翻车案例就是颜色字节序反了,白的地方变红,黑的地方变蓝,扫码器对着一个蓝块完全懵掉。大屏还可以用RGB颜色方案搭配品牌视觉:黑底白码、蓝底白码都没问题,但建议让深色模块的反光率尽量低,浅色模块尽量高。不要用纯红配纯绿这种对比度不强的组合,扫码器在不同光照下容易失败。5. 显示二维码的常见坑:从白屏到扫不出的完整排查5.1 白屏或直接没反应现象:上电后OLED背光亮(OLED没有背光,这里是比喻,实际是屏幕完全无显示),或者LCD屏全白/全黑,任何命令都无反应。原因:多数是初始化序列没走完,最常见的坑是没开启电荷泵,或者忘了发0xAF打开显示。还有一种情况是SPI的极性/相位配置和驱动IC不匹配,数据根本没进去。解决:检查初始化命令是否包含:0x8D, 0x14(电荷泵开启),0xAF(显示打开)。SPI配置用模式0或模式3都能工作,但要确认你的接线引脚没有接反。我一般会在初始化后立刻发送0xA5(全屏点亮)测试,如果能亮说明初始化成功;如果不亮,先在逻辑分析仪上看有没有波形,再看复位引脚时序。5.2 画面花屏、条纹或方向错乱现象:屏幕有内容,但二维码看起来像竖条纹拼图,或者左右镜像、上下颠倒,完全无法识别。原因:取模的扫描顺序和显存布局不一致。SSD1306按页-列布局,如果你取模时按“行”方向一次取8个像素,写进显存后这8个像素会被竖向拉伸成8行,导致画面撕裂。另外,SPI数据发送顺序如果是从高位到低位,而屏幕内部是按低位对齐,整个画面就会变成左右镜像。解决:先拿一个已知的简单图案(比如全屏对角线)测试取模方向。打印出二维码第0页的前8个字节,手工核对它们对应的像素位置。如果镜像,把SPI数据位序改成MSB或LSB与驱动IC对齐;如果纵向错位,调整打包循环里的y % 8方向。记住这句口诀:OLED垂直打包,取模就按页取;LCD水平连续,取模就按列连续。5.3 手机扫不出来或识别很慢现象:屏幕上确实有一个清晰的二维码,界面看起来完全正常,但手机相机对焦半天就是识别不了,偶尔离远一点反而能扫出来。原因:最常见是安静区不足。QR标准要求二维码四周至少有4个模块宽度的纯色边界。有些取模脚本把border裁掉了,或者屏幕边缘图形贴太近,手机裁切定位时找不到标准位置探测图形。另外,如果反色做错了——白码黑底没问题,但如果你做了半透明叠加,或者像素点阵的颜色不是纯黑纯白,对比度不够,也会识别失败。解决:取模时保留border4的安静区,并且不要把二维码贴边放。OLED上版本3二维码放大2倍后58×58,在128×64的屏上居中,上下各只有3像素边距,勉强够;但左右两侧有35像素,所以通常能扫。如果还扫不出,把二维码整体缩小一圈,或者改用版本2(25×25)放大2倍,给安静区留出更多空间。另外,检查一下是否误开了反色。OLED上如果你把图案刷成“黑底蓝字”之类的彩底,白码区域的蓝墨层会让透光率下降,手机在低亮度下识别率会明显下降。5.4 HardFault与内存不足现象:程序一运行到二维码显示函数就进入HardFault,或者编译时提示region RAM overflowed。原因:把整块二维码缓冲当成了普通数组超限访问,比如定义了oled_buf[128*8],实际写入时索引计算到了x (y/8)*128,但二维码宽度超过128,或者某页索引越界。还有一种情况是在函数内部定义了大数组,比如uint8_t qr_temp[128*64],这已经是8KB栈开销,STM32F103的默认栈只有2KB,一调用就爆栈。解决:所有显存缓冲和二维码数组都定义为static或者全局const,不要放函数局部变量。访问前先判断边界:if (screen_x OLED_WIDTH) continue;,if (screen_y 64) continue;。如果确实需要一块大缓冲区,可以改用malloc再判断返回,但嵌入式环境不建议。更好的做法是按需分块,比如把二维码切割成上下两半分别写显存,写完上半刷新后再写下半。5.5 刷新闪烁与撕裂现象:整屏刷新时,二维码会肉眼可见地从上到下刷一遍,期间画面闪烁。原因:SSD1306整屏刷新需要发送1024字节数据,在SPI速率2MHz下大约需要4ms,但加上命令开销和循环跳转,实际要6到8ms。反复整刷时,人眼能敏锐察觉这种刷新闪烁。另一方面,I2C模式下速率更低,闪烁更明显。解决:只在内容变化时刷新,不要在while(1)里无脑调用oled_flush()。用局部刷新代替整屏刷新,比如二维码位置固定时,只对该区域重新写页数据。如果必须实时刷新,可以开一个定时器,把刷新频率控制在30Hz以下,减少视觉疲劳。还有一个土办法:SPI速率提高到18MHz,前提是屏幕电源纹波足够干净,否则会产生横纹干扰。这种干扰看起来像灰色条纹,但实际上是SPI时钟噪声耦合到电源线的结果,示波器一量就能看到毛刺。6. 进阶玩法:MCU端实时生成二维码的取舍与优化6.1 什么时候才需要MCU端生成离线取模适合内容固定的场景,但如果你做的是一个带随机 Token 的签到系统,或者二维码每5秒更换一次,离线方案就废了。这时候只能把一套轻量级QR生成算法移植到MCU上。注意,不是把Python库搬过去,而是在C端实现QR编码的核心流程:数据编码、分块、生成纠错码、掩码选择以及模块映射。开源社区有现成C库,但大多是为PC或嵌入式ARM设计的,直接编进STM32工程时要注意两点:一是要按需裁剪掉不支持的模式,比如字母数字模式和字节模式可能二选一;二是要把所有动态内存改成静态数组,因为库里的malloc调用可能会在内存碎片时失败。我当时移植一个版本4的生成器,Flash增加了大约6KB,RAM峰值约3KB。对STM32F103来说压力不大,但如果你用的是只有16KB Flash的STM32F030,就要考虑是否把容错级别从M降到L,或者干脆限制版本不超过4。生成耗时的估算:72MHz主频下构建一个版本4的二维码,大约需要80到150ms,这个速度对“5秒换一次码”的场景完全够用,但如果你想连续生成并刷新多个码,要做到“生成完立即刷,刷完再算下一个”,避免生成期间卡住其他业务逻辑。6.2 预生成与局部刷新的配合技巧实时生成一个很实在的技巧是“预生成 双缓冲”:在定时器中断里空闲时提前生成下一帧二维码,把它放在备用缓冲区,当前显存里的二维码继续显示;到了切换时刻,直接把备用缓冲复制到显存并刷新局部区域。这样视觉上几乎无跳变,而且把生成耗时的抖动隔离在后台,不阻塞主循环。另一个技巧是“低分辨率生成,再放大显示”。如果你要显示在320×240的TFT上,但又不想让MCU生成大尺寸矩阵,可以先在内存中生成版本3(29×29)的点阵,再在上屏时按比例放大到116×116。放大用最近邻法就行,不会产生摩尔纹,而且二维码的抗干扰能力远强于你对画质的担心。放大时要注意安静区也一起放大,不要只放大码体,否则放大后的二维码四周没有足够宽的白边,识别率会突然下降。最后分享一个我的习惯:每次拿到新的取模脚本或者屏幕驱动,我都不会直接上二维码,而是先显示一张全屏幕的已知图案,比如棋盘格、渐变色带,肉眼确认方向和颜色没问题后,再放二维码。从那以后,我基本没再遇到过“白屏半小时然后发现是SPI极性配错”的乌龙。二维码显示这个事,90%的问题都出在取模方向和安静区,先把这两点刻在脑子里,再动手写代码,会省下大量调参时间。希望帮到你。本文还有配套的精品资源点击获取
RELATED

相关推荐

实时数仓与离线数仓的本质:业务节奏驱动的分层协同

实时数仓与离线数仓的本质:业务节奏驱动的分层协同

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

📅 2026/10/14 1:14:55
Python序列协议:自定义类的切片与散列实现

Python序列协议:自定义类的切片与散列实现

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

📅 2026/10/14 1:14:55
PyTorch入门实战:从张量、自动求导到完整训练循环

PyTorch入门实战:从张量、自动求导到完整训练循环

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

📅 2026/10/14 1:14:55
MORE NEWS

更多资讯

📰

OpenLayers地图前端架构设计:分层封装与工程实践指南

做地图前端这些年,我最大的感受是:OpenLayers 的入门曲线并不陡,API 也够完善,但真正让它“好用”的,从来不是某个 API 的熟练程度,而是整体架构怎么搭。很多项目一开始都是从“在某个页面里 new 一个 Map”…

📰

从零手写Java SPI框架:解决ServiceLoader无缓存与按名获取难题

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

📰

【股票交易】第 18 章 产品、客户与收入来源

回到目录 文章目录 18.1 收入总额下面装着什么 先看公司怎样组织业务 用苹果产品与服务表拆开收入 收入占比与毛利润贡献 产品类别收入不能代替独立利润 产品类别与地域分部是不同视角 18.2 数量、价格、组合与渠道 用宝洁披露拆解增长 不同品类可能向相反方向变化 按披露范围解…

📰

【股票交易】第 17 章 商业模式:客户为什么愿意付钱

回到目录 文章目录 17.1 客户购买的是一个结果 从使用结果理解客户价值 有用的产品仍然面对替代选择 个人体验与企业使用过程 预算与迁移条件影响购买 17.2 使用者、决策者与付款者 把使用、决策和付款分开 消费者选择与渠道采购 直接销售与间接销售 企业内部怎样形成采购决定 …

📰

Matlab机器视觉工具箱图像处理模块详解:从核心函数到实操避坑指南

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

📰

Node.js与Vue构建社区团购系统核心技术解析

1. 项目概述:基于Node.js与Vue的社区团购系统社区团购作为近年兴起的零售模式,正在彻底改变居民的日常采购方式。这个基于Node.js后端和Vue前端构建的系统(项目代号5tem94ur)正是瞄准了这一市场机遇。不同于传统电商平台&#xff…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬