模块设计之四十四: bmp280模块"/>
PX4模块设计之四十四: bmp280模块
int bmp280_main(int argc, char *argv[]);
PX4模块设计之四十四: bmp280模块
- 1. bmp280模块简介
- 2. 模块入口函数
- 2.1 主入口bmp280_main
- 2.2 自定义子命令custom_command
- 2.3 模块状态print_status【重载】
- 3. bmp280模块重要函数
- 3.1 模块启动ThisDriver::module_start
- 3.2 模块停止ThisDriver::module_stop
- 3.3 模块状态ThisDriver::module_status
- 3.4 设备实例对象初始化BMP280::instantiate
- 3.5 BMP280设备实例对象初始化BMP280::init
- 3.6 设备实例对象任务I2CSPIDriver::Run()
- 3.7 BMP280设备实例对象任务BMP280::RunImpl
- 4. 总结
- 5. 参考资料
1. bmp280模块简介
bmp280 <command> [arguments...]Commands:start[-I] Internal I2C bus(es)[-X] External I2C bus(es)[-s] Internal SPI bus(es)[-S] External SPI bus(es)[-b <val>] board-specific bus (default=all) (external SPI: n-th bus(default=1))[-c <val>] chip-select pin (for internal SPI) or index (for external SPI)[-m <val>] SPI mode[-f <val>] bus frequency in kHz[-q] quiet startup (no message if no device found)[-a <val>] I2C addressdefault: 118[-s] Internal SPI bus(es)[-S] External SPI bus(es)[-b <val>] board-specific bus (default=all) (external SPI: n-th bus(default=1))[-c <val>] chip-select pin (for internal SPI) or index (for external SPI)[-m <val>] SPI mode[-f <val>] bus frequency in kHz[-q] quiet startup (no message if no device found)stopstatus print status info
注1:print_usage函数是具体对应实现。
class BMP280 : public I2CSPIDriver<BMP280>
class I2CSPIDriver : public I2CSPIDriverBase
class I2CSPIDriverBase : public px4::ScheduledWorkItem, public I2CSPIInstance
class ScheduledWorkItem : public WorkItem
class WorkItem : public IntrusiveSortedListNode<WorkItem *>, public IntrusiveQueueNode<WorkItem *>
class I2CSPIInstance : public ListNode<I2CSPIInstance *>BMP280 //类继承关系└──> I2CSPIDriver└──> I2CSPIDriverBase├──> px4::ScheduledWorkItem│ └──> WorkItem│ ├──> IntrusiveSortedListNode│ └──> IntrusiveQueueNode└──> I2CSPIInstance└──> ListNode
注2:BMP280模块就是针对BMP280硬件芯片进行管理和数据采集的模块。
2. 模块入口函数
2.1 主入口bmp280_main
模块支持start/stop/status命令,除此以外支持BusCLIArguments的I2C/SPI默认参数选项"RXIa:Ssc: m:kb:f:q"。
bmp280_main├──> using ThisDriver = BMP280;├──> BusCLIArguments cli{true, true};├──> <CONFIG_I2C>│ ├──> cli.i2c_address = 0x76;│ └──> cli.default_i2c_frequency = 100 * 1000;├──> <CONFIG_SPI>│ └──> cli.default_spi_frequency = 10 * 1000 * 1000;├──> const char *verb = cli.parseDefaultArguments(argc, argv)├──> <!verb>│ ├──> ThisDriver::print_usage()│ └──> return -1├──> BusInstanceIterator iterator(MODULE_NAME, cli, DRV_BARO_DEVTYPE_BMP280)├──> <!strcmp(verb, "start")>│ └──> return ThisDriver::module_start(cli, iterator) //模块启动├──> <(!strcmp(verb, "stop")>│ └──> return ThisDriver::module_stop(iterator) //模块停止├──> <!strcmp(verb, "status")>│ └──> return ThisDriver::module_status(iterator) //模块状态├──> ThisDriver::print_usage()└──> return -1
2.2 自定义子命令custom_command
注:该模块采用了纯C语言代码实现,在main函数中直接执行命令,无需ModuleBase的custom_command重载实现。
2.3 模块状态print_status【重载】
该模块采用了纯C语言代码实现,在main函数中直接执行ThisDriver::print_usage()函数,无需ModuleBase的模块状态print_status重载实现。
BMP280::print_usage
void
BMP280::print_usage()
{PRINT_MODULE_USAGE_NAME("bmp280", "driver");PRINT_MODULE_USAGE_SUBCATEGORY("baro");PRINT_MODULE_USAGE_COMMAND("start");
#if defined(CONFIG_I2C)PRINT_MODULE_USAGE_PARAMS_I2C_SPI_DRIVER(true, true);PRINT_MODULE_USAGE_PARAMS_I2C_ADDRESS(0x76);
#elsePRINT_MODULE_USAGE_PARAMS_I2C_SPI_DRIVER(false, true);
#endifPRINT_MODULE_USAGE_DEFAULT_COMMANDS();
}
3. bmp280模块重要函数
3.1 模块启动ThisDriver::module_start
启动过程会将以下驱动信息关联到设备实例上:
- static I2CSPIDriverBase *BMP280::instantiate(const I2CSPIDriverConfig &config, int runtime_instance)
- int BMP280::init()
- void BMP280::RunImpl()
- void I2CSPIDriver::Run() final
ThisDriver::module_start(BMP280::module_start)└──> I2CSPIDriver::module_start└──> I2CSPIDriverBase::module_start
注:I2CSPIDriverBase::module_start会进行第一次的Run激活(px4::WorkItemSingleShot)。
3.2 模块停止ThisDriver::module_stop
ThisDriver::module_stop(BMP280::module_stop)└──> I2CSPIDriverBase::module_stop
注:I2CSPIDriverBase类的通用方法,不在这里展开。
3.3 模块状态ThisDriver::module_status
ThisDriver::module_status(BMP280::module_status)└──> I2CSPIDriverBase::module_status
注:I2CSPIDriverBase类的通用方法,不在这里展开。
3.4 设备实例对象初始化BMP280::instantiate
该方法在I2CSPIDriverBase::module_start函数里面调用,其目的是新建一个设备对象实例,并进行初始化。
BMP280::instantiate├──> bmp280::IBMP280 *interface = nullptr;├──> <CONFIG_I2C><config.bus_type == BOARD_I2C_BUS>│ └──> interface = bmp280_i2c_interface(config.bus, config.i2c_address, config.bus_frequency);├──> <CONFIG_SPI><config.bus_type == BOARD_SPI_BUS>│ └──> interface = bmp280_spi_interface(config.bus, config.spi_devid, config.bus_frequency, config.spi_mode);├──> <interface == nullptr>│ ├──> PX4_ERR("failed creating interface for bus %i", config.bus);│ └──> return nullptr;├──> <interface->init() != OK> // I2C/SPI总线初始化│ ├──> delete interface;│ ├──> PX4_DEBUG("no device on bus %i", config.bus);│ └──> return nullptr;├──> BMP280 *dev = new BMP280(config, interface); // 新建一个BMP280设备对象实例├──> <dev == nullptr>│ ├──> delete interface;│ └──> return nullptr;├──> <OK != dev->init()> // BMP280设备对象实例初始化│ ├──> delete dev;│ └──> return nullptr;└──> return dev;
3.5 BMP280设备实例对象初始化BMP280::init
BMP280设备实例对象初始化
BMP280::init├──> [reset sensor]├──> [check id]├──> [set config, recommended settings]├──> [get calibration and pre process them]├──> Start() // 重置模块状态机,然后触发ScheduleNow└──> return OK
3.6 设备实例对象任务I2CSPIDriver::Run()
BMP280设备初始化时以及设置定时时间,定时轮询Run过程,并调用业务实现方法RunImpl。
I2CSPIDriver::Run├──> static_cast<T *>(this)->RunImpl()└──> <should_exit()>└──> exit_and_cleanup() //优雅退出处理
3.7 BMP280设备实例对象任务BMP280::RunImpl
根据BMP280模块业务状态机变化,进行业务操作,发布sensor_baro消息。
BMP280::RunImpl├──> <_collect_phase>│ └──> collect(); // 获取测试数据,并发布sensor_baro消息├──> <else>│ └──> measure(); // 触发一次测试└──> ScheduleDelayed(_measure_interval);
4. 总结
具体逻辑业务后续再做深入,从模块代码角度:
-
输入: 芯片(硬件:bmp280)
-
输出: sensor_baro消息
uORB::PublicationMulti<sensor_baro_s> _sensor_baro_pub{ORB_ID(sensor_baro)};
5. 参考资料
【1】PX4开源软件框架简明简介
【2】PX4模块设计之十一:Built-In框架
【3】PX4模块设计之十二:High Resolution Timer设计
【4】PX4模块设计之十三:WorkQueue设计
【5】PX4模块设计之十七:ModuleBase模块
【6】PX4模块设计之三十:Hysteresis类
【7】PX4 modules_main
【8】PX4模块设计之四十一:I2C/SPI Bus Instance基础知识
更多推荐
PX4模块设计之四十四: bmp280模块
发布评论