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;//100MHzGPIO_Init(ADXL345_SPI_CS_GPIO_PORT, &GPIO_InitStructure);//初始化ADXL345_CS_HIGH();RCC_APB2PeriphResetCmd(ADXL345_SPI_RCC, ENABLE); //复位SPIRCC_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工作模式:设置为主SPISPI_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/pscSPI_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(高/低有效);BIT0-1:量程=16gADXL345_write_byte(POWER_CTL,   0x08);  //BIT3=0/1:(测量模式/待机模式);BIT2=0/1:(工作/休眠);ADXL345_write_byte(BW_RATE,     0x0e);  //低4位:输出数据速率=1600(此速率下,SPI速率要设置>=2M) ;BIT4=0/1(低功耗/正常)ADXL345_write_byte(INT_ENABLE,  0x00);  //中断功能设置:不使能ADXL345_write_byte(INT_MAP,     0x00);  //设置中断映射到INT1引脚还是INT2引脚ADXL345_write_byte(FIFO_CTL,    0x00);ADXL345_write_byte(OFSX, 0x00);   //XYZ偏移调整ADXL345_write_byte(OFSY, 0x00);ADXL345_write_byte(OFSZ, 0x00);printf("mems init ok \r\n");return 0;}elseprintf("mems init err!\r\n");return 1;
}

之前忘了SPI读写函数,补上

//读单字节
u8 ADXL345_read_byte(u16 add)
{ADXL345_CS_LOW() ;while(SPI_I2S_GetFlagStatus(ADXL345_SPIX, SPI_I2S_FLAG_TXE) == RESET);SPI_I2S_SendData(ADXL345_SPIX, (add | 0x0080) << 8 );while(SPI_I2S_GetFlagStatus(ADXL345_SPIX, SPI_I2S_FLAG_RXNE) == RESET);ADXL345_CS_HIGH();return SPI_I2S_ReceiveData(ADXL345_SPIX) & 0x00ff;
}
//写单字节
void ADXL345_write_byte(u16 add, u16 val)
{ADXL345_CS_LOW();while (SPI_I2S_GetFlagStatus(ADXL345_SPIX, SPI_I2S_FLAG_TXE) == RESET);SPI_I2S_SendData(ADXL345_SPIX, add << 8 | val);while (SPI_I2S_GetFlagStatus( ADXL345_SPIX, SPI_I2S_FLAG_RXNE) == RESET);SPI_I2S_ReceiveData(ADXL345_SPIX);ADXL345_CS_HIGH();
}

STM32:SPI驱动ADXL345相关推荐

  1. STC8H开发(六): SPI驱动ADXL345三轴加速度检测模块

    目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) ST ...

  2. STM32——SPI驱动SD卡

    文末有工程链接(FATFS文件系统也移植了) VCC:5V GND:GND MISO:PA6 MOSI:PA7 SCK:PA5 CS:PA4 /*外设驱动*/ /*.c*/ /*以下是SPI1口初始化 ...

  3. 0.96OLED STM32 SPI驱动(一)

    闲来无聊,翻出了一个OLED,本来想串流做个小显示器用,感觉难度太大.将就变成了下面这 个样子,姑且叫火柴人大乱斗之OLED. 火柴人之OLED 分两步走,先驱动OLED能显示一副图片,本篇讲述此内容 ...

  4. 钜泉光电ATT7053C芯片STM32 SPI驱动

    一.硬件(低速)光耦隔离,测试速率40Kbps较稳定,80Kbps不稳定. 二.MX软件SPI配置 SPI读函数 void Read_ATT7053_B( uint8_t addr, uint8_t ...

  5. STM32驱动ADXL345三轴传感器

    简介:STM32F103C8T6驱动ADXL345三轴倾斜度传感器源码介绍. 开发平台:KEIL ARM MCU型号:STM32F103C8T6 传感器型号:ADXL345 特别提示:驱动内可能使用了 ...

  6. STM32 SPI+DMA 驱动 SRAM LY68L6400SLIT 应用笔记

    关键词:库函数,STM32F407,SPI+DMA ,SPI-DMA,SRAM , LY68L6400SLIT,STM32CubeMX 编 辑:大黄蜂 说明:本笔记记录 基于 STM32F407 + ...

  7. STM32CubeMX | 基于STM32使用HAL库硬件SPI驱动WK2124一拖四SPI转四路串口芯片

    STM32CubeMX | 基于STM32使用HAL库硬件SPI驱动WK2124一拖四SPI转四路串口芯片 STM32基础工程生成 首先使用STM32CUBEMX生成STM32的基础工程,配置时钟到7 ...

  8. STM32使用硬件SPI驱动RC522门禁模块

    0.前言 RC522射频门禁识别模块非常常用,某宝卖家提供的程序基本都是使用软件模拟SPI的方式进行驱动的,但是实测使用软件模拟SPI识别速率.准确性没有硬件SPI驱动时高,因此本篇博客用于记录使用S ...

  9. 基础篇010.2 STM32驱动RC522 RFID模块之二:STM32硬件SPI驱动RC522

    目录 1. 实验硬件及原理图 1.1 RFID硬件 1.2 硬件原理图 2. 单片机与RFID硬件模块分析 3. 利用STM32CubeMX创建MDK工程 3.1 STM32CubeMX工程创建 3. ...

  10. 嵌入式开发-STM32硬件SPI驱动TFT屏

    嵌入式开发-STM32硬件SPI驱动TFT屏 这次用到的TFT屏 CubeMX设置 代码编写 增加的内容 需要注意问题 代码下载 这次用到的TFT屏 现在的TFT屏幕已经很便宜了,65536色屏幕,2 ...

最新文章

  1. C# 给PDF添加图片背景
  2. shell脚本编写乘法口诀
  3. 不敢相信?System.currentTimeMillis()存在性能问题
  4. Java Review - LinkedHashMap LinkedHashSet 源码解读
  5. 2021年5月信息系统项目管理师上午真题
  6. v4l打开video设备 ,执行VIDIOC_DQBUF,出现Resource temporarily unavailable 问题
  7. centos5安装oracle11,CentOS 6.5 x64 安装 Oracle11g R2
  8. EasyUI基础入门之Pagination(分页)
  9. mysql后天命令查下显示_MySQL命令
  10. 人工智能时代的危机_AI信任危机:如何前进
  11. Mac下如何把iphone资料备份到移动硬盘
  12. 新系统软件著作权申请流程及注意事项
  13. html怎么添加banner图,如何在wordpress首页中添加banner图片?
  14. python f检验 模型拟合度_Python 爬取北京二手房数据,分析北漂族买得起房吗? | 附完整源码...
  15. 什么是云计算,云计算是什么意思
  16. CSS兼容性技巧整理从IE6-IE9 火狐谷歌浏览器兼容
  17. 使用tensorflow进行简单的强化学习 1—Q-learning
  18. 机器学习理论基础学习10--- 高斯混合模型GMM
  19. MATLAB Signal Rrocessing(13)视频和音频
  20. termux获取sd卡读写权限_我牵手金士顿小蓝TF卡成功上岛啦

热门文章

  1. ios vue 添加本地音乐_VUE怎么添加音乐 本地音乐添加教程
  2. Weighted Boxes Fusion
  3. 【LOJ2863】「IOI2018」组合动作
  4. HTML网页上播放AVI视频代码示例
  5. 同一块芯片,同时使用多个SOCKET工作,应该注意什么问题?
  6. 进行一个幂的运算(数学)
  7. 【金三银四】Java基础知识面试题(2021最新版)
  8. 怎样学计算机打字最快,怎样学电脑快速打字
  9. Cosy主题3.0使用教程
  10. 7-163 判断正整数n是否同时含有奇数和偶数