TI中文支持网
TI专业的中文技术问题搜集分享网站

读取加速度传感器时的SPI时序问题

背景信息:

A使用的芯片  TM4C123GH6PMI

B 硬件环境    TM4C123G Launchpad

C 软件环境    TivaWare_C_Series-2.1.0.12573

D其它        CCS6.0.1  加速度传感器为mpu6500

   使用SSI0模块

   ROM_GPIOPinConfigure(GPIO_PA2_SSI0CLK);    //PA2功能配置为SSI0CLK,时钟线
   ROM_GPIOPinConfigure(GPIO_PA3_SSI0FSS);    //PA3功能配置为SSI0FSS,片选线
   ROM_GPIOPinConfigure(GPIO_PA5_SSI0TX);     //PA5功能配置为SSI0TX,数据发送线
   ROM_GPIOPinConfigure(GPIO_PA4_SSI0RX);       //PA4功能配置为SSI0RX,数据接收线

第一次弄这种与外接传感器通信读取数据的,很多地方不太明白,请大家多多帮助!

问题1: 用示波器观察PA5引脚的数据发送情况,发现接和不接传感器时波形不同?图一为不接传感器。图二为接上传感器后,在时钟空闲时仍存在数据变换,但是都是一些无用的数据,应该没有影响的吧?

 这个是不接传感器时的图像。

 这个是连接上传感器的图像。

 这个是时钟与片选图像。

问题2:SPI_Write_register和SPI_Read_register这两个函数中我分别对引入的参数WriteReg做了如下操作:WriteReg+=0x80;和WriteReg&=0x7F;目的是按照SPI的要求在进行写操作时把第一个字节的首位变为1,读操作的时候把第一个字节的首位变为0。请问这样的做法是否正确?

//往MPU6500的寄存器写入
uint8_t SPI_Write_register(uint8_t WriteReg,uint8_t Value)//WriteReg要写的寄存器地址,Value要写的寄存器值
{uint8_t status; WriteReg+=0x80;
//ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);ROM_GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE,GPIO_PIN_3);GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0);status=SPI_RW(WriteReg);SPI_RW(Value);GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,GPIO_PIN_3);return(status);
}
//读取MPU6500指定寄存器的值
uint8_t SPI_Read_register(uint8_t WriteReg)
{uint8_t status;WriteReg&=0x7F;ROM_GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE,GPIO_PIN_3);GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0);//status=SPI_RW(WriteReg);SPI_RW(WriteReg);status=SPI_RW(0);GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,GPIO_PIN_3);return(status);
}

 

问题3:用示波器观察PA4引脚的数据接收情况,发现一直处于低电平,既读出的数据一直为零。是不是我对mpu6500的寄存器的写操作没有成功,使得mpu6500没有被成功配置造成的?

下面是我的代码:

//----------------------------------------------------------------------------
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/sysctl.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/ssi.h"
#include "driverlib/pin_map.h"
#include "driverlib/adc.h"
#include "mpu6500.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
//----------------------------------------------------------------------------
unsigned char BUF[10];//接收数据缓存区
short T_X,T_Y,T_Z,T_T;//X,Y,Z轴,温度

void delay()
{
	unsigned int counter = 0;
	while(counter < 10000){
		counter++;
	}
}

//-------------------------------------------------------------------------------------------
// @brief SSI模块使能,并且设置相关端口初始状态
// @param none
// @return none
//_______________
//|
//			PA2(SSI0Clk)|-->SPICLK	时钟信号端
//	TIVA	PA3(SSI0Fss)|-->SYNC	帧信号端
//			PA5(SSI0Tx) |-->SDIN	SSI数据发送端(LM4F120->DAC8802)
//			PA4(SSI0Rx) |-->SDOUT
//		________________|
//
//-------------------------------------------------------------------------------------------
void ssi_en()
{
	uint32_t ui32Data;ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);			//使能外设SSI0模块ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);		//使能SSI0使用的外设GPIOA//SSI0端口功能使能ROM_GPIOPinConfigure(GPIO_PA2_SSI0CLK);					//PA2功能配置为SSI0CLK,时钟线ROM_GPIOPinConfigure(GPIO_PA3_SSI0FSS);					//PA3功能配置为SSI0FSS,帧信号ROM_GPIOPinConfigure(GPIO_PA5_SSI0TX);					//PA5功能配置为SSI0TX,数据发送线ROM_GPIOPinConfigure(GPIO_PA4_SSI0RX);//PA4功能配置为SSI0RX,数据发送线ROM_GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_2|GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5);	//配置PA2,PA3,PA4,PA5供外设SSI0使用ROM_SSIConfigSetExpClk(SSI0_BASE, ROM_SysCtlClockGet(), SSI_FRF_MOTO_MODE_3, SSI_MODE_MASTER, 1000000, 8);	//端口模式:1MHZ,8位数据ROM_SSIEnable(SSI0_BASE);				//使能SSIwhile(SSIDataGetNonBlocking(SSI0_BASE, &ui32Data)){};//清除缓冲区的数据,确保读到的数据时正确的。
}


/*unsigned char ssi_send_2_dac8802(unsigned long val)
{
	if(val > 16384) return 0;ROM_SSIDataPut(SSI0_BASE, DAC_AB + val);	//发数据+while(ROM_SSIBusy(SSI0_BASE));				//等待发送完成//数据发送结束时,LDAC线需要一个电平的跳变(H->L->H)
	ROM_GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_2, 0);
	delay();
	ROM_GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_2, GPIO_PIN_2);
	delay();return 1;
}*/
//**********************************************************************
//
uint8_t SPI_RW(uint8_t value)
{uint32_t ui32Data;uint8_t ui8Data;SSIDataPut(SSI0_BASE,value);while (ROM_SSIBusy(SSI0_BASE)){}ROM_SSIDataGet(SSI0_BASE, &ui32Data);ui8Data = ui32Data & 0xff;return(ui8Data);
}
//********************************************************************

//********************************************************************
//往MPU6500的寄存器写入
uint8_t SPI_Write_register(uint8_t WriteReg,uint8_t Value)//WriteReg要写的寄存器地址,Value要写的寄存器值
{uint8_t status;WriteReg+=0x80;
//ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);ROM_GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE,GPIO_PIN_3);GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0);status=SPI_RW(WriteReg);SPI_RW(Value);GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,GPIO_PIN_3);return(status);
}
//**********************************************************************

//读取MPU6500指定寄存器的值
uint8_t SPI_Read_register(uint8_t WriteReg)
{uint8_t status;WriteReg&=0x7F;ROM_GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE,GPIO_PIN_3);GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0);//status=SPI_RW(WriteReg);SPI_RW(WriteReg);status=SPI_RW(0);GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,GPIO_PIN_3);return(status);
}

//初始化MPU9250,根据需要请参考pdf进行修改************************
void Init_MPU9250(void)
{

	SPI_Write_register(PWR_MGMT_1, 0x00);	//解除休眠状态
	SPI_Write_register(SMPLRT_DIV, 0x07);
	SPI_Write_register(CONFIG, 0x06);
	SPI_Write_register(GYRO_CONFIG, 0x18);
	SPI_Write_register(ACCEL_CONFIG, 0x19);

}
//******读取MPU9250数据****************************************
void READ_MPU9250_ACCEL(void)
{BUF[0]=SPI_Read_register(ACCEL_XOUT_L);BUF[1]=SPI_Read_register(ACCEL_XOUT_H);T_X=	(BUF[1]<<8)|BUF[0];
 //  T_X/=164;//读取计算X轴数据BUF[2]=SPI_Read_register(ACCEL_YOUT_L);BUF[3]=SPI_Read_register(ACCEL_YOUT_H);T_Y=	(BUF[3]<<8)|BUF[2];
 //  T_Y/=164;//读取计算Y轴数据BUF[4]=SPI_Read_register(ACCEL_ZOUT_L);BUF[5]=SPI_Read_register(ACCEL_ZOUT_H);T_Z=	(BUF[5]<<8)|BUF[4];// T_Z/=164;//读取计算Z轴数据



}

void READ_MPU9250_GYRO(void)
{BUF[0]=SPI_Read_register(GYRO_XOUT_L);BUF[1]=SPI_Read_register(GYRO_XOUT_H);T_X=	(BUF[1]<<8)|BUF[0];T_X/=16.4;//读取计算X轴数据BUF[2]=SPI_Read_register(GYRO_YOUT_L);BUF[3]=SPI_Read_register(GYRO_YOUT_H);T_Y=	(BUF[3]<<8)|BUF[2];T_Y/=16.4;//读取计算Y轴数据BUF[4]=SPI_Read_register(GYRO_ZOUT_L);BUF[5]=SPI_Read_register(GYRO_ZOUT_H);T_Z=	(BUF[5]<<8)|BUF[4];T_Z/=16.4;//读取计算Z轴数据// BUF[6]=Single_Read(GYRO_ADDRESS,TEMP_OUT_L);// BUF[7]=Single_Read(GYRO_ADDRESS,TEMP_OUT_H);// T_T=(BUF[7]<<8)|BUF[6];// T_T = 35+ ((double) (T_T + 13200)) / 280;// 读取计算出温度
}

/*
void READ_MPU9250_MAG(void)
{Single_Write(GYRO_ADDRESS,0x37,0x02);//turn on Bypass ModeDelayms(10);Single_Write(MAG_ADDRESS,0x0A,0x01);Delayms(10);BUF[0]=Single_Read (MAG_ADDRESS,MAG_XOUT_L);BUF[1]=Single_Read (MAG_ADDRESS,MAG_XOUT_H);T_X=(BUF[1]<<8)|BUF[0];BUF[2]=Single_Read(MAG_ADDRESS,MAG_YOUT_L);BUF[3]=Single_Read(MAG_ADDRESS,MAG_YOUT_H);T_Y=	(BUF[3]<<8)|BUF[2];//读取计算Y轴数据BUF[4]=Single_Read(MAG_ADDRESS,MAG_ZOUT_L);BUF[5]=Single_Read(MAG_ADDRESS,MAG_ZOUT_H);T_Z=	(BUF[5]<<8)|BUF[4];//读取计算Z轴数据
}*/
void check(void)
{
	
	BUF[9]=SPI_Read_register(WHO_AM_I);
}
lihao guo:


xyz549040622:

回复 lihao guo:

那个不接从机的时候的数据应该不对呀。你看看那个发出去的波形,是你需要的格式和数据波形吗?看不出有什么问题

lihao guo:

回复 xyz549040622:

感谢您的回复!

发出去的波形我检查过是我想要的格式和数据。

//*************************************************************************
//读取MPU6500指定寄存器的值
uint8_t SPI_Read_register(uint8_t WriteReg)
{uint8_t status;WriteReg&=0x7F;ROM_GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE,GPIO_PIN_3);GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,0);//status=SPI_RW(WriteReg);SPI_RW(WriteReg);status=SPI_RW(0);GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_3,GPIO_PIN_3);return(status);
}

第一个字节为做了与运算后的寄存器地址,第二个字节为0代表读操作。

我检查过传感器是完好的,因为用I2C通信的时候能正确地读取出从机中寄存器的值。

我还想请问一下,我这一步的作法是否正确?这是我参考SPI协议后加上的,但是在网络上没看到其他人的代码中有做这一步。而且我尝试把这一步骤去掉,但读数还是一直为0.

WriteReg&=0x7F;

xyz549040622:

回复 lihao guo:

不知道你找到问题了没有,以前一直没有操作过SPI,都是用的IO模拟,向你学习下经验

赞(0)
未经允许不得转载:TI中文支持网 » 读取加速度传感器时的SPI时序问题
分享到: 更多 (0)