ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

IAR环境下STM8S003模拟串口配置与避坑指南

IAR环境下STM8S003模拟串口配置与避坑指南

简介:面向在 IAR Embedded Workbench 下开发 STM8S003 的嵌入式工程师,这份资源针对该芯片原生物理串口资源不足的痛点,给出基于 PC3、PC4 引脚配合定时器实现软件模拟 UART 的完整工程。内容涵盖 GPIO 推挽/开漏配置、波特率定时器周期设定、发送波形生成、查询与中断两种接收模式的处理逻辑,以及中断服务程序中的数据收发流程,适合已具备一定单片机基础、希望掌握资源受限场景下串口扩展思路的开发者参考。压缩包共 53 个文件,约 418KB,以 IAR 工程配置类文件(xcl、dnx、ewp、eww、dbgdt 等)为主,辅以 c 与 h 源文件、编译中间产物及 hex、map 输出,工程结构完整可直接导入调试。目前已有 425 人学习下载。读者可从中获得可运行的模拟串口示例代码、工程配置模板与收发实现细节,并在此基础上扩展多路模拟串口或适配不同波特率。

1. 装 IAR 之前先想清楚:STM8S003 的模拟串口不是“能编译就行”

STM8S003 这颗片子便宜、够用,很多小项目拿它当主控,但它的 UART 只有一组,一旦被别的外设占掉,或者板子上压根没把 UART 引脚引出来,串口调试就成了卡脖子的事。这时候常见的做法是用普通 GPIO 加定时器软件翻转电平,也就是模拟串口。听起来简单,实际装环境时最容易翻车的不是代码,而是 IAR 的器件支持包和工程配置——版本对不上,编译能过,下载进去跑起来波形全是毛刺。这篇笔记记录的是我在 IAR 里给 STM8S003 搭一套模拟串口环境的完整过程,从装什么版本、建工程、配定时器参数,到装坏了怎么救,适合刚接手这颗片子、手上只有 IAR 的开发者照着走一遍。

2. 环境准备与版本选择:IAR EWSTM8 装哪个、器件包怎么对

2.1 IAR EWSTM8 的版本取舍

STM8 系列在 IAR 里的支持走的是 EWSTM8 这条产品线,和 EWARM、EW430 是分开的安装包,别拿 ARM 版本的 IAR 去开 STM8 工程,器件列表里根本找不到 STM8S003。我一般选 EWSTM8 3.x 这一支,3.10 和 3.11 都用过,3.11 对新型号器件文件更新一些,但对 STM8S003 这种老型号两者没本质差别。真正要留意的是安装路径不要带中文和空格,IAR 的 license 校验和器件包索引对路径比较敏感,装在C:\Program Files (x86)\IAR Systems\Embedded Workbench 8.x这类默认路径最省事。

安装时组件勾选上 STM8 的器件支持(Device Support),以及 ST-LINK 的驱动组件。如果你用的是第三方的 ST-LINK 兼容下载器,驱动可以后面单独装,但 IAR 自带的 ST-LINK 驱动版本要和下载器固件匹配,否则会出现“能识别但下载失败”的情况。安装完成后先别急着建工程,打开一次 IAR,确认 Help 菜单里能看到 license 状态正常,再继续。

2.2 器件包与工程目标器件确认

新建工程时选STM8S003F3这个具体型号,不要选成STM8S003K3或者笼统的STM8S。两者的引脚数和 Flash 大小不同,选错了链接脚本里的存储区映射会偏,编译能过但运行时变量地址错乱,表现出来就是模拟串口时序莫名其妙地抖。工程建好后在 Options → General Options → Target 里核对器件型号,同时在 Linker 配置里确认用的是 IAR 自带的.icf文件,不要手工改过又忘了改回来。

时钟配置是模拟串口精度的根。STM8S003 内部 HSI 是 16MHz,出厂校准精度在常温下大概 ±1% 量级,做模拟串口够用,但前提是你在代码里明确把时钟源切到 HSI 并设好分频。我一般用 16MHz 主频不分频,定时器基准算起来最直观。如果项目里已经用了外部晶振,那就以实际晶振频率为准,定时器重装值要跟着重算,这一点后面配定时器时会再展开。

2.3 工程基础配置清单

建完工程先做几项固定配置,避免后面调试时被无关问题干扰:

  • 在 Options → C/C++ Compiler → Preprocessor 里确认没有多余的宏定义,模拟串口不需要额外宏。
  • 在 Debugger 选项里选 ST-LINK,接口选 SWIM,这是 STM8 的调试接口,不是 SWD,选错了连不上。
  • 在 Output Converter 里按需生成 hex,方便用别的工具烧录验证。
  • 关闭编译器的激进优化先跑通,等波形稳定了再逐级打开优化,优化等级变化会影响延时循环的时序。

这几项做完,工程骨架就算立住了,接下来才是模拟串口本身的实现。

3. 模拟串口实现:GPIO 翻转与定时器参数怎么配

3.1 模拟串口的基本原理与引脚选择

模拟串口的核心是用一个 GPIO 当发送脚,按波特率的时间间隔逐位输出起始位、8 位数据位和停止位。STM8S003 上我一般挑一个没被占用的普通 IO,比如 PD4 或者 PC3,具体看板子走线。选脚的原则是:这个脚不能同时被复用成别的功能,且输出驱动能力够。配置成推挽输出,初始电平拉高,因为串口空闲态是高电平。

发送一个字节的时序是:先拉低一个位时间作为起始位,然后从最低位开始依次输出 8 个数据位,最后拉高一个位时间作为停止位。位时间由波特率决定,比如 9600 波特率下一位约 104 微秒。这个时间精度直接决定通信能不能被对方正确采样,所以定时器的配置是整件事的关键。

3.2 定时器基准与重装值计算

用 TIM4 做位定时比较常见,它是 8 位定时器,配起来简单。假设主频 16MHz,预分频设为 16,则计数时钟 1MHz,一个计数 1 微秒。9600 波特率下位时间约 104 微秒,重装值取 104。代码里这样初始化:

// TIM4 初始化:1us 计数基准,用于模拟串口位定时 void SimUart_TimerInit(void) { TIM4_CR1 = 0x00; // 先停止定时器 TIM4_PSCR = 0x04; // 预分频 16,16MHz/16 = 1MHz TIM4_ARR = 104; // 9600bps 位时间约 104us TIM4_IER = 0x01; // 使能更新中断 TIM4_CR1 = 0x01; // 启动定时器 }

TIM4_PSCR写 4 表示 2 的 4 次方分频,即 16 分频,这是 STM8 定时器预分频寄存器的编码方式,不是直接写分频系数,这一点新手容易写错。TIM4_ARR是自动重装值,中断里每进一次就代表过了一个位时间。波特率变了就改这个值,比如 19200 波特率下位时间约 52 微秒,ARR 改成 52。改完记得重新算一遍误差,104 微秒对应 9615 波特率,误差约 0.16%,在可接受范围内。

3.3 发送状态机与中断服务

发送逻辑放在定时器中断里做状态机,主循环只管把待发字节塞进缓冲区。中断里根据当前状态决定输出起始位、数据位还是停止位:

// 定时器中断中的发送状态机 #pragma vector = TIM4_OVR_UIF_vector __interrupt void TIM4_ISR(void) { TIM4_SR = 0x00; // 清中断标志 switch (tx_state) { case 0: // 发起始位 TX_PIN = 0; tx_shift = tx_byte; tx_bitcnt = 0; tx_state = 1; break; case 1: // 发 8 位数据,低位先出 TX_PIN = (tx_shift & 0x01); tx_shift >>= 1; if (++tx_bitcnt >= 8) tx_state = 2; break; case 2: // 发停止位 TX_PIN = 1; tx_state = 0; tx_busy = 0; // 释放忙标志 break; } }

状态 0 拉低起始位,状态 1 逐位输出数据并右移,状态 2 拉高停止位后回到空闲。tx_busy标志让主循环知道当前能不能发下一个字节,避免字节被覆盖。这里没有做接收,因为多数调试场景只需要单片机往外打印,接收端用 USB 转串口模块接电脑即可。如果确实需要接收,得再加一个边沿捕获加采样状态机,复杂度会上去不少,建议先跑通发送再考虑。

3.4 主循环调用与缓冲区

主循环里封装一个发送函数,检查忙标志后装载字节并启动状态机:

// 发送一个字节,忙时直接返回,调用方自行控制节奏 void SimUart_SendByte(unsigned char dat) { if (tx_busy) return; tx_busy = 1; tx_byte = dat; tx_state = 0; }

调用方在打印字符串时逐字节调用,字节之间留出足够间隔,或者干脆在发送函数里加一个简单的等待。模拟串口没有硬件 FIFO,节奏全靠软件控制,这一点和真 UART 的体验差别要提前有心理准备。

4. 避坑与排查:模拟串口装完跑不通的几种典型情况

4.1 现象:串口助手收到乱码,波形毛刺多

原因通常是定时器基准算错或者主频配置和预期不一致。先确认代码里时钟初始化确实切到了 16MHz HSI,再核对TIM4_PSCR和TIM4_ARR的乘积是否等于位时间。还有一种情况是编译器优化把延时或状态机变量优化掉了,tx_busy这类跨中断和主循环共享的变量要加volatile,否则主循环读到的可能是寄存器缓存值,忙标志永远不释放或者永远忙。

4.2 现象:能发但对方收不到,示波器看电平不动

先查引脚配置,推挽输出方向寄存器DDR和数据寄存器ODR都要设对,只设一个脚可能一直是输入态。再查这个脚有没有被别的外设复用占用,STM8S003 的复用功能是分组的,选脚时对照数据手册的复用表确认。还有一种低级但常见的情况:下载进去的程序根本没跑起来,SWIM 连接正常但复位后停在某处,用调试器单步确认程序进了主循环再怀疑串口逻辑。

4.3 现象:IAR 编译报器件不支持或链接报存储区溢出

前者多半是装的是 EWARM 而不是 EWSTM8,或者器件支持包没勾选;后者检查工程目标型号是不是选成了 Flash 更小的型号,STM8S003F3 只有 8KB Flash,模拟串口加打印字符串很容易把空间吃紧。把调试打印精简,或者把不用的库函数裁掉,链接就能过。链接脚本不要手工改,改错了存储区映射,程序跑起来地址全乱。

4.4 现象:下载成功但复位后不运行

检查复位电路和选项字节。STM8 的选项字节里如果开了看门狗或者设了特殊的复位行为,程序可能反复复位。用 ST-LINK 工具读一下选项字节状态,确认看门狗是关闭的。另外确认下载时勾选了“下载后复位运行”,有些配置下下载完停在调试状态,松开调试器就不跑,容易误判成程序问题。

5. 装完怎么验证:用示波器和串口助手双重确认

环境搭完、代码烧进去,验证分两步走,别只信串口助手。第一步用示波器或者逻辑分析仪抓发送脚波形,看起始位是不是一个干净的下降沿、位宽是不是接近 104 微秒、停止位是不是稳定高电平。位宽偏差超过 3% 就要回头查定时器参数和主频配置,别急着调串口助手的波特率去凑,那是掩盖问题。第二步接 USB 转串口模块,地线共好,串口助手设 9600、8 数据位、无校验、1 停止位,让程序循环打印一串固定字符,看是否稳定无乱码。连续跑几分钟不丢字节,基本就算通了。

我一般还会做一个边界验证:把波特率改成 19200 重新算 ARR 再跑一遍,确认参数改动路径是通的,这样以后换波特率不用重新摸索。另外把优化等级从低到高逐级打开各跑一次,确认时序在优化后依然稳定,避免发布版本和调试版本行为不一致。从那以后我每次给 STM8 配模拟串口,都强制先抓波形再开串口助手,波形不对就绝不往下调,这个习惯帮我省掉了大量“到底是代码问题还是接线问题”的来回折腾。希望帮到你。

本文还有配套的精品资源,点击获取

返回列表