我一直在研究一系列psoc 6项目,以准备一些新视频并在embedded world上使用。对于其中一个项目,我需要一个动作敏感的遥控器......并且我们很方便地将一台博世bmi160运动传感器放到了cy8ckit-062-ble开发套件随附的新cy8ckit-028-epd屏蔽罩上。
在本文中,我将向您展示如何使用psoc 6制作完整的测试系统来与bmi160进行通话。步骤是:
克隆博世bmi160驱动程序库
创建一个新的psoc 6项目并添加驱动程序库
为博世驱动程序创建hal
创建主要固件并进行测试
克隆博世bmi160驱动程序库
当我开始这个时,我知道董事会有一个运动传感器,但我不知道是什么样的。我假设它是基于i2c的传感器,所以我连接了桥接控制面板并探测i2c总线。但是这就是它所说的:
那么......到底什么?然后,我看了看董事会,试图弄清楚发生了什么......低下,看看......我的电路板是在添加运动传感器之前完成的原型。这里是:
这里是一块带有传感器的电路板。
当我插入该板并使用bridge control panel进行测试时,我会得到:
接下来我做的就是看原理图。ok,您可以看到惯性测量单元(imu)是连接到i2c总线的bmi160。另一件很酷的事情是,devkit团队连接了两条中断线。这些线路通常用于imu向psoc 6发送信号(例如,用户可能开始移动)。
查看原理图后,下一步是查看bmi160数据表并尝试弄清楚如何与设备进行连接。通常这些设备有一堆寄存器,其位数字段的数量令人难以置信。这一直是这个过程中不好玩的部分。但是这次当我去博世网站上的bmi160设备页面时,有一个按钮显示“文档和驱动程序”,当您点击它时,会有一个链接到bmi160驱动程序的github。得分了!
要做到这一点,你只需要“git clonegit@github.com:boschsensortec / bmi160_driver.git”
使用博世bmi160驱动程序库创建新的psoc 6项目
所以,让我们继续测试它。首先创建一个新的psoc 63项目
使用空白示意图
给它一个名字
添加retarget i / o和freertos(从构建设置菜单中)
添加一个uart和一个i2c主控
要使i2c成为主设备,您需要双击并将其更改为主设备
然后分配引脚
运行“构建 - >生成应用程序”来获得您需要的所有pdl固件。
编辑stdio_user.h以使用uart(扫描stdio_user.h找到正确的位置)
#includeproject.h
/*mustremainuncommentedtousethisutility*/
#defineio_stdout_enable
#defineio_stdin_enable
#defineio_stdout_uartuart_1_hw
#defineio_stdin_uartuart_1_hw
将“bmi_driver”目录添加到cm4项目的包含路径。(要进入此菜单,请右键单击该项目并选择“构建设置”)
将bosch driver文件添加到项目中
为博世驱动程序创建hal
使用博世驱动器很简单。你所需要做的就是更新hal。
提供写入i2c寄存器的功能
提供读取i2c寄存器的功能
提供延迟指定毫秒数的功能
创建一个结构来保存初始化信息和函数指针
该器件实现了赛普拉斯所称的“ezi2c”协议,该协议也称为i2c eeprom协议。该器件被组织为一系列寄存器。每个寄存器都有一个从0-> 0xff(单字节地址)的地址。要写入注册表,您需要
发送i2c启动
发送7位i2c地址
发送一个写入位(aka a 0)
发送要写入的寄存器地址(不要将i2c地址与内部bmi160地址混淆)
发送您想要写入的8位值
发送一个停止
ezi2c的一个很酷的事情是,它可以跟踪地址,并在每次写入时自动递增寄存器地址。这意味着您可以编写一个地址序列,而无需为每个地址执行完整的事务。
鉴于引入写函数很简单:
staticint8_tbmi160burstwrite(uint8_tdev_addr,uint8_treg_addr,uint8_t*data,uint16_tlen)
{
cy_scb_i2c_mastersendstart(i2c_1_hw,dev_addr,cy_scb_i2c_write_xfer,0,&i2c_1_context);
cy_scb_i2c_masterwritebyte(i2c_1_hw,reg_addr,0,&i2c_1_context);
for(inti=0;i为了阅读你做一个类似的交易来写。具体的步骤是:
发送i2c启动
发送7位i2c地址
发送一个write位aka 0
发送您想要读取的寄存器地址
发送i2c重新启动
读一个字节
发送nak
发送一个停止
读取事务与写入类似,您可以通过发送ack继续读取连续字节。您读取的最后一个字节应该是nak,以告诉远程设备您正在读取。鉴于代码也很简单。
//thisfunctionsupportsthebmp180libraryandreadi2cregisters
staticint8_tbmi160burstread(uint8_tdev_addr,uint8_treg_addr,uint8_t*data,uint16_tlen)
{
cy_scb_i2c_mastersendstart(i2c_1_hw,dev_addr,cy_scb_i2c_write_xfer,0,&i2c_1_context);
cy_scb_i2c_masterwritebyte(i2c_1_hw,reg_addr,0,&i2c_1_context);
cy_scb_i2c_mastersendrestart(i2c_1_hw,dev_addr,cy_scb_i2c_read_xfer,0,&i2c_1_context);
for(inti=0;i我的读写功能都有一个错误。那个错误是?没有错误检查。我看到了一些间歇性的奇怪现象,其中i2c总线被锁定,最终需要重置才能修复。这可以通过检查i2c功能上的错误代码来防止。
既然我们有读写功能,我们可以设置我们的设备:要做到这一点:
设置一个类型为bmi160_dev的结构
初始化函数指针
初始化设备的设置
最后发送设置
staticstructbmi160_devbmi160dev;
staticvoidsensorsdeviceinit(void)
{
int8_trslt;
vtaskdelay(500);//guess
/*bmi160*/
bmi160dev.read=(bmi160_com_fptr_t)bmi160burstread;
bmi160dev.write=(bmi160_com_fptr_t)bmi160burstwrite;
bmi160dev.delay_ms=(bmi160_delay_fptr_t)vtaskdelay;
bmi160dev.id=bmi160_i2c_addr;//i2cdeviceaddress
rslt=bmi160_init(&bmi160dev);//initializethedevice
if(rslt==0)
{
printf(bmi160i2cconnection[ok].);
bmi160dev.gyro_cfg.odr=bmi160_gyro_odr_800hz;
bmi160dev.gyro_cfg.range=bmi160_gyro_range_125_dps;
bmi160dev.gyro_cfg.bw=bmi160_gyro_bw_osr4_mode;
/*selectthepowermodeofgyroscopesensor*/
bmi160dev.gyro_cfg.power=bmi160_gyro_normal_mode;
bmi160dev.accel_cfg.odr=bmi160_accel_odr_1600hz;
bmi160dev.accel_cfg.range=bmi160_accel_range_4g;
bmi160dev.accel_cfg.bw=bmi160_accel_bw_osr4_avg1;
bmi160dev.accel_cfg.power=bmi160_accel_normal_mode;
/*setthesensorconfiguration*/
bmi160_set_sens_conf(&bmi160dev);
bmi160dev.delay_ms(50);
}
else
{
printf(bmi160i2cconnection[fail].);
}
}
创建主要固件并进行测试
最后,我通过运行打印出加速数据的无限循环来测试固件。
voidmotiontask(void*arg)
{
(void)arg;
i2c_1_start();
sensorsdeviceinit();
structbmi160_sensor_dataacc;
while(1)
{
bmi160_get_sensor_data(bmi160_accel_only,&acc,null,&bmi160dev);
printf(x=%4dy=%4dz=%4d
,acc.x,acc.y,acc.z,);
vtaskdelay(200);
}
}
现在你应该有这样的:
最后整个节目一举成名
#includeproject.h
#includefreertos.h
#includetask.h
#include
#includebmi160.h
staticstructbmi160_devbmi160dev;
staticint8_tbmi160burstwrite(uint8_tdev_addr,uint8_treg_addr,uint8_t*data,uint16_tlen)
{
cy_scb_i2c_mastersendstart(i2c_1_hw,dev_addr,cy_scb_i2c_write_xfer,0,&i2c_1_context);
cy_scb_i2c_masterwritebyte(i2c_1_hw,reg_addr,0,&i2c_1_context);
for(inti=0;i
亿华通如何冲破燃料电池发展困境
成套购买成品质消费趋势:高端套系家电“璀璨”获上万忠粉
微软与小米、有人基金会达成合作 共同助力残障人士成就不凡
人脸识别市场虽然处于一个刚起步的阶段,但未来前景可期
峰会回顾第12期 | Wasm软件生态系统安全分析
如何使用PSoC 6制作完整的测试系统来与BMI160进行通话
植保无人机出现动力饱和的原因有哪些,该如何避免和解决
道尔芬智能在“创响江苏”扬州分赛中喜获二等奖并成功晋级省赛
5G车联网谁更具有行业优势
探索物联网HMI的端口转发和NAT功能
三阶高通滤波器具有合成电感器
首批7家湖北实验室集中揭牌
基于Python实现随机森林算法
混合动力车用锂离子电容器的开发
台积电4nm工艺2022年大规模量产_3nm工艺也在开发中
新华三已正式将大互联战略升级为数字化联接战略
东风汽车首款量产车明日正式首发:增程动力系统、续航可达860km
压摆率与大信号带宽(满功率带宽)的关系
FCA3000/3100系列计时器的功能特点及应用
Freescale的夜视,智能前灯控制和车道保持系统设计