- #include <msp430g2553.h>
- #include"mpu6050.h"
- #include "USCI_A0.h"
- #include "IMU.h "
- /*
- * ======== BCSplus_graceInit ========
- * Initialize MSP430 Basic Clock System
- */
- void BCSplus_graceInit(void)
- {
- /* USER CODE START (section: BCSplus_graceInit_prologue) */
- /* User initialization code */
- /* USER CODE END (section: BCSplus_graceInit_prologue) */
- /*
- * Basic Clock System Control 2
- *
- * SELM_0 -- DCOCLK
- * DIVM_0 -- Divide by 1
- * ~SELS -- DCOCLK
- * DIVS_1 -- Divide by 2
- * ~DCOR -- DCO uses internal resistor
- *
- * Note: ~<BIT> indicates that <BIT> has value zero
- */
- BCSCTL2 = SELM_0 | DIVM_0 | DIVS_1;
- if (CALBC1_16MHZ != 0xFF) {
- /* Adjust this accordingly to your VCC rise time */
- __delay_cycles(100000);
- /* Follow recommended flow. First, clear all DCOx and MODx bits. Then
- * apply new RSELx values. Finally, apply new DCOx and MODx bit values.
- */
- DCOCTL = 0x00;
- BCSCTL1 = CALBC1_16MHZ; /* Set DCO to 16MHz */
- DCOCTL = CALDCO_16MHZ;
- }
- /*
- * Basic Clock System Control 1
- *
- * XT2OFF -- Disable XT2CLK
- * ~XTS -- Low Frequency
- * DIVA_0 -- Divide by 1
- *
- * Note: ~XTS indicates that XTS has value zero
- */
- BCSCTL1 |= XT2OFF | DIVA_0;
- /*
- * Basic Clock System Control 3
- *
- * XT2S_0 -- 0.4 - 1 MHz
- * LFXT1S_0 -- If XTS = 0, XT1 = 32768kHz Crystal ; If XTS = 1, XT1 = 0.4 - 1-MHz crystal or resonator
- * XCAP_1 -- ~6 pF
- */
- BCSCTL3 = XT2S_0 | LFXT1S_0 | XCAP_1;
- /* USER CODE START (section: BCSplus_graceInit_epilogue) */
- /* User code */
- /* USER CODE END (section: BCSplus_graceInit_epilogue) */
- }/*
- * main.c
- */
- int main(void)
- {
- WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
- BCSplus_graceInit(); //MCLK = 16M,SMCLK = 8M,ack =32.768k
- WDTCTL = WDTPW | WDTTMSEL | WDTIS0;
- IE1 |= WDTIE;
- USCI_A0_init(); //uart 38400bps
- P1DIR |= BIT0; //initialize led control PIN
- _EINT();
- MPU6050_Init(); //initialize mpu6050
-
- while(1)
- {
- /*
- Get_Attitude();
- //MPU6050_Dataanl();
- // ReadMPU6050All();
- //Prepare_Data(); //耗時6.15ms
- //Uart1_Send_AF(); //耗時8.42ms
- P1OUT ^= BIT0;
- Get_Attitude();
- //ReadMPU6050All();
- //MPU6050_Dataanl(); //未使用多字節(jié)讀取,耗時6ms,使用多字節(jié)讀取,耗時3.6ms
- //Prepare_Data();
- // Uart1_Send_AF();
- P1OUT ^= BIT0;
- */
- }
-
- }
- //watchdog interrupt server program per 1ms
- #pragma vector=WDT_VECTOR
- __interrupt void WDT_ISR_HOOK(void)
- {
- /* USER CODE START (section: WDT_ISR_HOOK) */
- /* replace this comment with your code */
- static unsigned int count=0;
- static unsigned char ms2 = 0,ms5 = 0,ms10 = 0;
- count++;
- ms2++;
- ms5++;
- ms10++;
-
- if(ms2 == 2)
- {
- ms2 = 0;
- Prepare_Data();
- //MPU6050_Dataanl();
- }
- if(ms5 >= 4)
- {
- ms5 = 0;
- Get_Attitude();
-
- }
- if(ms10 >= 10)
- {
- ms10 = 0;
- Uart1_Send_AF();
- }
- if(count== 200)
- {
- count=0;
- P1OUT ^= BIT0;
- }
- /* USER CODE END (section: WDT_ISR_HOOK) */
- }
- /*
- * This file contains some mpu6050 operation.
- * By IC爬蟲 (1394024051@qq.com)
- * 2014-4-13 v1.0
- */
- #include "mpu6050.h"
- unsigned char mpu6050_buffer[14]; //I2C讀取后存放數據
- int ACC_OFFSET_X,ACC_OFFSET_Y,ACC_OFFSET_Z;
- int GYRO_OFFSET_X,GYRO_OFFSET_Y,GYRO_OFFSET_Z;
- unsigned char GYRO_OFFSET_OK = 1;
- unsigned char ACC_OFFSET_OK = 1;
- int MPU6050_ACC_LAST_X,MPU6050_ACC_LAST_Y,MPU6050_ACC_LAST_Z; //final accelerate speed
- int MPU6050_GYRO_LAST_X,MPU6050_GYRO_LAST_Y,MPU6050_GYRO_LAST_Z; //final gyro speed
- /**********************************************************/
- //函數名稱:void MPU6050_Dataanl
- //入口參數:無
- //出口參數:無
- //函數功能:MPU6050數據讀取并處理
- /**********************************************************/
- void MPU6050_Dataanl(void)
- {
- #ifndef READALL
- MPU6050_ACC_LAST_X = GetAccelX() - ACC_OFFSET_X;
- MPU6050_ACC_LAST_Y = GetAccelY() - ACC_OFFSET_Y;
- MPU6050_ACC_LAST_Z = GetAccelZ() - ACC_OFFSET_Z;
-
- MPU6050_GYRO_LAST_X = GetAnguX() - GYRO_OFFSET_X;
- MPU6050_GYRO_LAST_Y = GetAnguY() - GYRO_OFFSET_Y;
- MPU6050_GYRO_LAST_Z = GetAnguZ() - GYRO_OFFSET_Z;
- //------------------------------------------------------------------//
- //補償偏移
- if(!GYRO_OFFSET_OK)
- {
- static long int tempgx=0,tempgy=0,tempgz=0;
- static unsigned char cnt_g=0;
- if(cnt_g==0)
- {
- GYRO_OFFSET_X=0;
- GYRO_OFFSET_Y=0;
- GYRO_OFFSET_Z=0;
- tempgx = 0;
- tempgy = 0;
- tempgz = 0;
- cnt_g = 1;
- }
- tempgx+= MPU6050_GYRO_LAST_X;
- tempgy+= MPU6050_GYRO_LAST_Y;
- tempgz+= MPU6050_GYRO_LAST_Z;
- if(cnt_g==200)
- {
- GYRO_OFFSET_X=tempgx/cnt_g;
- GYRO_OFFSET_Y=tempgy/cnt_g;
- GYRO_OFFSET_Z=tempgz/cnt_g;
- cnt_g = 0;
- GYRO_OFFSET_OK = 1;
-
- }
- cnt_g++;
- }
- if(!ACC_OFFSET_OK)
- {
- static long int tempax=0,tempay=0,tempaz=0;
- static unsigned char cnt_a=0;
-
- if(cnt_a==0)
- {
- ACC_OFFSET_X = 0;
- ACC_OFFSET_Y = 0;
- ACC_OFFSET_Z = 0;
- tempax = 0;
- tempay = 0;
- tempaz = 0;
- cnt_a = 1;
-
- }
- tempax += MPU6050_ACC_LAST_X;//累加
- tempay += MPU6050_ACC_LAST_Y;
- tempaz += MPU6050_ACC_LAST_Z;
- if(cnt_a==200)
- {
- ACC_OFFSET_X = tempax/cnt_a;
- ACC_OFFSET_Y = tempay/cnt_a;
- ACC_OFFSET_Z = tempaz/cnt_a;
- cnt_a = 0;
- ACC_OFFSET_OK = 1;
-
- }
- cnt_a++;
- }
- //--------------------------------------------//
- #else
- struct MPU6050Struct *MPU6050WORK;
- MPU6050WORK = ReadMPU6050All();
- MPU6050_ACC_LAST_X = (MPU6050WORK ->MPU6050_ACC_X) - ACC_OFFSET_X;
- MPU6050_ACC_LAST_Y = (MPU6050WORK ->MPU6050_ACC_Y) - ACC_OFFSET_Y;
- MPU6050_ACC_LAST_Z = (MPU6050WORK ->MPU6050_ACC_Z) - ACC_OFFSET_Z;
-
- MPU6050_GYRO_LAST_X = (MPU6050WORK ->MPU6050_GYRO_X) - GYRO_OFFSET_X;
- MPU6050_GYRO_LAST_Y = (MPU6050WORK ->MPU6050_GYRO_Y) - GYRO_OFFSET_Y;
- MPU6050_GYRO_LAST_Z = (MPU6050WORK ->MPU6050_GYRO_Z) - GYRO_OFFSET_Z;
- if(!GYRO_OFFSET_OK)
- {
- static long int tempgx=0,tempgy=0,tempgz=0;
- static unsigned char cnt_g=0;
- if(cnt_g==0)
- {
- GYRO_OFFSET_X=0;
- GYRO_OFFSET_Y=0;
- GYRO_OFFSET_Z=0;
- tempgx = 0;
- tempgy = 0;
- tempgz = 0;
- cnt_g = 1;
- }
- tempgx+= MPU6050_GYRO_LAST_X;
- tempgy+= MPU6050_GYRO_LAST_Y;
- tempgz+= MPU6050_GYRO_LAST_Z;
- if(cnt_g==200)
- {
- GYRO_OFFSET_X=tempgx/cnt_g;
- GYRO_OFFSET_Y=tempgy/cnt_g;
- GYRO_OFFSET_Z=tempgz/cnt_g;
- cnt_g = 0;
- GYRO_OFFSET_OK = 1;
-
- }
- cnt_g++;
- }
- if(!ACC_OFFSET_OK)
- {
- static long int tempax=0,tempay=0,tempaz=0;
- static unsigned char cnt_a=0;
-
- if(cnt_a==0)
- {
- ACC_OFFSET_X = 0;
- ACC_OFFSET_Y = 0;
- ACC_OFFSET_Z = 0;
- tempax = 0;
- tempay = 0;
- tempaz = 0;
- cnt_a = 1;
-
- }
- tempax += MPU6050_ACC_LAST_X;//累加
- tempay += MPU6050_ACC_LAST_Y;
- tempaz += MPU6050_ACC_LAST_Z;
- if(cnt_a==200)
- {
- ACC_OFFSET_X = tempax/cnt_a;
- ACC_OFFSET_Y = tempay/cnt_a;
- ACC_OFFSET_Z = tempaz/cnt_a;
- cnt_a = 0;
- ACC_OFFSET_OK = 1;
-
- }
- cnt_a++;
- }
- #endif
-
- }
- /**********************************************************/
- //函數名稱:void MPU6050Init
- //入口參數:無
- //出口參數:無
- //函數功能:MPU6050初始化
- /**********************************************************/
- void MPU6050_Init()
- {
- #ifdef IMITATEIIC
- InitImitateIICPort();
- #else
- I2C_Init(SlaveAddr);
- #endif
- I2C_Write(PWR_MGMT_1,0x00); //resume from sleep.
- I2C_Write(SMPLRT_DIV, 0x07);
- I2C_Write(CONFIG, 0x06);
- I2C_Write(GYRO_CONFIG, 0x18);
- I2C_Write(ACCEL_CONFIG, 0x01);
- }
- /**********************************************************/
- //函數名稱:int Get16Bit
- //入口參數:address:讀取數據的地址
- //出口參數:無
- //函數功能:獲取MPU6050相應地址上的數據
- /**********************************************************/
- int Get16Bit (unsigned char address)
- {
- #ifndef MULTIREAD
- unsigned char ho,lo;
- int temp ;
- ho = I2C_Read(address);
- lo = I2C_Read(address+1);
- temp=ho;
- temp<<=8;
- temp+=lo;
- return temp ;
- #else
- return( Double_Read_ADXL345(address));
- #endif
- }
- /**********************************************************/
- //函數名稱:
- //入口參數:無
- //出口參數:無
- //函數功能:獲取MPU6050相應軸上的加速度數據
- /**********************************************************/
- // X/Y/Z-Axis Acceleration
- int GetAccelX ()
- {
- return Get16Bit(ACCEL_XOUT_H);
- }
- int GetAccelY ()
- {
- return Get16Bit(ACCEL_YOUT_H);
- }
- int GetAccelZ ()
- {
- return Get16Bit(ACCEL_ZOUT_H);
- }
- /**********************************************************/
- //函數名稱:
- //入口參數:無
- //出口參數:無
- //函數功能:獲取MPU6050相應軸上的角速度數據
- /**********************************************************/
- // X/Y/Z-Axis Angular velocity
- int GetAnguX ()
- {
- return Get16Bit(GYRO_XOUT_H);
- }
- int GetAnguY ()
- {
- return Get16Bit(GYRO_YOUT_H);
- }
- int GetAnguZ ()
- {
- return Get16Bit(GYRO_ZOUT_H);
- }
- #include"msp430iic.h"
- struct MPU6050Struct MPU6050Data;
- void InitImitateIICPort(void)
- {
- SET_SDA_OUT; //set SDA PIN is out mode
- SDA_HIGH; // set SDA PIN out is high
- SCL_HIGH; //set SCL PIN is input mode ,pull up register to SCL PIN high
- }
- /**************************************
- 起始信號
- **************************************/
- void ADXL345_Start(void)
- {
- SET_SDA_OUT;
- SDA_HIGH; //拉高數據線
- SCL_HIGH; //拉高時鐘線
- Delay5us(); //延時
- SDA_LOW; //產生下降沿
- Delay5us(); //延時
- SCL_LOW; //拉低時鐘線
- }
- /**************************************
- 停止信號
- **************************************/
- void ADXL345_Stop(void)
- {
- SET_SDA_OUT;
- SDA_LOW; //拉低數據線
- SCL_HIGH; //拉高時鐘線
- Delay5us(); //延時
- SDA_HIGH; //產生上升沿
- Delay5us(); //延時
- }
- /**************************************
- 發(fā)送應答信號
- 入口參數:ack (0:ACK 1:NAK)
- **************************************/
- void ADXL345_SendACK(unsigned char ack)
- {
- SET_SDA_OUT;
- if(ack)
- SDA_HIGH; //寫NACK應答信號
- else
- SDA_LOW; //寫ACK應答信號
- SCL_HIGH; //拉高時鐘線
- Delay5us(); //延時
- SCL_LOW; //拉低時鐘線
- Delay5us(); //延時
- }
- /**************************************
- 接收應答信號
- **************************************/
- unsigned char ADXL345_RecvACK(void)
- {
- unsigned char ack;
- //------------------//
- //一下兩句切不可調換順序,否則會導致時序錯誤
- SET_SDA_IN;
- SCL_HIGH; //拉高時鐘線
- //-----------------//
- Delay5us(); //延時
- ack = SDA_IN; //讀應答信號
- SCL_LOW; //拉低時鐘線
- Delay5us(); //延時
- return ack;
- }
- /**************************************
- 向IIC總線發(fā)送一個字節(jié)數據
- **************************************/
- void ADXL345_Senduchar(unsigned char dat)
- {
- unsigned char i,m;
- SET_SDA_OUT;
- for (i=8; i!=0; i--) //8位計數器
- {
- m=dat & 0x80; //移出數據的最高位
- if(m == 0x80)
- SDA_HIGH;
- else
- SDA_LOW;
- SCL_HIGH; //拉高時鐘線
- Delay5us(); //延時
- SCL_LOW; //拉低時鐘線
- dat=dat<<1;
- Delay5us(); //延時
- }
- ADXL345_RecvACK();
- }
- /**************************************
- 從IIC總線接收一個字節(jié)數據
- **************************************/
- unsigned char ADXL345_Recvuchar(void)
- {
- unsigned char i;
- unsigned char dat = 0;
- unsigned char m;
- SDA_HIGH; //使能內部上拉,準備讀取數據,
- SET_SDA_IN;
- for (i=8; i!=0; i--) //8位計數器
- {
- dat <<= 1;
- SCL_HIGH; //拉高時鐘線
- SET_SDA_IN;
- m = SDA_IN;
- if(m == I2C_SDA)
- dat = dat|0x01;
- Delay5us(); //延時
- SCL_LOW; //拉低時鐘線
- Delay5us(); //延時
- }
- return dat;
- }
- //******單字節(jié)寫入*******************************************
- void Single_Write_ADXL345(unsigned char REG_Address,unsigned char REG_data)
- {
- ADXL345_Start(); //起始信號
- ADXL345_Senduchar(SlaveAddress); //發(fā)送設備地址+寫信號
- ADXL345_Senduchar(REG_Address); //內部寄存器地址,請參考中文pdf22頁
- ADXL345_Senduchar(REG_data); //內部寄存器數據,請參考中文pdf22頁
- ADXL345_Stop(); //發(fā)送停止信號
- }
- //********單字節(jié)讀取*****************************************
- unsigned char Single_Read_ADXL345(unsigned char REG_Address)
- { unsigned char REG_data=0;
- ADXL345_Start(); //起始信號
- ADXL345_Senduchar(SlaveAddress); //發(fā)送設備地址+寫信號
- ADXL345_Senduchar(REG_Address); //發(fā)送存儲單元地址,從0開始
- ADXL345_Start(); //起始信號
- ADXL345_Senduchar(SlaveAddress+1); //發(fā)送設備地址+讀信號
- REG_data=ADXL345_Recvuchar(); //讀出寄存器數據
- ADXL345_SendACK(1); //NACK
- ADXL345_Stop(); //停止信號
- return REG_data;
- }
- //********多字節(jié)讀取*****************************************
- int Double_Read_ADXL345(unsigned char REG_Address)
- {
- unsigned char ValueL=0;
- int Value=0;
- ADXL345_Start(); //起始信號
- ADXL345_Senduchar(SlaveAddress); //發(fā)送設備地址+寫信號
- ADXL345_Senduchar(REG_Address); //發(fā)送存儲單元地址,從0開始
- ADXL345_Start(); //起始信號
- ADXL345_Senduchar(SlaveAddress+1); //發(fā)送設備地址+讀信號
-
- Value=ADXL345_Recvuchar(); //讀出寄存器數據
- ADXL345_SendACK(0); //ACK
-
- ValueL=ADXL345_Recvuchar(); //讀出寄存器數據
- ADXL345_SendACK(1); //NACK
-
- ADXL345_Stop(); //停止信號
- Value=(Value<<8)+ValueL;
- return Value;
- }
- struct MPU6050Struct *ReadMPU6050All()
- {
- unsigned char TempAcc1=0,TempAcc2=0,TempAcc3=0,TempAcc4=0,TempAcc5=0,TempAcc6=0;
- unsigned char TempGyro1=0,TempGyro2=0,TempGyro3=0,TempGyro4=0,TempGyro5=0,TempGyro6=0;
- ADXL345_Start(); //起始信號
- ADXL345_Senduchar(SlaveAddress); //發(fā)送設備地址+寫信號
- ADXL345_Senduchar(0x3B); //發(fā)送存儲單元地址,從0x3b開始
- ADXL345_Start(); //起始信號
- ADXL345_Senduchar(SlaveAddress+1); //發(fā)送設備地址+讀信號
-
- TempAcc2=ADXL345_Recvuchar(); //讀出寄存器數據
- ADXL345_SendACK(0); //ACK
-
- TempAcc1=ADXL345_Recvuchar(); //讀出寄存器數據
- ADXL345_SendACK(0); //ACK
-
- TempAcc4=ADXL345_Recvuchar(); //讀出寄存器數據
- ADXL345_SendACK(0); //ACK
-
- TempAcc3=ADXL345_Recvuchar(); //讀出寄存器數據
- ADXL345_SendACK(0); //ACK
-
- TempAcc6=ADXL345_Recvuchar(); //讀出寄存器數據
- ADXL345_SendACK(0); //ACK
-
- TempAcc5=ADXL345_Recvuchar(); //讀出寄存器數據
- ADXL345_SendACK(0); //ACK
-
- ADXL345_Recvuchar(); //丟棄不連續(xù)地址的數據
- ADXL345_SendACK(0); //ACK
-
- ADXL345_Recvuchar(); //丟棄不連續(xù)地址的數據
- ADXL345_SendACK(0);
-
- TempGyro2=ADXL345_Recvuchar(); //讀出寄存器數據
- ADXL345_SendACK(0); //ACK
-
- TempGyro1=ADXL345_Recvuchar(); //讀出寄存器數據
- ADXL345_SendACK(0);
-
- TempGyro4=ADXL345_Recvuchar(); //讀出寄存器數據
- ADXL345_SendACK(0); //ACK
-
- TempGyro3=ADXL345_Recvuchar(); //讀出寄存器數據
- ADXL345_SendACK(0);
-
- TempGyro6=ADXL345_Recvuchar(); //讀出寄存器數據
- ADXL345_SendACK(0); //ACK
-
- TempGyro5=ADXL345_Recvuchar(); //讀出寄存器數據
- ADXL345_SendACK(1); //NACK
-
- ADXL345_Stop();
- MPU6050Data.MPU6050_ACC_X=(TempAcc2<<8) + TempAcc1;
- MPU6050Data.MPU6050_ACC_Y=(TempAcc4<<8) + TempAcc3;
- MPU6050Data.MPU6050_ACC_Z=(TempAcc6<<8) + TempAcc5;
-
- MPU6050Data.MPU6050_GYRO_X=(TempGyro2<<8) + TempGyro1;
- MPU6050Data.MPU6050_GYRO_Y=(TempGyro4<<8) + TempGyro3;
- MPU6050Data.MPU6050_GYRO_Z=(TempGyro6<<8) + TempGyro5;
- return (&MPU6050Data);
- }
- /*
- * This file contains some uSCI_A0 operation.
- * By IC爬蟲 (1394024051@qq.com)
- * 2014-4-28 v1.0
- */
- //#include "msp430g2553.h"
- #include "USCI_A0.h"
- //#include "stdio.h"
- #include "mpu6050.h"
- #include "IMU.h"
- #define uchar unsigned char
- #define uint unsigned int
- //將“int”類型的數據分成兩個單字節(jié)的數據
- #define BYTE0(dwTemp) (*(char *)(&dwTemp))
- #define BYTE1(dwTemp) (*((char *)(&dwTemp) + 1))
- #define BYTE2(dwTemp) (*((char *)(&dwTemp) + 2))
- #define BYTE3(dwTemp) (*((char *)(&dwTemp) + 3))
- /*********************************************************
- *名稱:USCI_A0_init
- *功能:串口初始化
- *入口參數:無
- *出口參數:無
- *說明:設置為P1.1和P1.2為串口通信端口
- **********************************************************/
- void USCI_A0_init(void)
- {
- P1SEL = BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD
- P1SEL2 = BIT1 + BIT2;
- UCA0CTL1 |= UCSSEL_2; // SMCLK
- /*
- UCA0BR0 = 0x45; // 8MHz 115200
- UCA0BR1 = 0; // 8MHz 115200
- UCA0MCTL = 0x4a; // 8MHz 115200 */
- /*
- UCA0BR0 = 0x68;
- UCA0BR1 = 0;
- UCA0MCTL = 0x40;
- */
- UCA0MCTL = UCBRF_0 | UCBRS_4;
-
- /* Baud rate control register 0 */
- UCA0BR0 = 69;
- UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
-
- //IE2 |= UCA0RXIE + UCA0TXIE; // Enable USCI_A0 TX/RX interrupt
- //IE2 |= UCA0RXIE; // Enable USCI_A0 RX interrupt
- //__bis_SR_register(GIE); // Enter LPM3 w/ interrupts enabled
- }
- /*********************************************************
- *名稱:UartTX_Send_String
- *功能:串口發(fā)送字符串函數
- *入口參數:*data:數據指針 len :數據長度
- *出口參數:無
- *說明:
- **********************************************************/
- void UartTX_Send_String(unsigned char *Data,int len)
- {
- int j;
- for(j=0;j<len;j++)
- {
- UartTX_Send_char(*Data++);
- }
- }
- /*********************************************************
- *名稱:UartTX_Send_char
- *功能:串口發(fā)送字符函數
- *入口參數:c
- *出口參數:無
- *說明:
- **********************************************************/
- unsigned char UartTX_Send_char(unsigned char c)
- {
- UCA0TXBUF=c;
- while(!(IFG2&UCA0TXIFG));
- IFG2&=~UCA0TXIFG;
- return c;
- }
- /*********************************************************
- *名稱:int putchar
- *功能:串口發(fā)送字符函數
- *入口參數:ch
- *出口參數:無
- *說明:
- **********************************************************/
- int putchar(int ch)
- {
- UCA0TXBUF=ch;
- while(!(IFG2&UCA0TXIFG));
- //UCA0TXBUF=ch;
- IFG2&=~UCA0TXIFG;
- return ch;
- }
- void sendChar(unsigned char c)
- {
- while(!(IFG2&UCA0TXIFG));
- UCA0TXBUF=c;
- }
- void sendStr(unsigned char *s)
- {
- while(*s!='\0')
- {
- sendChar(*s);
- s++;
- }
- }
- /*********************************************************
- *名稱:void Uart1_Send_AF
- *功能:串口發(fā)送姿態(tài)數據
- *入口參數:無
- *出口參數:無
- *說明:每一次執(zhí)行這個函數就算是一幀數據,幀頭為0X88,功能字
- * 為0XAF
- **********************************************************/
- void Uart1_Send_AF(void)
- {
- unsigned char sum = 0;//累加串口發(fā)送的數據的值,做校驗用
- unsigned int _temp;
- sum += UartTX_Send_char(0x88); //幀頭
- sum += UartTX_Send_char(0xAF); //功能字
-
- sum += UartTX_Send_char(0x1c);
- sum += UartTX_Send_char( BYTE1(MPU6050_ACC_LAST_X) ); //發(fā)送加速度X軸數據的高8位
- sum += UartTX_Send_char( BYTE0(MPU6050_ACC_LAST_X) ); //發(fā)送加速度X軸數據的低8位
-
- sum += UartTX_Send_char( BYTE1(MPU6050_ACC_LAST_Y) ); //發(fā)送加速度Y軸數據的高8位
- sum += UartTX_Send_char( BYTE0(MPU6050_ACC_LAST_Y) ); //發(fā)送加速度Y軸數據的低8位
-
- sum += UartTX_Send_char( BYTE1(MPU6050_ACC_LAST_Z) ); //發(fā)送加速度Z軸數據的高8位
- sum += UartTX_Send_char( BYTE0(MPU6050_ACC_LAST_Z) ); //發(fā)送加速度Z軸數據的低8位
-
- sum += UartTX_Send_char( BYTE1(MPU6050_GYRO_LAST_X) ); //發(fā)送陀螺儀X軸數據的高8位
- sum += UartTX_Send_char( BYTE0(MPU6050_GYRO_LAST_X) ); //發(fā)送陀螺儀X軸數據的低8位
-
- sum += UartTX_Send_char( BYTE1(MPU6050_GYRO_LAST_Y) ); //發(fā)送陀螺儀Y軸數據的高8位
- sum += UartTX_Send_char( BYTE0(MPU6050_GYRO_LAST_Y) ); //發(fā)送陀螺儀Y軸數據的低8位
-
- sum += UartTX_Send_char( BYTE1(MPU6050_GYRO_LAST_Z) ); //發(fā)送陀螺儀Z軸數據的高8位
- sum += UartTX_Send_char( BYTE0(MPU6050_GYRO_LAST_Z) ); //發(fā)送陀螺儀Z軸數據的低8位
- sum += UartTX_Send_char(0);
- sum += UartTX_Send_char(0);
- sum += UartTX_Send_char(0);
- sum += UartTX_Send_char(0);
- sum += UartTX_Send_char(0);
- sum += UartTX_Send_char(0);
-
- _temp = (long int)(Q_ANGLE_X*100);
- sum += UartTX_Send_char( BYTE1(_temp) );
- sum += UartTX_Send_char( BYTE0(_temp) );
- _temp = (long int)(Q_ANGLE_Y*100);
- sum += UartTX_Send_char( BYTE1(_temp) );
- sum += UartTX_Send_char( BYTE0(_temp) );
-
- sum += UartTX_Send_char(0);
- sum += UartTX_Send_char(0);
- sum += UartTX_Send_char(0);
- sum += UartTX_Send_char(0);
- sum += UartTX_Send_char(0);
- sum += UartTX_Send_char(0);
-
- UartTX_Send_char(sum); //串口發(fā)送累加值用于校驗
- }
- /*
- * This file contains some IMU operation.
- * By IC爬蟲 (1394024051@qq.com)
- * 2014-4-29 v1.0
- */
- #include "IMU.h"
- #define RtA 57.324841 //弧度到角度
- #define AtR 0.0174533 //度到角度
- #define Acc_G 0.0011963 //加速度變成G
- #define Gyro_G 0.0152672 //角速度變成度
- #define Gyro_Gr 0.0002663
- #define FILTER_NUM 20
- int ACC_AVG_X,ACC_AVG_Y,ACC_AVG_Z; //平均值濾波后的ACC
- float GYRO_I_X,GYRO_I_Y,GYRO_I_Z; //陀螺儀積分
- float EXP_ANGLE_X,EXP_ANGLE_Y,EXP_ANGLE_Z;//期望角度
- float DIF_ANGLE_X,DIF_ANGLE_Y,DIF_ANGLE_Z;//期望角度和實際角度的差
- float Q_ANGLE_X,Q_ANGLE_Y,Q_ANGLE_Z; //四元數計算出的角度
- int ACC_X_BUF[FILTER_NUM],ACC_Y_BUF[FILTER_NUM],ACC_Z_BUF[FILTER_NUM]; //加速度滑動窗口濾波數組
- /**********************************************************/
- //函數名稱:Prepare_Data
- //入口參數:無
- //出口參數:無
- //函數功能:讀取MPU6050數據進行平滑濾波,為后續(xù)計算準備數據
- /**********************************************************/
- void Prepare_Data(void)
- {
- static unsigned char filter_cnt=0;
- long int temp1=0,temp2=0,temp3=0;
- unsigned char i;
-
- MPU6050_Dataanl();//完成傳感器數據的讀取和計算,并且對數據簡單處理
-
- ACC_X_BUF[filter_cnt] = MPU6050_ACC_LAST_X;//更新滑動窗口數組
- ACC_Y_BUF[filter_cnt] = MPU6050_ACC_LAST_Y;
- ACC_Z_BUF[filter_cnt] = MPU6050_ACC_LAST_Z;
-
- for(i=0;i<FILTER_NUM;i++)
- {
- temp1 += ACC_X_BUF[i];
- temp2 += ACC_Y_BUF[i];
- temp3 += ACC_Z_BUF[i];
- }
-
- ACC_AVG_X = temp1 / FILTER_NUM;
- ACC_AVG_Y = temp2 / FILTER_NUM;
- ACC_AVG_Z = temp3 / FILTER_NUM;
-
- filter_cnt++;
-
- if(filter_cnt==FILTER_NUM) filter_cnt=0;
-
- GYRO_I_X += MPU6050_GYRO_LAST_X*Gyro_G*0.02;//0.0001是時間間隔,兩次prepare函數的執(zhí)行周期
- GYRO_I_Y += MPU6050_GYRO_LAST_Y*Gyro_G*0.02;//示波器測量的得到的時間是20ms.
- GYRO_I_Z += MPU6050_GYRO_LAST_Z*Gyro_G*0.02;
- }
- void Get_Attitude(void)
- {
- IMUupdate( MPU6050_GYRO_LAST_X*Gyro_Gr,
- MPU6050_GYRO_LAST_Y*Gyro_Gr,
- MPU6050_GYRO_LAST_Z*Gyro_Gr,
- ACC_AVG_X,ACC_AVG_Y,ACC_AVG_Z); //*0.0174轉成弧度
- }
- ////////////////////////////////////////////////////////////////////////////////
- #define Kp 10.0f // proportional gain governs rate of convergence to accelerometer/magnetometer
- #define Ki 0.008f // integral gain governs rate of convergence of gyroscope biases
- #define halfT 0.004f // half the sample period采樣周期的一半
- float q0 = 1, q1 = 0, q2 = 0, q3 = 0; // quaternion elements representing the estimated orientation
- float exInt = 0, eyInt = 0, ezInt = 0; // scaled integral error
- /**********************************************************/
- //函數名稱:IMUupdate
- //入口參數:gx:浮點型的陀螺儀x軸數據
- // gy:浮點型的陀螺儀y軸數據
- // gz:浮點型的陀螺儀z軸數據
- // ax:浮點型的加速度x軸數據
- // ay:浮點型的加速度y軸數據
- // az:浮點型的加速度z軸數據
- //出口參數:無
- //函數功能:通過陀螺儀和加速度傳感器的數據用四元數計算姿態(tài)
- /**********************************************************/
- void IMUupdate(float gx, float gy, float gz, float ax, float ay, float az)
- {
- float norm;
- // float hx, hy, hz, bx, bz;
- float vx, vy, vz;// wx, wy, wz;
- float ex, ey, ez;
- //先把這些需要用到的值弄好
- float q0q0 = q0*q0;
- float q0q1 = q0*q1;
- float q0q2 = q0*q2;
- // float q0q3 = q0*q3;
- float q1q1 = q1*q1;
- // float q1q2 = q1*q2;
- float q1q3 = q1*q3;
- float q2q2 = q2*q2;
- float q2q3 = q2*q3;
- float q3q3 = q3*q3;
-
- if(ax*ay*az==0) return;
-
- norm = sqrt(ax*ax + ay*ay + az*az);//acc數據歸一化
- ax = ax /norm;
- ay = ay / norm;
- az = az / norm;
- // estimated direction of gravity and flux (v and w) 估計重力方向和流量/變遷
- vx = 2*(q1q3 - q0q2); //四元數中xyz的表示
- vy = 2*(q0q1 + q2q3);
- vz = q0q0 - q1q1 - q2q2 + q3q3 ;
- // error is sum of cross product between reference direction of fields and direction measured by sensors
- ex = (ay*vz - az*vy) ; //向量外積在相減得到差分就是誤差
- ey = (az*vx - ax*vz) ;
- ez = (ax*vy - ay*vx) ;
- exInt = exInt + ex * Ki; //對誤差進行積分
- eyInt = eyInt + ey * Ki;
- ezInt = ezInt + ez * Ki;
- // adjusted gyroscope measurements
- gx = gx + Kp*ex + exInt; //將誤差PI后補償到陀螺儀,即補償零點漂移
- gy = gy + Kp*ey + eyInt;
- gz = gz + Kp*ez + ezInt; //這里的gz由于沒有觀測者進行矯正會產生漂移,變現出來的就是積分自增或者自減
- // integrate quaternion rate and normalise //四元數的微分方程
- q0 = q0 + (-q1*gx - q2*gy - q3*gz)*halfT;
- q1 = q1 + (q0*gx + q2*gz - q3*gy)*halfT;
- q2 = q2 + (q0*gy - q1*gz + q3*gx)*halfT;
- q3 = q3 + (q0*gz + q1*gy - q2*gx)*halfT;
- // normalise quaternion
- norm = sqrt(q0*q0 + q1*q1 + q2*q2 + q3*q3);
- q0 = q0 / norm;
- q1 = q1 / norm;
- q2 = q2 / norm;
- q3 = q3 / norm;
- //Q_ANGLE.Yaw = atan2(2 * q1 * q2 + 2 * q0 * q3, -2 * q2*q2 - 2 * q3* q3 + 1)* 57.3; // yaw
- Q_ANGLE_Y = asin(-2 * q1 * q3 + 2 * q0* q2)* 57.3; // pitch
- Q_ANGLE_X = atan2(2 * q2 * q3 + 2 * q0 * q1, -2 * q1 * q1 - 2 * q2* q2 + 1)* 57.3; // roll
- }
- /*
- * This file contains some I2C operation.
- * By IC爬蟲 (1394024051@qq.com)
- * 2014-4-13 v1.0
- */
- #include "HardWareIIC.h"
- uchar I2CSendBuffer[2],I2CRecvBuffer; //I2C發(fā)送緩存和接收緩存
- int I2CSendPtr=0;
- /**********************************************************/
- //函數名稱:void I2C_Init
- //入口參數:SlaveAddr:從機的設備地址
- //出口參數:無
- //函數功能:I2C初始化,P1.6->SCL ,P1.7->SDA
- /**********************************************************/
- void I2C_Init (unsigned char SlaveAddr)
- {
- P1SEL |= BIT6+BIT7; // Assign I2C pins to USCI_B0
- P1SEL2|= BIT6+BIT7; // Assign I2C pins to USCI_B0
- UCB0CTL1 |= UCSWRST; // Enable SW reset
-
- UCB0CTL0 = UCMST+UCMODE_3+UCSYNC; // I2C Master, synchronous mode
- UCB0CTL0 &= ~(UCSLA10+UCA10); //7 bit add of slave and master
-
- UCB0CTL1 = UCSSEL_2+UCSWRST; // Use SMCLK, keep SW reset
-
- UCB0BR0 = 80; // fSCL = SMCLK/12 = ~100kHz
- UCB0BR1 = 0;
-
- UCB0I2COA = 0x01A5; //set own address
- UCB0I2CSA = SlaveAddr; // Set slave address
-
- IE2 &= ~(UCB0RXIE+UCB0TXIE); // disenable TX&RX interrupt
- UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
-
- }
- /**********************************************************/
- //函數名稱:void I2C_WriteInit
- //入口參數:無
- //出口參數:無
- //函數功能:I2C寫數據初始化,發(fā)送模式,接收中斷關閉,發(fā)送中斷關閉
- /**********************************************************/
- void I2C_WriteInit()
- {
- UCB0CTL1 |= UCTR; // UCTR=1 => Transmit Mode (R/W bit = 0)
- IFG2 &= ~UCB0TXIFG; //clean TX interrupt sign
- IE2 &= ~UCB0RXIE; // disable Receive ready interrupt
- IE2 &= ~UCB0TXIE; // disable Transmit ready interrupt
- }
- /**********************************************************/
- //函數名稱:void I2C_ReadInit
- //入口參數:無
- //出口參數:無
- //函數功能:I2C讀數據初始化,接收模式,接收中斷關閉,發(fā)送中斷關閉
- /**********************************************************/
- void I2C_ReadInit()
- {
- UCB0CTL1 &= ~UCTR; // UCTR=0 => Receive Mode (R/W bit = 1)
- IFG2 &= ~UCB0RXIFG;
- IE2 &= ~UCB0TXIE; // disable Transmit ready interrupt
- IE2 &= ~UCB0RXIE; // disable Receive ready interrupt
- }
- /**********************************************************/
- //函數名稱:I2C_Write
- //入口參數:address:需要寫入數據的設備的地址
- // data:發(fā)送的數據
- //出口參數:無
- //函數功能:I2C發(fā)送數據
- /**********************************************************/
- void I2C_Write(uchar address,uchar data)
- {
- I2C_WriteInit();
- UCB0CTL1 |= UCTXSTT; //generate start condition
- //while(UCB0CTL1 & UCTXSTT); //generate start condition ,and transmit slave address and write bit
- while(!(IFG2 & UCB0TXIFG)); //wait start condition and equipment address transmitted
- IFG2 &= ~UCB0TXIFG; //clean UCB0TXIFG
- while(UCB0CTL1 & UCTXSTT); //wait slave acknowledge
-
- UCB0TXBUF=address; //send address code
- while(!(IFG2 & UCB0TXIFG )); //wait sending over
- IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX int flag
-
- UCB0TXBUF=data; //send data
- while(!(IFG2 & UCB0TXIFG )); //wait sending over
- IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX int flag
-
- UCB0CTL1 |= UCTXSTP; // I2C stop condition
- while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
- }
- /**********************************************************/
- //函數名稱:uchar I2C_Read
- //入口參數:address:需要讀數據的設備的地址
- //出口參數:無
- //函數功能:I2C接收數據
- /**********************************************************/
- uchar I2C_Read(uchar address)
- {
- unsigned char data;
- while (UCB0STAT & UCBUSY); // wait until I2C module has finished all operations
- I2C_WriteInit();
- UCB0CTL1 |= UCTXSTT; // start condition generation
- while(UCB0CTL1 & UCTXSTT);
-
-
- UCB0TXBUF=address; //send address code
- while(!(IFG2 & UCB0TXIFG )); //wait sending over
- IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX int flag
-
- // __disable_interrupt();
- I2C_ReadInit();
- while(UCB0RXIFG & IFG2);
- IFG2 &= ~UCB0RXIFG;
- data = UCB0RXBUF;
-
- UCB0CTL1 |= UCTXSTP; // I2C stop condition
- while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
- return data;
- }
- /*----------------------------------------------------------------------------*/
- // Description:
- // Acknowledge Polling. The EEPROM will not acknowledge if a write cycle is
- // in progress. It can be used to determine when a write cycle is completed.
- /*----------------------------------------------------------------------------*/
- void I2C_AckPolling(void)
- {
- while (UCB0STAT & UCBUSY)
- {
- ;// wait until I2C module has
- } // finished all operations
- do
- {
- UCB0STAT = 0x00; // clear I2C interrupt flags
- UCB0CTL1 |= UCTR; // I2CTRX=1 => Transmit Mode (R/W bit = 0)
- UCB0CTL1 &= ~UCTXSTT;
- UCB0CTL1 |= UCTXSTT; // start condition is generated
- while (UCB0CTL1 & UCTXSTT) // wait till I2CSTT bit was cleared
- {
- if (!(UCNACKIFG & UCB0STAT))
- {
- break;// Break out if ACK received
- }
- }
- UCB0CTL1 |= UCTXSTP; // stop condition is generated after
- // slave address was sent => I2C communication is started
- while (UCB0CTL1 & UCTXSTP)
- {
- ;// wait till stop bit is reset
- }
- __delay_cycles(500); // Software delay
-
- } while (UCNACKIFG & UCB0STAT);
- }
- // USCI_B0 Data ISR
- // Notice : UCSIAB0RX_ISR should be handle with UCSIAB0TX_ISR
- #pragma vector = USCIAB0TX_VECTOR
- __interrupt void USCIAB0TX_ISR(void)
- {
- if (UCB0TXIFG & IFG2) // TX
- {
- UCB0TXBUF = I2CSendBuffer[I2CSendPtr]; // Load TX buffer
- I2CSendPtr--; // Decrement TX byte counter
- if (I2CSendPtr < 0)
- {
- while (!(IFG2 & UCB0TXIFG)); // wait for tx complete
- IE2 &= ~UCB0TXIE; // disable interrupts.
- IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX int flag
- __bic_SR_register_on_exit(LPM0_bits);// Exit LPM0
- }
- }
- else if (UCB0RXIFG & IFG2) // RX
- {
- I2CRecvBuffer = UCB0RXBUF; // store received data in buffer
- __bic_SR_register_on_exit(LPM0_bits); // Exit LPM0
- }
- }
復制代碼
|