】SPI 协议与ADXL345 三轴加速度传感器)
文章目录前言一、SPI基础概念二、SPI的时序三、IMX6ULL上的SPI3.1 概念及原理框图3.2 相关寄存器RXDATATXDATACONREGCONFIGREGSTATREG四、ADXL345加速度传感器五、SPI初始化六、SPI读写函数七、ADXL345与IMX6ULL通信八、UART、I2C与SPI对比前言在【ARM 裸机开发 (IMX6ULL-mini)】I2C协议详解这篇文章中详细讲解了IMX6ULL上的I2C协议这篇文章将讲解另一个常用的通信协议SPI。两者在许多外设中常常都能够使用但还是有很多差异的在这篇文章最后会总结两者的区别。除此以外本篇文章还会介绍ADXL345加速度传感器与IMX6ULL的SPI通信。一、SPI基础概念SPISerial Peripheral interface(串行外设接口)SPI 接口主要应用在 EEPROMFLASH实时时钟AD 转换器还有数字信号处理器和数字信号解码器之间。SPI 是一种高速的全双工同步的串行通信总线。SPI数据发送与I2C一样是高位先行。标准SPI采用四线组网方式如下图➢SCLK时钟信号线。与I2C类似的所有设备都都需要时钟信号线进行同步该信号由主机负责提供➢MOSI主出从入相当于主机的数据发送线➢MISO主入从出相当于主机的数据接收线➢CS片选信号与I2C不同SPI设备没有所谓的从机地址连接在总线上的设备通过CS片选信号选择。在同一时刻总线上只有一个外设被选择CS信号线通常是低电平有效的。二、SPI的时序SPI的通信时序与I2C不同I2C的时序是固定的时钟线(SCL)上的信号为高电平期间数据线(SDA)上的数据必须保持稳定。只有在时钟线(SCL)上的信号为低电平期间数据线(SCL)上的高电平或低电平状态才允许变化。但SPI的时序是取决于**时钟极性(Clock Polarity 简称CPOL)和时钟相位(Clock Phase简称CPHA)**的。➢CPOL规定了时钟信号线在空闲时的状态CPOL0表示时钟信号线在空闲时为低电平CPOL1表示时钟信号线在空闲是为高电平➢CPHA与I2C不同SPI的数据接收方并不是在时钟高或者低电平时采样的而是在时钟信号处于沿时至于是在上升沿还是下降沿取决于CPHA。CPHA0表示是在时钟信号变化的第一个沿时采样CPHA1表示是在时钟信号变化的第二个沿时采样。因此我们可以得到这样的时序图无论哪种工作方式SPI这种串行通信方式都是MSB先行的。和I2C类似大多数情况下与SPI外设的通信其实就是读写外设寄存器这些寄存器同样也有着各自的地址。由于四线制SPI是全双工通信方式在发送一个字节数据的同时其实也就接收到了一个字节因此对于SPI来说发送其实也就是接收。IMX6ULL有一个发送缓冲寄存器同时也有一个接收缓冲寄存器发送完一个字节之后接收缓冲寄存器也会收到一个字节。三、IMX6ULL上的SPI3.1 概念及原理框图IMX6ULL 自带的 SPI 外设叫做 ECSPI全称是 Enhanced Configurable Serial Peripheral Interface增强的SPI。ECSPI 有 6432 个接收**FIFO(RXFIFO)**和 6432 个发送FIFO(TXFIFO)。IMX6ULL中一共有3个SPI。其中SPI3是引出了引脚。IMX6ULL参考手册中的原理框图名称全称作用TXDATA发送FIFOTX FIFO64×32bitCPU 往这里写待发送数据写进去就进发送缓冲区RXDATA接收FIFORX FIFO64×32bit移位寄存器收到的数据存入这里CPU 读这个寄存器拿收到的数据STATREG状态寄存器标记 FIFO 满 / 空、传输完成、错误标志位INTREG中断寄存器中断使能、中断标志控制产生Interrupt RequestDMAREGDMA 寄存器DMA 相关配置产生DMA RequestsPERIODREG周期寄存器硬件片选延时TESTREG测试寄存器模块自测调试用CONREG控制寄存器核心配置主 / 从模式、CPOL/CPHA、MSB/LSB、数据位宽、硬件 SS 使能3.2 相关寄存器在一般的SPI通信中我们主要用到RXDATA、TXDATA、CONREG、CONFIGREG、STATREG这五个寄存器RXDATATXDATACONREGCONFIGREGSTATREG四、ADXL345加速度传感器ADXL345是一款三轴加速度传感器主要特点如下➢ 测量范围±2g、±4g、±8g、±16g设置➢ 分辨率最高13位3.9mg/LSB➢ 工作电压2.0V至3.6V➢ 低功耗测量模式仅0.23mA待机模式40μA➢ 核心功能1、三轴加速度测量X、Y、Z2、静态重力加速度测量 3、动态加速度震动、运动测量 4、自由落体检测 5、单击/双击检测 6、活动/非活动监测➢ 接口支持SPI3线和4线模式、I2C数字接口➢ 特色功能1、内置32级FIFO缓冲 2、可编程中断功能 3、自动休眠和唤醒功能➢ 应用场景1、移动设备方向检测 2、游戏和虚拟现实控制器3、运动检测和计步器4、防盗系统的运动检测5、工业振动监测6、医疗设备姿态检测时序图通过时序图可见ADXL345采用的是SPI通信模式3即CPOL1.CPHA1。这里需要注意一个细节ADXL345在向寄存器写入和读取时寄存器的最高位是不一样的读的时候最高位为1写的时候最高位为0。例如写数据到0x20寄存器时先发0x20再发要写入的数据读取时则需要先发0xA0之后进入读取时序。具体操作也是根据ADXL345参考手册操作相关寄存器。五、SPI初始化SPI3的四条线都是GPIO复用引脚因此我们需要将其配置为SPI模式。然后对SPI相关寄存器配置成我们想要的模式。voidspi3_channel0_init(void){//片选IOMUXC_SetPinMux(IOMUXC_UART2_TX_DATA_GPIO1_IO20,0);IOMUXC_SetPinConfig(IOMUXC_UART2_TX_DATA_GPIO1_IO20,0x10B1);//时钟IOMUXC_SetPinMux(IOMUXC_UART2_RX_DATA_ECSPI3_SCLK,0);IOMUXC_SetPinConfig(IOMUXC_UART2_RX_DATA_ECSPI3_SCLK,0x10B1);//MISOIOMUXC_SetPinMux(IOMUXC_UART2_RTS_B_ECSPI3_MISO,0);IOMUXC_SetPinConfig(IOMUXC_UART2_RTS_B_ECSPI3_MISO,0x10B1);//MOSIIOMUXC_SetPinMux(IOMUXC_UART2_CTS_B_ECSPI3_MOSI,0);IOMUXC_SetPinConfig(IOMUXC_UART2_CTS_B_ECSPI3_MOSI,0x10B1);//通信前CS拉高gpio_init(GPIO1,20,(GPIO_Type_t){1,gpio_output});//SPI寄存器设置ECSPI3-CONREG0;ECSPI3-CONREG|(720)|(0B111012)|(28)|(14)|(13)|(10);ECSPI3-CONFIGREG0;ECSPI3-CONFIGREG|(120)|(14)|(10);}六、SPI读写函数在完成初始化后根据SPI读即是写写即是读的特点我们可以写出这样一个读写函数unsignedcharspi3_read_write(unsignedchardata){while((ECSPI3-STATREG(10))0);ECSPI3-TXDATAdata;while((ECSPI3-STATREG(13))0);returnECSPI3-RXDATA;}七、ADXL345与IMX6ULL通信根据ADXL345参考手册寄存器配置0x310x0B开启满分辨率±16g0.0039g/LSB换算公式。原始数据拼接低字节0x32在前高字节0x33左移 8 位CS 软件控制片选等可以写出ADXL345的读函数、写函数、初始化函数、数据获取函数等。structADXL345_Data{shortx;shorty;shortz;floatx_g;floaty_g;floatz_g;};externvoidadxl345_write(unsignedcharreg_addr,unsignedchardata);externunsignedcharadxl345_read(unsignedcharreg_addr);externvoidadxl345_init(void);externstructADXL345_Dataadxl345_read_data(void);voidadxl345_write(unsignedcharreg_addr,unsignedchardata){// CS lowgpio_set_value(GPIO1,20,0);//主机发送寄存器地址spi3_read_write(reg_addr);//主机发送数据spi3_read_write(data);// CS highgpio_set_value(GPIO1,20,1);}unsignedcharadxl345_read(unsignedcharreg_addr){unsignedchardata;// CS lowgpio_set_value(GPIO1,20,0);//主机发送读取的寄存器地址spi3_read_write(reg_addr|0x80);//主机接收数据dataspi3_read_write(0x00);// CS highgpio_set_value(GPIO1,20,1);//返回数据returndata;}voidadxl345_init(void){//关闭中断adxl345_write(0x2E,0x08);//设置满分辨率和满量程adxl345_write(0x31,0x0B);//设置低功耗模式配置采样速率adxl345_write(0x2C,0x08);//配置测量和唤醒模式adxl345_write(0x2D,0x0B);}structADXL345_Dataadxl345_read_data(void){structADXL345_Datadata;//x轴数据data.xadxl345_read(0x32)|adxl345_read(0x33)8;//y轴数据data.yadxl345_read(0x34)|adxl345_read(0x35)8;//z轴数据data.zadxl345_read(0x36)|adxl345_read(0x37)8;//获得三轴加速度data.x_gdata.x*0.0039;data.y_gdata.y*0.0039;data.z_gdata.z*0.0039;returndata;}八、UART、I2C与SPI对比