pixhawk 源码分析-SPI驱动-MS5611

2023-05-16

最近学习了一下SPI的驱动软件,在此将其进行总结。

本文使用的代码为pixhawk 1.5.5版本的源码
源码下载地址

第一步函数入口:

老规矩,所有px4的代码的函数入口都是在启动脚本中,启动脚本地址为 

Firmware\ROMFS\px4fmu_common\init.d  目录下 rc.sensors   软件中默认启动不需要做任何修改

    if (!strcmp(verb, "start")) {
        ms5611::start(busid, device_type == 5607 ? MS5607_DEVICE : MS5611_DEVICE);
    }

第二步MS5611与MS5611_SPI的实例化:

start 函数中调用了  start_bus函数,其中包含两个输入参数 bus_options 是ms5611的一些配置信息,如总线协议,设备地址等,device_type是设备型号,芯片名称等。

        started = started | start_bus(bus_options[i], device_type);

start_bus 函数的主要功能

1、运行ms5611_spi.cpp的init函数                        -- SPI的初始化

2、new MS5611 创建MS5611的类并运行构造函数,并将 read ioctl measured 等虚函数进行重写

3、运行ms5611.cpp 中的init 函数

4、open 设备地址,并通过句柄执行ioctl 函数

/**
 * Start the driver.
 */
bool
start_bus(struct ms5611_bus_option &bus, enum MS56XX_DEVICE_TYPES device_type)
{
	if (bus.dev != nullptr) {
		errx(1, "bus option already started");
	}

	prom_u prom_buf;
	device::Device *interface = bus.interface_constructor(prom_buf, bus.busnum);

	if (interface->init() != OK) {        //调用ms5611_spi.cpp 的初始化函数
		delete interface;
		warnx("no device on bus %u", (unsigned)bus.busid);
		return false;
	}

    /*创建对象 MS5611 重构虚函数,运行构造函数*/
	bus.dev = new MS5611(interface, prom_buf, bus.devpath, device_type);

	if (bus.dev != nullptr && OK != bus.dev->init()) {
		delete bus.dev;
		bus.dev = NULL;
		return false;
	}
    /*打开设备*/
	int fd = open(bus.devpath, O_RDONLY);

	/* set the poll rate to default, starts automatic data collection */
	if (fd == -1) {
		errx(1, "can't open baro device");
	}
    /* ioctl 入口,函数入口-开启循环 */
	if (ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT) < 0) {
		close(fd);
		errx(1, "failed setting default poll rate");
	}

	close(fd);
	return true;
}

第三步:ms5611_spi的初始化

在ms5611_spi.cpp 中,首先对SPI接口进行了配置 SPI::init()  --工作模式,频率等

然后对ms5611进行了reset,并尝试是否能读取ms5611的PROM。

int
MS5611_SPI::init()
{
	int ret;

	ret = SPI::init();

	if (ret != OK) {
		DEVICE_DEBUG("SPI init failed");
		goto out;
	}

	/* send reset command */
	ret = _reset();

	if (ret != OK) {
		DEVICE_DEBUG("reset failed");
		goto out;
	}

	/* read PROM */
	ret = _read_prom();

	if (ret != OK) {
		DEVICE_DEBUG("prom readout failed");
		goto out;
	}

out:
	return ret;
}

第四步:ms5611类的实例化并运行init函数

本段代码,创建了环形缓冲区,并发送采集命令,获取采集后的数据

int
MS5611::init()
{
	int ret;

	ret = CDev::init();

	if (ret != OK) {
		DEVICE_DEBUG("CDev init failed");
		goto out;
	}

	/* allocate basic report buffers */
	_reports = new ringbuffer::RingBuffer(2, sizeof(sensor_baro_s));

	if (_reports == nullptr) {
		DEVICE_DEBUG("can't get memory for reports");
		ret = -ENOMEM;
		goto out;
	}

	/* register alternate interfaces if we have to */
	_class_instance = register_class_devname(BARO_BASE_DEVICE_PATH);

	struct baro_report brp;
	/* do a first measurement cycle to populate reports with valid data */
	_measure_phase = 0;
	_reports->flush();

	/* this do..while is goto without goto */
	do {
		/* do temperature first */
		if (OK != measure()) {
			ret = -EIO;
			break;
		}

		usleep(MS5611_CONVERSION_INTERVAL);

		if (OK != collect()) {
			ret = -EIO;
			break;
		}

		/* now do a pressure measurement */
		if (OK != measure()) {
			ret = -EIO;
			break;
		}

		usleep(MS5611_CONVERSION_INTERVAL);

		if (OK != collect()) {
			ret = -EIO;
			break;
		}

		/* state machine will have generated a report, copy it out */
		_reports->get(&brp);

		ret = OK;

		_baro_topic = orb_advertise_multi(ORB_ID(sensor_baro), &brp,
						  &_orb_class_instance, (is_external()) ? ORB_PRIO_HIGH : ORB_PRIO_DEFAULT);


		if (_baro_topic == nullptr) {
			warnx("failed to create sensor_baro publication");
		}

	} while (0);

out:
	return ret;
}

第五段:工作队列进入循环,开始采集

先open设备地址,然后运行ioctl。最后进入work_queue函数,开始循环采集并通过orb将其发送出来。

	int fd = open(bus.devpath, O_RDONLY);    //通过地址打开设备获取句柄

	/* set the poll rate to default, starts automatic data collection */
	if (fd == -1) {
		errx(1, "can't open baro device");
	}
        
        //运行ioctl,从这里进入循环
	if (ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT) < 0) {
		close(fd);
		errx(1, "failed setting default poll rate");
	}

	close(fd);

总结:大致的ms5611驱动的流程就是这样,注意区分各个init函数的调用。这里用了各种类与继承等,还有命名空间等,所以出现了好多同名或大小写不一样的函数,有时候就会找错地方。这里一定要注意。

1、先初始化SPI的接口                --ms5611_spi.cpp

2、再初始化ms5611模块             --ms5611.cpp

3、通过work_queue 函数进行循环采集。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

pixhawk 源码分析-SPI驱动-MS5611 的相关文章

  • 树莓派3B使用mavlink串口连接PIXHAWK_V5

    参考网址 xff1a http ardupilot org dev docs raspberry pi via mavlink html https dev px4 io en robotics dronekit html https do
  • day3. -2 NX的SPI操作

    1 NVIDIA在线文档 https docs nvidia com jetson l4t index html page Tegra 20Linux 20Driver 20Package 20Development 20Guide hw
  • UART,SPI,IIC,RS232通信时序和规则

    一 UART 1 串口通信方式 2 串口通信步骤 注意 xff1a 串口协议规定 xff0c 闲置时必须是高电平 校验位 xff1a 是使用奇偶校验 停止位必须高电平 一个0和多个0区分是靠掐时间 异步通信 xff1a 时钟各不一样 二 I
  • 外设驱动库开发笔记6:AD719x系列ADC驱动

    前面我们讨论了AD7705这种ADC器件的驱动开发 在实际中我们使用更多的是AD719x系列的ADC芯片 包括有AD7191 AD7192和AD7193等 接下来我们就来设计并开发AD719x的驱动程序 1 功能概述 AD7192是一款适合
  • elasticjob 源码分析

    简介 elasticjob是基于quartz构建支持分片的分布式弹性可伸缩的job执行组件 zookeeper节点数据设计 job leader election latch instance 主节点的实例ID 临时节点 在节点选举成功后添
  • 基于c3c2440 Linux SPI驱动程序移植与测试

    基于c3c2440 Linux SPI驱动程序移植与测试 环境 ubuntu14 04 TQ2440开发板 linux3 0内核 linux3 0内核移植笔记点此 1 配置内核 Device Drivers gt SPI support g
  • RT-Thread记录(十六、SFUD组件 — SPI Flash的读写)

    从本文开始 测试学习一些 RT Thread 常用的组件与软件包 先从刚学完的 SPI 设备开始 目录 前言 一 SFUD 组件简介 1 1 基本简介 1 2 SFUD 对 Flash 的管理 二 SFUD 组件操作函数 2 1 初始化相关
  • Hadoop中Mapreduce的Job任务提交流程源码解析

    一 源码解析步骤 1 设置断点 在Driver的job任务提交打上断点进行Debug调试进入其中 F7 进入 F8 下一步 Alt Shift F7 强制进入 Shift F8 退出 进入waitForCompletion 2 submit
  • 使用Linux内核里的spi屏驱动-fbtft

    Linux内核里已经提供spi接口小屏的设备驱动 在内核的配置选项 make menuconfig ARCH arm CROSS COMPILE arm linux gnueabihf Device Drivers gt Graphics
  • Raspberry Pi 与Arduino SPI通信

    本教程介绍了使用SPI 串行外围设备接口总线 进行Raspberry Pi与Arduino通讯和控制的基本框架 SPI代表了一种非常完善的芯片间通信方法 该方法在两种设备的硬件中均实现 在这里 我们将详细探讨SPI 讨论硬件和软件注意事项
  • mission planner SITL仿真系统配置

    背景 主要参考ArduPilot的官网 作者还拥有个人公众号 会写一些感悟文章 知圈 二维码如下 欢迎扫描关注 关注后有作者微信 欢迎添加交流 链路图 图源 Cygwin 下载 去官网下载Cygwin 作者电脑windows 10 64位
  • SpringBoot系列--自定义Starter

    提到Spring Boot时 很多人想到的是它的自动化装配特性 当我们项目需要Redis MongoDB时 只需要引入相应的 spring boot starter data redis spring boot starter data m
  • 各种通信接口的简单对比

    对比表 同步方式与异步方式的主要区别在于 是否传输时钟信号 只要是通訊前雙方需要設定相同波特率的 都是異步傳輸方式 异步传输 Asynchronous Transmission 每次异步传输的信息都以一个起始位开头 它通知接收方数据已经到达
  • STM32+MS5611测气压温度例程详解,测试无误

    硬件平台 STM32F10X MS5611 JLink 软件平台 Keil 4 一 基础知识 首先 MS5611是什么 MS5611气压传感器是集合SPI和I C 高达20 MHz 总线接口的高分辨率气压传感器 分辨率可达到10cm 内部有
  • 气压计MS5611编程操作流程

    文章更新版本 时间 备注 修订人 V0 1 发布于 2019 09 21 11 03 46 初始版本 libo 文章目录 一 开发笔记 二 初始化与工作流程 1 从PROM读取出厂校准值 2 启动温度AD转换 读取AD值 3 启动气压AD转
  • Wifi模块—源码分析Wifi热点扫描2(Android P)

    一 前言 这次接着讲Wifi工程流程中的Wifi热点扫描过程部分的获取扫描结果的过程 也是Wifi扫描过程的延续 可以先看前面Wifi扫描的分析过程 Wifi模块 源码分析Wifi热点扫描 Android P 二 图示调用流程 这次的调用流
  • SPI菊花链原理和配置

    一 概述 在一个主机和多个从器件的典型 SPI 系统中 通常采用专门的片选信号来寻址从器件 随着从器件数量不断增加 片选线也随之增多 这种情况将给电路板布板带来很大的挑战 一个布板方法就是采用菊链结构 本文详细讲述了 SPI 系统的菊链配置
  • Android-模块化通信-简单实用的android spi机制

    目录 前言 一 spi是什么 二 ServiceLoader 1 ExportTableLoader 2 ExportTable 3 LazyLoader 4 ServiceLoader 三 应用 四 总结 前言 为了实现Android 模
  • android 休眠唤醒机制分析(一) — wake_lock

    Android的休眠唤醒主要基于wake lock机制 只要系统中存在任一有效的wake lock 系统就不能进入深度休眠 但可以进行设备的浅度休眠操作 wake lock一般在关闭lcd tp但系统仍然需要正常运行的情况下使用 比如听歌
  • Spidev 不使用 ioctl 同时写入/读取

    我希望找到一些帮助 即使这个问题可能更多地与硬件相关而不是与软件相关 我们将会看到 我正在开发基于 Freescales P1021 处理器 ppc e500v2 内核 的定制板 将连接外部 PCB 并可通过 SPI 进行配置 该外部 PC

随机推荐