1. CMS32入门:从零认识这颗单片机

大家好,我是你们的嵌入式讲师。今天咱们聊聊CMS32系列单片机。说实话,我第一次接触CMS32是在一个工业控制项目里,当时客户要求国产化替代,我翻遍了手册,发现这颗芯片的性价比确实让人眼前一亮。

CMS32系列,说白了就是中微半导体推出的32位ARM Cortex-M0+内核单片机。它不像STM32那样名声在外,但胜在稳定、便宜、供货足。我有个朋友做智能家居,批量采购时一颗能省好几块钱,一年下来省出一辆代步车。

1.1 发展历史:从8位到32位的跨越

中微半导体早年主打8位MCU,在消费电子领域积累了不少口碑。大概2018年左右,他们开始推32位产品线,CMS32就是主力。我记得当时第一颗芯片是CMS32M53xx系列,主频48MHz,内置12位ADC,直接对标STM32F0。

为什么会这样?因为物联网爆发了。8位机跑不了复杂协议栈,32位才是未来。CMS32系列这几年迭代很快,从M0+内核到集成运放、比较器,甚至有些型号直接内置了LCD驱动。你想想看,一颗芯片搞定触摸、显示、通信,省了多少外围器件。

关键节点:

  • 2018年:首款CMS32量产,48MHz M0+内核
  • 2020年:推出集成运放型号,主频提升至72MHz
  • 2022年:发布低功耗系列,休眠功耗低至1μA
  • 2024年:产品线超过50个型号,覆盖工业、汽车、消费

1.2 应用领域:它到底能干什么?

我做过一个项目,用CMS32M5733做电机控制。无刷直流电机,六步换向,PWM频率20kHz。这颗芯片内置了硬件乘除法器,算角度和速度时快得很。以前用8位机算一次要几十微秒,现在几微秒搞定。

CMS32的应用场景其实很广:

领域 典型应用 推荐型号
工业控制 PLC、变频器、伺服驱动 CMS32M57xx
智能家居 智能灯、窗帘、门锁 CMS32L05x
汽车电子 车窗控制、座椅调节 CMS32M53xx
消费电子 电动牙刷、剃须刀、玩具 CMS32F03x
医疗设备 血压计、血氧仪、体温计 CMS32L05x

嗯,这里要注意:选型时别只看主频。我见过有人用72MHz的芯片做电池供电产品,结果功耗超标。低功耗场景一定要选L系列,它们有专门的休眠模式和快速唤醒电路。

1.3 选型指南:怎么挑到合适的芯片?

选型这事儿,我踩过不少坑。曾经有个项目,我选了Flash最小的型号,结果Bootloader加上应用代码,空间只剩2KB。后来加功能时痛苦得要命,只能换芯片重新画板子。

我个人习惯按这个顺序来选:

  1. 先看Flash和RAM:Bootloader至少预留8KB,应用代码按实际需求上浮30%。
  2. 再看外设:需要几路UART?几路ADC?有没有DAC需求?
  3. 然后看封装:TSSOP20适合小产品,LQFP64适合功能复杂的板子。
  4. 最后看供货:冷门型号容易缺货,优先选通用型号。

我的小技巧:选型时留出至少2个GPIO作为备用。万一后期要加个LED指示灯或者调试口,不用重新打板。

下面这张图是我自己整理的CMS32选型思路,你可以参考一下:

CMS32选型决策流程 开始选型 需求分析 Flash & RAM 够吗? 是 否 换更大容量型号 检查外设需求 确认型号 选型时留20%余量

1.4 开发环境搭建:别让工具卡住你

搭建开发环境这事儿,说简单也简单,说麻烦也麻烦。我刚开始用CMS32时,装驱动就折腾了半天。后来发现是Windows的驱动签名问题,关了强制签名就好了。

你需要准备这些东西:

  • IDE:推荐Keil MDK v5.38以上版本,或者IAR for ARM。我个人习惯用Keil,插件多,调试方便。
  • 编译器:ARM Compiler v6或者GCC。Keil自带AC6,直接能用。
  • 调试器:J-Link、ST-Link或者CMS32自家的CMS-ICE。我建议用J-Link,稳定,速度快。
  • 驱动:CMS32的USB虚拟串口驱动,官网下载。
  • SDK:中微官方提供的CMS32 Firmware Library,包含外设驱动和例程。

避坑指南:我曾经因为Keil版本太低,编译CMS32的SDK时报了一堆错。后来发现SDK要求AC6编译器,而旧版Keil默认用AC5。解决办法:升级Keil到5.38以上,或者在工程设置里手动切换编译器。

安装步骤其实很简单:

  1. 先装Keil MDK,一路默认就行。
  2. 装CMS32的器件包。双击.pack文件,Keil会自动识别。
  3. 装调试器驱动。J-Link的话,装SEGGER的驱动包。
  4. 下载SDK,解压到工作目录。

验证环境是否搭好,最快的方法是打开SDK里的一个例程,比如GPIO点灯。编译通过,下载到板子上,灯亮了,就说明环境没问题。

// 一个简单的点灯程序
#include "CMS32M57xx.h"

void delay(void) {
    for(uint32_t i = 0; i < 500000; i++);
}

int main(void) {
    // 使能GPIOB时钟
    RCC->AHBENR |= RCC_AHBENR_GPIOBEN;
    // 配置PB0为推挽输出
    GPIOB->MODER &= ~(3 << (0 * 2));
    GPIOB->MODER |= (1 << (0 * 2));
    
    while(1) {
        GPIOB->ODR ^= (1 << 0);  // 翻转PB0
        delay();
    }
}

嗯,这里要注意:CMS32的GPIO默认是输入模式,而且内部没有上拉。如果你直接配置成输出,引脚电平是不确定的。我习惯先拉高或者拉低再使能输出。

我的习惯:每次新建工程时,先把系统时钟配置好。CMS32默认用内部HSI振荡器,精度一般。如果项目对时序要求高,建议切换到外部晶振,8MHz或者16MHz都行。