普中PZ6806L开发板实战:从STM32F103ZET6入门到VSCode+PlatformIO开发环境搭建 1. 开箱与初印象从包装到板载资源拿到普中PZ6806L开发板的第一感觉是它的“分量感”很足。这不仅仅是指物理重量更是指板载资源的丰富程度。包装盒内除了开发板本体通常还会附带一根USB数据线Micro-USB或Type-C取决于批次、一本快速入门指南以及一个用于下载程序的ST-LINK V2仿真器模块部分套餐。板子本身是经典的蓝色PCB元器件布局紧凑而清晰所有接口和关键芯片都做了丝印标注这对于新手快速上手非常友好。板子的核心是一颗STM32F103ZET6这是ST公司基于ARM Cortex-M3内核的经典微控制器。为什么是它对于学习者和项目开发者而言F103系列堪称“国民MCU”资源丰富、生态成熟、资料海量。ZET6这个型号意味着它拥有144个引脚、512KB的Flash存储器和64KB的SRAM以及丰富的外设多达11个定时器、13个通信接口包括USART、I2C、SPI、CAN、USB、3个ADC和2个DAC。这样的配置足以应对从基础GPIO控制到复杂通信协议、电机控制乃至小型图形界面开发的绝大多数应用场景。PZ6806L的开发板设计者显然深谙“一站式学习”的理念。除了核心MCU板子上几乎集成了你能想到的所有常用模块和接口显示与输入一个2.8寸的TFT-LCD彩色触摸屏通常为ILI9341驱动、一个0.96寸的OLED显示屏接口、4个独立按键、1个五向摇杆、1个电容触摸按键。传感器与执行器DS18B20温度传感器接口、红外接收头、蜂鸣器、光敏电阻、电位器用于ADC采样、继电器模块、步进电机驱动接口、直流电机驱动接口。通信与存储ESP8266 WiFi模块接口、NRF24L01无线模块接口、SD卡槽、EEPROM芯片AT24C02。调试与下载标准的JTAG/SWD调试接口兼容ST-LINK和J-Link以及一个独立的USB转串口芯片通常是CH340G用于串口通信和供电。扩展接口将MCU的绝大部分GPIO引脚以2.54mm间距的排针形式引出方便连接自定义的外设和面包板。这种“大而全”的设计其优势在于“开箱即用”。你不需要为了学习ADC而去单独焊接一个电位器电路也不需要为了驱动电机而先搭建一个H桥。所有的实验都可以在单板上完成极大地降低了初学者的硬件门槛让你能快速将注意力集中在软件和算法逻辑上。当然这也带来一个“幸福的烦恼”面对琳琅满目的模块初学者可能会感到无从下手。我的建议是遵循“由简入繁”的路径从点亮一个LED开始然后是按键控制、串口打印再逐步深入到定时器中断、ADC采样、PWM输出最后挑战触摸屏、文件系统、网络通信等复杂应用。2. 开发环境搭建告别Keil MDK的另一种选择一提到STM32开发很多人第一反应就是Keil MDK现为ARM Keil。它确实是行业标准之一但对于学生或个人开发者其授权费用是个现实问题。因此基于PZ6806L我更倾向于推荐完全免费且功能强大的开源工具链这不仅能让你合法合规地开发还能让你更贴近底层理解编译和链接的过程。我的选择是“VSCode PlatformIO IDE OpenOCD”这套组合拳。下面详细说说为什么以及如何做。2.1 为什么选择PlatformIO而非Keil首先完全免费且开源没有任何版权或代码大小限制。其次跨平台在Windows、macOS、Linux上体验完全一致。最重要的是它极大地简化了项目管理。在Keil中你需要手动管理芯片支持包、添加源文件路径、配置编译选项、链接脚本等过程繁琐且容易出错。PlatformIO通过一个platformio.ini配置文件搞定一切。你只需要在这个文件里指定开发板型号如board genericSTM32F103ZE和框架如framework stm32cubePlatformIO就会自动下载对应的工具链、CMSIS库、HAL库或标准外设库。对于PZ6806L由于其MCU型号明确我们可以在PlatformIO的Board列表中找到兼容的板型定义或者直接使用通用的F103ZE配置。它内置的库管理器让你可以像npm或pip一样一键添加第三方库例如用于OLED显示的U8g2、用于JSON解析的ArduinoJson等这对于快速原型开发来说效率极高。2.2 具体搭建步骤安装VSCode从官网下载安装。安装PlatformIO插件在VSCode的扩展商店中搜索“PlatformIO IDE”并安装。安装完成后VSCode左侧会出现一个蚂蚁头状的图标。创建新项目点击PlatformIO图标选择“New Project”。在项目创建向导中Name输入你的项目名如pz6806l_led_blink。Board在搜索框输入STM32F103ZE选择类似“Generic STM32F103ZE”的选项。PlatformIO的板型支持非常灵活即使没有完全匹配的“PZ6806L”选择核心MCU相同的通用板型即可后续的引脚配置完全由代码决定。Framework选择“STM32Cube”。我推荐使用STM32Cube HAL库而非标准外设库SPL。HAL库是ST主推的下一代库抽象层次更高代码可移植性更好虽然效率上略有损耗但对于学习和大多数应用来说完全足够且ST官方持续维护。点击“Finish”PlatformIO会自动创建项目骨架并下载必要的工具链和框架这可能需要几分钟时间。配置调试器OpenOCDPlatformIO默认集成了OpenOCD这是一个开源的片上调试器软件。对于PZ6806L配套的ST-LINK V2配置非常简单。在项目根目录的platformio.ini文件中添加以下配置[env:genericSTM32F103ZE] platform ststm32 board genericSTM32F103ZE framework stm32cube ; 调试器配置 debug_tool stlink upload_protocol stlink ; 设置晶振频率根据板载晶振通常是8MHz board_build.f_cpu 72000000L这段配置告诉PlatformIO使用ST-LINK进行程序上传和调试并且CPU主频是72MHz通过内部PLL将8MHz外部晶振倍频得到。2.3 第一个程序点亮LEDPZ6806L上通常有一个用户LED连接在某个GPIO上比如PE5。我们来写一个简单的闪烁程序。在src目录下创建main.c#include main.h #include stm32f1xx_hal.h // HAL库头文件 // 全局句柄定义 UART_HandleTypeDef huart1; // 简单的延时函数基于HAL的Tick void Delay(uint32_t nCount) { uint32_t tickstart HAL_GetTick(); while((HAL_GetTick() - tickstart) nCount); } int main(void) { // HAL库初始化 HAL_Init(); // 系统时钟配置通常使用CubeMX生成这里简化 SystemClock_Config(); // 初始化LED引脚PE5为推挽输出 __HAL_RCC_GPIOE_CLK_ENABLE(); // 使能GPIOE时钟 GPIO_InitTypeDef GPIO_InitStruct {0}; GPIO_InitStruct.Pin GPIO_PIN_5; GPIO_InitStruct.Mode GPIO_MODE_OUTPUT_PP; // 推挽输出 GPIO_InitStruct.Pull GPIO_NOPULL; GPIO_InitStruct.Speed GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOE, GPIO_InitStruct); while (1) { HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_5); // 翻转PE5电平 Delay(500); // 延时500ms } } // 系统时钟配置函数简化版实际项目建议用CubeMX生成 void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct {0}; // 配置HSE外部高速晶振和PLL RCC_OscInitStruct.OscillatorType RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState RCC_HSE_ON; RCC_OscInitStruct.HSEPredivValue RCC_HSE_PREDIV_DIV1; RCC_OscInitStruct.PLL.PLLState RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLMUL RCC_PLL_MUL9; // 8MHz * 9 72MHz HAL_RCC_OscConfig(RCC_OscInitStruct); // 配置系统时钟源和分频 RCC_ClkInitStruct.ClockType RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider RCC_SYSCLK_DIV1; // HCLK 72MHz RCC_ClkInitStruct.APB1CLKDivider RCC_HCLK_DIV2; // APB1 36MHz RCC_ClkInitStruct.APB2CLKDivider RCC_HCLK_DIV1; // APB2 72MHz HAL_RCC_ClockConfig(RCC_ClkInitStruct, FLASH_LATENCY_2); }编写完成后点击VSCode底部状态栏的“→”箭头上传按钮PlatformIO会自动编译并将程序通过ST-LINK烧录到开发板。如果一切顺利你应该能看到LED开始闪烁。注意上述时钟配置是简化版在实际复杂项目中强烈建议使用STM32CubeMX图形化工具来初始化引脚、时钟树和外设生成完整的工程代码然后再导入到PlatformIO项目中。这能避免大量手动配置容易出错的问题。3. 核心外设实战从GPIO到通信协议当开发环境跑通第一个LED闪烁起来后真正的学习才刚刚开始。PZ6806L的丰富外设为我们提供了绝佳的实战平台。下面我挑几个关键外设结合常见应用场景和容易踩的坑分享一下我的实操经验。3.1 GPIO与中断按键消抖的哲学控制LED是输出读取按键就是输入。但按键输入远不是HAL_GPIO_ReadPin那么简单机械按键的抖动是第一个拦路虎。我的做法是硬件消抖与软件消抖相结合。硬件上可以在按键两端并联一个0.1uF的电容吸收瞬间的抖动毛刺。但开发板上通常没有预留这个电容的位置所以我们主要依靠软件消抖。最简单的软件消抖是在检测到按键按下后延时10-20ms再读一次。但在实际项目中这种“死等”的延时非常低效会阻塞整个系统。更优的方案是使用定时器中断进行状态扫描。创建一个全局的按键状态机在定时器中断比如每5ms一次中采样按键引脚电平。只有当连续多次采样比如3次都是按下状态才认为是一次有效的按键事件。这种方法非阻塞且消抖效果稳定。在PZ6806L上你可以很方便地使用一个基本定时器如TIM6来实现这个功能。3.2 ADC采样获取模拟世界的钥匙板载的电位器连接到了ADC通道用于演示模拟量采集。使用STM32CubeMX配置ADC时有几个关键点时钟配置ADC的时钟不能超过14MHz对于F103。通常由APB2时钟分频得到。采样时间需要根据信号源阻抗来设置足够的采样时间确保采样电容能充放电到稳定值。对于电位器这种低阻抗源可以设置较短的采样时间如1.5个周期对于高阻抗传感器则需要更长时间。DMA传输如果需要连续、高速采样比如音频信号务必启用DMA。让ADC在后台自动将转换结果搬运到内存数组中CPU只需在数组满后处理数据效率极高。这是体现STM32性能优势的关键技巧。一个常见的坑是采样值跳动。即使输入电压稳定ADC读数最后几位也总是在跳变。这除了电源噪声、参考电压不稳等硬件原因软件上可以采取均值滤波或中值滤波来平滑数据。对于低速信号连续采样10次然后取平均值效果立竿见影。3.3 定时器与PWM控制力的体现定时器是STM32的灵魂外设之一。PZ6806L的定时器资源丰富可以用于精确延时、产生PWM波驱动电机/舵机、编码器接口测速等。以驱动板载的蜂鸣器或无源蜂鸣器播放音乐为例就需要用到PWM。通过CubeMX配置一个定时器如TIM3的某个通道如CH1为PWM Generation模式。关键参数是ARR自动重装载值和CCR捕获比较值。ARR决定了PWM的频率Frequency Timer_CLK / (ARR 1)CCR决定了占空比Duty CCR / (ARR 1)。改变CCR就能改变输出方波的占空比而对于无源蜂鸣器改变ARR即频率就能改变音调。驱动直流电机时通常使用双路互补PWM配合H桥电路这需要用到定时器的高级控制功能如刹车、死区插入等以防止上下桥臂直通短路。PZ6806L的电机驱动接口通常已经接好了H桥芯片你只需要关注产生正确的两路PWM信号即可。3.4 串口通信调试与对话的基石串口USART是嵌入式开发中最重要、最常用的调试和通信接口。PZ6806L板载的USB转串口芯片CH340连接到了MCU的某个USART上如USART1。使用HAL库进行串口收发务必理解其“阻塞”、“中断”、“DMA”三种模式的区别阻塞模式HAL_UART_Transmit和HAL_UART_Receive会一直等待发送或接收完成才返回。简单但会卡住程序只适合在初始化或非实时任务中使用。中断模式调用HAL_UART_Transmit_IT或HAL_UART_Receive_IT后函数立即返回发送或接收完成后会触发中断回调函数。适合不定长、非连续的数据收发。DMA模式最高效的方式。数据搬运完全由DMA控制器完成不占用CPU时间。特别适合高速、大数据量的通信如GPS模块数据接收、与上位机的大量数据交换。一个高级技巧是实现printf重定向这样就能像在PC上一样使用printf函数通过串口打印信息极大提升调试效率。只需重写_write或fputc函数将其指向串口的发送函数即可。3.5 SPI/I2C与外围器件拓展世界板载的OLED屏通常为SSD1306、EEPROMAT24C02、SD卡、无线模块等都需要通过SPI或I2C总线驱动。这里以I2C驱动OLED为例分享一个排错经验。I2C通信失败十有八九是时序问题。首先确认上拉电阻。I2C总线是开漏输出必须接上拉电阻通常4.7kΩ到VCC否则无法输出高电平。开发板上通常已经焊接了。其次检查时钟速度。HAL库的I2C初始化函数里可以设置时钟频率不要超过从设备如OLED支持的最高速度SSD1306通常是400kHz。如果还是不行尝试降低时钟频率比如降到100kHz甚至更低很多通信问题在低速下会消失这能帮你确认是否是时序过于紧张导致的。对于SPI驱动SD卡最大的坑在于电平转换。大多数SD卡是3.3V供电而STM32F103的IO口虽然可以容忍5V输入但输出高电平是5V如果VDD是5V。直接连接可能会损坏SD卡。PZ6806L的SD卡槽电路应该已经考虑了电平匹配。如果没有你需要一个电平转换芯片或电阻分压电路。4. 项目进阶与资源整合从模块到系统当你能熟练驱动各个独立模块后下一步就是将它们整合起来完成一个综合性的小项目。这才是PZ6806L这类“全能板”价值的真正体现。例如我们可以做一个“环境数据采集与显示系统”功能描述通过DS18B20采集温度通过ADC读取光敏电阻值代表光照强度将数据实时显示在TFT液晶屏上同时通过串口发送到电脑并通过WiFi模块ESP8266上传到网络服务器如ThingsBoard或自建TCP服务器。涉及技术点单总线协议驱动DS18B20。需要严格按照时序图编写代码对延时精度有要求最好使用系统滴答定时器SysTick来实现微秒级延时。ADC多通道扫描同时采集电位器和光敏电阻如果连接在不同通道。使用DMA进行循环采集。TFT液晶驱动移植LCD驱动库如TFT_eSPI或直接编写ILI9341底层函数。重点优化刷屏速度避免闪烁。可以采用局部刷新、建立显示缓冲区等策略。实时操作系统RTOS当任务多起来后裸机的while(1)轮询架构会变得难以维护。强烈建议引入FreeRTOS。你可以创建不同的任务一个任务负责传感器数据采集一个任务负责GUI刷新一个任务处理串口通信一个任务管理WiFi连接和数据上传。任务间通过队列、信号量、事件标志组进行同步和通信。这能让你更好地理解多任务、资源管理、优先级调度等核心嵌入式概念。将FreeRTOS移植到PlatformIO项目中非常简单通常只需通过库管理器安装即可。网络通信AT指令控制ESP8266。这里的关键是设计一个健壮的AT指令解析状态机。不要用简单的延时等待回复而是要在串口接收中断中解析接收到的数据根据预设的响应关键字如“OK”“ERROR”“IPD”来触发状态转移和回调函数。处理超时和重发机制是保证连接稳定的关键。在这个项目中你可能会遇到内存不足的问题。当同时使用LCD帧缓冲区、网络数据缓冲区、RTOS的任务栈和堆时64KB的RAM可能会捉襟见肘。这时就需要精细地管理内存使用malloc时要谨慎并确保释放调整RTOS任务栈大小到刚好够用将常量字符串和大的查找表放到Flash中使用const关键字如果使用LCD缓冲区可以考虑使用单色或低色彩深度的缓冲区来节省空间。另一个常见问题是任务优先级设置不当导致的系统卡顿。例如如果GUI刷新任务的优先级最高且执行时间很长可能会阻塞网络任务导致WiFi断连。合理的优先级设计原则是对实时性要求高的任务如电机控制、关键信号采集优先级高但执行时间要短对实时性要求低但计算量大的任务如复杂算法、数据打包优先级低。必要时可以使用二值信号量让高优先级任务等待低优先级任务释放资源。通过这样一个综合项目你会深刻体会到嵌入式系统开发是一个软硬件紧密结合、需要全局考虑和权衡的过程。PZ6806L开发板就像一块练功的木人桩上面集成了各种“穴位”让你可以反复练习和印证各种“招式”外设驱动、协议、RTOS等直到融会贯通。当你能够流畅地在这块板子上实现一个构思的功能时你就已经具备了独立进行STM32项目开发的核心能力。接下来的路就是根据具体项目需求去选择更专用、更核心板化的硬件并运用在这里积累的经验了。