蓝桥杯嵌入式之MEME传感器(LIS302DL、三轴加速度传感器)讲解

扩展板提供了一个三轴加速度传感器(LIS302DL)。由于该模块的知识非常多,所以可以参考网上的教程。在这里只是讲解如何使用。

LIS302DL可以进行IIC通信和SPI通信,但因为线路的连接而只能使用IIC通信。LIS302DL的电路连接图为

由于P2中的5—6和7—8引脚是LIS302DL中断引脚,例程中并没有使用,所以本次讲解也没有使用到。

IIC初始化

由于在比赛的时候会给IIC的驱动代码,但是因为EEPROM的通信方式也是IIC通信,所以在LIS302DL中使用IIC通信的话需要修改I/O的选择。IIC和SPI的通信方式由CS引脚选择,但是CS的引脚接成高电平,所以默认为IIC的通信方式,只需对IIC进行初始化即可。

IIC初始化代码为

//I2C总线初始化
void i2c_init()
{
  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

  GPIO_InitStructure.GPIO_Pin = SDA_Pin | SCL_Pin;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   // **

  GPIO_Init(I2C_PORT, &GPIO_InitStructure);
}

由于IIC的通信方式需要I/O既做输入,又做输出,需要不断的转换,所以不能只修改IIC初始化的I/O选择,而应该设置宏定义或者所有的地方都进行修改。

LIS302DL的初始化

LIS302DL的初始化代码为

void LIS302DL_Config(void)
{
  LIS302DL_Write(CTRL_REG1,0x47);
  LIS302DL_Write(CTRL_REG2,0x00);
  LIS302DL_Write(CTRL_REG3,0xC1);
  LIS302DL_Write(FF_WU_THS_1,0x28);    
  LIS302DL_Write(FF_WU_DURATION_1,40);    
//  LIS302DL_Write(FF_WU_CFG_1,0x10);    
}

只需第一句的代码也可以正常使用LIS302DL。这些代码都是对一些寄存器进行赋值,具体的寄存器使用说明可以参考LIS302DL的使用手册。其中相关的宏定义为

#define CTRL_REG1       0x20
#define CTRL_REG2       0x21
#define CTRL_REG3       0x22
#define FF_WU_THS_1     0x32
#define FF_WU_DURATION_1   0x33
#define FF_WU_CFG_1     0x30

下面是对一些寄存器赋值的说明(依据LIS302DL初始化代码为例)

void LIS302DL(void)
{
  LIS302DL_Write(CTRL_REG1,0x47);
  //DR=0,加速度的采集频率为 200Hz;
  //PD=1,LIS302DL工作在普通功耗模式;
  //FS=0,最大测量范围为 2g(2.3g),灵敏度为 18mg/LSB(16.2),受温度影响为 0.01%, 在0加速度时.飘移为 40mg;
  //STP=0,STM=0,表示 LIS302DL 工作在普通模式,即非自检模式;
  //Zen=1,表示使能 Z 轴方向加速度采集; 
  //Yen=1,表示使能 Y 轴方向加速度采集; 
  //Xen=1,表示使能 X 轴方向加速度采集; 
  LIS302DL_Write(CTRL_REG2,0x00);
  //SIM=0,表示 SPI 口为 4 总线;(这个要先看cs决定)
  //BOOT=0,表示不要刷新存储器的内容,为普通模式;
  //FDS=0,表示禁用高通滤器;
  //HP_FF_W_U2=0, 禁用自由落体/唤醒高通滤波器 2;
  //HP_FF_W_U1=0, 禁用自由落体/唤醒高通滤波器 1;
  //HP_coeff2=0,HP_coeff1=0,DR=0, 表示自由落体/唤醒高通滤波器的输出截止频率为 2Hz;
  LIS302DL_Write(CTRL_REG3,0xC1);
  //IHL=1,表示在中断发生时,中断脚(INT1 和 INT2)输出低电平;
  //PP_OD=1,表示中断脚开漏输出;
  //I2CFG2=0,I2CFG1=0,I2CFG0=0,表示 INT2 脚输出低电平;
  //I1CFG2=0,I1CFG1=0,I1CFG0=1,表示 INT1 脚是根据自由落体/唤醒 1 寄存器的输出而发生变化;
  LIS302DL_Write(FF_WU_THS_1,0x28);
  //DCRM=0,表示在不再有中断发生时,持续时间计数器会被复位到初值;
  //THS0~THS6,用来设置自由落体/唤醒的下限值--720mg;  
  LIS302DL_Write(FF_WU_DURATION_1,40);  
  //当 DR=1 时,加速度的采集频率为 ;  
  LIS302DL_Write(FF_WU_CFG_1,0x10);    
  //AOI=1,表示所有中断事件相或后输出;
  //LIR=0,表示将中断请求不锁存;
  //ZHIE=0,表示在 Z 输出寄存器的值大于 Z 轴的设置值时,将不会使能 Z 轴中断;
  //ZLIE=1,表示在 Z 输出寄存器的值小于 Z 轴的设置值时,将不使能中断请求;
  //YHIE=0,表示在 Y 输出寄存器的值大于 Y 轴的设置值时,将不会使能 Y 轴中断;
  //YLIE=1,表示在 Y 输出寄存器的值小于 Y 轴的设置值时,将不会使能 Y 轴中断;
  //XHIE=1,表示在 X 输出寄存器的值大于 X 轴的设置值时,将不会使能 X 轴中断;
  //XLIE=0,表示在 X 输出寄存器的值小于 X 轴的设置值时,将不会使能 X 轴中断;
}

LIS302DL的读写函数

LIS302DL的写函数为

void LIS302DL_Write(unsigned char reg,unsigned char info)
{  
  I2CStart(); 
  I2CSendByte(0x38);  
  I2CWaitAck();     
  I2CSendByte(reg);  
  I2CWaitAck(); 
  I2CSendByte(info); 
  I2CWaitAck();
  I2CStop();
}

由于LIS302DL的地址选择都接地,所以LIS302DL的地址为0x38。

LIS302DL的读函数

uint8_t LIS302DL_Read(uint8_t address)
{
  unsigned char val;
  I2CStart(); 
  I2CSendByte(0x38);  
  I2CWaitAck();     
  
  I2CSendByte(address);  
  I2CWaitAck(); 
  
  I2CStart();
  I2CSendByte(0x39); 
  I2CWaitAck();
  val = I2CReceiveByte(); 
  I2CSendNotAck();
  I2CStop();
  
  return(val);
}

读指令为0x39。

其读写代码和EEPROM的差不多,但是指令不一样,容易混淆。

LIS302DL是否存在判断

在使用前先判断LIS302DL是否存在,虽然代码非常简单,但是其重要性不言而喻的。模块不存在而直接使用的话会有一些错误的数据,造成错误的行为。

LIS302DL是否存在的代码为

if(LIS302DL_Check() == 1)
{
  LCD_DisplayStringLine(Line3, (u8 *)" MEMS STATUS: OK");
}
else
{
  LCD_DisplayStringLine(Line3, (u8 *)" MEMS STATUS: ERROR");        
}

函数LIS302DL_Check的定义为

uint8_t LIS302DL_Check(void)
{
  if(LIS302DL_Read(0x0f))
  {
    return 1;
  }
  else
  {
    return 0;
  }
}

LIS302DL显示讲解

LIS302DL显示的代码为

ptr = Lis302DL_Output();
      
snprintf((char *)str, sizeof(str), " X Reg:%d    ", ptr[0]);
LCD_DisplayStringLine(Line6,str);
snprintf((char *)str, sizeof(str), " Y Reg:%d    ", ptr[1]);
LCD_DisplayStringLine(Line7,str);
snprintf((char *)str, sizeof(str), " Z Reg:%d    ", ptr[2]);
LCD_DisplayStringLine(Line8,str);  
Delay_Ms(200);

指针ptr的定义为

u8 *ptr;

函数Lis302DL_Output的定义为

u8* Lis302DL_Output(void)
{
  if((LIS302DL_Read(0x27) & 0x08) != 0)
  {
    
    alz[0] = (LIS302DL_Read(0x29));  //x
    alz[1] = (LIS302DL_Read(0x2B));  //y
    alz[2] = (LIS302DL_Read(0x2D));  //z
  }

  return alz;
}

其分别读出相应寄存器的值,这些寄存器的使用说明为

测试各个方向的加速度的话需要将读取到的数据除以18。如果只测偏移度的话,数组ptr的值不变。

数组在相应文件的定义为

u8 alz[3] ;

原文发布于微信公众号 - IT界的小白帽(l1084504793)

原文发表时间:2019-05-25

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券