ICM20948 DMP代码详解(5)

news/2024/9/16 18:30:43 标签: ICM20948, DMP

接前一篇文章:ICM20948 DMP代码详解(4)

 

上一回开始深入到代码,先从EMP-App中的入口函数main开头,该函数在EMD-App\src\ICM20948\main.c中,再次贴出其代码如下:

int main (void)
{
	int rc = 0;

	/* Hardware initialization */
	sysclk_init();
	board_init();
	sysclk_enable_peripheral_clock(ID_TC0);

	/* Configure Device - Host Interface */
	configure_console();

#ifdef INV_MSG_ENABLE
	/* Setup message logging */
	INV_MSG_SETUP(INV_MSG_ENABLE, msg_printer);
#endif

	INV_MSG(INV_MSG_LEVEL_INFO, "##########################");
	INV_MSG(INV_MSG_LEVEL_INFO, "     ICM20948 example     ");
	INV_MSG(INV_MSG_LEVEL_INFO, "     Ver: %s", EMD_RELEASE_VERSION_STRING);
	INV_MSG(INV_MSG_LEVEL_INFO, "##########################");

	/* Initialize External Sensor Interrupt */
	ext_int_initialize(&ext_interrupt_handler);
	interface_initialize();

	/* Configure sysTick Timer */
	SysTick_Config(sysclk_get_cpu_hz() / MILLISECONDS_PER_SECOND);

	/*
	* Initialize icm20948 serif structure
	*/
	struct inv_icm20948_serif icm20948_serif;
	icm20948_serif.context   = 0; /* no need */
	icm20948_serif.read_reg  = idd_io_hal_read_reg;
	icm20948_serif.write_reg = idd_io_hal_write_reg;
	icm20948_serif.max_read  = 1024*16; /* maximum number of bytes allowed per serial read */
	icm20948_serif.max_write = 1024*16; /* maximum number of bytes allowed per serial write */

	icm20948_serif.is_spi = interface_is_SPI();

	/*
	* Reset icm20948 driver states
	*/
	inv_icm20948_reset_states(&icm_device, &icm20948_serif);

	inv_icm20948_register_aux_compass(&icm_device, INV_ICM20948_COMPASS_ID_AK09916, AK0991x_DEFAULT_I2C_ADDR);

	/*
	* Setup the icm20948 device
	*/
	rc = icm20948_sensor_setup();

	/*
	* Now that Icm20948 device was initialized, we can proceed with DMP image loading
	* This step is mandatory as DMP image are not store in non volatile memory
	*/
	rc += load_dmp3();
	check_rc(rc, "Error sensor_setup/DMP loading.");

	/*
	* Initialize Dynamic protocol stuff
	*/
	DynProTransportUart_init(&transport, iddwrapper_transport_event_cb, 0);
	DynProtocol_init(&protocol, iddwrapper_protocol_event_cb, 0);

	InvScheduler_init(&scheduler);
	InvScheduler_initTask(&scheduler, &commandHandlerTask, "commandHandlerTask", CommandHandlerTaskMain, 0, INVSCHEDULER_TASK_PRIO_MIN, 1);
	InvScheduler_initTask(&scheduler, &blinkerLedTask, "blinkerLedTask", BlinkerLedTaskMain, 0, INVSCHEDULER_TASK_PRIO_MIN+1, 1000000/SCHEDULER_PERIOD);
	InvScheduler_startTask(&blinkerLedTask, 0);
	InvScheduler_startTask(&commandHandlerTask, 0);

	hw_timer_start(20);		// Start the timestamp timer at 20 Hz.
	while (1)
    {
		InvScheduler_dispatchTasks(&scheduler);

		if (irq_from_device == 1) {
			inv_icm20948_poll_sensor(&icm_device, (void *)0, build_sensor_event_data);

			__disable_irq();
			irq_from_device = 0;
			__enable_irq();
		}
	}

	return 0;
}

上一回也提到,由于工程中的代码是适配TDK SAMG55开发板的(TDK SAMG55 Dev Kit)的,而笔者的目标平台是乐鑫的ESP32系列模组,因此属于系统初始化的相关内容(以下代码片段)可以略过。

	/* Hardware initialization */
	sysclk_init();
	board_init();
	sysclk_enable_peripheral_clock(ID_TC0);

	/* Configure Device - Host Interface */
	configure_console();

#ifdef INV_MSG_ENABLE
	/* Setup message logging */
	INV_MSG_SETUP(INV_MSG_ENABLE, msg_printer);
#endif

	INV_MSG(INV_MSG_LEVEL_INFO, "##########################");
	INV_MSG(INV_MSG_LEVEL_INFO, "     ICM20948 example     ");
	INV_MSG(INV_MSG_LEVEL_INFO, "     Ver: %s", EMD_RELEASE_VERSION_STRING);
	INV_MSG(INV_MSG_LEVEL_INFO, "##########################");

	/* Initialize External Sensor Interrupt */
	ext_int_initialize(&ext_interrupt_handler);
	interface_initialize();

	/* Configure sysTick Timer */
	SysTick_Config(sysclk_get_cpu_hz() / MILLISECONDS_PER_SECOND);

当然,这里的略过并不是说完全不关注,而只是不用深入其具体实现,但是仍然需要留意系统的相关时钟、外设(尤其是i2c)接口的初始化,以便后边对到ESP32(ESP-IDF)中。

从以下部分开始,才是需要重点关注的内容:

	/*
	* Initialize icm20948 serif structure
	*/
	struct inv_icm20948_serif icm20948_serif;
	icm20948_serif.context   = 0; /* no need */
	icm20948_serif.read_reg  = idd_io_hal_read_reg;
	icm20948_serif.write_reg = idd_io_hal_write_reg;
	icm20948_serif.max_read  = 1024*16; /* maximum number of bytes allowed per serial read */
	icm20948_serif.max_write = 1024*16; /* maximum number of bytes allowed per serial write */

	icm20948_serif.is_spi = interface_is_SPI();

struct inv_icm20948_serif的定义在EMD-Core\sources\Invn\Devices\Drivers\ICM20948\Icm20948Serif.h中,如下:

/** @brief ICM20948 serial interface
 */
struct inv_icm20948_serif {
	void *     context;
	int      (*read_reg)(void * context, uint8_t reg, uint8_t * buf, uint32_t len);
	int      (*write_reg)(void * context, uint8_t reg, const uint8_t * buf, uint32_t len);
	uint32_t   max_read;
	uint32_t   max_write;
	inv_bool_t is_spi;
};

其中包含了6个成员:

  • void *context

可以理解成句柄。

  • int      (*read_reg)(void * context, uint8_t reg, uint8_t * buf, uint32_t len);

寄存器读回调函数。后文书实际用到的时候再深入讲解。

  • int      (*write_reg)(void * context, uint8_t reg, const uint8_t * buf, uint32_t len);

寄存器写回调函数。后文书实际用到的时候再深入讲解。

  • uint32_t   max_read;

最大能够读取的字节数。

  • uint32_t   max_write;

最大能够写入的字节数。

  • inv_bool_t is_spi;

是否为SPI接口。由于ICM20948可以支持I2C和SPI两种接口,因此以此标志进行区分。

e91538fb7d9d4756971f1fd5e97b01da.png

485d7edc71cc49b5a61e531cfae52a8f.png

回到main函数中。以上代码片段是在主函数中新建了一个struct inv_icm20948_serif 的对象icm20948_serif,然后对其进行初始化。

  • *context设置为0即NULL,不需要;
  • read_reg函数指针设置为idd_io_hal_read_reg;
  • write_reg函数指针设置为idd_io_hal_write_reg;
  • max_read设置为16 * 1024,即16K字节;
  • max_write也设置为16K字节;
  • is_spi设置为interface_is_SPI()的返回值。

interface_is_SPI函数在EMD-App\src\ICM20948\system.c中,代码如下:

inv_bool_t interface_is_SPI(void)
{
#if SERIF_TYPE_SPI
	return true;
#else
	return false;
#endif	
}

官方代码中是根据SERIF_TYPE_SPI宏来进行判断的。如果是自己的硬件,已经确定好使用I2C或SPI,直接返回false或true就好。

至此,main函数中的第一段所关注的代码就解析完了,余下代码的解析请看后篇。

 

 


http://www.niftyadmin.cn/n/5645469.html

相关文章

ubantu安装mysql + redis数据库并使用C/C++操作数据库

mysql 安装mysql ubuntu 安装 MySql_ubuntu安装mysql-CSDN博客 Ubuntu 安装 MySQL 密码设置_ubuntu安装mysql后设置密码-CSDN博客 service mysql restart1 C/C连接数据库 C/C 连接访问 MySQL数据库_c mysql-CSDN博客 ubuntu安装mysql的c开发环境_ubuntu 搭建mysql c开发…

# 键盘字母上有下标数字,输入时怎么一键去掉,关闭键盘上的下标数字。‌

键盘字母上有下标数字,输入时怎么一键去掉,关闭键盘上的下标数字。‌ 一、问题描述: 如下图,有的笔记本电脑键盘上,没有数字小键盘,数字小键盘会和字母混和在一起,这样打字时,不容…

Spring6详细学习笔记(IOC+AOP)

一、Spring系统架构介绍 1.1、定义 Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器(框架)。Spring官网 Spring是一款主流的Java EE 轻量级开源框架,目的是用于简化Java企业级引用的开发难度和开发周期。从简单性、可测试性和松耦…

Redis 篇-深入了解基于 Redis 实现分布式锁(解决多线程安全问题、锁误删问题和确保锁的原子性问题)

🔥博客主页: 【小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍ 文章目录 1.0 分布式锁概述 1.1 Redis 分布式锁实现思路 1.2 实现基本的分布式锁 2.0 Redis 分布式锁误删问题 2.1 解决 Redis 分布式锁误删问题 3.0 Redis 分布式锁原子性问题…

第十章 【后端】环境准备(10.4)——Vagrant

10.4 Vagrant Vagrant 官网 Vagrant 镜像仓库 下载 安装 直接 install。 设置环境变量 Vagrant 默认将镜像保存在用户文件夹的 .vagrant.d 目录下,若用户文件夹在C盘,下载的镜像文件会大量占用C盘空间。设置环境变量 VAGRANT_HOME 后,Vagrant 会将镜像保存到环境变量指定…

智能交通系统如何利用大数据、云计算和物联网技术优化交通流量、减少拥堵|智能交通系统|大数据|云计算|物联网|交通流量优化|减少拥堵

目录 1. 智能交通系统的定义与构成 1.1 智能交通系统的组成 1.2 智能交通系统的目标 2. 大数据技术在智能交通中的应用 2.1 交通数据采集与分析 2.2 实时交通监控与预测 3. 云计算在智能交通中的作用 3.1 云平台的数据处理能力 3.2 云计算的弹性扩展 4. 物联网技术在…

SpringBoot集成Redis——RedisTemplate

1. 依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId> </dependency> 2. 配置 # redis单机 spring.data.redis.database0 spring.data.redis.host192.168.229.10…

【ShuQiHere】从残差思想到 ResNet:深度学习的突破性创新

【ShuQiHere】引言 在深度学习的迅速发展中&#xff0c;卷积神经网络&#xff08;CNN&#xff09;凭借其在计算机视觉领域的出色表现&#xff0c;已经成为一种主流的神经网络架构。然而&#xff0c;随着网络层数的增加&#xff0c;研究人员逐渐发现了一个关键问题&#xff1a;…