1. 课程导学与开发环境搭建
各位同学,欢迎来到《CMS32 CAN通信与Bootloader开发实战》的第一章。我是这门课的主讲,做了十几年嵌入式固件开发,踩过的坑比走过的路还多。今天咱们先把地基打牢——聊聊CMS32芯片是什么、CAN协议怎么玩、Bootloader到底干嘛用,最后把开发环境搭起来,跑个点灯程序。
说实话,很多工程师学CAN通信和Bootloader,上来就啃协议栈和代码,结果越学越懵。我个人的习惯是:先搞清楚“这东西为什么存在”,再动手。所以这一章,咱们不急着写代码,先把概念理清楚。
本章核心目标:
- 了解CMS32芯片的定位与资源
- 理解CAN协议的基本原理
- 建立Bootloader的宏观认知
- 完成开发环境搭建并运行第一个程序
1.1 CMS32芯片简介
CMS32是国民技术推出的一款基于ARM Cortex-M0+内核的32位微控制器。你想想看,在工业控制、汽车电子、物联网终端这些领域,它算是性价比很高的选择。
我最早接触CMS32是在一个车载网关项目上。当时客户要求成本压到最低,但CAN接口、低功耗、宽温范围一个都不能少。选来选去,CMS32正好满足——它内置了CAN控制器,省掉了外挂CAN芯片的成本和PCB面积。
来看一下CMS32的主要资源:
| 资源项 | 参数 |
|---|---|
| 内核 | ARM Cortex-M0+,最高48MHz |
| Flash | 64KB ~ 128KB |
| SRAM | 8KB ~ 16KB |
| CAN接口 | 1路CAN 2.0B,支持标准帧和扩展帧 |
| 其他外设 | UART、SPI、I2C、ADC、定时器 |
| 工作温度 | -40°C ~ +105°C |
嗯,这里要注意:CMS32的CAN控制器是集成在芯片内部的,但物理层还需要外接一个CAN收发器,比如TJA1050或者SN65HVD230。别问我为什么知道——我第一次画板子就忘了加收发器,调试了一整天发现CAN总线一点反应都没有。
1.2 CAN协议基础
CAN(Controller Area Network)是德国博世公司在80年代为汽车电子设计的串行通信协议。说白了,它就是为了解决车上那么多ECU(电子控制单元)之间怎么可靠地传数据。
为什么CAN能成为工业通信的常青树?我个人总结三点:
- 多主通信:任何节点都可以主动发消息,不需要主机轮询
- 实时性强:基于优先级的总线仲裁,高优先级报文不等待
- 可靠性高:差分信号传输,抗干扰能力强;还有CRC校验、错误帧检测
CAN协议里有两个核心概念你必须搞懂:
- 标准帧(CAN 2.0A):11位标识符,数据段最多8字节
- 扩展帧(CAN 2.0B):29位标识符,数据段最多8字节
我在项目中遇到过一个问题:两个设备用CAN通信,一个只支持标准帧,另一个默认发扩展帧,结果两边死活对不上话。后来查了半天才发现是帧格式不匹配。所以做CAN通信,第一件事就是确认帧格式。
CAN的物理层用的是差分信号——CAN_H和CAN_L两根线。显性电平(逻辑0)和隐性电平(逻辑1)通过电压差来区分。这也是CAN抗干扰能力强的根本原因。
小提示:CAN总线的终端电阻很重要。标准CAN总线两端各需要120Ω电阻,用来消除信号反射。没有终端电阻,总线在高速通信时会出现波形畸变。我见过有人偷懒不焊终端电阻,结果通信距离超过1米就开始丢包。
1.3 Bootloader概念
Bootloader,直译就是“引导加载程序”。它是一段在系统上电后最先执行的代码,负责初始化硬件、检查固件版本、决定是跳转到应用程序还是进入固件升级模式。
你想想看,产品已经卖出去了,发现固件有bug或者需要增加新功能,难道要把设备拆回来重新烧录?Bootloader就是为了解决这个问题——通过CAN、UART、USB等接口远程升级固件。
一个典型的Bootloader工作流程是这样的:
- 系统上电,CPU从复位向量跳转到Bootloader入口
- Bootloader初始化时钟、外设(比如CAN控制器)
- 检查升级标志(比如某个GPIO电平、Flash中的标志位)
- 如果需要升级,进入固件接收和烧写流程
- 如果不需要升级,跳转到应用程序入口
这里有个关键点:Bootloader和应用程序在Flash中是分区域存放的。Bootloader通常放在Flash的低地址区,应用程序放在高地址区。跳转的时候要修改中断向量表偏移,否则中断会跑飞。
警告:Bootloader开发中最容易翻车的就是中断向量表配置。我曾经在一个项目里,Bootloader跳转到APP后,所有中断都不响应——因为忘了把VTOR寄存器指向APP的中断向量表。这个问题查了整整两天。
1.4 开发板介绍
本课程使用的开发板是基于CMS32芯片设计的,板载资源如下:
- CMS32主控芯片
- CAN收发器(TJA1050)
- USB转串口(用于调试和烧录)
- LED指示灯(2个)
- 按键(2个)
- CAN接口端子
板子的CAN接口已经接好了终端电阻,默认是120Ω。如果你要级联多块板子,记得把中间节点的终端电阻去掉。
1.5 IDE安装与配置
我们使用的IDE是ARM Keil MDK,版本建议5.38及以上。安装步骤不复杂,但有几个坑我帮你提前踩了:
- 从Keil官网下载MDK安装包,注意选择ARM版本
- 安装时路径不要带中文和空格
- 安装完成后,打开Pack Installer,安装CMS32的器件支持包
- 如果Pack Installer下载慢,可以去国民技术官网手动下载并导入
配置工程时,有几点要注意:
- 选择正确的芯片型号(CMS32L051或具体型号)
- 时钟配置:外部晶振8MHz,PLL倍频到48MHz
- Debug工具选择CMSIS-DAP或J-Link
小提示:Keil的工程配置里,Target标签页的“ARM Compiler”建议选V6版本,编译效率更高。但如果你用V6编译报错,可以切回V5试试——有些老代码对V6支持不好。
1.6 第一个点灯程序
好了,理论说完了,咱们动手写个点灯程序。这是嵌入式开发的“Hello World”,也是验证开发环境是否搭好的标准方法。
代码很简单,就是让板子上的LED以500ms的间隔闪烁:
#include "CMS32L051.h"
// 延时函数,简单粗暴
void delay(volatile uint32_t count) {
while(count--);
}
int main(void) {
// 使能GPIOB时钟
SYS->AHBEN |= (1 << 1);
// 配置PB0为推挽输出
GPIOB->MODER &= ~(0x3 << (0 * 2));
GPIOB->MODER |= (0x1 << (0 * 2));
while(1) {
GPIOB->BSRR = (1 << 0); // PB0输出高电平,LED亮
delay(500000);
GPIOB->BRR = (1 << 0); // PB0输出低电平,LED灭
delay(500000);
}
}
编译通过后,用调试器下载到板子。如果LED开始闪烁,恭喜你——开发环境搭建成功!
嗯,这里有个小细节:延时函数的计数值500000是基于48MHz主频估算的,实际延时可能不是精确的500ms。精确延时要用定时器,咱们后面章节会讲。
本章知识结构
为了让你对本章内容有个整体把握,我画了一张知识结构图:
这张图把本章的知识点串起来了。中心是课程导学与环境搭建,四个分支分别对应芯片、协议、Bootloader和开发工具,每个分支下面还有具体的子知识点。你可以把它当作本章的导航地图。
好了,第一章的内容就到这里。开发环境搭好了,点灯程序跑起来了,接下来咱们就可以正式进入CAN通信的世界了。