123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710 |
- /*
- * MPU6050.c
- *
- * Created on: Oct 26, 2021
- * Author: Administrator
- */
- #include "MPU6050.h"
- #include "main.h"
- #include <stdio.h>
- extern int t;
- extern int a;
- extern int b;
- extern int c;
- //void addr_check_point(u8 addr){
- // if (addr != 0x69)
- // {
- // printf("checkpoint error addr");
- // }
- //}
- //void common_check_point(u8 value){
- //printf("<checkpoint> value => %x\n", value);
- //}
- u8 IIC_Write_Byte(u8 reg, u8 value)
- {
-
- return IIC_Write_Len(a, reg, 1, &value);
- }
- u8 IIC_Read_Byte(u8 reg)
- {
- u8 value = 0;
- IIC_Read_Len(a, reg, 1, &value);
- return value;
- }
- u8 IIC_Write_Len1(u8 addr, u8 reg, u8 len, u8 *buf)
- {
-
- addr=a;
- addr = (addr << 1) | 0;
- u8 data[10] = {0};
- data[0] = reg;
- for (int i = 0; i < len; i++)
- {
- data[1 + i] = buf[i];
- }
- if (HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)addr, (uint8_t *)data, len + 1, 10000) != HAL_OK
- ||HAL_I2C_Master_Transmit(&hi2c2, (uint16_t)addr, (uint8_t *)data, len + 1, 10000) != HAL_OK
- ||HAL_I2C_Master_Transmit(&hi2c3, (uint16_t)addr, (uint8_t *)data, len + 1, 10000) != HAL_OK)
- {
- printf("++write len byte fail\r\n");
- return 1;
-
- }
- return 0;
- }
- // IIC连续写
- u8 IIC_Write_Len(u8 addr, u8 reg, u8 len, u8 *buf)
- {
-
- addr=a;
-
- if (t == 1)
- {
- addr = (addr << 1) | 0;
- u8 data[10] = {0};
- data[0] = reg;
- for (int i = 0; i < len; i++)
- {
- data[1 + i] = buf[i];
- }
- if (HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)addr, (uint8_t *)data, len + 1, 10000) != HAL_OK)
- {
- printf("++write len byte fail\r\n");
- return 1;
- }
- }
- else if (t == 2)
- {
- addr = (addr << 1) | 0;
- u8 data[10] = {0};
- data[0] = reg;
- for (int i = 0; i < len; i++)
- {
- data[1 + i] = buf[i];
- }
- if (HAL_I2C_Master_Transmit(&hi2c2, (uint16_t)addr, (uint8_t *)data, len + 1, 10000) != HAL_OK)
- {
- printf("++write len byte fail\r\n");
- return 1;
- }
- }
- else if (t == 3)
- {
- addr = (addr << 1) | 0;
- u8 data[10] = {0};
- data[0] = reg;
- for (int i = 0; i < len; i++)
- {
- data[1 + i] = buf[i];
- }
- if (HAL_I2C_Master_Transmit(&hi2c3, (uint16_t)addr, (uint8_t *)data, len + 1, 10000) != HAL_OK)
- {
- printf("++write len byte fail\r\n");
- return 1;
- }
- }
- return 0;
- }
- u8 IIC_Read_Len1(u8 addr, u8 reg, u8 len, u8 *buf)
- {addr=a;
- u8 tmp = (addr << 1) | 0;
- if (HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)tmp, (uint8_t *)®, 1, 10000) != HAL_OK
- ||HAL_I2C_Master_Transmit(&hi2c2, (uint16_t)tmp, (uint8_t *)®, 1, 10000) != HAL_OK
- ||HAL_I2C_Master_Transmit(&hi2c3, (uint16_t)tmp, (uint8_t *)®, 1, 10000) != HAL_OK)
- {
- printf("++write byte fail\r\n");
- return 1;
-
-
- // return addr_test;
- }
- tmp = (addr << 1) | 1;
- if (HAL_I2C_Master_Receive(&hi2c1, (uint16_t)tmp, (uint8_t *)buf, len, 10000) != HAL_OK
- ||HAL_I2C_Master_Receive(&hi2c2, (uint16_t)tmp, (uint8_t *)buf, len, 10000) != HAL_OK
- ||HAL_I2C_Master_Receive(&hi2c3, (uint16_t)tmp, (uint8_t *)buf, len, 10000) != HAL_OK)
- {
-
- printf("--read byte fail\r\n");
-
-
- }
-
- }
- // IIC连续读
- u8 IIC_Read_Len(u8 addr, u8 reg, u8 len, u8 *buf)
- {
-
- addr=a;
- if (t == 1)
- {
- u8 tmp = (addr << 1) | 0;
- if (HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)tmp, (uint8_t *)®, 1, 10000) != HAL_OK)
- {
- printf("++write byte fail\r\n");
- return 1;
- // return addr_test;
- }
- tmp = (addr << 1) | 1;
- if (HAL_I2C_Master_Receive(&hi2c1, (uint16_t)tmp, (uint8_t *)buf, len, 10000) != HAL_OK)
- {
- printf("--read byte fail\r\n");
- }
- }
- else if (t == 2)
- {
- u8 tmp = (addr << 1) | 0;
- if (HAL_I2C_Master_Transmit(&hi2c2, (uint16_t)tmp, (uint8_t *)®, 1, 10000) != HAL_OK)
- {
- printf("++write byte fail\r\n");
- return 1;
- // return addr_test;
- }
- tmp = (addr << 1) | 1;
- if (HAL_I2C_Master_Receive(&hi2c2, (uint16_t)tmp, (uint8_t *)buf, len, 10000) != HAL_OK)
- {
- printf("--read byte fail\r\n");
- }
- }
- else if (t == 3)
- {
- u8 tmp = (addr << 1) | 0;
- if (HAL_I2C_Master_Transmit(&hi2c3, (uint16_t)tmp, (uint8_t *)®, 1, 10000) != HAL_OK)
- {
- printf("++write byte fail\r\n");
- return 1;
- // return addr_test;
- }
- tmp = (addr << 1) | 1;
- if (HAL_I2C_Master_Receive(&hi2c3, (uint16_t)tmp, (uint8_t *)buf, len, 10000) != HAL_OK)
- {
- printf("--read byte fail\r\n");
- }
- }
-
- // return -1;
- }
- // 初始化MPU6050
- // 返回值: 0,成功
- // 其他,错误代码
- u8 MPU_Init(void)
- {
- u8 res = 0;
- IIC_Write_Byte(MPU_PWR_MGMT1_REG, 0X80); // 复位MPU6050
- HAL_Delay(100);
- IIC_Write_Byte(MPU_PWR_MGMT1_REG, 0X00); // 唤醒MPU6050
- MPU_Set_Gyro_Fsr(3); // 陀螺仪传感器,±2000dps
- MPU_Set_Accel_Fsr(0); // 加速度传感器 ±2g
- MPU_Set_Rate(50); // 设置采样率50HZ
- IIC_Write_Byte(MPU_INT_EN_REG, 0X00); // 关闭所有中断
- IIC_Write_Byte(MPU_USER_CTRL_REG, 0X00); // I2C主模式关闭
- IIC_Write_Byte(MPU_FIFO_EN_REG, 0X00); // 关闭FIFO
- IIC_Write_Byte(MPU_INTBP_CFG_REG, 0X80); // INT引脚低电平有效
- res = IIC_Read_Byte(MPU_DEVICE_ID_REG);
- printf("the addr is:%d\r\n", res);
- // if(res==a)//器件ID正确
- // {
- IIC_Write_Byte(MPU_PWR_MGMT1_REG, 0X01); // 设置CLKSEL,PLL X 轴为参考
- IIC_Write_Byte(MPU_PWR_MGMT2_REG, 0X00); // 加速度陀螺仪都工作
- MPU_Set_Rate(50); // 设置采样率为50HZ
- // }
- // else
- // {
- // return 1;
- // }
- return 0;
- }
- // 设置MPU6050陀螺仪传感器满量程范围
- // fsr:0,±250dps;1,±500dps;2,±1000dps;3,±2000dps
- // 返回值:0,设置成功
- // 其他,设置失败
- u8 MPU_Set_Gyro_Fsr(u8 fsr)
- {
- return IIC_Write_Byte(MPU_GYRO_CFG_REG, fsr << 3); // 设置陀螺仪满量程范围
- }
- // 设置MPU6050加速度传感器满量程范围
- // fsr:0,±2g;1,±4g;2,±8g;3,±16g
- // 返回值:0,设置成功
- // 其他,设置失败
- u8 MPU_Set_Accel_Fsr(u8 fsr)
- {
- return IIC_Write_Byte(MPU_ACCEL_CFG_REG, fsr << 3); // 设置加速度传感器满量程范围
- }
- // 设置MPU6050的数字低通滤波器
- // lpf:数字低通滤波频率(Hz)
- // 返回值:0,设置成功
- // 其他,设置失败
- u8 MPU_Set_LPF(u16 lpf)
- {
- u8 data = 0;
- if (lpf >= 188)
- data = 1;
- else if (lpf >= 98)
- data = 2;
- else if (lpf >= 42)
- data = 2;
- else if (lpf >= 42)
- data = 3;
- else if (lpf >= 20)
- data = 4;
- else if (lpf >= 10)
- data = 5;
- else
- data = 6;
- return IIC_Write_Byte(MPU_CFG_REG, data); // 设置数字低通滤波器
- }
- // 设置MPU6050的采样率(假定Fs=1KHz)
- // rate:4~1000(Hz)
- // 返回值:0,设置成功
- // 其他,设置失败
- u8 MPU_Set_Rate(u16 rate)
- {
- u8 data;
- if (rate > 1000)
- rate = 1000;
- if (rate < 4)
- rate = 4;
- data = 1000 / rate - 1;
- data = IIC_Write_Byte(MPU_SAMPLE_RATE_REG, data); // 设置数字低通滤波器
- return MPU_Set_LPF(rate / 2); // 自动设置LPF为采样率的一半
- }
- // 得到温度值
- // 返回值:温度值(扩大了100倍)
- short MPU_Get_Temperature(void)
- {
- u8 buf[2];
- short raw;
- float temp;
- IIC_Read_Len(a, MPU_TEMP_OUTH_REG, 2, buf);
- raw = ((u16)buf[0] << 8) | buf[1];
- temp = 36.53 + ((double)raw) / 340;
- return temp * 100;
- ;
- }
- // 得到陀螺仪值(原始值)
- // gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)
- // 返回值:0,成功
- // 其他,错误代码
- u8 MPU_Get_Gyroscope(short *gx, short *gy, short *gz)
- {
- u8 buf[6], res;
- res = IIC_Read_Len(a, MPU_GYRO_XOUTH_REG, 6, buf);
- if (res == 0)
- {
- *gx = ((u16)buf[0] << 8) | buf[1];
- *gy = ((u16)buf[2] << 8) | buf[3];
- *gz = ((u16)buf[4] << 8) | buf[5];
- }
- return res;
- }
- // 得到加速度值(原始值)
- // ax,ay,az:陀螺仪x,y,z轴的原始读数(带符号)
- // 返回值:0,成功
- // 其他,错误代码
- u8 MPU_Get_Accelerometer(short *ax, short *ay, short *az)
- {
- u8 buf[6], res;
- res = IIC_Read_Len(a, MPU_ACCEL_XOUTH_REG, 6, buf);
- if (res == 0)
- {
- *ax = ((u16)buf[0] << 8) | buf[1];
- *ay = ((u16)buf[2] << 8) | buf[3];
- *az = ((u16)buf[4] << 8) | buf[5];
- }
- return res;
- ;
- }
- /*--------------------以下为使用板载固件DMP的相关代码,这个融合得到的姿态角效果很好*/
- /**
- * @brief 获取当前毫秒值
- * @param 存储最新毫秒值的变量
- * @retval 无
- */
- int get_tick_count(unsigned long *count)
- {
- count[0] = HAL_GetTick();
- return 0;
- }
- #include "inv_mpu.h"
- #include "inv_mpu_dmp_motion_driver.h"
- /* Data requested by client. */
- #define PRINT_ACCEL (0x01)
- #define PRINT_GYRO (0x02)
- #define PRINT_QUAT (0x04)
- #define ACCEL_ON (0x01)
- #define GYRO_ON (0x02)
- #define MOTION (0)
- #define NO_MOTION (1)
- /* Starting sampling rate. */ // 100
- #define DEFAULT_MPU_HZ (50)
- struct rx_s
- {
- unsigned char header[3];
- unsigned char cmd;
- };
- struct hal_s
- {
- unsigned char sensors;
- unsigned char dmp_on;
- unsigned char wait_for_tap;
- volatile unsigned char new_gyro;
- unsigned short report;
- unsigned short dmp_features;
- unsigned char motion_int_mode;
- struct rx_s rx;
- };
- static struct hal_s hal = {0};
- /* USB RX binary semaphore. Actually, it's just a flag. Not included in struct
- * because it's declared extern elsewhere.
- */
- volatile unsigned char rx_new;
- /* The sensors can be mounted onto the board in any orientation. The mounting
- * matrix seen below tells the MPL how to rotate the raw data from thei
- * driver(s).
- * TODO: The following matrices refer to the configuration on an internal test
- * board at Invensense. If needed, please modify the matrices to match the
- * chip-to-body matrix for your particular set up.
- */
- static signed char gyro_orientation[9] = {-1, 0, 0,
- 0, -1, 0,
- 0, 0, 1};
- /* Every time new gyro data is available, this function is called in an
- * ISR context. In this example, it sets a flag protecting the FIFO read
- * function.
- */
- static void gyro_data_ready_cb(void)
- {
- hal.new_gyro = 1;
- }
- enum packet_type_e
- {
- PACKET_TYPE_ACCEL,
- PACKET_TYPE_GYRO,
- PACKET_TYPE_QUAT,
- PACKET_TYPE_TAP,
- PACKET_TYPE_ANDROID_ORIENT,
- PACKET_TYPE_PEDO,
- PACKET_TYPE_MISC
- };
- #define BYTE u_char
- /* Send data to the Python client application.
- * Data is formatted as follows:
- * packet[0] = $
- * packet[1] = packet type (see packet_type_e)
- * packet[2+] = data
- */
- void send_packet(char packet_type, void *data)
- {
- #define MAX_BUF_LENGTH (18)
- char buf[MAX_BUF_LENGTH], length;
- memset(buf, 0, MAX_BUF_LENGTH);
- buf[0] = '$';
- buf[1] = packet_type;
- if (packet_type == PACKET_TYPE_ACCEL || packet_type == PACKET_TYPE_GYRO)
- {
- short *sdata = (short *)data;
- buf[2] = (char)(sdata[0] >> 8);
- buf[3] = (char)sdata[0];
- buf[4] = (char)(sdata[1] >> 8);
- buf[5] = (char)sdata[1];
- buf[6] = (char)(sdata[2] >> 8);
- buf[7] = (char)sdata[2];
- length = 8;
- }
- else if (packet_type == PACKET_TYPE_QUAT)
- {
- long *ldata = (long *)data;
- buf[2] = (char)(ldata[0] >> 24);
- buf[3] = (char)(ldata[0] >> 16);
- buf[4] = (char)(ldata[0] >> 8);
- buf[5] = (char)ldata[0];
- buf[6] = (char)(ldata[1] >> 24);
- buf[7] = (char)(ldata[1] >> 16);
- buf[8] = (char)(ldata[1] >> 8);
- buf[9] = (char)ldata[1];
- buf[10] = (char)(ldata[2] >> 24);
- buf[11] = (char)(ldata[2] >> 16);
- buf[12] = (char)(ldata[2] >> 8);
- buf[13] = (char)ldata[2];
- buf[14] = (char)(ldata[3] >> 24);
- buf[15] = (char)(ldata[3] >> 16);
- buf[16] = (char)(ldata[3] >> 8);
- buf[17] = (char)ldata[3];
- length = 18;
- }
- else if (packet_type == PACKET_TYPE_TAP)
- {
- buf[2] = ((char *)data)[0];
- buf[3] = ((char *)data)[1];
- length = 4;
- }
- else if (packet_type == PACKET_TYPE_ANDROID_ORIENT)
- {
- buf[2] = ((char *)data)[0];
- length = 3;
- }
- else if (packet_type == PACKET_TYPE_PEDO)
- {
- long *ldata = (long *)data;
- buf[2] = (char)(ldata[0] >> 24);
- buf[3] = (char)(ldata[0] >> 16);
- buf[4] = (char)(ldata[0] >> 8);
- buf[5] = (char)ldata[0];
- buf[6] = (char)(ldata[1] >> 24);
- buf[7] = (char)(ldata[1] >> 16);
- buf[8] = (char)(ldata[1] >> 8);
- buf[9] = (char)ldata[1];
- length = 10;
- }
- else if (packet_type == PACKET_TYPE_MISC)
- {
- buf[2] = ((char *)data)[0];
- buf[3] = ((char *)data)[1];
- buf[4] = ((char *)data)[2];
- buf[5] = ((char *)data)[3];
- length = 6;
- }
- // cdcSendDataWaitTilDone((BYTE*)buf, length, CDC0_INTFNUM, 100);
- }
- /* These next two functions converts the orientation matrix (see
- * gyro_orientation) to a scalar representation for use by the DMP.
- * NOTE: These functions are borrowed from Invensense's MPL.
- */
- static inline unsigned short inv_row_2_scale(const signed char *row)
- {
- unsigned short b;
- if (row[0] > 0)
- b = 0;
- else if (row[0] < 0)
- b = 4;
- else if (row[1] > 0)
- b = 1;
- else if (row[1] < 0)
- b = 5;
- else if (row[2] > 0)
- b = 2;
- else if (row[2] < 0)
- b = 6;
- else
- b = 7; // error
- return b;
- }
- static inline unsigned short inv_orientation_matrix_to_scalar(
- const signed char *mtx)
- {
- unsigned short scalar;
- /*
- XYZ 010_001_000 Identity Matrix
- XZY 001_010_000
- YXZ 010_000_001
- YZX 000_010_001
- ZXY 001_000_010
- ZYX 000_001_010
- */
- scalar = inv_row_2_scale(mtx);
- scalar |= inv_row_2_scale(mtx + 3) << 3;
- scalar |= inv_row_2_scale(mtx + 6) << 6;
- return scalar;
- }
- static inline void run_self_test(void)
- {
- int result;
- char test_packet[4] = {0};
- long gyro[3], accel[3];
- result = mpu_run_self_test(gyro, accel);
- if (result == 0x7)
- {
- /* Test passed. We can trust the gyro data here, so let's push it down
- * to the DMP.
- */
- float sens;
- unsigned short accel_sens;
- mpu_get_gyro_sens(&sens);
- gyro[0] = (long)(gyro[0] * sens);
- gyro[1] = (long)(gyro[1] * sens);
- gyro[2] = (long)(gyro[2] * sens);
- dmp_set_gyro_bias(gyro);
- mpu_get_accel_sens(&accel_sens);
- accel[0] *= accel_sens;
- accel[1] *= accel_sens;
- accel[2] *= accel_sens;
- dmp_set_accel_bias(accel);
- }
- /* Report results. */
- test_packet[0] = 't';
- test_packet[1] = result;
- send_packet(PACKET_TYPE_MISC, test_packet);
- }
- #define INT_EXIT_LPM0 12
- void DMP_Init(void)
- {
- printf("checkpoint Func DMP_Init\n");
- struct int_param_s int_param;
- /* Set up gyro.
- * Every function preceded by mpu_ is a driver function and can be found
- * in inv_mpu.h.
- */
- int_param.cb = gyro_data_ready_cb;
- int_param.pin = 16;
- int_param.lp_exit = INT_EXIT_LPM0;
- int_param.active_low = 1;
- int result = mpu_init(&int_param);
- printf("mpu_init, %d\r\n", result);
- if (result == 0) // mpu初始化
- {
- if (!mpu_set_sensors(INV_XYZ_GYRO | INV_XYZ_ACCEL)) // 设置需要的传感器
- printf("mpu_set_sensor complete ......\r\n");
- if (!mpu_configure_fifo(INV_XYZ_GYRO | INV_XYZ_ACCEL)) // 设置fifo
- printf("mpu_configure_fifo complete ......\r\n");
- if (!mpu_set_sample_rate(DEFAULT_MPU_HZ)) // 设置采集样率
- printf("mpu_set_sample_rate complete ......\r\n");
- unsigned short gyro_rate = 0, gyro_fsr = 0;
- unsigned char accel_fsr = 0;
- mpu_get_sample_rate(&gyro_rate);
- mpu_get_gyro_fsr(&gyro_fsr);
- mpu_get_accel_fsr(&accel_fsr);
- printf("gyro_rate %d, gyro_fsr %d, accel_fsr %d\r\n", gyro_rate, gyro_fsr, accel_fsr);
- if (!dmp_load_motion_driver_firmware()) // 加载dmp固件
- printf("dmp_load_motion_driver_firmware complete ......\r\n");
- if (!dmp_set_orientation(inv_orientation_matrix_to_scalar(gyro_orientation)))
- printf("dmp_set_orientation complete ......\r\n"); // 设置陀螺仪方向
- if (!dmp_enable_feature(DMP_FEATURE_6X_LP_QUAT | DMP_FEATURE_TAP |
- DMP_FEATURE_ANDROID_ORIENT | DMP_FEATURE_SEND_RAW_ACCEL | DMP_FEATURE_SEND_CAL_GYRO |
- DMP_FEATURE_GYRO_CAL))
- printf("dmp_enable_feature complete ......\r\n");
- if (!dmp_set_fifo_rate(DEFAULT_MPU_HZ)) // 设置速率
- printf("dmp_set_fifo_rate complete ......\r\n");
- run_self_test(); // 自检(非必要)
- if (!mpu_set_dmp_state(1)) // 使能
- printf("mpu_set_dmp_state complete ......\r\n");
- }
- }
- #define q30 1073741824.0
- uint8_t Read_DMP(float *Pitch, float *Roll, float *Yaw)
- {
- short gyro[3], accel[3], sensors;
- float q0 = 1.0f, q1 = 0.0f, q2 = 0.0f, q3 = 0.0f;
- unsigned long sensor_timestamp;
- unsigned char more;
- long quat[4];
- int ret = dmp_read_fifo(gyro, accel, quat, &sensor_timestamp, &sensors, &more);
- // printf("dmp_read_fifo, %d\r\n", ret);
- if (ret)
- {
- return 1;
- }
- if (sensors & INV_WXYZ_QUAT)
- {
- q0 = quat[0] / q30;
- q1 = quat[1] / q30;
- q2 = quat[2] / q30;
- q3 = quat[3] / q30;
- *Pitch = (float)asin(-2 * q1 * q3 + 2 * q0 * q2) * 57.3;
- *Roll = (float)atan2(2 * q2 * q3 + 2 * q0 * q1, -2 * q1 * q1 - 2 * q2 * q2 + 1) * 57.3; // roll
- *Yaw = (float)atan2(2 * (q1 * q2 + q0 * q3), q0 * q0 + q1 * q1 - q2 * q2 - q3 * q3) * 57.3;
- return 0;
- }
- else
- {
- return 2;
- }
- }
|