电子工程师技术服务社区
公告
登录
|
注册
首页
技术问答
厂商活动
正点原子
板卡试用
资源库
下载
文章
社区首页
文章
x-nucleo-iks01a3使用之磁场传感器LIS2MDL
分 享
扫描二维码分享
x-nucleo-iks01a3使用之磁场传感器LIS2MDL
LIS2MDL
iks01a3
lpx11U68
hehung
关注
发布时间: 2019-09-24
丨
阅读: 1870
# 1、传感器介绍 本文使用了x-nucleo-iks01a3板子上的传感器LIS2MDL,LIS2MDL是一个磁场传感器,具有以下特点: LIS2MDL是3D磁力计,磁场动态范围为±50高斯。包括支持标准、快速模式、快速模式增强和高速(100 kHz、400 kHz、1 MHz和3.4 MHz)的I2C串行总线接口和SPI串行标准接口。该装置可以被配置成产生用于磁场检测的中断信号。并且采用塑料地面网格阵列封装(LGA),保证在-40°C至+85°C的温度范围内工作。 LIS2MDL支持16bit输出,电压范围为1.71V至3.6V。 本文将介绍如何通过在lpc11U68结合x-nucleo-iks01a3实现对磁场数据的读取。 # 2、原理图 原理图如下: ![](https://cf04.ickimg.com/bbsimages/201909/f93002a7c32301fda6159209e902f3d9.jpg) 从原理图中可以知道该芯片的IIC地址是0x3C,使用的是板子上的I2C总线1. 传感器在板子上的位置如下: ![](https://cf04.ickimg.com/bbsimages/201909/da5dc60c6389a7519a2c77724b6732a9.jpg) # 3、寄存器 寄存器总览: ![](https://cf04.ickimg.com/bbsimages/201909/425767fde6124599b687766e832d67cb.jpg) 该芯片的寄存器数量比较多,而且需要使用到的寄存器也是比较多的,具体如下: ## WHO_AM_I寄存器(0x4F) 传感器的固有ID寄存器,这个该磁场传感器固有的产品识别号,如读取的值是0x40就表示数据是正确的。 ![](https://cf04.ickimg.com/bbsimages/201909/683ebcf92d37fc2b4a27a921e221a48d.jpg) ## 配置寄存器CFG_REG_A(0x60) 该寄存器对该芯片的操作进行配置,配置的数据就是对芯片进行初始化,如下所示。 bit7的含义是是否使用温度补偿,如果需要补偿就设置为1,否则为0,之后读取的温度寄存器的数据将不会更新,时钟保持为0. 同时还需要对MD1,MD0这两位数据进行设置,默认的是1,需要设置成0,如果两位数据都是1的话是idle模式,不会进行工作的。 其中转换频率设置为ODR1和ODR0两位可以不用进行设置,默认是00,也就是10Hz。 ![](https://cf04.ickimg.com/bbsimages/201909/f56baf3da7a9812464e61b9591462221.jpg) ![](https://cf04.ickimg.com/bbsimages/201909/79ae48ffb6c06250ca9d0774ddba3aa2.jpg) ## 三轴磁场输出寄存器 磁场数据为三轴数据,分为X,Y,Z轴,每一轴使用了一个2bytes的寄存器来存储数据,分别如下。 对于三轴的数据可以直接读取对应的寄存器就行了。 注意:因为这个数据是带有正负号的,而且是16bit的,所以返回的数据类型一定要设置成short,不要设置成int型,不然都不到负数,short是16bit的类型,可以直接得到负号显示的,使用int型数据的话,由于数据是32bits的,当数据为负数的时候也最高位为1,显示的数据会很大,但是一直不会得到负数。 ![](https://cf04.ickimg.com/bbsimages/201909/628cd7ea01b85f51e6c481ebca05c0e9.jpg) ![](https://cf04.ickimg.com/bbsimages/201909/ce8dba2020022573d97bb71fe91a1b03.jpg) ## 温度寄存器 温度寄存器,也是2bytes的,分为高位和低位,数据手册中描述的不是很清楚,获取的数据总是和实际温度差别比较大,数据应该还要特殊处理一下显示才会正确,图片描述如下。 ![](https://cf04.ickimg.com/bbsimages/201909/6cc36653de15991d5810106812281499.jpg) # 3、代码实现 还是采用lpc11U68+x-nucleo-iks01a3的组合方式。 IIC的操作不做过多介绍,下面直接开始IIC的读写操作的代码。 ```c //LIS2MDL写 static int IIC_WrDat_LIS2MDL(uint8_t IIC_Add, uint8_t IIC_Reg, uint8_t IIC_Data) { uint8_t ret_suc = 1; IIC_Start(); IIC_Send_Byte(IIC_Add & 0xfe); ret_suc = IIC_Wait_Ack(); if(ret_suc == 1) {IIC_Stop();return -1;} IIC_Send_Byte(IIC_Reg); //write data ret_suc = IIC_Wait_Ack(); if(ret_suc == 1) {IIC_Stop();return -1;} IIC_Send_Byte(IIC_Data); ret_suc = IIC_Wait_Ack(); if(ret_suc == 1) {IIC_Stop();return -1;} IIC_Stop(); return 0; } //LIS2MDL读 static int IIC_Read_LIS2MDL(uint8_t IIC_Add, uint8_t IIC_Reg) { int ret; uint8_t ret_suc = 1; IIC_Start(); IIC_Send_Byte(IIC_Add & 0xfe); ret_suc = IIC_Wait_Ack(); if(ret_suc == 1) {IIC_Stop();return -1;} IIC_Send_Byte(IIC_Reg); ret_suc = IIC_Wait_Ack(); if(ret_suc == 1) {IIC_Stop();return -1;} IIC_Start(); IIC_Send_Byte(IIC_Add | 0x01); ret_suc = IIC_Wait_Ack(); if(ret_suc == 1) {IIC_Stop();return -1;} ret=IIC_Read_Byte(0); IIC_Stop(); return ret; } ``` 寄存器的读写,使用IIC操作对芯片的各个寄存器进行读取,代码实现中需要将数据读取20次,如果在这之读取到了正确的数据就返回数据退出循环,如果数据不对就继续循环,20次之后还没有读到正确的数据才会退出,之后返回读取错误的数字。 ```c //设置寄存器 int Set_Reg_LIS2MDL(uint8_t add, uint8_t reg, uint8_t dat) { int ret_succ = -1; uint8_t i = 20u; //失败之后尝试的次数 do{ if(0 == IIC_WrDat_LIS2MDL(add, reg, dat)) { ret_succ = 0; //设置成功 break; } else { i--; //获取失败,再次尝试 } }while(i>0u); return ret_succ; } //读取寄存器 int Get_Reg_LIS2MDL(uint8_t add, uint8_t reg) { uint8_t i = 20u; int ret_get = -1; do{ ret_get = IIC_Read_LIS2MDL(add, reg); if(-1 != ret_get) { break; //获取数据成功 } else { i--; //获取失败,再次尝试 } }while(i>0u); return ret_get; } ``` 寄存器的操作,下面是几个寄存器的读取函数。 下面的读取XYZ轴的数据的时候直接读取了2次,将高位进行左移8位在加上低位数据就是获取的数据了。 ```c //读取我是谁 int Get_WHO_AM_I_LIS2MDL(void) { return Get_Reg_LIS2MDL(LIS2MDL_ADDR_W_1, LIS2MDL_REG_WHO_AM_I); } //获取状态寄存器 int Get_Status_LIS2MDL(void) { return Get_Reg_LIS2MDL(LIS2MDL_ADDR_W_1, LIS2MDL_CFG_STATUS); } short GET_X_LIS2MDL(void) { return (Get_Reg_LIS2MDL(LIS2MDL_ADDR_W_1, LIS2MDL_OUTX_H)<<8)|(Get_Reg_LIS2MDL(LIS2MDL_ADDR_W_1, LIS2MDL_OUTX_L)); } short GET_Y_LIS2MDL(void) { return (Get_Reg_LIS2MDL(LIS2MDL_ADDR_W_1, LIS2MDL_OUTY_H)<<8)|(Get_Reg_LIS2MDL(LIS2MDL_ADDR_W_1, LIS2MDL_OUTY_L)); } short GET_Z_LIS2MDL(void) { return (Get_Reg_LIS2MDL(LIS2MDL_ADDR_W_1, LIS2MDL_OUTZ_H)<<8)|(Get_Reg_LIS2MDL(LIS2MDL_ADDR_W_1, LIS2MDL_OUTZ_L)); } short Get_Temp_LIS2MDL(void) { return (Get_Reg_LIS2MDL(LIS2MDL_ADDR_W_1, LIS2MDL_TEMP_H)<<8)|(Get_Reg_LIS2MDL(LIS2MDL_ADDR_W_1, LIS2MDL_TEMP_L)); } ``` 串口的发送程序,将获取的数据发送到上位机 ```c //发送数据到串口 void Send_Uart_LIS2MDL(void) { char str[35] = {0}; send_str((uint8_t *)"<-----------START--------->\r\n"); sprintf(str,"X:%d | Y:%d | Z:%d\r\n", GET_X_LIS2MDL(),GET_Y_LIS2MDL(),GET_Z_LIS2MDL()); send_str((uint8_t *)str); sprintf(str,"Temp:%d\r\n", Get_Temp_LIS2MDL()); send_str((uint8_t *)str); sprintf(str,"Status:0x%X\r\n", Get_Status_LIS2MDL()); send_str((uint8_t *)str); sprintf(str,"Who_am_i:%X\r\n",Get_WHO_AM_I_LIS2MDL()); send_str((uint8_t *)str); send_str((uint8_t *)"<------------END---------->\r\n\n"); } ``` 上述函数中使用的宏定义都在.h文件中进行定义的,如下所示: ```c /@@*register address*/ #define LIS2MDL_OFFSET_X_REG_L (0x45U) #define LIS2MDL_OFFSET_X_REG_H (0x46U) #define LIS2MDL_OFFSET_Y_REG_L (0x47U) #define LIS2MDL_OFFSET_Y_REG_H (0x48U) #define LIS2MDL_OFFSET_Z_REG_L (0x49U) #define LIS2MDL_OFFSET_Z_REG_H (0x4AU) #define LIS2MDL_REG_WHO_AM_I (0x4FU) #define LIS2MDL_CFG_A (0x60U) #define LIS2MDL_CFG_B (0x61U) #define LIS2MDL_CFG_C (0x62U) #define LIS2MDL_CFG_INT_CTRL (0x63U) #define LIS2MDL_CFG_SOURCE (0x64U) #define LIS2MDL_CFG_THS_L (0x65U) #define LIS2MDL_CFG_THS_H (0x66U) #define LIS2MDL_CFG_STATUS (0x67U) #define LIS2MDL_OUTX_L (0x68U) #define LIS2MDL_OUTX_H (0x69U) #define LIS2MDL_OUTY_L (0x6AU) #define LIS2MDL_OUTY_H (0x6BU) #define LIS2MDL_OUTZ_L (0x6CU) #define LIS2MDL_OUTZ_H (0x6DU) #define LIS2MDL_TEMP_L (0x6EU) #define LIS2MDL_TEMP_H (0x6FU) /@@*IIC slave address write and read*/ /@@*SD0 connect to power supply*/ #define LIS2MDL_ADDR_W_1 0x3CU #define LIS2MDL_ADDR_R_1 0x3DU ``` 最后是初始化时的操作,初始化的时候初始化了2个寄存器,一个是CFG_REG_A,初始化值是0x80,也就是设置了温度补偿,操作模式设置为了连续模式,这样就会一直采集数据存储到寄存器中,一直工作,工作频率是10Hz。 ```c //初始化传感器LIS2MDL if(0 == Set_Reg_LIS2MDL(LIS2MDL_ADDR_W_1, LIS2MDL_CFG_A, 0x80)) { send_str((unsigned char *)"IF_CTRL set successful\r\n"); } else { send_str((unsigned char *)"IF_CTRL set fail\r\n"); } if(0 == Set_Reg_LIS2MDL(LIS2MDL_ADDR_W_1, LIS2MDL_CFG_C, 0x10)) { send_str((unsigned char *)"IF_CTRL set successful\r\n"); } else { send_str((unsigned char *)"IF_CTRL set fail\r\n"); } ``` # 5、显示效果 ![](https://cf04.ickimg.com/bbsimages/201909/360fdf46b9f664ff926cc85bf8a1cf94.jpg) ![](https://cf04.ickimg.com/bbsimages/201909/63bd178b2ee17e0591b25e95f05690ae.jpg) ![](https://cf04.ickimg.com/bbsimages/201909/ecd28e4cf4340271aec2f10f2f45a600.jpg) 从上图中可以看出,随着转动传感器方向,所返回的数据会变化,该传感器的灵敏度很高,测量的数据十分的准确。
原创作品,未经权利人授权禁止转载。详情见
转载须知
。
举报文章
点赞
(
1
)
hehung
关注
评论
(0)
登录后可评论,请
登录
或
注册
相关文章推荐
MK-米客方德推出工业级存储卡
Beetle ESP32 C3 蓝牙数据收发
Beetle ESP32 C3 wifi联网获取实时天气信息
开箱测评Beetle ESP32-C3 (RISC-V芯片)模块
正点原子数控电源DP100测评
DP100试用评测-----开箱+初体验
Beetle ESP32 C3环境搭建
【花雕体验】16 使用Beetle ESP32 C3控制8X32位WS2812硬屏之二
X
你的打赏是对原创作者最大的认可
请选择打赏IC币的数量,一经提交无法退回 !
100IC币
500IC币
1000IC币
自定义
IC币
确定
X
提交成功 ! 谢谢您的支持
返回
我要举报该内容理由
×
广告及垃圾信息
抄袭或未经授权
其它举报理由
请输入您举报的理由(50字以内)
取消
提交