第一章:PX4与SPI基础

各位同学好,我是你们的飞控开发工程师。今天咱们来聊聊PX4驱动SPI设备这件事。说实话,我刚开始接触PX4的时候,也被它的架构绕得晕头转向。但别担心,我会用最接地气的方式,带你把这块硬骨头啃下来。

1.1 PX4架构概览

先说说PX4的整体架构。说白了,它就是一个模块化的实时操作系统。我习惯把它想象成一个三层蛋糕:最底层是硬件抽象层,中间是核心调度层,最上面是应用层。

为什么会这样设计?你想想看,如果所有代码都揉在一起,改一个传感器驱动就得重新编译整个固件,那得多痛苦。PX4把驱动、控制算法、通信协议都拆成了独立的模块,每个模块各司其职。

核心模块关系:

  • uORB(微对象请求代理):模块间的消息总线,所有数据都通过它传递
  • Driver Framework:驱动框架,负责管理硬件外设
  • Navigator/Commander:导航与任务管理
  • Estimator:状态估计,比如EKF2

我记得第一次看PX4源码时,最让我头疼的就是uORB。但后来发现,它其实就是个发布-订阅模型。传感器驱动发布数据,控制算法订阅数据,就这么简单。

应用层 (Application Layer) 导航模块 任务规划 遥控器处理 日志记录 通过uORB与下层通信 核心调度层 (Core Layer) EKF2状态估计 姿态控制 位置控制 混控器 实时调度,优先级管理 硬件抽象层 (HAL) SPI驱动 I2C驱动 UART驱动 GPIO ADC 直接操作寄存器,提供统一接口

1.2 SPI协议原理

SPI,全称串行外设接口。嗯,名字挺唬人,但说白了就是四根线的事:

信号线 名称 作用
SCLK 时钟线 由主机产生,决定通信速率
MOSI 主机输出/从机输入 主机发送数据给从机
MISO 主机输入/从机输出 从机发送数据给主机
CS 片选线 低电平有效,选中对应从机

SPI有四种模式,由时钟极性(CPOL)和时钟相位(CPHA)决定。我刚开始做项目时,经常因为模式不匹配导致通信失败。后来学乖了,每次拿到新传感器,第一件事就是看数据手册里的时序图。

我的小技巧:调试SPI通信时,先用逻辑分析仪抓波形。看看时钟是不是对的,数据是不是在正确的边沿采样。这比盯着代码看半天管用多了。

1.3 飞控中的SPI总线拓扑

在PX4飞控上,SPI总线是怎么连的?我以Pixhawk为例,给你画个图:

STM32F7 主控 SPI1 总线 (高速传感器) ICM-20602 (IMU) BMI088 (IMU) IST8310 (磁力计) MS5611 (气压计) SPI2 总线 (外部设备) 外部GPS模块 外部光流传感器 扩展IO板

看到没?SPI1总线上挂的都是高速传感器,IMU、磁力计这些。SPI2总线留给外部设备。为什么要分开?因为IMU数据需要高频率读取,如果和低速设备混在一起,会严重影响实时性。

注意:SPI总线上所有设备共享SCLK、MOSI、MISO三根线。每个设备有独立的CS片选线。我曾经遇到过一个问题:两个设备的CS引脚在PCB上不小心短接了,结果一读A设备,B设备也跟着响应,数据全乱了。

1.4 PX4中的SPI驱动框架

在PX4里写SPI驱动,其实有固定的套路。我总结一下核心步骤:

  1. 继承基类:从SPI类派生你的设备驱动
  2. 实现probe():检测设备是否存在,读取ID寄存器
  3. 实现init():初始化设备,配置寄存器
  4. 实现ioctl():处理控制命令
  5. 注册到uORB:发布传感器数据

给你看个最简单的SPI读操作示例:

// 读取SPI设备寄存器
uint8_t spi_read_reg(uint8_t reg) {
    uint8_t tx_buf[2] = {reg | 0x80, 0x00};  // 最高位置1表示读
    uint8_t rx_buf[2] = {0};
    
    struct spi_transfer_t transfer = {
        .tx_buf = tx_buf,
        .rx_buf = rx_buf,
        .len = 2
    };
    
    spi_transfer(SPI_DEV, &transfer, 1);
    return rx_buf[1];  // 第二个字节是读到的数据
}

这里有个细节:SPI读操作时,第一个字节发的是寄存器地址(最高位置1),同时主机要发一个空字节来产生时钟,从机才会把数据送出来。这个坑我踩过,第一次写驱动时忘了发空字节,读回来的全是0xFF。

关键点总结:

  • SPI是全双工通信,收发同时进行
  • CS片选必须由软件精确控制,时序要求严格
  • PX4中SPI驱动通过SPIDev类管理总线
  • 每个SPI设备在启动时注册,通过uORB发布数据

好了,这一章的基础知识就讲到这里。记住,理解PX4的架构和SPI协议是后面写驱动的基础。下一章我们会动手写一个真实的传感器驱动,到时候这些概念都会用上。

课后建议:找一块Pixhawk飞控板,用万用表量一下SPI总线的引脚,看看CS片选是怎么分配的。动手操作比看书印象深刻多了。

专注资料整理