STM32F407使用SPI协议读取ADXL345三轴加速度

STM32F407使用SPI协议读取ADXL345三轴加速度

在这里插入图片描述
在一开始,模块默认的SPI协议就是4线,根据手册,我们进行实物连接。

根据实物图进行连接

PB12---CS                 <-------------------->        CS

PB13---SCK               <-------------------->        SCL        

PB14---MISO             <-------------------->        SDO

PB15---MOSI             <-------------------->        SDA

注意不要接反了,3V3,GDN正常接3V3/5V 和 GND就行

我们这里要仔细阅读ADXL345的手册关于SPI的那一章

在这里插入图片描述
我们先来分析这段话
在这里插入图片描述

大体意思就是

SPI通信有两种接线方式:SPI是一种常见的通信协议,用于微控制器和传感器之间的数据交换。SPI可以以3线或4线模式工作。3线模式指的是只使用时钟线(SCLK)、数据线(SDI/SDO)和芯片选择线(CS)。4线模式则额外增加了一个数据线(SDO/SDI),专门用于从传感器到微控制器的数据传输。

通过寄存器设置通信模式:ADXL345内部有一个叫做DATA_FORMAT的寄存器,地址是0x31。通过修改这个寄存器里的一个位(位D6),可以选择是使用3线还是4线SPI模式。如果把位D6清零,就表示使用4线模式;如果把位D6设为1,则表示使用3线模式。

通信速度和时序:SPI通信的速度由时钟速度决定。这里提到,如果负载电容不超过100皮法拉(pF),SPI的最大时钟速度可以达到5MHz。时钟极性(CPOL)和时钟相位(CPHA)的设置决定了数据在时钟的哪个边缘被采样。这里提到的时钟极性为1、时钟相位为1,意味着数据在时钟的上升沿被采样。

CS引脚的处理:在SPI通信开始之前,需要确保CS(芯片选择)引脚处于高电平。这样做是为了确保在设置好时钟极性和相位之后,传感器处于正确的初始状态。

3线SPI的特别建议:如果你使用的是3线SPI模式,建议将SDO引脚通过一个10千欧姆(kΩ)的电阻下拉到地,或者直接接到VDD I/O(电源电压)。这是为了确保在通信时,SDO引脚的电平状态是确定的

在这里插入图片描述

大体意思就是

CS线的作用:CS是“Chip Select”的缩写,意为“芯片选择”。在SPI通信中,CS线用于告诉SPI从设备(在这个例子中是ADXL345传感器)“嘿,现在轮到你了,我们开始通信吧”。这根线在开始传输数据之前要设置为低电平,告诉从设备“现在开始传输数据”;传输结束之后,CS线要设置回高电平,表示“传输结束,你可以休息了”。

SCLK线的控制:SCLK代表“Serial Clock”,即串行时钟。这个时钟信号是由SPI主设备(比如STM32微控制器)提供的,它用来同步数据的发送和接收。当没有数据传输发生时,SCLK保持在高电平状态,等待下一次数据传输的开始。

SDI和SDO线:SDI是“Serial Data Input”的缩写,意为串行数据输入;SDO是“Serial Data Output”的缩写,意为串行数据输出。在SPI通信中,SDI线用于从主设备向从设备发送数据,而SDO线则用于从从设备向主设备发送数据。

数据更新和采样:在SPI通信中,数据在SCLK的下降沿(即时钟信号从高变低的时刻)更新,这意味着在这一刻,主设备和从设备会改变它们发送的数据。而在SCLK的上升沿(即时钟信号从低变高的时刻),主设备会采样从设备发送过来的数据。

多字节传输:如果你需要一次性发送或接收多个数据字节,就需要使用多字节位(MB)。在第一个字节传输之后,接下来的每个8个时钟脉冲会使得ADXL345自动切换到下一个寄存器进行读取或写入,无需额外的命令。

传输结束和CS失效:一旦停止发送时钟脉冲,数据传输就会停止,这时CS信号也就失效,表示当前的通信已经结束。

访问不同的寄存器:如果你需要读取或写入ADXL345中不连续的寄存器,那么在两次传输之间,CS信号必须先失效,然后再激活,以便开始新的传输。

在这里插入图片描述

大体意思就是

时序图的作用:时序图是一种图表,用来展示在SPI通信中,各种信号(比如CS、SCLK、SDI、SDO)随时间变化的状态。图38是针对3线式SPI的读取或写入操作的时序图,而图36和图37则是4线式SPI的读取和写入操作的时序图。这些图帮助我们理解在数据传输过程中,信号应该如何正确地变化。

逻辑阈值和时序参数:在SPI通信中,有一些关键的参数需要遵守,比如信号的高低电平阈值,以及信号变化的时间点。这些参数确保了数据能够正确无误地被发送和接收。表9和表10中列出了必须满足的逻辑阈值和时序参数,以保证SPI通信的正确性。

通信速率与输出数据速率(ODR)的匹配:SPI通信速率(也就是SPI时钟的速度)和输出数据速率(ODR,即传感器输出数据的频率)需要相互匹配。如果SPI通信速率很快(2MHz或更高),那么推荐使用较高的ODR,比如3200Hz或1600Hz。如果通信速率慢一些(至少400kHz),那么推荐使用800Hz的ODR。这样做是为了确保数据能够被正确地采样,不会因为速率不匹配而丢失数据或产生噪声。

速率设置不当的后果:如果你设置的ODR高于推荐的值,那么可能会因为SPI通信速率跟不上而导致数据采样出现问题,比如数据丢失或额外噪声。这就好比一个人试图在很短的时间内读完一本书,结果可能会漏掉一些内容或者读错字

再来看时序图
在这里插入图片描述

时序图总结

1.相位和极性都配置为1。
2.在对寄存器进行读时,地址高位为1;对寄存器进行写时地址高位为0。
3.读取多字节时,次高位也要为1。

代码编写

查看ADXL345的手册,我可以看到相关寄存器

在这里插入图片描述

可以看到,发送命令0X00,就能得到ADXL345设备的ID号,验证模块是正常的并且还能验证通信成功。
那么我们是不是只要代码这么写呢:SPI_Flash_SendReadByte(0x00);
回到我们之前那句话:发送指令,地址最高位为 1 代表读,而我们想要读出设备ID,那么就需要将这个 地址 0X00 | 0X80 ----》 1000 0000,其实:后五位代表地址,最高位代表读还是写,次高位代表读取多个字节。所以 获取 ADXL345 的设备ID代码如下:

uint32_t SPI_ADXL345_ReadID(void)
{
	uint32_t temp = 0;
	/*开始通讯,CS低电平*/
	GPIO_ResetBits(GPIOB,GPIO_Pin_12);
	
	SPI_Flash_SendReadByte(0x80);
	
	temp = SPI_Flash_SendReadByte(0xFF); //这里0XFF只是为了交换数据读出ID
	
	
	/*结束通讯,CS高电平*/
	GPIO_SetBits(GPIOB,GPIO_Pin_12);
	
	
	return temp;	
}

问题

在main函数中初始化并调用这个函数,结果却发现 ,设备ID读不出来总是 0,反正就是读不出来真正的ID 0XE5。这是为什么呢,相信或许很多人都卡在了这一步。

在模块中有个R4电阻,而ADXL345模块默认是关闭SPI协议的。解决办法就是需要手动将ADXL345 模块上的R4电阻给扣掉。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值