STM32F4-DISCO 学习之 SPI 驱动 LIS302DL

/ 0评 / 0

我搞到的板子可能比较老,是LIS302DL的,这个支持SPI和I2C双接口,当然我们用的就是SPI接口,这个SPI通信速度是10MHz,但是,他内部AD的转换速度是Hz级的.

时序参数图:

QQ截图20150910164500

他接在SPI1上,我们APB2是84MHz的,要到16分频啊,5.25MHz,不过也远大于数据生成速率了.我们也不会总是不断访问他.但是Discovery上的LIS302DL已经有相关的Example了[文件名stm32f4_discovery_lis302dl.*].我们就学习一下ST的写法以及思想.但是SPI_BaudRatePrescaler_4需要往下面调整一下,好做实验,如果稳定,我们再往上调整.

QQ截图20150911094756

得到SPI_BaudRatePrescaler_16.然后从LIS302DL_Init着手分析:

void LIS302DL_Init(LIS302DL_InitTypeDef *LIS302DL_InitStruct)
{
  uint8_t ctrl = 0x00;
  /* Configure the low level interface ---------------------------------------*/
  LIS302DL_LowLevel_Init();
  /* Configure MEMS: data rate, power mode, full scale, self test and axes */
  ctrl = (uint8_t) (LIS302DL_InitStruct->Output_DataRate | LIS302DL_InitStruct->Power_Mode | 
                    LIS302DL_InitStruct->Full_Scale | LIS302DL_InitStruct->Self_Test | 
                    LIS302DL_InitStruct->Axes_Enable);
  /* Write value to MEMS CTRL_REG1 regsister */
  LIS302DL_Write(&ctrl, LIS302DL_CTRL_REG1_ADDR, 1);
}

传递一个结构体,然后结构体里面就有该芯片的一些参数,然后这个结构体经过组织,就可以写入到LIS302DL了.这个函数,把初始化分成两部分,一部分是LowLevelInit,打开外设时钟,配置SPI时序,对于我们之前配置过的来说,没什么难度.看看结构体,以及相应的寄存器中.其中Ctrl_Reg1内容如下:

/*******************************************************************************
*  CTRL_REG1 Register: Control Register 1
*  Read Write register
*  Default value: 0x07
*  7 DR: Data Rate selection.
*        0 - 100 Hz output data rate
*        1 - 400 Hz output data rate
*  6 PD: Power Down control.
*        0 - power down mode
*        1 - active mode
*  5 FS: Full Scale selection.
*        0 - Typical measurement range 2.3
*        1 - Typical measurement range 9.2
*  4:3 STP-STM Self Test Enable:
*              STP |  STM |   mode
*            ----------------------------
*               0  |  0   |   Normal mode
*               0  |  1   |   Self Test M
*               1  |  0   |   Self Test P
*  2 Zen: Z axis enable.
*         0 - Z axis disabled
*         1- Z axis enabled
*  1 Yen: Y axis enable.
*         0 - Y axis disabled
*         1- Y axis enabled
*  0 Xen: X axis enable.
*         0 - X axis disabled
*         1- X axis enabled
********************************************************************************/
#define LIS302DL_CTRL_REG1_ADDR                 0x20

比如设置Power Mode,如果0x40就是相当于PD置位,否则PD复位,所以头文件也有如下定义.

/** @defgroup Power_Mode_selection
  * @{
  */
#define LIS302DL_LOWPOWERMODE_POWERDOWN                   ((uint8_t)0x00)
#define LIS302DL_LOWPOWERMODE_ACTIVE                      ((uint8_t)0x40)

的包括其他的LIS302DL_FilterConfig,LIS302DL_InterruptConfig都有类似的调用.深入到更底层的体验,发现归根到底调用的是LIS302DL_SendByte发送各种,里面还有超时判断.以防死在那一行.新建一个测试SPI最基本的函数:

uint8_t LIS302DL_WHO_AM_I(void)
{
    uint8_t pBuffer = 0x00;
    LIS302DL_CS_LOW();
    LIS302DL_SendByte(READWRITE_CMD | LIS302DL_WHO_AM_I_ADDR);
    pBuffer = LIS302DL_SendByte(DUMMY_BYTE);
    LIS302DL_CS_HIGH();
    return pBuffer;
}

如程序所示,逻辑非常简单,在主程序写一个测试:

temp = LIS302DL_WHO_AM_I();
printf("LIS302DL ID = %2x
", temp);
Delay(500);

确实得到ID是0x3B:

QQ截图20150911103403

的我们就可以对程序改进一点点,这样目的是为了初始化前识别设备在不在.

uint8_t LIS302DL_Init(LIS302DL_InitTypeDef *LIS302DL_InitStruct)
{
    uint8_t ctrl = 0x00;
    /* Configure the low level interface ---------------------------------------*/
    LIS302DL_LowLevel_Init();
    if(LIS302DL_WHO_AM_I() == 0x3B)
    {
        /* Configure MEMS: data rate, power mode, full scale, self test and axes */
        ctrl = (uint8_t) (LIS302DL_InitStruct->Output_DataRate | LIS302DL_InitStruct->Power_Mode | 
                          LIS302DL_InitStruct->Full_Scale | LIS302DL_InitStruct->Self_Test | 
                          LIS302DL_InitStruct->Axes_Enable);
        /* Write value to MEMS CTRL_REG1 regsister */
        LIS302DL_Write(&ctrl, LIS302DL_CTRL_REG1_ADDR, 1);
        return 1;
    }
    else
    {
        return 0;
    }
}

顺手根据ST的驱动,写一个Demo来试试这个芯片.

#include "stm32f4xx.h"
#include "SysTick.h"
#include "DUART.h"
#include "LIS302DL.h"
uint8_t temp;
uint8_t Buffer[6];
__IO int8_t X_Offset, Y_Offset, Z_Offset  = 0x00;
LIS302DL_InitTypeDef  LIS302DL_InitStruct;
LIS302DL_FilterConfigTypeDef LIS302DL_FilterStruct;
int main(void)
{
    SysTick_Init();
    DUSART_Init();
    LIS302DL_InitStruct.Power_Mode = LIS302DL_LOWPOWERMODE_ACTIVE;
    LIS302DL_InitStruct.Output_DataRate = LIS302DL_DATARATE_100;
    LIS302DL_InitStruct.Axes_Enable = LIS302DL_XYZ_ENABLE;
    LIS302DL_InitStruct.Full_Scale = LIS302DL_FULLSCALE_2_3;
    LIS302DL_InitStruct.Self_Test = LIS302DL_SELFTEST_NORMAL;
    LIS302DL_Init(&LIS302DL_InitStruct);
    /* MEMS High Pass Filter configuration */
    LIS302DL_FilterStruct.HighPassFilter_Data_Selection = LIS302DL_FILTEREDDATASELECTION_OUTPUTREGISTER;
    LIS302DL_FilterStruct.HighPassFilter_CutOff_Frequency = LIS302DL_HIGHPASSFILTER_LEVEL_1;
    LIS302DL_FilterStruct.HighPassFilter_Interrupt = LIS302DL_HIGHPASSFILTERINTERRUPT_1_2;
    LIS302DL_FilterConfig(&LIS302DL_FilterStruct);
    while (1)
    {
        LIS302DL_Read(Buffer, LIS302DL_OUT_X_ADDR, 6);
        X_Offset = Buffer[0];
        Y_Offset = Buffer[2];
        Z_Offset = Buffer[4];
        printf("X = %d,Y = %d,Z = %d ", X_Offset, Y_Offset, Z_Offset);
        Delay(500);
    }
}

通过移动板子,观察到X,Y,Z的变化.

QQ截图20150911104137

通过这个变化,可以结合LED显示,来观察.也可以自行发挥,这就不多说了.工程项目打包:

SPI驱动LIS302DL 

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注