背景信息:
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模拟,向你学习下经验