LIS3DH是一個三軸加速度傳感器,可用於檢測X、Y、Z軸上的加速度,以及設置閾值,在加速度超出閾值時觸發中斷。
支持SPI和IIC讀寫。
測試
下面主要是IIC方式讀寫:ui
1、寄存器讀寫流程
首先硬件鏈接會決定該模塊的IIC地址
若是SAO腳接地,IIC地址爲0X30(不包含最低位).
若是接V3.3,則IIC地址爲0X32(不包含最低位).
spa
這個器件地址很重要,由於讀寫寄存器都是要先寫一下對應的器件地址,而後再寫命令的code
注意先發送的器件地址只是前7位,最後一位決定的是讀寫位,0是寫寄存器,1爲讀寄存器,因此寫寄存器時是寫「LIS_ADDR|0x00」,讀的時候則是「LIS_ADDR|0x01」blog
a、主機向從機寫一個字節,下表是經過IIC向LIS3DH寄存器寫一個字節的流程。簡單來講就是先寫1個字節的寫命令+IIC地址,再寫一個字節的你要寫的寄存器地址,最後寫一個字節你要寫入寄存器的內容
事件
示例:it
//IIC寫一個字節 //reg:寄存器地址 //data:數據 //返回值:0,正常 //其餘,錯誤代碼 uint8_t LIS_Write_Byte(uint8_t reg,uint8_t data) { IIC_Start(); IIC_Send_Byte(LIS_ADDR|0x00);//發送器件地址+寫命令 if(IIC_Wait_Ack()) //等待應答 { IIC_Stop(); return 1; } IIC_Send_Byte(reg|0x00); //寫寄存器地址 D7位爲低用於單字節傳輸 IIC_Wait_Ack(); //等待應答 IIC_Send_Byte(data); //發送數據 if(IIC_Wait_Ack()) //等待ACK { IIC_Stop(); return 1; } IIC_Stop(); AP_interface->ol_Sleep(5000); return 0; }
b、LIS3DH讀寄存器一個字節
流程:先寫1個字節的寫命令+IIC地址,再寫你要讀的寄存器。而後寫1個字節的讀命令+IIC地址,最後讀一個字節的數據
io
示例:class
//IIC讀一個字節 //reg:寄存器地址 //返回值:讀到的數據 uint8_t LIS_Read_Byte(uint8_t reg) { uint8_t res=0x00; IIC_Start(); IIC_Send_Byte(LIS_ADDR|0x00);//發送器件地址+寫命令 if(IIC_Wait_Ack()) //等待ACK { IIC_Stop(); return 1; } IIC_Send_Byte(reg); //寫寄存器地址 IIC_Wait_Ack(); //等待應答 IIC_Start(); IIC_Send_Byte(LIS_ADDR|0x01); //發送器件地址+讀命令 IIC_Wait_Ack(); //等待應答 res = IIC_Read_Byte(0); //讀取數據,發送nACK IIC_Stop(); //產生一箇中止條件 return res; }
c、IIC連續寫寄存器:stream
示例:
//IIC連續寫 //addr:器件地址 //reg:寄存器地址 //len:寫入長度 //buf:數據區 //返回值:0,正常 // 其餘,錯誤代碼 uint8_t LIS_Write_Len(uint8_t addr,uint8_t reg,uint8_t len,uint8_t *buf) { uint8_t i; IIC_Start(); IIC_Send_Byte(LIS_ADDR|0x00);//發送器件地址+寫命令 if(IIC_Wait_Ack()) //等待應答 { IIC_Stop(); return 1; } IIC_Send_Byte(reg|0x80); //寫寄存器地址 D7位爲高用於多字節傳輸 IIC_Wait_Ack(); //等待應答 for(i=0;i<len;i++) { IIC_Send_Byte(buf[i]); //發送數據 if(IIC_Wait_Ack()) //等待ACK { IIC_Stop(); return 1; } } IIC_Stop(); return 0; }
d、IIC方式連續讀寄存器。注意MAK和NMAK。
示例:
//IIC連續讀 //addr:器件地址 //reg:要讀取的寄存器地址 //len:要讀取的長度 //buf:讀取到的數據存儲區 //返回值:0,正常 // 其餘,錯誤代碼 uint8_t LIS_Read_Len(uint8_t addr,uint8_t reg,uint8_t len,uint8_t *buf) { IIC_Start(); IIC_Send_Byte(LIS_ADDR|0x00);//發送器件地址+寫命令 if(IIC_Wait_Ack()) //等待應答 { IIC_Stop(); return 1; } IIC_Send_Byte(reg|0x80); //寫寄存器地址 D7位爲高用於多字節傳輸 IIC_Wait_Ack(); //等待應答 IIC_Start(); IIC_Send_Byte(LIS_ADDR|0x01);//發送器件地址+讀命令 IIC_Wait_Ack(); //等待應答 while(len) { if(len==1)*buf=IIC_Read_Byte(0);//讀數據,發送nACK else *buf=IIC_Read_Byte(1); //讀數據,發送ACK len--; buf++; } IIC_Stop(); //產生一箇中止條件 return 0; }
2、設置閾值震動觸發中斷應用
首先,經過讀取一個叫WHO_AM_I的寄存器,能夠用來肯定芯片可用,由於這個寄存器讀取的值是恆定的0x33。
設置閾值觸發中斷示例:
該實例設置了中斷鎖存。即直到從新讀取INT1_SRC寄存器前,中斷都不會被清除,引腳會被一直強拉到從新讀取INT1_SRC爲止。
LIS_Write_Byte(CTRL_REG1,0x3F); //設置低功耗模式 xyz軸使能 採樣頻率25HZ LIS_Write_Byte(CTRL_REG2,0x09); //高通濾波正常模式,數據從內部濾波器到輸出寄存器 高通濾波器使能到中斷1 LIS_Write_Byte(CTRL_REG3,0x40); //使能AOI中斷1 LIS_Write_Byte(CTRL_REG4,0x80); //分辨率爲+-2g 則單位爲 4000/(2^8)=16mg 僅在LSB和MSB被讀時才更新數據 LIS_Write_Byte(CTRL_REG5,0x08); //寄存器鎖存中斷,只有讀INT1_SRC能夠恢復 LIS_Write_Byte(INT1_THS,0x10); //設置閾值 16*16=256 mg LIS_Write_Byte(INT1_DURATION,0x00); //中斷持續時間設置,此處設爲0,由於不讀INT1_SRC中斷就一直鎖存 LIS_Read_Byte(REFERENCE); //讀虛寄存器,強制將高通濾波器值加載到當前加速度值,開始比較 //INT1_CFG使能中斷 中斷模式爲 「OR」組合 只使能xyz軸高事件 //LIS_Write_Byte(INT1_CFG,0x2A); //INT1_CFG使能中斷 中斷模式6-direction position 使能xyz軸高低事件 LIS_Write_Byte(INT1_CFG,0xFF); LIS_Read_Byte(INT1_SRC);//清除中斷位
另外,還能夠設置中斷觸發指定時間,隨後引腳會還原。主要經過設置INT1_DURATION (33h)寄存器
這個ODR能夠經過GTRL_REG1設置。
最後中斷持續時間就是INT1_DURATION/ODR
3、FIFO模式讀取X、Y、Z軸方向加速度值
出於高速讀寫的需求,可能須要使用FIFO方式來進行加速度的讀取
LIS3DH的FIFO模式有4種:
一、Bypass mode
中間模式,只有切換模式的時候用獲得
二、FIFO mode
數據填充滿緩衝區後,中止繼續填充
三、Stream mode
數據持續輸出,填充滿緩衝區後會覆蓋舊的數據,數據依次向前推一字節
四、Stream-to-FIFO mode
FIFObuffer開始處於stream模式,等到中斷腳選擇觸發時,切換到FIFO模式。FIFO_CTRL_REG (2Eh)的TR位能夠決定是INT1腳仍是INT2腳來進行控制
示例:讀取XYZ軸方向的加速度,用Stream mode。
watermark是指配置FSS [4:0]來檢查讀取的時候數據總量是否超出指定的範圍。由於FIFO的緩衝區最多爲32級,好比能夠設置爲20,則讀取的時候,若是當時數據超出20個,則FIFO_SRC_REG (2Fh) (WTM)位會被置1,不然爲0。
同時FIFO_SRC_REG (2Fh) 的 OVRN_FIFO會被置1,若是32級緩衝區所有滿了。
//測試FIFO IIC_WriteByte(LIS3DH_CTRL_REG1,0x80|0x0F); //0010 0111 低功耗模式 IIC_WriteByte(LIS3DH_CTRL_REG2,0x00); //高通濾波關閉 IIC_WriteByte(LIS3DH_CTRL_REG3,0x06); //使能FIFO中斷 0000 0110 IIC_WriteByte(LIS3DH_CTRL_REG4,0x00); //分辨率+-16g 0011 0000 IIC_WriteByte(LIS3DH_CTRL_REG5,0x48); //FIFO使能 0100 1000 IIC_WriteByte(LIS3DH_FIFO_CTRL,0x80|0x1D); //0100 1111 配置FIFO模式和水印 IIC_ReadByte(LIS3DH_INT1_SRC); //清除中斷位 collect_LIS_Data(); void collect_LIS_Data(void) { uint16_t LIS_temp_data[3] = {0,0,0}; uint8_t data_len,i; FIFO_data_len = IIC_ReadByte(LIS3DH_FIFO_SRC); FIFO_data_len &= 0x1F; for(i=0;i<FIFO_data_len;i++) { LIS3DH_ReadData(LIS_temp_data); //讀取3個方向的數據 } }
數據會不斷刷新,因此要定時讀取,讀取間隔能夠經過ODR來控制調整。