DSP

IMU模块ADIS16448调试过程及经验总结

2019-07-13 14:37发布

        ADIS16448集成了陀螺仪、加速度计、磁力计及气压计为一体的IMU模块,我在这里总结下此模块的使用及调试经验。         首先说下硬件环境:MCU为TMS320C6722(DSP);IMU为ADIS16448;数据传输接口为SPI通信,五线连接:SIMO,SOMI,CLK,CS(片选),第五根线为IMU数据准备好引脚。         ADIS16448模块的使用相对较为简单,手册也只有24页的长度,相对DSP及ublox的手册阅读工作量来说小得多。 一、数据读取方式         ADIS16448提供了两种方式将数据传输给MCU。方式一为single register read,也就是由MCU向ADIS16448发送获取数据的指令。比如想获取加速度计x轴方向的数据,就发送一条读取加速度计x轴方向的数据地址的指令,这样ADIS16448就会向MCU返回加速度计x轴方向的数据。方式二为Burst Read,指ADIS16448定周期准备好数据,一旦准备好数据就将上面提到的数据准备好引脚置高(也就是产生一个高电位脉冲)从而使MCU产生外部中断,在外部中断中接收ADIS16448发送过来的数据,这些数据包含了陀螺仪、加速度计、磁力计及气压计的数据。         从上面的简述中可以分析得知,single register read模式读取数据的主动性由MCU掌控,MCU可以在任意时间读取任意传感器的数据,但是只能每次只能读取一个传感器的单方向数据;Burst Read模式读取数据的主动性在于ADIS16448,因为IMU只有将数据准备好,向MCU发送脉冲信号使其产生外部中断,MCU才能接收数据,但是好处是将所有传感器的数据一次全部传送过来。 二、通信设置         1.对于SPI的设置,ADIS16448做了规定:                  这些设置对于ADIS16448来说是不可编程的,所以在编写MCU方的SPI驱动时要注意。         2.这里有一个注意事项:                  注意到Figure 3中有个tSTALL,其叫做Stall Time。这个Stall Time很重要。当用方式一single register read模式读取数据时,Stall Time就是MCU向IMU发送读取控制指令的最小间隔时间。举个例子,我想获取IMU的加速度计x轴和y轴的数据,若用single register read模式读取数据,MCU需要向IMU发送两个读取指令,这个Stall Time就是两条读取指令的最小间隔时间。若不加Stall Time,读出来的数据会有问题。而用Burst Read模式读取数据的话,因为其传感器数据为连续发送,所以不存在Stall Time,手册上也给了相关说明:                 3.读取指令手册给了相关说明:                  DIN对应的是SIMO引脚,DOUT对应的是SOMI引脚。MCU对于IMU有两个操作:读操作和写操作。通过DIN的的第一位来分辨为读操作还是写操作,0为读操作,1为写操作。当为读操作时,A6-A0为所要读取寄存器的地址,此时DC7-DC0写为0;当为写操作时,A6-A0为所要写入寄存器的地址,此时DC7-DC0为写入寄存器的数据。         4.还有一点需要注意,因为SPI为全双工同步通信,所以,在接收数据的同时也要发送数据。                  上面的时序图表明,所要读取的数据与发送的指令总是错开一个十六位,这是因为SPI为全双工同步通信,而IMU处理数据需要一定时间。也就是,当你发送0x0400时,返回的不是XGYRO_OUT,紧接着之后当发送完0x0600后(此时所要读取的数据为YGYRO_OUT),此时接收的数据为XGYRO_OUT,在写MCU方的程序时,这一点要注意。 三、示例代码         这里给出用方式一single register read模式读取陀螺仪、加速度计、磁力计及气压计的程序。         //Read IMU Data CMD #define Read_PROD_ID 0x00005600 #define Read_XGYRO_OUT_CMD 0x00000400 #define Read_YGYRO_OUT_CMD 0x00000600 #define Read_ZGYRO_OUT_CMD 0x00000800 #define Read_XACCL_OUT_CMD 0x00000A00 #define Read_YACCL_OUT_CMD 0x00000C00 #define Read_ZACCL_OUT_CMD 0x00000E00 #define Read_XMAGN_OUT_CMD 0x00001000 #define Read_YMAGN_OUT_CMD 0x00001200 #define Read_ZMAGN_OUT_CMD 0x00001400 #define Read_ZMAGN_OUT_CMD 0x00001400 #define Read_BARO_OUT_CMD 0x00001600 #define Read_TEMP_OUT_CMD 0x00001800 #define Read_XGYRO_OFF_CMD 0x00001A00 #define Read_YGYRO_OFF_CMD 0x00001C00 #define Read_ZGYRO_OFF_CMD 0x00001E00 #define Read_XACCL_OFF_CMD 0x00002000 #define Read_YACCL_OFF_CMD 0x00002200 #define Read_ZACCL_OFF_CMD 0x00002400 Uint8 XMT_OVER_FLAG =0;//SPI1 Receive Data Flag, XMT_OVER_FLAG=1 when receive a 16-bit data is finished Uint32 Non_Burst_Read_Data=0; Int16 XGYRO_OUT=0; Int16 YGYRO_OUT=0; Int16 ZGYRO_OUT=0; Int16 XACCL_OUT=0; Int16 YACCL_OUT=0; Int16 ZACCL_OUT=0; Int16 XMAGN_OUT=0; Int16 YMAGN_OUT=0; Int16 ZMAGN_OUT=0; Uint16 BARO_OUT=0; float gx=0; float gy=0; float gz=0; float ax=0; float ay=0; float az=0; float mx=0; float my=0; float mz=0; void main (void) { /*********************************************/ // Relocate interrupt vector table CSL_intcSetVectorPtr(vectors); interrupt_configuration(); pll_configuration(); dMAX_configuration(); spi1_configuration(); intc_configuration(); RTI_configuration(); /*********************************************/ get_IMU_data(); while(1) { } } void get_IMU_data(void) { IMU_test(Read_XGYRO_OUT_CMD); delay(200); //GYROSCOPES OUTPUT IMU_test(Read_YGYRO_OUT_CMD); delay(200); XGYRO_OUT = (Int16)Non_Burst_Read_Data; gx = XGYRO_OUT/25 ; IMU_test(Read_ZGYRO_OUT_CMD); delay(200); YGYRO_OUT = (Int16)Non_Burst_Read_Data; gy = YGYRO_OUT/25 ; IMU_test(Read_XACCL_OUT_CMD); delay(200); ZGYRO_OUT = (Int16)Non_Burst_Read_Data; gz = ZGYRO_OUT/25; //ACCELEROMETERS OUTPUT IMU_test(Read_YACCL_OUT_CMD); delay(200); XACCL_OUT = (Int16)Non_Burst_Read_Data; ax = XACCL_OUT/1200 ; IMU_test(Read_ZACCL_OUT_CMD); delay(200); YACCL_OUT = (Int16)Non_Burst_Read_Data; ay = YACCL_OUT/1200; IMU_test(Read_XMAGN_OUT_CMD ); delay(200); ZACCL_OUT = (Int16)Non_Burst_Read_Data; printf(" Non_Burst_Read_Data= %d ",ZACCL_OUT); az = ZACCL_OUT/1200; //GMAGNETOMETERS OUTPUT IMU_test(Read_YMAGN_OUT_CMD); delay(200); XMAGN_OUT = (Int16)Non_Burst_Read_Data; mx = XMAGN_OUT/7; IMU_test(Read_ZMAGN_OUT_CMD); delay(200); YMAGN_OUT = (Int16)Non_Burst_Read_Data; my = YMAGN_OUT/7; IMU_test(Read_BARO_OUT_CMD); delay(200); ZMAGN_OUT = (Int16)Non_Burst_Read_Data; mz = ZMAGN_OUT/7; //BAROMETRIC PRESSURE OUTPUT IMU_test(Read_BARO_OUT_CMD); delay(200); BARO_OUT = (Uint16)Non_Burst_Read_Data; } void IMU_test(Uint32 CMD) { McASP0_ptr[McASPPDCLR] |= 0x00008000; //Chip Select IMU XMT_OVER_FLAG = 0; spi1_ptr[SPIDAT0] = CMD; //Read IMU Data CMD,write data to SPIDAT0 Register while(XMT_OVER_FLAG == 0); } void delay(Uint32 number) //delay,Stall Time { int temp_count=0; while(temp_count
        main中get_IMU_data()函数之前的函数均为各个外设的驱动函数,不同的MCU,驱动函数自然不同,所以这些函数的内容便没有贴出来。delay(200)函数对应的就是Stall Time。