How to enable 1.3 mpu6050 (Large End) and M4 FPU
Original article. You are welcome to repost it. For reposted content, please indicate the source.
The most recent time is the I2C of stm32. I know that the I2C of stm32 is not easy to use, because I have used analog I2C, and I have also written the AVR I2C, that is, the twi hardware driver, so I want to try writing stm32 hardware I2C... In order to avoid the trouble caused by the Library, the standard library of ikef4 was upgraded to 1.3.0, but it seems that the problem persists. So I found the cpal library written by St to I2C on the Internet, and read it with its English manuals and examples. I think it is very good and has quite a complete set of functions, it should be good to use according to the manual configuration, so I started to load it into my own project. It requires a timer to manage the timeout. When a communication problem occurs, you can see the timeout mechanism and perform some simple processing. By default, it uses the stopick interrupt, this is easy to handle. You can use a thread of RTT to replace javasick or another timer. It also requires that the two I2C-related interruptions be set to the highest priority, although I think the advantages are uncomfortable, I can only set it like this. In fact, the hardware defects of I2C in stm32 are here, so I need to respond to I2C interruption in the first time. Otherwise, problems may occur, even if I write I2C of stm32, the two interrupt priorities need to be set very high. However, I found something that I think may not be acceptable, that is, there is a macro In the interrupt, __cpal_i2c_timeout, defined as follows
1 #define __CPAL_I2C_TIMEOUT_DETECT ((pDevInitStruct->wCPAL_Timeout == CPAL_I2C_TIMEOUT_MIN) || 2 (pDevInitStruct->wCPAL_Timeout == CPAL_I2C_TIMEOUT_DEFAULT)) 3 4 #define __CPAL_I2C_TIMEOUT(cmd, timeout) pDevInitStruct->wCPAL_Timeout = CPAL_I2C_TIMEOUT_MIN + (timeout); 5 while (((cmd) == 0) && (!__CPAL_I2C_TIMEOUT_DETECT)); 6 if (__CPAL_I2C_TIMEOUT_DETECT) 7 { 8 return CPAL_I2C_Timeout (pDevInitStruct); 9 }10 pDevInitStruct->wCPAL_Timeout = CPAL_I2C_TIMEOUT_DEFAULT
That is to say, this cpal database needs to try out the interrupt with the highest priority, and there is a while in the interrupt with the highest priority. Is that the interrupt with the highest priority? Do I have to respond to other interruptions? Can the RTT Thread Scheduling be pleasant? Can the points be completed in the correct time? Will the collected data become worse? Abandon it ..
After giving up the cpal library, there are three other options: the purchased board has a written I2C hardware library, which is not open source. To make it faster, use the library, after the compilation is complete, you can run it on the board and find that it will be stuck .. No .. I didn't know what the problem was. Later I thought it was because c99 was not used. The default MDK is c89. There are also two options: Write the hardware I2C yourself or simulate I2C with simple brute force... After several days of hard work, the progress was too slow. Our first task was to fly first and then change it slowly, so we decided to use the simulation I2C, as long as it was encapsulated, it is easy to put the better I2C written later.
Simulate I2C. Let's talk about mpu6050... There are a lot of materials on the mpu6050 network. It's easy to set everything. I'm a little lazy, I don't use FIFO, So I'm too lazy to set it up. I plan to port 0x48 from 0x3b, to read all the data, the simple method is to read the data in one byte and then forcibly convert it to the format for calculation. But does this really work? In the Union test, the minor F4 mode is used, that is, the low data level is stored in the low memory address, and the high data level is stored in the high memory address, however, if you look at the mpu6050 manual, you will find that it is a big-end mode. The low data level is stored in the high memory address, while the high data level is saved in the low memory address. For example:
If all data is read sequentially, The LSB and MSB are reversed and must be converted once .. As a result, I am too lazy. I have written I2C continuous reads, but I don't need to forget it. I can solve this problem using struct and union. I will define a hybrid structure of struct and union in the following way:
1 typedef struct 2 { 3 union 4 { 5 struct 6 { 7 u8 data_L; 8 u8 data_H; 9 } b;10 u16 data;11 } acce_x;12 union 13 {14 struct 15 {16 u8 data_L;17 u8 data_H;18 } b;19 u16 data;20 } acce_y;21 union 22 {23 struct 24 {25 u8 data_L;26 u8 data_H;27 } b;28 u16 data;29 } acce_z;30 31 union 32 {33 struct 34 {35 u8 data_L;36 u8 data_H;37 } b;38 u16 data;39 } temp;40 41 union 42 {43 struct 44 {45 u8 data_L;46 u8 data_H;47 } b;48 u16 data;49 } gyro_x;50 union 51 {52 struct 53 {54 u8 data_L;55 u8 data_H;56 } b;57 u16 data;58 } gyro_y;59 union 60 {61 struct 62 {63 u8 data_L;64 u8 data_H;65 } b;66 u16 data;67 } gyro_z;68 69 }MPU6050_DATA_T;
View code
It is easy to read data. One byte can be read in one byte, for example, in the high byte of accx, In the mpu6050_data_t-> acce_x. B .data_h, and in the lower byte, we can use mpu6050_data_t.acce_x.data to retrieve data. We don't need to convert the data between LSB and MSB. Ha, lazy people use lazy methods, but this method is not efficient after all, wait for the plane to fly and change it .. Haha ..
The read data is as follows:
It seems that the gyro_z data is a bit problematic. I will take a closer look at it later. These values are not processed. We need to convert the raw data according to the selected range ..
I used lsm303dlh to calculate the attitude data, that is, inverse trigonometric function calculation. The data is not filtered in different scenarios .. The endpoint here is that we need to use the inverse trigonometric function, while M4 is with FPU and does not need to be white .. It is much faster .. Haha .. Enable FPU .. The following steps are required:
Systemini contains the following sentence:
1 /* FPU settings ------------------------------------------------------------*/2 #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)3 SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */4 #endif
So the first step is to set these two macros, __fpu_present, __fpu_used, and find them in stm32f4xx. h.
1 # DEFINE _ mpu_present 1 /*! <Stm32f4xx provides an MPU 2 # DEFINE _ fpu_present 1 /*! <FPU present defined
If we need FPU, we need to use the mathematical functions provided by arm for us. We need to include the arm_math.h header file,
You also need to add
Arm_cortexmxx_math.libIn the project file
\ Libraries \ cmsis \ Lib \ arm.
* The Library installer contains prebuilt versions of the libraries in the <code> lib </code> folder.
*-Arm_cortexm4lf_math.lib (little endian and floating point unit on Cortex-M4)
*-Arm_cortexm4bf_math.lib (big endian and floating point unit on Cortex-M4)
*-Arm_cortexm4l_math.lib (little endian on Cortex-M4)
*-Arm_cortexm4b_math.lib (big endian on Cortex-M4)
*-Arm_cortexm3l_math.lib (little endian on Cortex-M3)
*-Arm_cortexm3b_math.lib (big endian on Cortex-M3)
*-Arm_cortexm0l_math.lib (little endian on Cortex-M0)
*-Arm_cortexm0b_math.lib (big endian on Cortex-M3)
Stm32f407: we use the small-end mode with FPU and support floating-point operations. Therefore, the library we want to add is arm_cortexm4lf_math.lib. An error will be found after compilation. We need to add the arm_math_cm4 macro, everything is ready. You can use the FPU of M4 .. Haha ..
Let's take a look at the stm32f40x \ libraries \ cmsis \ dsp_lib \ source directory and find many files. For example, if you want to explain the file, you can check the name until you get a rough idea. The explanation depends on the online explanation and matrix calculation, the filter function may be used later .. It instantly feels tall ..
Basicmathfunctions
Provides a variety of basic floating point operation functions, such as addition, subtraction, multiplication, division, and other operations.
Commontables
The arm_common_tables.c file provides bitwise flip or related parameter tables.
Complexmathfunctions
Repeat mathematical functions, such as vector processing and modulo calculation.
Controllerfunctions
Control Function, mainly PID control function. The arm_sin_cos_f32/-q31.c function provides the 360-point positive cosine function table and the arbitrary cosine function value calculation function.
Fastmathfunctions
Quick mathematical functions: Provides the 256-point positive cosine function table and any angle of the positive cosine function value calculation function, and the Q-value square operation:
Arm_cos_f32/_ q15/_ q31.c: Provides the 256-point cosine function table and any angle cosine value calculation function.
Arm_sin_f32/_ q15/_ q31.c: provides a 256-point sine function table and any angle sine value calculation function.
Arm_sqrt_q15/q31.c: provides a function for iterative calculation of the square root. For the square root operation of m4f, The vsqrt command is executed.
Filteringfunctions
The filter function is mainly used for fir and LMS (least root mean square) filters.
Matrixfunctions
Matrix processing functions.
Statisticsfunctions
Statistical functions, such as average, RMS, and variance/standard deviation.
Supportfunctions
Function functions are supported, such as data copying, conversion between Q format and floating point format, and conversion between any Q format.
Transformfunctions
Conversion Function. Including complex FFT (cfft)/complex FFT inverse (cifft), Real FFT (rfft)/real FFT inverse (rifft), and DCT (discrete cosine transformation) and supporting initialization functions.
The next step is to upload the mpu6050 raw data to MATLAB for data processing .. To write the serial port of MATLAB .... Communication Protocols may also start to need simple planning, because they are prepared to do remote control via 2401, and communication protocols should also be considered ..