我搞到的板子可能比较老,是LIS302DL的,这个支持SPI和I2C双接口,当然我们用的就是SPI接口,这个SPI通信速度是10MHz,但是,他内部AD的转换速度是Hz级的.
时序参数图:
他接在SPI1上,我们APB2是84MHz的,要到16分频啊,5.25MHz,不过也远大于数据生成速率了.我们也不会总是不断访问他.但是Discovery上的LIS302DL已经有相关的Example了[文件名stm32f4_discovery_lis302dl.*].我们就学习一下ST的写法以及思想.但是SPI_BaudRatePrescaler_4需要往下面调整一下,好做实验,如果稳定,我们再往上调整.
得到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:
的我们就可以对程序改进一点点,这样目的是为了初始化前识别设备在不在.
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的变化.
通过这个变化,可以结合LED显示,来观察.也可以自行发挥,这就不多说了.工程项目打包:



