This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
背景信息:
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)|-->*** 时钟信号端 // 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); //使能SSI while(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 Mode Delayms(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); }
感谢您的回复!
发出去的波形我检查过是我想要的格式和数据。
//************************************************************************* //读取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;