Project 08 of 11: 项目 08 / 11:Tianjin Jintie STM32 Internship天津津铁 STM32 嵌入式实习

During a month of foundational training at Tianjin Jintie, I planned my own STM32 learning sequence and combined external sensors, display, encoder, servo, and LED control in a working bare-metal demo.在天津津铁一个月的基础实习中,我自行安排 STM32 学习顺序,从外设小实验做起,最后把传感器、显示、编码器、舵机与 LED 控制接进同一套裸机演示。

Company mark · Tianjin Jintie STM32 Internship / 实习单位标识 · 天津津铁 STM32 嵌入式实习Company mark · Tianjin Jintie STM32 Internship / 实习单位标识 · 天津津铁 STM32 嵌入式实习
FIG. 01图 01Company mark · Tianjin Jintie STM32 Internship实习单位标识 · 天津津铁 STM32 嵌入式实习

From Arduino to STM32从 Arduino 到 STM32

In February 2025 I saw an embedded-intern opening at Tianjin Jintie Communications online, applied, and went. Jintie is a wholly owned subsidiary of Tianjin Rail Transit Group, so every morning I walked into the Group's headquarters building, which still strikes me as a slightly surreal way to spend an internship. The title was embedded intern; in practice it was a month of foundational training. The engineer tossed me a batch of introductory material, and on my desk sat an STM32F103C8T6 Blue Pill, an ST-Link and a pile of external modules. An intern was hardly worth him stopping his own work to teach step by step, so the rest of the route was mine to find.

2025 年 2 月,我在网上看到天津津铁通信招嵌入式实习生,投了就去了。津铁通信是天津轨道交通集团旗下的全资子公司,我每天上班进的是轨道交通集团的总部大楼,这段实习说起来还挺神奇。岗位叫嵌入式实习生,实际是一个月的基础培训。工程师甩给我一批入门资料,桌上一块 STM32F103C8T6 Blue Pill、一只 ST-Link,外加一堆外接模块。我一个实习生,也犯不着让他停下手里的活来手把手教,剩下的路得自己摸。

Before this, the only microcontroller I had used was the Arduino Nano the university handed out, for the car and the seven-segment counter. Keil, ST-Link, the Standard Peripheral Library, interrupts, timers, PWM, ADC: I knew none of them, a complete beginner. To me a microcontroller meant calling one function to set a pin high and another to set it low.

来之前,我只用过学校发的 Arduino Nano,做过小车和数码管计数器。Keil、ST-Link、标准外设库、中断、定时器、PWM、ADC,一样都不懂,纯小白。在我眼里,单片机就是调一个函数让引脚变高,再调一个函数让它变低。

There was no syllabus, so I set the order myself. Later topics make no sense until the earlier ones do, so I combined the engineer's material with online tutorials and laid out a route: GPIO first, then EXTI and timers, then PWM, UART and ADC, and finally one integrated demo. I wanted to know why things worked, and in particular what an effect Arduino produced with a single function call actually took on an STM32.

没有课表,学习顺序是我自己排的。前面的没弄懂,后面的就看不明白,所以我结合工程师给的资料和网上的教程,定了一条路:先 GPIO,再 EXTI 和定时器,然后 PWM、UART、ADC,最后把它们接成一个综合 demo。我是奔着知其所以然去学的,想弄清楚以前 Arduino 一个函数就出来的效果,换到 STM32 上到底要经过哪些步骤。

First Board Tests第一次上板

Before I touched a single peripheral, the Keil environment held me up for quite a while. Keil is an old piece of software and anything but beginner-friendly. I had to download the device pack from ST's website, then work through the Magic Wand settings one by one: library paths, compiler, whether the ST-Link was detected, the program's start address. I had no idea what a start address or a bootloader was, so I searched and fumbled my way through until the environment built and the ST-Link could download.

外设还没碰,Keil 的环境先折腾了我好一阵。Keil 是个很老的软件,对小白一点都不友好。要去 ST 官网下器件支持包,再在魔术棒里一项项设置库路径、编译器、ST-Link 能不能识别、程序的起始地址。什么叫起始地址、什么叫 bootloader,我那时完全不知道,只能边查边摸索,最后环境总算配通,ST-Link 也能下载了。

I split the checks apart: first the computer had to compile, then the ST-Link had to download, and finally the board had to do something visible. PC13 toggling every 300 ms was that first visible thing, and the moment the little LED blinked, the toolchain and the hardware had finally met.

我把检查拆开来做:电脑上先能编译,ST-Link 再能下载,最后看板子上有没有看得见的动作。PC13 每 300 ms 翻转一次,那盏小灯一闪,工具链和实物算是第一次接上了。

The initial GPIO and OLED program still holds that setup. It enables the GPIOB and GPIOC clocks, uses PB4 and PB5 to supply the OLED (only acceptable for a low-current breadboard exercise), initializes the display and drives PC13. This was also where remembering the name GPIO_SetBits() stopped being enough. I started following it down into clocks, pin modes and registers, and spent a lot of time chewing through ST's manuals and forum threads. Behind a single set-bit call, the peripheral clock has to be on and the mode configured before the pin will do as it is told.

最初的 GPIO 与 OLED 程序还留着当时的配置:先开 GPIOB、GPIOC 的时钟,用 PB4、PB5 两个引脚给 OLED 供电(小电流的面包板练习才敢这么接),再初始化屏幕、控制 PC13。也是从这里开始,光记住 GPIO_SetBits() 这个函数名已经不够了。我顺着它往下追时钟、引脚模式和寄存器,花了大把时间啃 ST 的手册和论坛帖子。一句置位背后,得先给外设开时钟、配好模式,引脚才会听话。

STM32F103C8T6 pinout reference / STM32F103C8T6 引脚定义参考
STM32F103C8T6 pinout referenceSTM32F103C8T6 引脚定义参考

The OLED had one strange episode. The code was right, it compiled, it flashed, the wiring checked out, and the screen would not light no matter what. In the end I moved to another pair of ordinary GPIO pins with software-emulated I²C, and the screen came on. At the time I did not even know what separated hardware I²C from software I²C; I was just baffled that it stayed dark. Thinking about it now, I most likely ran into the STM32F103's well-known hardware I²C lockup; the analysis is in I²C Communication and OLED Debugging.

OLED 也出过一次怪事。代码是对的,编译能过,烧录没问题,接线查了也没错,屏幕就是死活不亮。最后换了一对普通 GPIO,改用软件模拟 I²C,屏幕亮了。那时我连硬件 I²C 和软件 I²C 有什么区别都不知道,只是纳闷它为什么不亮。现在想想,很可能是撞上了 STM32F103 硬件 I²C 卡死的老问题,展开的分析在 I²C 通信与 OLED 调试里。

Peripheral Integration外设组合

Apart from that, things went fairly smoothly. Most of the work built on example projects, so compile errors were rare, and the bugs were mostly logic that came straight once I traced it through. GPIO, OLED, encoder, servo, DHT11, light sensor, PWM and UART each ran first in a project of its own, and then I merged them one at a time into a single bare-metal program. The hardware stayed a Blue Pill with every module on breadboard and jumper wires.

除了 OLED 这一下,整个过程总体挺顺。大部分是在例程基础上开发,编译错误不多,顶多是逻辑没捋顺,捋清楚改改代码就好了。GPIO、OLED、编码器、舵机、DHT11、光敏传感器、PWM 和 UART,我先在各自的独立工程里跑通,再一个个并进同一套裸机程序。硬件还是那块 Blue Pill,模块全靠面包板和杜邦线连着。

In the final demo every peripheral worked at once. A button switched what the encoder controlled, target light in one mode and servo speed in the other. The OLED showed measured light, the target, LED output, temperature and humidity; UART sent light readings and debug output to the computer; PC13 stayed on as a status light. EXTI handled the encoder, TIM3 set the pace for slower tasks, TIM4 produced PWM, and the temperature, humidity and light reads waited for a timer flag before running.

最后的 demo 里,所有外设同时工作。按键切换编码器的控制对象,一种模式调目标光照,另一种调舵机速度;OLED 显示实测光照、目标值、LED 输出和温湿度;UART 把光照数据和调试信息发到电脑上;PC13 那盏灯留下来当状态灯。EXTI 处理编码器,TIM3 给慢任务打节拍,TIM4 输出 PWM,温湿度和光照的读取等定时器的 flag 到了再做。

I wrote the application flow, encoder mapping, mode switching and the integrated main loop; the OLED, DHT11, encoder and servo drivers were standard drivers from online and ST examples that I reworked heavily. I had not met an RTOS yet, so it was all bare metal, interrupts plus timer-driven polling, and every delay a blocking delay(). The logic was nothing elegant. All these tasks ran at very low rates, though, and it worked fine.

应用流程、编码器映射、模式切换和综合主循环是我写的;OLED、DHT11、编码器和舵机的驱动,是拿网上的标准驱动和 ST 例程魔改来的。那时还不知道 RTOS,全是裸机,中断加定时器轮询,延时一律是阻塞式 delay(),逻辑谈不上漂亮。好在这些任务的频率都很低,跑起来没毛病。

Light Calibration光照标定

To turn a target light value into an LED output, I stepped the PWM point by point, read the ADC, recorded 16 pairs on this breadboard, and wrote a lookup and interpolation function. PWM runs from 0 to 1000 while ADC falls from 1600 to 480, and a target between two records gets its output by linear interpolation. The program looks up PWM from the target; measured ADC is only displayed and printed. I definitely thought about feedback correction at the time, but it never went in, and the demo kept this feedforward version. The interpolation, where to add calibration points and which way feedback should correct are worked through in Light Calibration and Lookup Control.

想把目标光照换算成 LED 的输出,我一点一点调 PWM、读 ADC,在这套面包板上记了 16 组数据,再写了查表插值函数。PWM 从 0 加到 1000,ADC 从 1600 降到 480,目标落在两个记录点之间,就用线性插值算输出。程序按目标查表得到 PWM,实测的 ADC 只拿来显示和打印。反馈修正我当时肯定想过,最后没做进去,demo 里留下的是这套前馈。插值怎么算、哪里该补测、加反馈该往哪个方向修,在光照标定与查表控制里推了一遍。

End of the Placement实习结束

In about 20 working days I covered the whole route on my own. The engineer ran things hands-off and never set a target for me. At the end I showed him the demo and talked through how I understood the peripherals working together and what I had found along the way, and he said I had learned it solidly.

大约 20 个工作日,这条路线我一个人走完了。工程师那边是散养,没要求我做到什么程度。最后我给他演示了 demo,讲了讲我对这些外设怎么配合的理解,还有自己的一些发现,他说我学得挺扎实。

The training material also covered PID and the ATP, ATO and ATS systems common in rail transit. I read them closely, though I never wrote or tuned a PID loop. The first time I read about PID it seemed almost magical that one formula could bring something to the position you want, quickly and stably. I also found myself mapping the bench exercises onto a train: carriage lighting and ventilation fans, station-entry signals, all of it needs microcontrollers, just with sturdier, more reliable hardware and designs. The breadboard on my desk felt like a miniature of those systems.

培训资料里还有 PID 和 ATP、ATO、ATS 这些轨道交通里常用的东西,我读得很仔细,只是 PID 没有真写过,也没调过。第一次读到 PID,我觉得它很神奇,一个公式就能让东西又快又稳地逼近想要的位置。那时我也会把桌上这些小练习往车上想:车厢里的照明和通风扇、进站的信号控制,背后都离不开单片机,只是会换成更稳、更可靠的方案。面包板上的这一套,算是那些系统的一个小缩影。

When I later took on FOC, Timer, ADC, PWM and interrupts all came up again at once. This time sampling had to line up exactly with switching, and each calculation had to finish before the next cycle began. The peripherals I had learned one by one in Tianjin were now bound together in motor control, and bound far more tightly.

后来做 FOC,Timer、ADC、PWM 和中断我又全碰了一遍。这回采样要和开关时刻严丝合缝地对上,每一次计算都得赶在下一个周期之前算完。天津那一个月里一个个分开学的外设,到了电机控制里被绑到了一起,而且绑得更紧。

Development notes开发笔记

Debugging records and technical notes tied to the decisions and artifacts on this project page.与这个项目页面中的设计决策和工程材料直接关联的调试记录与技术笔记。

2 notes2 篇
  1. 01I²C Communication and OLED DebuggingI²C 通信与 OLED 调试Studying pull-ups, transfer timing and acknowledgment, then comparing software and peripheral I²C when troubleshooting an OLED.从上拉、电平、地址与应答,研究软件和硬件 I²C 的区别,以及 OLED 不显示时怎样定位问题。
  2. 02Light Calibration and Lookup Control光照标定与查表控制Working through an ADC-to-PWM interpolation example, uneven calibration intervals and a possible correction for changing ambient light.从目标 ADC 到 PWM 的一次插值计算,研究采样点分布、标定条件和环境光变化后的修正思路。

Public Project Files公开项目资料

Uploaded evidence served from the public asset folder. Use the file index to preview documents, source code, media, PDFs, and downloadable artifacts without leaving the page.这里列出已经上传到公开目录的项目证据。可以在左侧索引里选择文件,在右侧直接预览文档、源码、媒体、PDF 和可下载附件。

9 files9 个文件

Related media相关媒体

Board photos, schematic sheets, videos, and test captures that show this project at specific stages.展示这个项目具体阶段的板卡照片、原理图分页、视频和测试截图。

Open in media archive在媒体库中查看