我搞到的板子可能比较老,是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显示,来观察.也可以自行发挥,这就不多说了.工程项目打包: