1.7 CAN - 实验篇
1.7 CAN - 实验篇
Sarzn这一章开始我们将使用真正的大疆主控板来完成接下来的学习 这一章开始我们将使用真正的大疆主控板来完成接下来的学习
我这里采用的大疆 A 板, 它的参数如下
主控单元为: STM32F427IIH6 12MHz 晶振, 可配置最高主频 180MHz
CAN 发送: 把发送数据放到 CAN 发送邮箱中, 有它自主控制发送, 放进去就不管了. 我们用到的 STM32F427, 每条 CAN 总线上有 3 个发送邮箱 这也意味着, 考虑到发送需要时间, 我们在代码层面上, 最多只能同时朝总线灌3 个 can 帧, 再多就发不出去了
CAN 接收: 从接收队列(FIFO 队列)选择接收, 可配合中断使用 我们用到的 STM32F427, 每条 CAN 总线上有 2 个接收队列
这个实验中, 我们要利用 CAN 信号来点灯.
- CAN1 自发自收
- 发送方发送一字节数据指明灯的序号
- 接收方接收后直接在中断函数中处理信息, 熄灭对应的灯, 直到下次指令重新点灯
用到的有关元件与对应引脚, 详细请参考大疆 A 型开发板用户手册
- LED1-8: PG1-PG8, 低电平点亮
- CAN1: PD0, PD1 在 APB1 总线上



CubeMX配置
和之前的一样, 配置完基本的内容(时钟树性能拉满)之后…
- 配置PG1-8 为 GPIO_Output 作为 LED, 并将其初始电平配置为 high
- 配置 PD0, PD1 为 CAN1
接下来进入CAN1 的详细配置选项

发现是 45MHz, 根据刚刚原理篇学过的妙妙小公式, 如果我的预分频为 9, Tq 应该是 200ns 也是对的. 说明我们是对的 接下来就要分配相位缓冲段 1 和相位缓冲段 2 的时间片
根据妙妙小公式, 同步段保持 1 个时间片不变, 相位缓冲段 1 和相位缓冲段都各分配 2个时间片, 这样比较合理
但是如果你在上图的情况下直接选择相位缓冲段 1 为 2
的话会报错
这样, 我们就美美配置好了
Bit Timings Parameters(位时序)
决定波特率
| 选项 | 含义 |
|---|---|
| Prescaler (for Time Quantum) | 分频系数,决定一个时间片 Tq 多长。Tq = Prescaler / f_APB1 |
| Time Quantum | 一个 Tq 的时长,由 Prescaler 自动算出 |
| Time Quanta in Bit Segment 1 | BS1 占几个 Tq(= 传播段 + 相位缓冲段1) |
| Time Quanta in Bit Segment 2 | BS2 占几个 Tq(= 相位缓冲段2);采样点在 BS1 与 BS2 之间 |
| Time for one Bit | 一个 bit 总时长 =(1 + BS1 + BS2)× Tq |
| Baud Rate | 波特率 = 1 / 位时间 = 1 Mbps,这组配置的最终产物 |
| ReSynchronization Jump Width | 即 SJW,重同步时相位缓冲段最多伸缩几个 Tq |
Basic Parameters(基本行为开关)
| 选项 | 含义 |
|---|---|
| Time Triggered Communication Mode | 时间触发通信(TTCAN),按时间表调度、给帧打时间戳;普通场合用不到 |
| Automatic Bus-Off Management | 进入 bus-off 后是否由硬件自动按协议恢复。关=需软件手动恢复 |
| Automatic Wake-Up Mode | 睡眠时检测到总线活动是否自动唤醒。关=需软件手动唤醒 |
| Automatic Retransmission | 发送失败(仲裁失利/出错)是否自动重发。注意:这里 Disable 表示: 开启自动重传, CubeMX 这项是反逻辑的(对应寄存器 NART),Disable NART = 允许重传 |
| Receive Fifo Locked Mode | 接收 FIFO 满时:Disable=新帧覆盖旧帧;Enable=锁住丢弃新帧 |
| Transmit Fifo Priority | 发送顺序:Disable=按报文 ID 优先级发;Enable=按进入邮箱的先后(FIFO)发 |
最后把模式改为静默回环, 再去 NVIC 设置勾上对应的中断就可以生成代码了!
看到这里不妨想一想: 我们如果这样配置分频器和相位缓冲段的时间片的话, 采样点是在 60%. 这有一点靠前了. 但是理想的应该是在 75% 左右. 那么聪明的你想到了怎样的配置呢? 请在评论区写下来吧!
代码
首先我们配置滤波器的宏(macro)定义
总的来说就是这样: 编号[3:] | FIFOx[2:2] | ID类型[1:1] | 帧类型[0:0]
1 | /* Private macro -------------------------------------------------------------*/ |
然后, 设置一个CAN 启动并且开启中断的函数
1 | /* Private user code ---------------------------------------------------------*/ |
填HAL结构体写入滤波器
把打包好的 Object_Para 拆开,连同 ID、Mask_ID 一起,填进 HAL 的 CAN_FilterTypeDef 结构体,最后交给 HAL_CAN_ConfigFilter 写进滤波器
1 | /** |
写发送的标准数据帧的内容
1 | /** |
接收数据之后, LED的控制函数
1 | /** |
写接收中断函数
1 | /** |
利用我们之前写好的函数初始化 can 以及配置滤波器
1 | /* USER CODE BEGIN 2 */ |
利用发送数据函数, 开始点灯
1 | /* Infinite loop */ |
烧录
记得把之前的 daplink 的 cfg 文件改成 f4 哦
也是美美用上 can 了!









