通过SPI传输BMI160数据到nrf528xx

主控和外设之间的联系

在完成代码之前,我们手里会有两份代码,一份是nrf528xx的SDK,一份是BMI160传感器的SDK,怎么利用SDK完成我们的需求呢?首先我们要搞明白,主控和外设之间的联系是什么?传感器给的SDK具体是什么内容。
我们这次的需求是通过SPI进行传输,SPI通过6条线将传感器和主控芯片联系在一起,如图:
在这里插入图片描述

传感器是一个商用的物品,已经没有第二次烧录的可能性,他里面已经烧录了代码,只要连接引脚,通过引脚给他指令就可以工作,可以理解成一个蓄势待发的玩具青蛙,等待一个指令就可以不停的跳(工作)。引脚也可以理解成一个硬件级别的API接口哈哈
而传感器的SDK就相当于一个指令集,比如一个蓝牙耳机,你看说明书他会告诉你怎么按(API接口)可以播放音乐、暂停音乐。类似的,一般的传感器会提供SPI或者是I2C的通信,SDK会告诉你怎么通过函数API让他开始传输数据,哈哈这里就比较复杂一点,没法对6条线实物操作,好像你只能把他掐断了,但他也工作不了,需要自己写代码去驱动。什么是驱动,就是拿着他的SDK放在自己代码中。
BMI160 API of SDK

那有人问了,函数API怎么就能通过六条线进行指令啦?这涉及到通信啦,大家感兴趣的话可以了解一下SPI 通信、计算机网络,但是对于我们代码来说其实属于最高级别的应用层,直接黑盒子拿API来使用。如果问代码为啥可以变成 0/1进行通信,那就得去学学计科计组和编译啦。

在与BMI160进行交互时,通常我们会通过其寄存器来配置设备、读取数据以及执行其他操作。这些寄存器包括配置寄存器、数据寄存器、状态寄存器等。大家看到SDK里面有很多宏定义,大部分都是寄存器的一些地址,这也是需要硬件商家提供的,让API的每一个对应函数功能都去找对应的寄存器存或者取数据。不用理会其中的为啥这个宏定义就i是1或者2,这就是硬件商家规定好的,就像你给一个物体打个标签区分他们一样,你只要看他的变量名字就好了。
ADDR

好,我们了解了传感器SDK一般会给我们的东西,仔细琢磨可以知道他是怎么运作,想直接用的话你可以直接把他当成黑盒子,直接调用他给出的API就好,涉及的库直接记得依赖进来就好。

关键

我们刚才说通过SPI线进行驱动传感器才会工作,那SPI的传输数据代码到底是属于谁的呢?是主控的!因为我们烧写的代码是在主控上进行的,写的代码就要调用主控上的SPI端口。 好像传感器的SDK也有写到SPI,但他实际上只是变量写了SPI相关字眼,实际上函数参数导入主控上SPI对象,告诉你应该从哪个寄存器存或者取,然后根本还是要用主控上SPI去读取。
主控上一般都会给出I2C和SPI的示例代码,只要进行调用对应的函数就好了。

// nrf_drv_spi_transfer 是nrf528xx的API, spi_read_transfer是自己命名的函数
int8_t spi_read_transfer(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
{
	ret_code_t ret ;
	uint8_t read_temp[ length + 1 ] ;
	reg_addr = reg_addr | 0x80; 
  ret = nrf_drv_spi_transfer(&spi, &reg_addr, 1, read_temp, length + 1 ) ;	
	nrf_delay_ms(5); 
	for( int i = 1 ; i < length + 1 ; i ++ )
	  reg_data[i-1] = read_temp[i] ;
	
	return (int8_t)ret;	
}

int8_t spi_write_transfer(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
{
	ret_code_t ret;
	uint8_t write_temp[ length + 1 ] ;
	reg_addr = reg_addr & 0x7F;
	write_temp[0] = reg_addr ;
	for( int i = 1 ; i < length + 1 ; i ++ )
	  write_temp[i] = reg_data[i-1] ;

  ret = nrf_drv_spi_transfer(&spi, write_temp, length + 1, &no_use, 1 ) ;
	nrf_delay_ms(5) ;
	
	return (int8_t)ret;	
}

我们来看看bmi160的SDK
在这里插入图片描述
dev->read底层用的是nrf52的SPI接口,具体代码在bmi160的示例中:

sensor.read = spi_read_transfer;
sensor.write = spi_write_transfer;

他将sensor这个类的read句柄接入了spi_read_transfer,而这个函数本质是nrf_drv_spi_transfer()

示例

整体流程是:
1、实例化bmi160(BMI160 SDK)
2、实例化SPI(nrf52 SDK)
3、将bmi160 设置的SPI句柄实例化
3、读取传感器数据(BMI160 SDK)
github 示例

可能的bug

  1. 如果数据一直是0的话,看是否激活sensor进行工作,比如bmi160就需要以下这句代码让他不断读取数据
// set configuration
 sensor_calibration.acc_cg.power = BMI160_ACC_NORMAL_MODE; // power mode
 sensor_calibration.gyro_cfg.power = BMI160_GYRO_NORMAL_MODE; // power mode
  1. 如果和蓝牙一起使用注意 spi和蓝牙的优先级
spi_config0.irq_priority = 2;
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值