datasheet

STM32:SPI驱动ADXL345

2019-06-13来源: 互联网关键字:STM32  SPI驱动  ADXL345

ADXL345为3轴数字加速度计。支持SPI或I2C访问。网上例子大多是I2C,这里使用4线SPI。


一、遇过的坑

调试过程花了几个小时,遇到一些小坑。


1.开始的时候,无论如何都无法读取芯片ID。这可是最基础的一步啊,SPI,I2C都试过。无奈之下,对照原理图与手册的管脚说明,发现Vs接到地了。其实这个管脚要接电源电压。老实说,一看名字还以为要接地,毕竟一般IC接地脚名字为Vss。让硬件工程师飞线修改。终于可以进行通信了。


2.发现数据跳动比较大。静止放置,也会出现很大的数据波动。看上去并不是噪声导致的。最后发现手册上对SPI速率与输出数据速率的相关性。重新修改SPI速率,输出数据终于稳定多了,再加上软件滤波,终于满足项目使用。


3.芯片手册推荐读取加速度数据时使用多字节连续读取,这样可确保数据完整性。我估计当CS被脚拉低后芯片就会禁止修改相关数据寄存器和FIFO的修改。不过手册对于多字节读取的时序图太粗略。



暂时没时间搞单次多字节读取。估计STM32的硬件SPI没有办法做到,以后有时间再研究。


二、代码

 


 

/******************ADXL345寄存器命令定义**********************/

#define DEVICE_ID           0X00        //获取器件ID,0XE5

#define THRESH_TAP          0X1D        //敲击阀值

#define OFSX                0X1E //x轴调整偏移值

#define OFSY                0X1F

#define OFSZ                0X20

#define DUR                 0X21

#define Latent              0X22

#define Window              0X23

#define THRESH_ACK          0X24

#define THRESH_INACT        0X25

#define TIME_INACT          0X26

#define ACT_INACT_CTL       0X27

#define THRESH_FF           0X28

#define TIME_FF             0X29

#define TAP_AXES            0X2A

#define ACT_TAP_STATUS      0X2B

#define BW_RATE             0X2C

#define POWER_CTL           0X2D

 

#define INT_ENABLE          0X2E

#define INT_MAP             0X2F

#define INT_SOURCE          0X30

#define DATA_FORMAT        0X31

#define DATA_X0            0X32

#define DATA_X1            0X33

#define DATA_Y0            0X34

#define DATA_Y1            0X35

#define DATA_Z0            0X36

#define DATA_Z1            0X37

#define FIFO_CTL            0X38

#define FIFO_STATUS         0X39

 

#define I_M_DEVID      ((uint8_t)0xE5) //器件ID=0XE5

 

/******************SPI管脚配置宏**********************/

#define ADXL345_SPIX                      SPI2

#define ADXL345_SPI_RCC                   RCC_APB1Periph_SPI2

 

#define ADXL345_SPI_SCK_PIN               GPIO_Pin_13

#define ADXL345_SPI_SCK_GPIO_PORT         GPIOB

#define ADXL345_SPI_SCK_GPIO_RCC          RCC_AHB1Periph_GPIOB

#define ADXL345_SPI_SCK_SOURCE            GPIO_PinSource13

#define ADXL345_SPI_SCK_AF                GPIO_AF_SPI2

 

#define ADXL345_SPI_MISO_PIN              GPIO_Pin_14

#define ADXL345_SPI_MISO_GPIO_PORT        GPIOB

#define ADXL345_SPI_MISO_GPIO_RCC         RCC_AHB1Periph_GPIOB

#define ADXL345_SPI_MISO_SOURCE           GPIO_PinSource14

#define ADXL345_SPI_MISO_AF               GPIO_AF_SPI2

 

#define ADXL345_SPI_MOSI_PIN              GPIO_Pin_15

#define ADXL345_SPI_MOSI_GPIO_PORT        GPIOB

#define ADXL345_SPI_MOSI_GPIO_RCC         RCC_AHB1Periph_GPIOB

#define ADXL345_SPI_MOSI_SOURCE           GPIO_PinSource15

#define ADXL345_SPI_MOSI_AF               GPIO_AF_SPI2

 

#define ADXL345_SPI_CS_PIN                GPIO_Pin_12

#define ADXL345_SPI_CS_GPIO_PORT          GPIOB

#define ADXL345_SPI_CS_GPIO_RCC           RCC_AHB1Periph_GPIOB

 

#define ADXL345_CS_LOW()       GPIO_ResetBits(ADXL345_SPI_CS_GPIO_PORT, ADXL345_SPI_CS_PIN)

#define ADXL345_CS_HIGH()      GPIO_SetBits(ADXL345_SPI_CS_GPIO_PORT, ADXL345_SPI_CS_PIN)

// SPI2 :PB12(cs) ,PB13(clk) ,PB14(miso)  ,PB15(mosi)

static void  _spi_init(void)

{

    GPIO_InitTypeDef  GPIO_InitStructure;

    SPI_InitTypeDef  SPI_InitStructure;

 

    RCC_AHB1PeriphClockCmd(ADXL345_SPI_SCK_GPIO_RCC|ADXL345_SPI_CS_GPIO_RCC, ENABLE);//使能GPIO时钟

    RCC_APB1PeriphClockCmd(ADXL345_SPI_RCC, ENABLE);//使能SPI时钟

 

    //sck miso mosi初始化设置

    GPIO_InitStructure.GPIO_Pin = ADXL345_SPI_SCK_PIN| ADXL345_SPI_MISO_PIN | ADXL345_SPI_MOSI_PIN ;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;   //复用功能

    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽输出

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; 

    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; 

    GPIO_Init(ADXL345_SPI_SCK_GPIO_PORT, &GPIO_InitStructure); 

 

    GPIO_PinAFConfig(ADXL345_SPI_SCK_GPIO_PORT,  ADXL345_SPI_SCK_SOURCE,  ADXL345_SPI_SCK_AF);  //复用配置

    GPIO_PinAFConfig(ADXL345_SPI_MISO_GPIO_PORT, ADXL345_SPI_MISO_SOURCE, ADXL345_SPI_MISO_AF); //复用配置

    GPIO_PinAFConfig(ADXL345_SPI_MOSI_GPIO_PORT, ADXL345_SPI_MOSI_SOURCE, ADXL345_SPI_MOSI_AF); //复用配置

    

    //cs初始化设置

    GPIO_InitStructure.GPIO_Pin = ADXL345_SPI_CS_PIN;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出

    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz

    GPIO_Init(ADXL345_SPI_CS_GPIO_PORT, &GPIO_InitStructure);//初始化

    ADXL345_CS_HIGH();

 

    RCC_APB2PeriphResetCmd(ADXL345_SPI_RCC, ENABLE); //复位SPI

    RCC_APB2PeriphResetCmd(ADXL345_SPI_RCC, DISABLE); //停止复位SPI

    //spi配置

    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工

    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;        //设置SPI工作模式:设置为主SPI

    SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;        //设置SPI的数据大小:SPI发送接收16位帧结构

    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;        //串行同步时钟的空闲状态为高电平

    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;    //串行同步时钟的第二个跳变沿(上升或下降)数据被采样

    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;        //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制

    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32;        //定义波特率预分频的值:波特率预分频值 84M/psc

    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;    //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始

    SPI_InitStructure.SPI_CRCPolynomial = 7;    //CRC值计算的多项式

    SPI_Init(ADXL345_SPIX, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器

 

    SPI_Cmd(ADXL345_SPIX, ENABLE); //使能SPI外设

}

/***********************************全局函数***********************************/

 

//读取三个方向的加速度

void memsdrv_ReadXYZ(int16_t *x, int16_t *y, int16_t *z)

{

    uint8_t BUF[6];

 

    BUF[0] = ADXL345_read_byte(0x32);

    BUF[1] = ADXL345_read_byte(0x33);

 

    BUF[2] = ADXL345_read_byte(0x34);

    BUF[3] = ADXL345_read_byte(0x35);

 

    BUF[4] = ADXL345_read_byte(0x36);

    BUF[5] = ADXL345_read_byte(0x37);

 

    *x = ((u16)BUF[1] << 8) + BUF[0];

    *y = ((u16)BUF[3] << 8) + BUF[2];

    *z = ((u16)BUF[5] << 8) + BUF[4];

 

}

//初始化ADXL345.

//返回值:0,初始化成功;其他值,初始化失败.

u8  memsdrv_Init(void)

{

    _spi_init();

    //_exit_init();

    delay_ms(500);

    if( ADXL345_read_byte( DEVICE_ID ) == I_M_DEVID )

    {

ADXL345_write_byte(DATA_FORMAT, 0X0b); //BIT6:SPI4线模式(默认);BIT5:中断电平0/1(高/

[1] [2]

关键字:STM32  SPI驱动  ADXL345

编辑:什么鱼 引用地址:http://www.eeworld.com.cn/mcu/ic464492.html
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:STM32 CDC HOST初步调试
下一篇:IAR环境下STM32F103ZET6+IAP方案的实现

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

STM32 FSMC 外部使用SRAM

数据,以及与硬盘等外部存储器交换的数据。只要计算机在运行中,CPU就会把需要运算的数据调到内存中进行运算,当运算完成后CPU再将结果传送出来,内存的运行也决定了计算机的稳定运行。SRAM怎么用:使用STM32的FSMC功能,将SRAM映射为单片机的的内部地址,进行指针操作。图中 A0~A18为地址线(即 2^19=512K,1K=1024); IO0~15 为数据线,总共 16根数据线, CS2 和 CS1 都是片选信号,不过 CS2 是高电平有效CS1 是低电平有效; OE 是输出使能信号( 读信号); WE 为写使能信号; UB 和LB 分别为高字节控制和低字节控制信号。 (1)FSMC-外部SRAM 编程流程分析
发表于 2019-06-17
STM32 FSMC 外部使用SRAM

STM32F042 基于CubeMX HAL库CAN的配置

"stm32f0xx_hal.h" CAN_HandleTypeDef hcan;  CAN_FilterConfTypeDef  sFilterConfig;static CanTxMsgTypeDef        TxMessage;static CanRxMsgTypeDef        RxMessage; void SystemClock_Config(void);static void MX_GPIO_Init(void);static void
发表于 2019-06-17
STM32F042 基于CubeMX HAL库CAN的配置

STM32F407 SPI flash

STM32F407 SPI接口:STM32F4XX时钟计算HCLK=168M PCLK1 =HCLK/4 =42M PCLK2 =HCLK/2 =84MSPI2、SPI3在PCLK1,最大时钟为42MSPI1在PCLK2,最大时钟为84MSTM32F4 支持的最大SPI时钟为37.5Mbits/s 因此需要分频。例程选择SPI2 分频后为21M串行Flash W25Q64BVSSIG (最高支持80MHz)。测试:全部写入0XAA 数据长度8192K 擦除:20.798 写入耗时42.599S 读:9.008S百度的参照时间擦除:8.9S 写入22.5S 读出 1.8S  校验时间1.8S 芯片特点
发表于 2019-06-17
STM32F407 SPI flash

STM32F4 USART1 TX RX FIFO

。***********************************************************************************************************///#include "stm32f4xx.h"#include "bspdebug_usartbsp_debug_uart.h"#include "bsp.h"#include <stdio.h>#define  debug_uart_tx_buf_size  1*1024#define  debug_uart_rx_buf_size  1*1024static uint8_t g_TxBuf
发表于 2019-06-17

STM32 SRAM内存管理

; 者: 硬石嵌入式开发团队  * 版    本: V1.0  * 编写日期: 2015-10-04  * 功    能: 动态内存分配管理实现  ******************************************************************************  * 说明:  * 本例程配套硬石stm32开发板YS-F1Pro使用。  *   * 淘宝:  * 论坛:http://www.ing10bbs.com  *  
发表于 2019-06-17

STM32F03开发板--系统时钟设置SysTick

首先我先分析下startup_stm32f0xx.s启动代码,其中/* Call the clock system intitialization function.*/  bl  SystemInit/* Call the application's entry point.*/  bl main发现开发板上电启动过程中,先调用了SystemInit()函数,再进入main()函数。SystemInit()函数在文件system_stm32f0xx.c中,它的作用是设置系统时钟SYSCLK。下面是SystemInit()源码:void SystemInit (void){ 
发表于 2019-06-17
STM32F03开发板--系统时钟设置SysTick

小广播

何立民专栏

单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2019 EEWORLD.com.cn, Inc. All rights reserved