Рефакторинг проекта
This commit is contained in:
88
Robot_balancer/PID/Drivers/I2C.c
Normal file
88
Robot_balancer/PID/Drivers/I2C.c
Normal file
@ -0,0 +1,88 @@
|
||||
#include <I2C.h>
|
||||
|
||||
void I2C3_Stop()
|
||||
{
|
||||
I2C3->CR2 |= I2C_CR2_STOP; // установка бит стоп
|
||||
|
||||
while (!(I2C3->ISR & I2C_ISR_STOPF))
|
||||
__NOP(); // Ждём остановку
|
||||
I2C3->ICR |= I2C_ICR_STOPCF; // Сброс флага STOP
|
||||
|
||||
I2C3->CR2 = 0; // сброс настроек паредачи-приёма
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// чтение
|
||||
//
|
||||
void I2C3_Read(unsigned char Address, unsigned char *Data, unsigned char Size)
|
||||
{
|
||||
while (I2C3->ISR & I2C_ISR_BUSY)
|
||||
__NOP(); // Ждём освобождения линии I2C3
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
// I2C3->CR2 &= ~(I2C_CR2_SADD_Msk); // сброс адреса Slave
|
||||
// I2C3->CR2 &= ~(I2C_CR2_NBYTES_Msk); // сброс кол-ва принимаемых байт I2C3
|
||||
|
||||
I2C3->CR2 &= ~(I2C_CR2_SADD_Msk | I2C_CR2_NBYTES_Msk); // сокращение вызовов команд для установки битов в один вызов;
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
// I2C3->CR2 |= (Address << (I2C_CR2_SADD_Pos)) & I2C_CR2_SADD_Msk; // Установка адреса Slave
|
||||
// I2C3->CR2 |= (Size << (I2C_CR2_NBYTES_Pos)) & I2C_CR2_NBYTES_Msk; // Установка кол-ва байтов принимаемых
|
||||
// I2C3->CR2 |= I2C_CR2_RD_WRN; // режим чтения
|
||||
|
||||
I2C3->CR2 |= ((Address << (I2C_CR2_SADD_Pos)) & I2C_CR2_SADD_Msk) | // сокращение вызовов команд для установки битов в один вызов;
|
||||
((Size << (I2C_CR2_NBYTES_Pos)) & I2C_CR2_NBYTES_Msk) |
|
||||
I2C_CR2_RD_WRN;
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
I2C3->CR2 &= ~(I2C_CR2_AUTOEND | I2C_CR2_RELOAD); // отключение автозавершения и автоповторения
|
||||
I2C3->CR2 |= I2C_CR2_AUTOEND; // включение автозавершения
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
I2C3->CR2 |= I2C_CR2_START; // старт чтения
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
while (Size--) // Проход по байтам
|
||||
{
|
||||
while (!(I2C3->ISR & I2C_ISR_RXNE))
|
||||
__NOP(); // Ждём байт
|
||||
*Data++ = I2C3->RXDR; // Запись байта
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
while (!(I2C3->ISR & I2C_ISR_STOPF))
|
||||
__NOP(); // Ждём остановку
|
||||
I2C3->ICR |= I2C_ICR_STOPCF; // Сброс флага STOP
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// запись
|
||||
//
|
||||
void I2C3_Write(unsigned char Address, unsigned char *Data, unsigned char Size)
|
||||
{
|
||||
while (I2C3->ISR & I2C_ISR_BUSY)
|
||||
__NOP(); // Ждём освобождения линии I2C3
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
// I2C3->CR2 &= ~(I2C_CR2_SADD_Msk); // сброс адреса Slave
|
||||
// I2C3->CR2 &= ~(I2C_CR2_NBYTES_Msk); // сброс кол-ва записываемых байт I2C3
|
||||
|
||||
I2C3->CR2 &= ~(I2C_CR2_SADD_Msk | I2C_CR2_NBYTES_Msk); // сокращение вызовов команд для установки битов в один вызов;
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
// I2C3->CR2 |= (Address << (I2C_CR2_SADD_Pos)) & I2C_CR2_SADD_Msk; // Установка адреса Slave
|
||||
// I2C3->CR2 |= (Size << (I2C_CR2_NBYTES_Pos)) & I2C_CR2_NBYTES_Msk; // Установка кол-ва байтов отдаваемых
|
||||
// I2C3->CR2 |= I2C_CR2_RD_WRN; // режим записи
|
||||
|
||||
I2C3->CR2 |= ((Address << (I2C_CR2_SADD_Pos)) & I2C_CR2_SADD_Msk) | // сокращение вызовов команд для установки битов в один вызов;
|
||||
((Size << (I2C_CR2_NBYTES_Pos)) & I2C_CR2_NBYTES_Msk);
|
||||
I2C3->CR2 &= ~I2C_CR2_RD_WRN; // режим записи
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
I2C3->CR2 &= ~(I2C_CR2_AUTOEND | I2C_CR2_RELOAD); // отключение автозавершения и автоповторения
|
||||
I2C3->CR2 |= I2C_CR2_AUTOEND; // включение автозавершения
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
I2C3->CR2 |= I2C_CR2_START; // старт записи
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
while (Size--) // проход по байтам
|
||||
{
|
||||
while (!(I2C3->ISR & I2C_ISR_TXE))
|
||||
__NOP(); // Ждём байт
|
||||
I2C3->TXDR = *Data++; // Запись байта
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
while (!(I2C3->ISR & I2C_ISR_STOPF))
|
||||
__NOP(); // Ждём остановку
|
||||
I2C3->ICR |= I2C_ICR_STOPCF; // Сброс флага STOP
|
||||
}
|
4
Robot_balancer/PID/Drivers/I2C.h
Normal file
4
Robot_balancer/PID/Drivers/I2C.h
Normal file
@ -0,0 +1,4 @@
|
||||
#include "stm32g431xx.h"
|
||||
void I2C3_Stop();
|
||||
void I2C3_Read(unsigned char Address, unsigned char *Data, unsigned char Size);
|
||||
void I2C3_Write(unsigned char Address, unsigned char *Data, unsigned char Size);
|
134
Robot_balancer/PID/Drivers/LSM6DS3.c
Normal file
134
Robot_balancer/PID/Drivers/LSM6DS3.c
Normal file
@ -0,0 +1,134 @@
|
||||
#include "LSM6DS3.h"
|
||||
|
||||
|
||||
volatile float accel_filter_coeff = 0.3f; // Коэффициент ФНЧ для акселерометра (0.1-0.5)
|
||||
volatile float gyro_filter_coeff = 0.2f; // Коэффициент ФНЧ для гироскопа (0.1-0.3)
|
||||
volatile float comp_filter_coeff = 0.93f; // Коэффициент комплементарного фильтра (0.9-0.98)
|
||||
|
||||
volatile int16_t filt_acc_x, filt_acc_y, filt_acc_z;
|
||||
volatile int16_t filt_gyro_x, filt_gyro_y, filt_gyro_z;
|
||||
volatile int16_t angle_pitch, angle_roll;
|
||||
// Функция для чтения одного регистра
|
||||
uint8_t LSM6DS3_ReadRegister(uint8_t reg)
|
||||
{
|
||||
uint8_t value;
|
||||
I2C3_Write(LSM6DS3_ADDRESS, ®, 1); // Отправляем адрес регистра
|
||||
I2C3_Read(LSM6DS3_ADDRESS, &value, 1); // Читаем значение регистра
|
||||
return value;
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
// Функция для записи в регистр
|
||||
void LSM6DS3_WriteRegister(uint8_t reg, uint8_t value)
|
||||
{
|
||||
uint8_t data[2] = {reg, value};
|
||||
I2C3_Write(LSM6DS3_ADDRESS, data, 2);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
// Инициализация LSM6DS3
|
||||
void LSM6DS3_Init()
|
||||
{
|
||||
// Проверка WHO_AM_I (должен вернуть 0x69)
|
||||
uint8_t who_am_i = LSM6DS3_ReadRegister(LSM6DS3_WHO_AM_I);
|
||||
if (who_am_i != 0x69)
|
||||
{
|
||||
// Ошибка - датчик не ответил
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
// Настройка акселерометра (104 Гц, +-2g)
|
||||
LSM6DS3_WriteRegister(LSM6DS3_CTRL1_XL, 0x40);
|
||||
|
||||
// Настройка гироскопа (104 Гц, 245 dps)
|
||||
LSM6DS3_WriteRegister(LSM6DS3_CTRL2_G, 0x40);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
// Чтение данных акселерометра
|
||||
void LSM6DS3_ReadAccelerometer(volatile int16_t *x, volatile int16_t *y, volatile int16_t *z)
|
||||
{
|
||||
uint8_t data[6];
|
||||
uint8_t reg = LSM6DS3_OUTX_L_A; // Начинаем чтение с первого регистра данных акселерометра
|
||||
|
||||
I2C3_Write(LSM6DS3_ADDRESS, ®, 1);
|
||||
I2C3_Read(LSM6DS3_ADDRESS, data, 6);
|
||||
|
||||
*x = (int16_t)((data[1] << 8) | data[0]);
|
||||
*y = (int16_t)((data[3] << 8) | data[2]);
|
||||
*z = (int16_t)((data[5] << 8) | data[4]);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
// Чтение данных гироскопа
|
||||
void LSM6DS3_ReadGyroscope(volatile int16_t *x, volatile int16_t *y, volatile int16_t *z)
|
||||
{
|
||||
uint8_t data[6];
|
||||
uint8_t reg = LSM6DS3_OUTX_L_G; // Начинаем чтение с первого регистра данных гироскопа
|
||||
|
||||
I2C3_Write(LSM6DS3_ADDRESS, ®, 1);
|
||||
I2C3_Read(LSM6DS3_ADDRESS, data, 6);
|
||||
|
||||
*x = (int16_t)((data[1] << 8) | data[0]);
|
||||
*y = (int16_t)((data[3] << 8) | data[2]);
|
||||
*z = (int16_t)((data[5] << 8) | data[4]);
|
||||
}
|
||||
|
||||
volatile int16_t acc_x, acc_y, acc_z;
|
||||
volatile int16_t gyro_x, gyro_y, gyro_z;
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
void Filter_SensorData()
|
||||
{
|
||||
// Более быстрая фильтрация акселерометра
|
||||
filt_acc_x += accel_filter_coeff * (acc_x - filt_acc_x);
|
||||
filt_acc_y += accel_filter_coeff * (acc_y - filt_acc_y);
|
||||
filt_acc_z += accel_filter_coeff * (acc_z - filt_acc_z);
|
||||
|
||||
// Фильтрация гироскопа с преобразованием
|
||||
filt_gyro_x += gyro_filter_coeff * ((gyro_x / GYRO_SCALE) - filt_gyro_x);
|
||||
filt_gyro_y += gyro_filter_coeff * ((gyro_y / GYRO_SCALE) - filt_gyro_y);
|
||||
filt_gyro_z += gyro_filter_coeff * ((gyro_z / GYRO_SCALE) - filt_gyro_z);
|
||||
}
|
||||
|
||||
// Быстрый расчет углов по акселерометру
|
||||
void Calculate_Accel_Angles()
|
||||
{
|
||||
// Быстрая нормализация
|
||||
float inv_norm = 1.0f / sqrt(filt_acc_x * filt_acc_x + filt_acc_y * filt_acc_y + filt_acc_z * filt_acc_z);
|
||||
float ax = filt_acc_x * inv_norm;
|
||||
float ay = filt_acc_y * inv_norm;
|
||||
float az = filt_acc_z * inv_norm;
|
||||
|
||||
// Оптимизированный расчет углов
|
||||
angle_pitch = -atan2(ay, az) * RAD_TO_DEG;
|
||||
angle_roll = atan2(ax, sqrt(ay * ay + az * az)) * RAD_TO_DEG;
|
||||
}
|
||||
|
||||
// Ускоренный комплементарный фильтр
|
||||
void Complementary_Filter()
|
||||
{
|
||||
static float pitch = 0, roll = 0;
|
||||
|
||||
// Получаем углы из акселерометра
|
||||
Calculate_Accel_Angles();
|
||||
|
||||
// Интегрируем данные гироскопа с небольшим усилением
|
||||
pitch += filt_gyro_x * DT * 1.1f; // +10% к скорости отклика
|
||||
roll += filt_gyro_y * DT * 1.1f;
|
||||
|
||||
// Комплементарный фильтр с динамическими коэффициентами
|
||||
float alpha = comp_filter_coeff;
|
||||
|
||||
// Автоматическая подстройка коэффициента при быстром движении
|
||||
if (fabsf(filt_gyro_x) > 20.0f || fabsf(filt_gyro_y) > 20.0f)
|
||||
{
|
||||
alpha = 0.96f; // Больше доверия гироскопу при быстром движении
|
||||
}
|
||||
|
||||
pitch = pitch * alpha + angle_pitch * (1.0f - alpha);
|
||||
roll = roll * alpha + angle_roll * (1.0f - alpha);
|
||||
|
||||
// Ограничение углов
|
||||
pitch = fmod(pitch, 360.0f);
|
||||
roll = fmod(roll, 360.0f);
|
||||
|
||||
angle_pitch = pitch;
|
||||
angle_roll = roll;
|
||||
}
|
49
Robot_balancer/PID/Drivers/LSM6DS3.h
Normal file
49
Robot_balancer/PID/Drivers/LSM6DS3.h
Normal file
@ -0,0 +1,49 @@
|
||||
#include "stm32g431xx.h"
|
||||
#include "I2C.h"
|
||||
#include <math.h>
|
||||
#define LSM6DS3_ADDRESS 0xD6
|
||||
|
||||
// Регистры LSM6DS3
|
||||
#define LSM6DS3_WHO_AM_I 0x0F
|
||||
#define LSM6DS3_CTRL1_XL 0x10
|
||||
#define LSM6DS3_CTRL2_G 0x11
|
||||
#define LSM6DS3_OUTX_L_G 0x22
|
||||
#define LSM6DS3_OUTX_H_G 0x23
|
||||
#define LSM6DS3_OUTY_L_G 0x24
|
||||
#define LSM6DS3_OUTY_H_G 0x25
|
||||
#define LSM6DS3_OUTZ_L_G 0x26
|
||||
#define LSM6DS3_OUTZ_H_G 0x27
|
||||
#define LSM6DS3_OUTX_L_A 0x28 // Правильное название регистра для акселерометра
|
||||
#define LSM6DS3_OUTX_H_A 0x29
|
||||
#define LSM6DS3_OUTY_L_A 0x2A
|
||||
#define LSM6DS3_OUTY_H_A 0x2B
|
||||
#define LSM6DS3_OUTZ_L_A 0x2C
|
||||
#define LSM6DS3_OUTZ_H_A 0x2D
|
||||
|
||||
uint8_t LSM6DS3_ReadRegister(uint8_t reg);
|
||||
void LSM6DS3_WriteRegister(uint8_t reg, uint8_t value);
|
||||
void LSM6DS3_Init();
|
||||
void LSM6DS3_ReadAccelerometer(volatile int16_t *x, volatile int16_t *y, volatile int16_t *z);
|
||||
void LSM6DS3_ReadGyroscope(volatile int16_t *x, volatile int16_t *y, volatile int16_t *z);
|
||||
|
||||
extern volatile int16_t acc_x, acc_y, acc_z;
|
||||
extern volatile int16_t gyro_x, gyro_y, gyro_z;
|
||||
|
||||
// Коэффициенты фильтр
|
||||
#define GYRO_SCALE 65.5f // Для +-500: 32768/500
|
||||
#define RAD_TO_DEG 57.29578f // Преобразование радиан в градусы
|
||||
#define DT 0.001f // Период дискретизации (10 мс)
|
||||
|
||||
// Настраиваемые коэффициенты фильтрации
|
||||
extern volatile float accel_filter_coeff; // Коэффициент ФНЧ для акселерометра (0.1-0.5)
|
||||
extern volatile float gyro_filter_coeff; // Коэффициент ФНЧ для гироскопа (0.1-0.3)
|
||||
extern volatile float comp_filter_coeff; // Коэффициент комплементарного фильтра (0.9-0.98)
|
||||
|
||||
extern volatile int16_t filt_acc_x, filt_acc_y, filt_acc_z;
|
||||
extern volatile int16_t filt_gyro_x, filt_gyro_y, filt_gyro_z;
|
||||
extern volatile int16_t angle_pitch, angle_roll;
|
||||
|
||||
void Filter_SensorData();
|
||||
void Calculate_Accel_Angles();
|
||||
void Complementary_Filter();
|
||||
|
@ -358,6 +358,7 @@
|
||||
<name>CCIncludePath2</name>
|
||||
<state>$PROJ_DIR$/Core</state>
|
||||
<state>$PROJ_DIR$/Drivers</state>
|
||||
<state>$PROJ_DIR$/Utils</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>CCStdIncCheck</name>
|
||||
@ -1174,11 +1175,11 @@
|
||||
</option>
|
||||
<option>
|
||||
<name>OGLastSavedByProductVersion</name>
|
||||
<state>9.50.1.69312</state>
|
||||
<state>9.60.3.7274</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>OGChipSelectEditMenu</name>
|
||||
<state></state>
|
||||
<state>default None</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>GenLowLevelInterface</name>
|
||||
@ -1224,7 +1225,7 @@
|
||||
</option>
|
||||
<option>
|
||||
<name>GFPUDeviceSlave</name>
|
||||
<state></state>
|
||||
<state>default None</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>FPU2</name>
|
||||
@ -1444,7 +1445,7 @@
|
||||
</option>
|
||||
<option>
|
||||
<name>OutputFile</name>
|
||||
<state></state>
|
||||
<state>$FILE_BNAME$.o</state>
|
||||
</option>
|
||||
<option>
|
||||
<name>CCLibConfigHeader</name>
|
||||
@ -2220,6 +2221,27 @@
|
||||
</group>
|
||||
<group>
|
||||
<name>Drivers</name>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\Drivers\I2C.c</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\Drivers\I2C.h</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\Drivers\LSM6DS3.c</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\Drivers\LSM6DS3.h</name>
|
||||
</file>
|
||||
</group>
|
||||
<group>
|
||||
<name>Utils</name>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\Utils\PID.c</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\Utils\PID.h</name>
|
||||
</file>
|
||||
</group>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\main.cpp</name>
|
||||
|
@ -2947,6 +2947,27 @@
|
||||
</group>
|
||||
<group>
|
||||
<name>Drivers</name>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\Drivers\I2C.c</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\Drivers\I2C.h</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\Drivers\LSM6DS3.c</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\Drivers\LSM6DS3.h</name>
|
||||
</file>
|
||||
</group>
|
||||
<group>
|
||||
<name>Utils</name>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\Utils\PID.c</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\Utils\PID.h</name>
|
||||
</file>
|
||||
</group>
|
||||
<file>
|
||||
<name>$PROJ_DIR$\main.cpp</name>
|
||||
|
43
Robot_balancer/PID/Utils/PID.c
Normal file
43
Robot_balancer/PID/Utils/PID.c
Normal file
@ -0,0 +1,43 @@
|
||||
#include "PID.h"
|
||||
|
||||
float KP = 100;
|
||||
float KI = 1;
|
||||
float KD = 1;
|
||||
float integral = 0;
|
||||
float lastError = 0;
|
||||
float limit = 1000; //ограничение интегральной составляющей
|
||||
float target = 0.0f; //желаемое значение(вертикально)
|
||||
float pid_update(float target, float current, float dt);
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
float pid_update(float target, float current, float dt)
|
||||
{
|
||||
float error = target - current;
|
||||
float p = KP * error;
|
||||
|
||||
float i = error * dt;
|
||||
integral += KI * i;
|
||||
integral = integral > limit ? integral = limit : (integral < -limit ? integral = -limit : integral);
|
||||
|
||||
float d = (KD * (error - lastError))/dt;
|
||||
lastError = error;
|
||||
|
||||
float output = p + integral + d;
|
||||
return output; // Управляющее воздействие/крутящий момент
|
||||
}
|
||||
// float pid_update(float target, float current, float dt){
|
||||
// float error = (target - current)*dt;
|
||||
// float pPart = KP*(target - current);
|
||||
// integral += error;
|
||||
// float iPart = KI *integral;
|
||||
// float dPart = KD *(error - lastError)/dt;
|
||||
// lastError = error;
|
||||
|
||||
// if (integral > limit) {
|
||||
// integral = limit;
|
||||
// }
|
||||
// else if (integral < -limit){
|
||||
// integral = -limit;
|
||||
// }
|
||||
// float output = pPart + iPart + dPart;
|
||||
// return output; //Управляющее воздействие/крутящий момент
|
||||
// }
|
10
Robot_balancer/PID/Utils/PID.h
Normal file
10
Robot_balancer/PID/Utils/PID.h
Normal file
@ -0,0 +1,10 @@
|
||||
float pid_update(float target, float current, float dt);
|
||||
float perevod(float pid_result);
|
||||
|
||||
extern float KP;
|
||||
extern float KI;
|
||||
extern float KD;
|
||||
extern float integral;
|
||||
extern float lastError;
|
||||
extern float limit; // ограничение интегральной составляющей
|
||||
extern float target; // желаемое значение(вертикально)
|
@ -1,12 +1,111 @@
|
||||
#include "stm32g4xx.h"
|
||||
#include "stm32g431xx.h"
|
||||
#include <math.h>
|
||||
#include "LSM6DS3.h"
|
||||
#include "PID.h"
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// PС11 - I2C3_SDA
|
||||
// PA8 - I2C3_SCL
|
||||
//
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
volatile uint32_t counter = 0;
|
||||
float res;
|
||||
float u;
|
||||
extern "C" void TIM2_IRQHandler(void)
|
||||
{
|
||||
if (TIM2->SR & TIM_SR_UIF) // Проверить флаг обновления
|
||||
{
|
||||
TIM2->SR &= ~TIM_SR_UIF; // Сбросить флаг
|
||||
|
||||
counter++;
|
||||
|
||||
// Чтение данных акселерометра
|
||||
LSM6DS3_ReadAccelerometer(&acc_x, &acc_y, &acc_z);
|
||||
// Чтение данных гироскопа
|
||||
LSM6DS3_ReadGyroscope(&gyro_x, &gyro_y, &gyro_z);
|
||||
|
||||
Filter_SensorData();
|
||||
Complementary_Filter();
|
||||
|
||||
u = pid_update(target, angle_pitch, DT);
|
||||
if (fabsf(u) < 0.001f){
|
||||
u = 0.001f;
|
||||
}
|
||||
res = (48/u);
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
int main()
|
||||
{
|
||||
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOCEN;
|
||||
GPIOC->MODER &= ~(GPIO_MODER_MODE6_Msk);
|
||||
GPIOC->MODER |= GPIO_MODER_MODER6_0;
|
||||
GPIOC->BSRR = GPIO_BSRR_BS6;
|
||||
while(1)
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN; // тактирование порт A
|
||||
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOCEN; // тактирование порт C
|
||||
RCC->APB1ENR1 |= RCC_APB1ENR1_I2C3EN; // тактирование I2C3
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
GPIOC->MODER &= ~GPIO_MODER_MODE6_Msk; // очистка пина C6 - использую под LED
|
||||
GPIOC->MODER &= ~GPIO_MODER_MODE11_Msk; // очистка пина C11
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE8_Msk; // очистка пина A8
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
GPIOC->MODER |= GPIO_MODER_MODE6_0; // установка бита выхода
|
||||
GPIOA->MODER |= GPIO_MODER_MODE8_1; // установка бита режима альтернативной функции
|
||||
GPIOC->MODER |= GPIO_MODER_MODE11_1; // установка бита режима альтернативной функции
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
GPIOC->BSRR = GPIO_BSRR_BS6; // установка в высокий C6
|
||||
//------------------------------------------------------------------------- ----------------------------------
|
||||
RCC->APB1ENR1 |= RCC_APB1ENR1_TIM2EN; // Включить тактирование TIM2
|
||||
TIM2->PSC = 16 - 1; // Предделитель 16 МГц / 16 = 1000 кГц
|
||||
TIM2->ARR = 1000 - 1; // Автоматическая перезагрузка (0.001 секунда)
|
||||
TIM2->DIER |= TIM_DIER_UIE; // Разрешить прерывание по обновлению
|
||||
TIM2->CR1 |= TIM_CR1_CEN; // Включить таймер
|
||||
NVIC_EnableIRQ(TIM2_IRQn);
|
||||
NVIC_SetPriority(TIM2_IRQn, 15); // Уровень приоритета
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
GPIOA->OTYPER &= ~GPIO_OTYPER_OT8_Msk; // Сброс режима
|
||||
GPIOC->OTYPER &= ~GPIO_OTYPER_OT11_Msk; // Сброс режима
|
||||
GPIOA->OTYPER |= GPIO_OTYPER_OT8; // Установка в Open-Drain
|
||||
GPIOC->OTYPER |= GPIO_OTYPER_OT11; // Установка в Open-Drain
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR8; // сброс скорости пина
|
||||
GPIOC->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR11; // сброс скорости пина
|
||||
GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR8_1; // установка в высокую скорость
|
||||
GPIOC->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR11_1; // установка в высокую скорость
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD8_Msk; // очистка подтяжки
|
||||
GPIOC->PUPDR &= ~GPIO_PUPDR_PUPD11_Msk; // очистка подтяжки
|
||||
GPIOA->PUPDR |= GPIO_PUPDR_PUPD8_1; // вклчюение подтяжки PULL_UP
|
||||
GPIOC->PUPDR |= GPIO_PUPDR_PUPD11_1; // вклчюение подтяжки PULL_UP
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
GPIOA->AFR[1] &= ~GPIO_AFRH_AFSEL8_Msk; // сброс альтернативной функции
|
||||
GPIOC->AFR[1] &= ~GPIO_AFRH_AFSEL11_Msk; // сброс альтернативной функции
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
GPIOA->AFR[1] |= (2U << GPIO_AFRH_AFSEL8_Pos); // установка AF2
|
||||
GPIOC->AFR[1] |= (8U << GPIO_AFRH_AFSEL11_Pos); // Установка AF8
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
I2C3->CR1 &= ~I2C_CR1_PE; // Отключение I2C3
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
// 400 кГц
|
||||
I2C3->TIMINGR = (0 << I2C_TIMINGR_PRESC_Pos) | // PRESC=0 (делитель 1) -> I2CCLK=16 МГц
|
||||
(3 << I2C_TIMINGR_SCLDEL_Pos) | // SCLDEL=3 -> t_HD;STA=0.25 мкс
|
||||
(1 << I2C_TIMINGR_SDADEL_Pos) | // SDADEL=1 -> t_HD;DAT=0.0625 мкс
|
||||
(15 << I2C_TIMINGR_SCLH_Pos) | // SCLH=15 -> t_HIGH=1 мкс
|
||||
(15 << I2C_TIMINGR_SCLL_Pos); // SCLL=15 -> t_LOW=1 мкс
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
I2C3->CR1 |= I2C_CR1_PE; // Включение I2C3
|
||||
for (volatile int i = 0; i < 100000; ++i)
|
||||
; // задержка
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
while (I2C3->ISR & I2C_ISR_BUSY)
|
||||
__NOP(); // Ждём освобождения линии I2C3
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
LSM6DS3_Init();
|
||||
while (1)
|
||||
{
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user