2、单片机选型与硬件平台:STM32/GD32选型依据、最小系统电路、电源设计、晶振与复位电路
好,咱们开始第二章。这一章聊的是硬件选型和最小系统设计。说白了,就是决定用哪颗芯片,以及怎么让它跑起来。
很多初学者喜欢一上来就画原理图、焊板子。我个人习惯是,先花半天时间把选型定死。芯片选错了,后面所有工作都得推倒重来。我在项目中遇到过不止一次,因为选型时少看了一个外设资源,导致后期不得不换平台,那叫一个痛苦。
2.1 STM32 vs GD32:怎么选?
先说说这两家的关系。GD32是国产兆易创新的产品,指令集和STM32高度兼容。说白了,你拿STM32的代码,改几个头文件,基本就能在GD32上跑。但两者还是有区别的。
| 对比项 | STM32(意法半导体) | GD32(兆易创新) |
|---|---|---|
| 主频 | 通常72MHz~240MHz | 同定位下略高,可达108MHz~200MHz |
| Flash速度 | 零等待执行(ART加速器) | 零等待执行,但部分型号需注意预取配置 |
| 价格 | 较高,尤其近两年涨价严重 | 便宜,性价比突出 |
| 供货 | 交期不稳定 | 国产芯片,供货相对稳定 |
| 生态 | 极其成熟,资料多如牛毛 | 兼容STM32生态,但部分库需适配 |
| 抗干扰 | 经过大量工业验证,稳定 | 中低端应用没问题,极端环境需测试 |
我的建议是:
- 做产品量产,尤其是成本敏感的暖通控制器,优先考虑GD32。省下来的钱够买好几个传感器了。
- 做样机或学习,用STM32。资料多,遇到问题好查。我记得第一次用GD32时,有个定时器配置死活不对,最后发现是库函数里一个宏定义和STM32不一样。
- 如果项目要求高可靠性,比如医院空调、数据中心精密空调,我建议用STM32。抗干扰和长期稳定性确实更让人放心。
核心原则:选型不是选最好的,而是选最合适的。暖通空调控制对算力要求不高,但对IO数量和PWM通道数有要求。先列需求,再选芯片。
2.2 最小系统电路
芯片选好了,接下来就是让它能工作。最小系统,说白了就是让单片机“活过来”的最低配置。包括:电源、晶振、复位、下载电路。
嗯,这里要注意。很多新手画最小系统,照着网上的图抄一遍就完事了。但实际项目中,每个引脚怎么接都是有讲究的。
2.2.1 电源设计
单片机需要稳定的3.3V供电。暖通空调系统里,通常有24V交流或12V直流输入。所以需要一级降压。
我个人习惯用两级方案:
- 第一级:用DC-DC降压芯片(比如MP2359、TPS5430),把12V或24V降到5V。效率高,发热小。
- 第二级:用LDO(比如AMS1117-3.3),把5V降到3.3V。纹波小,给单片机供电更干净。
我曾经在一个项目中,为了省成本,直接用LDO从12V降到3.3V。结果LDO烫得能煎鸡蛋,没几天就烧了。后来老老实实加了DC-DC,问题解决。
警告:单片机电源引脚旁边,一定要加0.1μF和10μF的去耦电容。而且电容要尽量靠近芯片引脚。这不是玄学,是电磁兼容的基本要求。不加的话,单片机容易死机、复位、甚至烧坏。
2.2.2 晶振电路
晶振是单片机的心脏。没有它,单片机就没法按节奏工作。
STM32/GD32通常需要两个晶振:
- 主晶振(HSE):8MHz。用于产生系统时钟。为什么是8MHz?因为内部PLL可以倍频到72MHz或更高。
- RTC晶振(LSE):32.768kHz。用于实时时钟,省电。
晶振电路其实很简单,就是晶振两端各接一个20pF左右的电容到地。但这里有个坑:
避坑指南:我曾经遇到过晶振不起振的情况。查了半天,发现是PCB布局时,晶振走线太长,而且旁边有高频信号干扰。后来把晶振紧贴芯片引脚,走线尽量短,地线包一圈,问题解决。记住:晶振走线越短越好,周围不要走其他信号线。
代码里配置时钟也很简单,以STM32为例:
// 配置系统时钟为72MHz
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
// 使能HSE晶振
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 8; // 8MHz / 8 = 1MHz
RCC_OscInitStruct.PLL.PLLN = 72; // 1MHz * 72 = 72MHz
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; // 72MHz / 2 = 36MHz? 不对,这里PLLP是主时钟输出
// 实际STM32F103的PLLP是分频系数,通常设为RCC_PLLP_DIV2,输出72MHz
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
// 配置系统时钟源为PLL
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;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; // APB1最大36MHz
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // APB2最大72MHz
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
这段代码看着长,其实逻辑很简单:先让外部8MHz晶振工作,然后通过PLL倍频到72MHz,最后把系统时钟切换到PLL输出。
2.2.3 复位电路
复位电路的作用,就是让单片机在上电时,从一个确定的状态开始运行。
最简单的复位电路:一个10kΩ上拉电阻接到3.3V,一个0.1μF电容接到GND,中间引出复位引脚。上电瞬间,电容充电,复位引脚保持低电平,等电容充满后,引脚变为高电平,单片机开始运行。
但实际项目中,我建议加一个复位芯片,比如MAX809。为什么?
- 它能提供精确的复位阈值。当电压低于某个值(比如2.93V)时,强制复位。
- 它能防止电压抖动导致的误复位。
我曾经在一个项目中,电源纹波比较大,导致单片机频繁复位。用示波器一看,复位引脚在电压波动时出现了毛刺。后来加了一个复位芯片,世界清净了。
总结一下最小系统设计要点:
- 电源:两级降压,DC-DC + LDO,去耦电容不能省
- 晶振:走线短,远离干扰,匹配电容要选对
- 复位:RC电路够用,但工业应用建议加复位芯片
- 下载电路:SWD接口,留出SWDIO、SWCLK、GND、3.3V四个引脚
嗯,这一章的内容就这些。选型和最小系统是硬件设计的基础,基础打牢了,后面写代码、调参数才能顺风顺水。下一章我们聊传感器选型与接口设计,到时候见。