Compare commits

...

5 Commits

Author SHA1 Message Date
8f4e8b627b Добавлено пересечение нуля. Алг проверен в матлаб
+заготовки для статичтики АЦП и глобальной переменной микросекундых тиков
2025-11-11 00:36:15 +03:00
4491f11b3d Тесты фильтрования
Оно добавляют задержку и сдвиг по фазе надо чет думать
2025-11-10 07:55:07 +03:00
79ff2667c4 Всякие фиксы модели и заготовки для АЦП
И почему то все равно MATLAB намертво блокирует mingw64.... Приходится перезапускать матлаб для перекомпиляции
2025-11-09 21:04:52 +03:00
be84043f18 Добавлена простенькая симуляция АЦП в сканирующем режиме.
Но надо отлаживать и сравнивать с работой реального (в плане разных режимов работы, доделать прерывания/дма, флаги и так далее)
2025-11-09 02:06:25 +03:00
61202f2a94 Добавлены ПДФки для удобства 2025-11-09 02:04:02 +03:00
83 changed files with 3594 additions and 351 deletions

4
.gitignore vendored
View File

@ -58,3 +58,7 @@ JLinkLog.txt
# VS Code Generated Files
/.vs/
/MATLAB/MCU.exp
/MATLAB/MCU.lib
/MATLAB/MCU.mexw64.manifest
/MATLAB/upp_r2023.slx.autosave

View File

@ -262,8 +262,8 @@ typedef struct
{
__IO uint32_t CCR;
__IO uint32_t CNDTR;
__IO uint32_t CPAR;
__IO uint32_t CMAR;
__IO uint64_t CPAR;
__IO uint64_t CMAR;
} DMA_Channel_TypeDef;
typedef struct

View File

@ -310,8 +310,8 @@ typedef struct
{
__IO uint32_t CCR;
__IO uint32_t CNDTR;
__IO uint32_t CPAR;
__IO uint32_t CMAR;
__IO uint64_t CPAR;
__IO uint64_t CMAR;
} DMA_Channel_TypeDef;
typedef struct

View File

@ -215,8 +215,8 @@ typedef struct
{
__IO uint32_t CCR;
__IO uint32_t CNDTR;
__IO uint32_t CPAR;
__IO uint32_t CMAR;
__IO uint64_t CPAR;
__IO uint64_t CMAR;
} DMA_Channel_TypeDef;
typedef struct

View File

@ -220,8 +220,8 @@ typedef struct
{
__IO uint32_t CCR;
__IO uint32_t CNDTR;
__IO uint32_t CPAR;
__IO uint32_t CMAR;
__IO uint64_t CPAR;
__IO uint64_t CMAR;
} DMA_Channel_TypeDef;
typedef struct

View File

@ -284,8 +284,8 @@ typedef struct
{
__IO uint32_t CCR;
__IO uint32_t CNDTR;
__IO uint32_t CPAR;
__IO uint32_t CMAR;
__IO uint64_t CPAR;
__IO uint64_t CMAR;
} DMA_Channel_TypeDef;
typedef struct

View File

@ -290,8 +290,8 @@ typedef struct
{
__IO uint32_t CCR;
__IO uint32_t CNDTR;
__IO uint32_t CPAR;
__IO uint32_t CMAR;
__IO uint64_t CPAR;
__IO uint64_t CMAR;
} DMA_Channel_TypeDef;
typedef struct

View File

@ -218,8 +218,8 @@ typedef struct
{
__IO uint32_t CCR;
__IO uint32_t CNDTR;
__IO uint32_t CPAR;
__IO uint32_t CMAR;
__IO uint64_t CPAR;
__IO uint64_t CMAR;
} DMA_Channel_TypeDef;
typedef struct

View File

@ -223,8 +223,8 @@ typedef struct
{
__IO uint32_t CCR;
__IO uint32_t CNDTR;
__IO uint32_t CPAR;
__IO uint32_t CMAR;
__IO uint64_t CPAR;
__IO uint64_t CMAR;
} DMA_Channel_TypeDef;
typedef struct

View File

@ -287,8 +287,8 @@ typedef struct
{
__IO uint32_t CCR;
__IO uint32_t CNDTR;
__IO uint32_t CPAR;
__IO uint32_t CMAR;
__IO uint64_t CPAR;
__IO uint64_t CMAR;
} DMA_Channel_TypeDef;
typedef struct

View File

@ -293,8 +293,8 @@ typedef struct
{
__IO uint32_t CCR;
__IO uint32_t CNDTR;
__IO uint32_t CPAR;
__IO uint32_t CMAR;
__IO uint64_t CPAR;
__IO uint64_t CMAR;
} DMA_Channel_TypeDef;
typedef struct
@ -592,7 +592,7 @@ typedef struct _memory
{
//uint8_t RESERVED[FLASH_BASE_SHIFT];
uint8_t FLASH_BASE[FLASH_SIZE];
uint8_t FLASH_BASE[10];
uint8_t FLASH_BANK1_END[10];
uint8_t SRAM_BASE[SRAM_SIZE];
uint8_t SRAM_BB_BASE[SRAM_SIZE];

View File

@ -362,8 +362,8 @@ typedef struct
{
__IO uint32_t CCR;
__IO uint32_t CNDTR;
__IO uint32_t CPAR;
__IO uint32_t CMAR;
__IO uint64_t CPAR;
__IO uint64_t CMAR;
} DMA_Channel_TypeDef;
typedef struct

View File

@ -362,8 +362,8 @@ typedef struct
{
__IO uint32_t CCR;
__IO uint32_t CNDTR;
__IO uint32_t CPAR;
__IO uint32_t CMAR;
__IO uint64_t CPAR;
__IO uint64_t CMAR;
} DMA_Channel_TypeDef;
typedef struct

View File

@ -361,8 +361,8 @@ typedef struct
{
__IO uint32_t CCR;
__IO uint32_t CNDTR;
__IO uint32_t CPAR;
__IO uint32_t CMAR;
__IO uint64_t CPAR;
__IO uint64_t CMAR;
} DMA_Channel_TypeDef;
typedef struct

View File

@ -363,8 +363,8 @@ typedef struct
{
__IO uint32_t CCR;
__IO uint32_t CNDTR;
__IO uint32_t CPAR;
__IO uint32_t CMAR;
__IO uint64_t CPAR;
__IO uint64_t CMAR;
} DMA_Channel_TypeDef;
typedef struct

View File

@ -223,9 +223,9 @@ typedef struct
{
__IO uint32_t CR; /*!< DMA stream x configuration register */
__IO uint32_t NDTR; /*!< DMA stream x number of data register */
__IO uint32_t PAR; /*!< DMA stream x peripheral address register */
__IO uint32_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint32_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint64_t PAR; /*!< DMA stream x peripheral address register */
__IO uint64_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint64_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint32_t FCR; /*!< DMA stream x FIFO control register */
} DMA_Stream_TypeDef;

View File

@ -223,9 +223,9 @@ typedef struct
{
__IO uint32_t CR; /*!< DMA stream x configuration register */
__IO uint32_t NDTR; /*!< DMA stream x number of data register */
__IO uint32_t PAR; /*!< DMA stream x peripheral address register */
__IO uint32_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint32_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint64_t PAR; /*!< DMA stream x peripheral address register */
__IO uint64_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint64_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint32_t FCR; /*!< DMA stream x FIFO control register */
} DMA_Stream_TypeDef;

View File

@ -334,9 +334,9 @@ typedef struct
{
__IO uint32_t CR; /*!< DMA stream x configuration register */
__IO uint32_t NDTR; /*!< DMA stream x number of data register */
__IO uint32_t PAR; /*!< DMA stream x peripheral address register */
__IO uint32_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint32_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint64_t PAR; /*!< DMA stream x peripheral address register */
__IO uint64_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint64_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint32_t FCR; /*!< DMA stream x FIFO control register */
} DMA_Stream_TypeDef;

View File

@ -358,9 +358,9 @@ typedef struct
{
__IO uint32_t CR; /*!< DMA stream x configuration register */
__IO uint32_t NDTR; /*!< DMA stream x number of data register */
__IO uint32_t PAR; /*!< DMA stream x peripheral address register */
__IO uint32_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint32_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint64_t PAR; /*!< DMA stream x peripheral address register */
__IO uint64_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint64_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint32_t FCR; /*!< DMA stream x FIFO control register */
} DMA_Stream_TypeDef;

View File

@ -241,9 +241,9 @@ typedef struct
{
__IO uint32_t CR; /*!< DMA stream x configuration register */
__IO uint32_t NDTR; /*!< DMA stream x number of data register */
__IO uint32_t PAR; /*!< DMA stream x peripheral address register */
__IO uint32_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint32_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint64_t PAR; /*!< DMA stream x peripheral address register */
__IO uint64_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint64_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint32_t FCR; /*!< DMA stream x FIFO control register */
} DMA_Stream_TypeDef;

View File

@ -241,9 +241,9 @@ typedef struct
{
__IO uint32_t CR; /*!< DMA stream x configuration register */
__IO uint32_t NDTR; /*!< DMA stream x number of data register */
__IO uint32_t PAR; /*!< DMA stream x peripheral address register */
__IO uint32_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint32_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint64_t PAR; /*!< DMA stream x peripheral address register */
__IO uint64_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint64_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint32_t FCR; /*!< DMA stream x FIFO control register */
} DMA_Stream_TypeDef;

View File

@ -238,9 +238,9 @@ typedef struct
{
__IO uint32_t CR; /*!< DMA stream x configuration register */
__IO uint32_t NDTR; /*!< DMA stream x number of data register */
__IO uint32_t PAR; /*!< DMA stream x peripheral address register */
__IO uint32_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint32_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint64_t PAR; /*!< DMA stream x peripheral address register */
__IO uint64_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint64_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint32_t FCR; /*!< DMA stream x FIFO control register */
} DMA_Stream_TypeDef;

View File

@ -224,9 +224,9 @@ typedef struct
{
__IO uint32_t CR; /*!< DMA stream x configuration register */
__IO uint32_t NDTR; /*!< DMA stream x number of data register */
__IO uint32_t PAR; /*!< DMA stream x peripheral address register */
__IO uint32_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint32_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint64_t PAR; /*!< DMA stream x peripheral address register */
__IO uint64_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint64_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint32_t FCR; /*!< DMA stream x FIFO control register */
} DMA_Stream_TypeDef;

View File

@ -344,9 +344,9 @@ typedef struct
{
__IO uint32_t CR; /*!< DMA stream x configuration register */
__IO uint32_t NDTR; /*!< DMA stream x number of data register */
__IO uint32_t PAR; /*!< DMA stream x peripheral address register */
__IO uint32_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint32_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint64_t PAR; /*!< DMA stream x peripheral address register */
__IO uint64_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint64_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint32_t FCR; /*!< DMA stream x FIFO control register */
} DMA_Stream_TypeDef;

View File

@ -345,9 +345,9 @@ typedef struct
{
__IO uint32_t CR; /*!< DMA stream x configuration register */
__IO uint32_t NDTR; /*!< DMA stream x number of data register */
__IO uint32_t PAR; /*!< DMA stream x peripheral address register */
__IO uint32_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint32_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint64_t PAR; /*!< DMA stream x peripheral address register */
__IO uint64_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint64_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint32_t FCR; /*!< DMA stream x FIFO control register */
} DMA_Stream_TypeDef;

View File

@ -345,9 +345,9 @@ typedef struct
{
__IO uint32_t CR; /*!< DMA stream x configuration register */
__IO uint32_t NDTR; /*!< DMA stream x number of data register */
__IO uint32_t PAR; /*!< DMA stream x peripheral address register */
__IO uint32_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint32_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint64_t PAR; /*!< DMA stream x peripheral address register */
__IO uint64_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint64_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint32_t FCR; /*!< DMA stream x FIFO control register */
} DMA_Stream_TypeDef;

View File

@ -345,9 +345,9 @@ typedef struct
{
__IO uint32_t CR; /*!< DMA stream x configuration register */
__IO uint32_t NDTR; /*!< DMA stream x number of data register */
__IO uint32_t PAR; /*!< DMA stream x peripheral address register */
__IO uint32_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint32_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint64_t PAR; /*!< DMA stream x peripheral address register */
__IO uint64_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint64_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint32_t FCR; /*!< DMA stream x FIFO control register */
} DMA_Stream_TypeDef;

View File

@ -383,9 +383,9 @@ typedef struct
{
__IO uint32_t CR; /*!< DMA stream x configuration register */
__IO uint32_t NDTR; /*!< DMA stream x number of data register */
__IO uint32_t PAR; /*!< DMA stream x peripheral address register */
__IO uint32_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint32_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint64_t PAR; /*!< DMA stream x peripheral address register */
__IO uint64_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint64_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint32_t FCR; /*!< DMA stream x FIFO control register */
} DMA_Stream_TypeDef;

View File

@ -333,9 +333,9 @@ typedef struct
{
__IO uint32_t CR; /*!< DMA stream x configuration register */
__IO uint32_t NDTR; /*!< DMA stream x number of data register */
__IO uint32_t PAR; /*!< DMA stream x peripheral address register */
__IO uint32_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint32_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint64_t PAR; /*!< DMA stream x peripheral address register */
__IO uint64_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint64_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint32_t FCR; /*!< DMA stream x FIFO control register */
} DMA_Stream_TypeDef;

View File

@ -354,9 +354,9 @@ typedef struct
{
__IO uint32_t CR; /*!< DMA stream x configuration register */
__IO uint32_t NDTR; /*!< DMA stream x number of data register */
__IO uint32_t PAR; /*!< DMA stream x peripheral address register */
__IO uint32_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint32_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint64_t PAR; /*!< DMA stream x peripheral address register */
__IO uint64_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint64_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint32_t FCR; /*!< DMA stream x FIFO control register */
} DMA_Stream_TypeDef;

View File

@ -384,9 +384,9 @@ typedef struct
{
__IO uint32_t CR; /*!< DMA stream x configuration register */
__IO uint32_t NDTR; /*!< DMA stream x number of data register */
__IO uint32_t PAR; /*!< DMA stream x peripheral address register */
__IO uint32_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint32_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint64_t PAR; /*!< DMA stream x peripheral address register */
__IO uint64_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint64_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint32_t FCR; /*!< DMA stream x FIFO control register */
} DMA_Stream_TypeDef;

View File

@ -360,9 +360,9 @@ typedef struct
{
__IO uint32_t CR; /*!< DMA stream x configuration register */
__IO uint32_t NDTR; /*!< DMA stream x number of data register */
__IO uint32_t PAR; /*!< DMA stream x peripheral address register */
__IO uint32_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint32_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint64_t PAR; /*!< DMA stream x peripheral address register */
__IO uint64_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint64_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint32_t FCR; /*!< DMA stream x FIFO control register */
} DMA_Stream_TypeDef;

View File

@ -362,9 +362,9 @@ typedef struct
{
__IO uint32_t CR; /*!< DMA stream x configuration register */
__IO uint32_t NDTR; /*!< DMA stream x number of data register */
__IO uint32_t PAR; /*!< DMA stream x peripheral address register */
__IO uint32_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint32_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint64_t PAR; /*!< DMA stream x peripheral address register */
__IO uint64_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint64_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint32_t FCR; /*!< DMA stream x FIFO control register */
} DMA_Stream_TypeDef;

View File

@ -361,9 +361,9 @@ typedef struct
{
__IO uint32_t CR; /*!< DMA stream x configuration register */
__IO uint32_t NDTR; /*!< DMA stream x number of data register */
__IO uint32_t PAR; /*!< DMA stream x peripheral address register */
__IO uint32_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint32_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint64_t PAR; /*!< DMA stream x peripheral address register */
__IO uint64_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint64_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint32_t FCR; /*!< DMA stream x FIFO control register */
} DMA_Stream_TypeDef;

View File

@ -363,9 +363,9 @@ typedef struct
{
__IO uint32_t CR; /*!< DMA stream x configuration register */
__IO uint32_t NDTR; /*!< DMA stream x number of data register */
__IO uint32_t PAR; /*!< DMA stream x peripheral address register */
__IO uint32_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint32_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint64_t PAR; /*!< DMA stream x peripheral address register */
__IO uint64_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint64_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint32_t FCR; /*!< DMA stream x FIFO control register */
} DMA_Stream_TypeDef;

View File

@ -372,9 +372,9 @@ typedef struct
{
__IO uint32_t CR; /*!< DMA stream x configuration register */
__IO uint32_t NDTR; /*!< DMA stream x number of data register */
__IO uint32_t PAR; /*!< DMA stream x peripheral address register */
__IO uint32_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint32_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint64_t PAR; /*!< DMA stream x peripheral address register */
__IO uint64_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint64_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint32_t FCR; /*!< DMA stream x FIFO control register */
} DMA_Stream_TypeDef;

View File

@ -364,9 +364,9 @@ typedef struct
{
__IO uint32_t CR; /*!< DMA stream x configuration register */
__IO uint32_t NDTR; /*!< DMA stream x number of data register */
__IO uint32_t PAR; /*!< DMA stream x peripheral address register */
__IO uint32_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint32_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint64_t PAR; /*!< DMA stream x peripheral address register */
__IO uint64_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint64_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint32_t FCR; /*!< DMA stream x FIFO control register */
} DMA_Stream_TypeDef;

View File

@ -365,9 +365,9 @@ typedef struct
{
__IO uint32_t CR; /*!< DMA stream x configuration register */
__IO uint32_t NDTR; /*!< DMA stream x number of data register */
__IO uint32_t PAR; /*!< DMA stream x peripheral address register */
__IO uint32_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint32_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint64_t PAR; /*!< DMA stream x peripheral address register */
__IO uint64_t M0AR; /*!< DMA stream x memory 0 address register */
__IO uint64_t M1AR; /*!< DMA stream x memory 1 address register */
__IO uint32_t FCR; /*!< DMA stream x FIFO control register */
} DMA_Stream_TypeDef;

View File

@ -27,7 +27,7 @@
#endif
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE static __forceinline
#define __STATIC_FORCEINLINE //static __forceinline
#endif
#ifndef __NO_RETURN
@ -91,10 +91,15 @@
#define __CLZ
#define __CTZ
#define __RBIT
#ifdef __MINGW64__
#ifndef __weak
#define __weak __attribute__((weak))
#endif
#else
#ifndef __weak
#define __weak
#endif
#endif
#define __DSB()
#define __ISB()
#define __NOP()

View File

@ -0,0 +1,351 @@
#include "stm32_matlab_adc.h"
#include "stm32_matlab_dma.h"
#include <string.h>
/////////////////////////////---SIMULINK FUNCTIONS---//////////////////////////
void Simulate_ADCs(void)
{
#ifdef USE_ADC1
ADC_Simulation(ADC1, &adc1s);
#endif
#ifdef USE_ADC2
ADC_Simulation(ADC2, &adc2s);
#endif
#ifdef USE_ADC3
ADC_Simulation(ADC3, &adc3s);
#endif
}
/////////////////////////////---ADC SIMULATION---/////////////////////////////
void ADC_Simulation(ADC_TypeDef* ADCx, struct ADC_Sim* ADCS)
{
if (!(ADCx->CR2 & ADC_CR2_ADON)) return;
// ПЕРВОЕ: Проверка внешнего триггера (для режима по триггеру)
if (!(ADCx->CR2 & ADC_CR2_CONT)) { // Только если не continuous mode
ADC_Check_External_Trigger(ADCx, ADCS);
}
// ВТОРОЕ: Software trigger
if (ADCx->CR2 & ADC_CR2_SWSTART) {
ADC_Start_Conversion(ADCx, ADCS);
ADCx->CR2 &= ~ADC_CR2_SWSTART;
}
// ТРЕТЬЕ: Обработка текущего преобразования
if (ADCS->conversion_time_elapsed >= 0) {
ADCS->conversion_time_elapsed += ADCS->simulation_step;
// ИСПОЛЬЗУЕМ ОБЩЕЕ ВРЕМЯ ДЛЯ ВСЕЙ ПОСЛЕДОВАТЕЛЬНОСТИ
double total_time = ADC_Get_Total_Sequence_Time(ADCx, ADCS);
if (ADCS->conversion_time_elapsed >= total_time) {
ADC_Complete_Conversion(ADCx, ADCS); // Обрабатываем ВСЕ каналы
// Continuous mode auto-restart
if (ADCx->CR2 & ADC_CR2_CONT) {
ADC_Start_Conversion(ADCx, ADCS);
}
}
}
}
void ADC_Start_Conversion(ADC_TypeDef* ADCx, struct ADC_Sim* ADCS)
{
// Определяем канал для конверсии
if (ADCx->CR1 & ADC_CR1_SCAN) {
// Режим сканирования
ADCS->current_rank = 0;
ADCS->current_channel = ADC_Get_Sequence_Channel(ADCx, 0);
}
else {
// Одиночный канал
ADCS->current_channel = ADC_Get_Sequence_Channel(ADCx, 0);
}
ADCS->conversion_time_elapsed = 0;
}
void ADC_Complete_Conversion(ADC_TypeDef* ADCx, struct ADC_Sim* ADCS)
{
uint32_t seq_len = ADC_Get_Sequence_Length(ADCx);
// Обрабатываем ВСЕ каналы последовательности за один вызов
for (uint32_t rank = 0; rank < seq_len; rank++) {
uint32_t channel = ADC_Get_Sequence_Channel(ADCx, rank);
// 1. Конвертируем один канал
double analog_val = 0;
if (ADCS->channel_connected[channel]) {
analog_val = ADCS->channel_values[channel];
}
if (analog_val < 0) analog_val = 0;
if (analog_val > 3.3) analog_val = 3.3;
// Вычисляем значение АЦП
ADCS->last_conversion_value = (uint16_t)((analog_val / 3.3) * 4095.0);
// Добавляем шум
int32_t noisy_value = (int32_t)ADCS->last_conversion_value + (rand() % (2 * ADC_NOISE_LSB + 1)) - ADC_NOISE_LSB;
if (noisy_value < 0) noisy_value = 0;
if (noisy_value > 4095) noisy_value = 4095;
ADCS->last_conversion_value = (uint16_t)noisy_value;
// 2. Записываем в DR
ADCx->DR = ADCS->last_conversion_value;
// 3. Устанавливаем флаг EOC
ADCx->SR |= ADC_SR_EOC;
// 4. СРАЗУ вызываем DMA для этой конверсии
if (ADCx->CR2 & ADC_CR2_DMA) {
if (ADCx == ADC3) {
DMA_Sim_Transfer(DMA2, 0); // Выполняем одну передачу
}
else if (ADCx == ADC1) {
DMA_Sim_Transfer(DMA2, 4); // Для ADC1
}
}
}
// Устанавливаем EOS в конце последовательности
ADCx->SR |= ADC_SR_EOC;
ADCS->conversion_time_elapsed = -1;
}
/////////////////////////////---TIMER TRIGGER SUPPORT---//////////////////////////
uint8_t ADC_Check_Timer_Trigger(ADC_TypeDef* ADCx, uint32_t trigger_source)
{
// Анализируем источник триггера из регистров ADC
switch (trigger_source) {
#ifdef ADC_EXTERNALTRIGCONV_T2_TRGO
case ADC_EXTERNALTRIGCONV_T2_TRGO:
return Slave_Channels.TIM2_TRGO;
#endif
#ifdef ADC_EXTERNALTRIGCONV_T3_TRGO
case ADC_EXTERNALTRIGCONV_T3_TRGO:
return Slave_Channels.TIM3_TRGO;
#endif
#ifdef ADC_EXTERNALTRIGCONV_T8_TRGO
case ADC_EXTERNALTRIGCONV_T8_TRGO:
return Slave_Channels.TIM8_TRGO;
#endif
#ifdef ADC_EXTERNALTRIGCONV_T1_CC1
case ADC_EXTERNALTRIGCONV_T1_CC1:
#endif
#ifdef ADC_EXTERNALTRIGCONV_T1_CC2
case ADC_EXTERNALTRIGCONV_T1_CC2:
#endif
#ifdef ADC_EXTERNALTRIGCONV_T1_CC3
case ADC_EXTERNALTRIGCONV_T1_CC3:
#endif
#ifdef ADC_EXTERNALTRIGCONV_T2_CC2
case ADC_EXTERNALTRIGCONV_T2_CC2:
#endif
#ifdef ADC_EXTERNALTRIGCONV_T2_CC3
case ADC_EXTERNALTRIGCONV_T2_CC3:
#endif
#ifdef ADC_EXTERNALTRIGCONV_T2_CC4
case ADC_EXTERNALTRIGCONV_T2_CC4:
#endif
#ifdef ADC_EXTERNALTRIGCONV_T3_CC1
case ADC_EXTERNALTRIGCONV_T3_CC1:
#endif
#ifdef ADC_EXTERNALTRIGCONV_T4_CC4
case ADC_EXTERNALTRIGCONV_T4_CC4:
#endif
#ifdef ADC_EXTERNALTRIGCONV_T5_CC1
case ADC_EXTERNALTRIGCONV_T5_CC1:
#endif
#ifdef ADC_EXTERNALTRIGCONV_T5_CC2
case ADC_EXTERNALTRIGCONV_T5_CC2:
#endif
#ifdef ADC_EXTERNALTRIGCONV_T5_CC3
case ADC_EXTERNALTRIGCONV_T5_CC3:
#endif
#ifdef ADC_EXTERNALTRIGCONV_T8_CC1
case ADC_EXTERNALTRIGCONV_T8_CC1:
#endif
#ifdef ADC_EXTERNALTRIGCONV_Ext_IT11
case ADC_EXTERNALTRIGCONV_Ext_IT11:
#endif
default:
return 0;
}
}
void ADC_Check_External_Trigger(ADC_TypeDef* ADCx, struct ADC_Sim* ADCS)
{
#ifdef STM32F1
// Для STM32F1 проверяем бит EXTTRIG
if (!(ADCx->CR2 & ADC_CR2_EXTTRIG)) return;
// Получаем источник триггера и фронт
uint32_t trigger_source = (ADCx->CR2 & ADC_CR2_EXTSEL); // Для F1 EXTSEL[2:0] биты 19:17
uint32_t trigger_edge = (ADCx->CR2 & ADC_CR2_EXTTRIG) ? 1 : 0; // Для F1 просто включен/выключен
#elif defined(STM32F4)
// Для STM32F4 проверяем EXTEN и EXTSEL
if (!(ADCx->CR2 & ADC_CR2_EXTEN)) return; // Для F4 проверяем EXTEN
// Получаем источник триггера и фронт
uint32_t trigger_source = (ADCx->CR2 & ADC_CR2_EXTSEL);
uint32_t trigger_edge = (ADCx->CR2 & ADC_CR2_EXTEN);
#else
return; // Неподдерживаемая платформа
#endif
uint8_t current_trigger_state = ADC_Check_Timer_Trigger(ADCx, trigger_source);
uint8_t trigger_occurred = 0;
#ifdef STM32F1
// Для F1 - простой rising edge при наличии триггера
if (trigger_edge) {
trigger_occurred = current_trigger_state && !ADCS->last_trigger_state;
}
#endif
#ifdef STM32F4
switch (trigger_edge)
{
case ADC_EXTERNALTRIGCONVEDGE_RISING:
trigger_occurred = current_trigger_state && !ADCS->last_trigger_state;
break;
case ADC_EXTERNALTRIGCONVEDGE_FALLING:
trigger_occurred = !current_trigger_state && ADCS->last_trigger_state;
break;
case ADC_EXTERNALTRIGCONVEDGE_RISINGFALLING:
trigger_occurred = (current_trigger_state && !ADCS->last_trigger_state) ||
(!current_trigger_state && ADCS->last_trigger_state);
break;
default:
break;
}
#endif
if (trigger_occurred) {
ADC_Start_Conversion(ADCx, ADCS);
}
ADCS->last_trigger_state = current_trigger_state;
}
/////////////////////////////---REGISTER-BASED FUNCTIONS---///////////////////
double ADC_Get_Total_Conversion_Time(ADC_TypeDef* ADCx, struct ADC_Sim* ADCS)
{
// Получаем sampling time из регистров
uint32_t sampling_cycles = ADC_Get_Sampling_Cycles(ADCx, ADCS->current_channel);
// Conversion cycles фиксированы для разрешения
uint32_t conversion_cycles = 12; // Для 12-bit
double total_cycles = sampling_cycles + conversion_cycles;
double adc_clock = ADCS->adc_clock_freq; // Частота шины
return total_cycles / adc_clock;
}
double ADC_Get_Total_Sequence_Time(ADC_TypeDef* ADCx, struct ADC_Sim* ADCS)
{
uint32_t total_cycles = 0;
uint32_t seq_len = ADC_Get_Sequence_Length(ADCx);
for (uint32_t rank = 0; rank < seq_len; rank++) {
uint32_t channel = ADC_Get_Sequence_Channel(ADCx, rank);
uint32_t sampling_cycles = ADC_Get_Sampling_Cycles(ADCx, channel);
total_cycles += sampling_cycles + 12; // sampling + conversion
}
return total_cycles / ADCS->adc_clock_freq;
}
uint32_t ADC_Get_Sampling_Cycles(ADC_TypeDef* ADCx, uint32_t channel)
{
// Получаем sampling time из SMPR1/SMPR2
uint32_t smpr_code;
if (channel <= 9) {
smpr_code = (ADCx->SMPR2 >> (channel * 3)) & 0x7;
}
else {
smpr_code = (ADCx->SMPR1 >> ((channel - 10) * 3)) & 0x7;
}
// Convert SMPR code to actual cycles
static const uint32_t cycles_map[8] = { 3, 15, 28, 56, 84, 112, 144, 480 };
return (smpr_code < 8) ? cycles_map[smpr_code] : 3;
}
uint32_t ADC_Get_Sequence_Length(ADC_TypeDef* ADCx)
{
#ifdef ADC_SQR1_L
return ((ADCx->SQR1 & ADC_SQR1_L) >> ADC_SQR1_L_Pos) + 1;
#else
return ((ADCx->SQR1 & 0x00F00000) >> 20) + 1;
#endif
}
uint32_t ADC_Get_Sequence_Channel(ADC_TypeDef* ADCx, uint32_t rank)
{
if (rank > 15) return 0;
if (rank < 6) {
return (ADCx->SQR3 >> (rank * 5)) & 0x1F;
}
else if (rank < 12) {
return (ADCx->SQR2 >> ((rank - 6) * 5)) & 0x1F;
}
else {
return (ADCx->SQR1 >> ((rank - 12) * 5)) & 0x1F;
}
}
/////////////////////////////---CHANNEL FUNCTIONS---///////////////////////////
void ADC_Set_Channel_Value(ADC_TypeDef* ADCx, uint32_t channel, double voltage)
{
#ifdef USE_ADC1
if (ADCx == ADC1 && channel < 19) {
adc1s.channel_values[channel] = voltage;
adc1s.channel_connected[channel] = 1;
}
#endif
#ifdef USE_ADC2
if (ADCx == ADC2 && channel < 19) {
adc2s.channel_values[channel] = voltage;
adc2s.channel_connected[channel] = 1;
}
#endif
#ifdef USE_ADC3
if (ADCx == ADC3 && channel < 19) {
adc3s.channel_values[channel] = voltage;
adc3s.channel_connected[channel] = 1;
}
#endif
}
/////////////////////////////---INITIALIZATION---/////////////////////////////
void ADC_SIM_DEINIT(void)
{
#ifdef USE_ADC1
memset(&adc1s, 0, sizeof(adc1s));
#endif
#ifdef USE_ADC2
memset(&adc2s, 0, sizeof(adc2s));
#endif
#ifdef USE_ADC3
memset(&adc3s, 0, sizeof(adc3s));
#endif
}
///////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,57 @@
#ifndef _MATLAB_ADC_H_
#define _MATLAB_ADC_H_
#include "stm32_matlab_conf.h"
#ifdef STM32F1
#define ADC_NOISE_LSB 30 // Большой шум STMF103 в LSB (квантах АЦП)
#endif
#ifdef STM32F4
#define ADC_NOISE_LSB 20 // Шум в LSB (квантах АЦП)
#endif
/////////////////////////////---STRUCTURES---///////////////////////////
struct ADC_Sim
{
double conversion_time_elapsed;
uint32_t current_channel;
uint32_t current_rank;
uint16_t last_conversion_value;
double channel_values[19];
uint8_t channel_connected[19];
// Timing
double simulation_step;
double adc_clock_freq;
// Добавьте для поддержки триггеров
uint8_t external_trigger_enabled;
uint32_t trigger_source;
uint8_t last_trigger_state;
};
///////////////////////////////////////////////////////////////////////
///////////////////////////---FUNCTIONS---///////////////////////////
void Simulate_ADCs(void);
void ADC_Simulation(ADC_TypeDef* ADCx, struct ADC_Sim* ADCS);
void ADC_Start_Conversion(ADC_TypeDef* ADCx, struct ADC_Sim* ADCS);
void ADC_Complete_Conversion(ADC_TypeDef* ADCx, struct ADC_Sim* ADCS);
void ADC_Check_External_Trigger(ADC_TypeDef* ADCx, struct ADC_Sim* ADCS);
double ADC_Get_Total_Conversion_Time(ADC_TypeDef* ADCx, struct ADC_Sim* ADCS);
double ADC_Get_Total_Sequence_Time(ADC_TypeDef* ADCx, struct ADC_Sim* ADCS);
uint32_t ADC_Get_Sampling_Cycles(ADC_TypeDef* ADCx, uint32_t channel);
uint32_t ADC_Get_Sequence_Length(ADC_TypeDef* ADCx);
uint32_t ADC_Get_Sequence_Channel(ADC_TypeDef* ADCx, uint32_t rank);
void ADC_DMA_Sim_Transfer(ADC_TypeDef* ADCx, struct ADC_Sim* ADCS);
void ADC_Set_Channel_Value(ADC_TypeDef* ADCx, uint32_t channel, double voltage);
void ADC_SIM_DEINIT(void);
///////////////////////////////////////////////////////////////////////
#endif // _MATLAB_ADC_H_

View File

@ -0,0 +1,591 @@
#include "stm32_matlab_dma.h"
#include <string.h>
// DMA stream simulation structures
#ifdef USE_DMA1
struct DMA_Stream_Sim dma1_stream0s;
struct DMA_Stream_Sim dma1_stream1s;
struct DMA_Stream_Sim dma1_stream2s;
struct DMA_Stream_Sim dma1_stream3s;
struct DMA_Stream_Sim dma1_stream4s;
struct DMA_Stream_Sim dma1_stream5s;
struct DMA_Stream_Sim dma1_stream6s;
struct DMA_Stream_Sim dma1_stream7s;
#endif
#ifdef USE_DMA2
struct DMA_Stream_Sim dma2_stream0s;
struct DMA_Stream_Sim dma2_stream1s;
struct DMA_Stream_Sim dma2_stream2s;
struct DMA_Stream_Sim dma2_stream3s;
struct DMA_Stream_Sim dma2_stream4s;
struct DMA_Stream_Sim dma2_stream5s;
struct DMA_Stream_Sim dma2_stream6s;
struct DMA_Stream_Sim dma2_stream7s;
#endif
void DMA_Call_IRQHandller(DMA_TypeDef* DMAx, uint32_t stream);
// Модифицируем основную функцию выполнения передачи
void DMA_Sim_Transfer(DMA_TypeDef* DMAx, uint32_t stream)
{
struct DMA_Stream_Sim* stream_sim = DMA_Get_Stream_Sim(DMAx, stream);
if (!stream_sim) return;
// Проверяем включен ли stream в регистрах
uint8_t hardware_enabled = DMA_Is_Stream_Enabled(DMAx, stream);
if (!hardware_enabled) {
// Если аппаратно выключен, сбрасываем состояние
if (stream_sim->enabled) {
memset(stream_sim, 0, sizeof(struct DMA_Stream_Sim));
}
return;
}
// Если аппаратно включен, инициализируем если нужно
if (!stream_sim->enabled) {
stream_sim->peripheral_address = DMA_Get_Peripheral_Address(DMAx, stream);
stream_sim->memory_address = DMA_Get_Memory_Address(DMAx, stream);
stream_sim->buffer_size = DMA_Get_Buffer_Size(DMAx, stream);
stream_sim->circular_mode = DMA_Get_Circular_Mode(DMAx, stream);
stream_sim->data_size = DMA_Get_DataSize(DMAx, stream); // Сохраняем размер данных
stream_sim->current_index = 0;
stream_sim->transfer_complete = 0;
stream_sim->enabled = 1;
stream_sim->transfer_enabled = 1;
}
// Проверяем нужно ли выполнить передачу
if (!stream_sim->transfer_enabled) return;
if (!stream_sim->peripheral_address || !stream_sim->memory_address) return;
// ВЫПОЛНЯЕМ ПЕРЕДАЧУ С УЧЕТОМ РАЗМЕРА ДАННЫХ
switch (stream_sim->data_size) {
case 1: // 8-bit data
{
uint8_t current_value = *(uint8_t*)stream_sim->peripheral_address;
((uint8_t*)stream_sim->memory_address)[stream_sim->current_index] = current_value;
}
break;
case 2: // 16-bit data
{
uint16_t current_value = *(uint16_t*)stream_sim->peripheral_address;
((uint16_t*)stream_sim->memory_address)[stream_sim->current_index] = current_value;
}
break;
case 4: // 32-bit data
{
uint32_t current_value = *(uint32_t*)stream_sim->peripheral_address;
((uint32_t*)stream_sim->memory_address)[stream_sim->current_index] = current_value;
}
break;
default: // По умолчанию 8-bit
{
uint8_t current_value = *(uint8_t*)stream_sim->peripheral_address;
((uint8_t*)stream_sim->memory_address)[stream_sim->current_index] = current_value;
}
break;
}
stream_sim->current_index++;
// Проверяем завершение передачи
if (stream_sim->current_index >= stream_sim->buffer_size) {
stream_sim->transfer_complete = 1;
if (stream_sim->circular_mode) {
stream_sim->current_index = 0;
} else {
stream_sim->transfer_enabled = 0;
stream_sim->enabled = 0;
DMA_Call_IRQHandller(DMAx, stream);
}
}
}
/////////////////////////////---HELPER FUNCTIONS---//////////////////////////
struct DMA_Stream_Sim* DMA_Get_Stream_Sim(DMA_TypeDef* DMAx, uint32_t stream)
{
#ifdef USE_DMA1
if (DMAx == DMA1) {
switch (stream) {
case 0: return &dma1_stream0s;
case 1: return &dma1_stream1s;
case 2: return &dma1_stream2s;
case 3: return &dma1_stream3s;
case 4: return &dma1_stream4s;
case 5: return &dma1_stream5s;
case 6: return &dma1_stream6s;
case 7: return &dma1_stream7s;
}
}
#endif
#ifdef USE_DMA2
if (DMAx == DMA2) {
switch (stream) {
case 0: return &dma2_stream0s;
case 1: return &dma2_stream1s;
case 2: return &dma2_stream2s;
case 3: return &dma2_stream3s;
case 4: return &dma2_stream4s;
case 5: return &dma2_stream5s;
case 6: return &dma2_stream6s;
case 7: return &dma2_stream7s;
}
}
#endif
return NULL;
}
uint8_t DMA_Is_Stream_Enabled(DMA_TypeDef* DMAx, uint32_t stream)
{
// Проверяем регистры DMA чтобы определить включен ли stream
#ifdef STM32F1
if (DMAx == DMA1) {
volatile uint32_t* cr_reg = NULL;
switch (stream) {
case 0: cr_reg = &DMA1_Channel1->CCR; break;
case 1: cr_reg = &DMA1_Channel2->CCR; break;
case 2: cr_reg = &DMA1_Channel3->CCR; break;
case 3: cr_reg = &DMA1_Channel4->CCR; break;
case 4: cr_reg = &DMA1_Channel5->CCR; break;
case 5: cr_reg = &DMA1_Channel6->CCR; break;
case 6: cr_reg = &DMA1_Channel7->CCR; break;
}
if (cr_reg) {
return (*cr_reg & DMA_CCR_EN) != 0;
}
}
#elif defined(STM32F4)
if (DMAx == DMA1) {
volatile uint32_t* cr_reg = NULL;
switch (stream) {
case 0: cr_reg = &DMA1_Stream0->CR; break;
case 1: cr_reg = &DMA1_Stream1->CR; break;
case 2: cr_reg = &DMA1_Stream2->CR; break;
case 3: cr_reg = &DMA1_Stream3->CR; break;
case 4: cr_reg = &DMA1_Stream4->CR; break;
case 5: cr_reg = &DMA1_Stream5->CR; break;
case 6: cr_reg = &DMA1_Stream6->CR; break;
case 7: cr_reg = &DMA1_Stream7->CR; break;
}
if (cr_reg) {
return (*cr_reg & DMA_SxCR_EN) != 0;
}
}
else if (DMAx == DMA2) {
volatile uint32_t* cr_reg = NULL;
switch (stream) {
case 0: cr_reg = &DMA2_Stream0->CR; break;
case 1: cr_reg = &DMA2_Stream1->CR; break;
case 2: cr_reg = &DMA2_Stream2->CR; break;
case 3: cr_reg = &DMA2_Stream3->CR; break;
case 4: cr_reg = &DMA2_Stream4->CR; break;
case 5: cr_reg = &DMA2_Stream5->CR; break;
case 6: cr_reg = &DMA2_Stream6->CR; break;
case 7: cr_reg = &DMA2_Stream7->CR; break;
}
if (cr_reg) {
return (*cr_reg & DMA_SxCR_EN) != 0;
}
}
#endif
return 0;
}
uint32_t* DMA_Get_Peripheral_Address(DMA_TypeDef* DMAx, uint32_t stream)
{
// Получаем адрес периферии из регистров DMA
#ifdef STM32F1
if (DMAx == DMA1) {
switch (stream) {
case 0: return (uint64_t*)DMA1_Channel1->CPAR;
case 1: return (uint64_t*)DMA1_Channel2->CPAR;
case 2: return (uint64_t*)DMA1_Channel3->CPAR;
case 3: return (uint64_t*)DMA1_Channel4->CPAR;
case 4: return (uint64_t*)DMA1_Channel5->CPAR;
case 5: return (uint64_t*)DMA1_Channel6->CPAR;
case 6: return (uint64_t*)DMA1_Channel7->CPAR;
}
}
#elif defined(STM32F4)
if (DMAx == DMA1) {
volatile uint64_t* par_reg = NULL;
switch (stream) {
case 0: par_reg = &DMA1_Stream0->PAR; break;
case 1: par_reg = &DMA1_Stream1->PAR; break;
case 2: par_reg = &DMA1_Stream2->PAR; break;
case 3: par_reg = &DMA1_Stream3->PAR; break;
case 4: par_reg = &DMA1_Stream4->PAR; break;
case 5: par_reg = &DMA1_Stream5->PAR; break;
case 6: par_reg = &DMA1_Stream6->PAR; break;
case 7: par_reg = &DMA1_Stream7->PAR; break;
}
if (par_reg) {
return (uint64_t*)*par_reg;
}
}
else if (DMAx == DMA2) {
volatile uint64_t* par_reg = NULL;
switch (stream) {
case 0: par_reg = &DMA2_Stream0->PAR; break;
case 1: par_reg = &DMA2_Stream1->PAR; break;
case 2: par_reg = &DMA2_Stream2->PAR; break;
case 3: par_reg = &DMA2_Stream3->PAR; break;
case 4: par_reg = &DMA2_Stream4->PAR; break;
case 5: par_reg = &DMA2_Stream5->PAR; break;
case 6: par_reg = &DMA2_Stream6->PAR; break;
case 7: par_reg = &DMA2_Stream7->PAR; break;
}
if (par_reg) {
return (uint64_t*)*par_reg;
}
}
#endif
return NULL;
}
uint32_t* DMA_Get_Memory_Address(DMA_TypeDef* DMAx, uint32_t stream)
{
// Получаем адрес памяти из регистров DMA
#ifdef STM32F1
if (DMAx == DMA1) {
switch (stream) {
case 0: return (uint64_t*)DMA1_Channel1->CPAR;
case 1: return (uint64_t*)DMA1_Channel2->CPAR;
case 2: return (uint64_t*)DMA1_Channel3->CPAR;
case 3: return (uint64_t*)DMA1_Channel4->CPAR;
case 4: return (uint64_t*)DMA1_Channel5->CPAR;
case 5: return (uint64_t*)DMA1_Channel6->CPAR;
case 6: return (uint64_t*)DMA1_Channel7->CPAR;
}
}
#elif defined(STM32F4)
if (DMAx == DMA1) {
volatile uint64_t* mar_reg = NULL;
switch (stream) {
case 0: mar_reg = &DMA1_Stream0->M0AR; break;
case 1: mar_reg = &DMA1_Stream1->M0AR; break;
case 2: mar_reg = &DMA1_Stream2->M0AR; break;
case 3: mar_reg = &DMA1_Stream3->M0AR; break;
case 4: mar_reg = &DMA1_Stream4->M0AR; break;
case 5: mar_reg = &DMA1_Stream5->M0AR; break;
case 6: mar_reg = &DMA1_Stream6->M0AR; break;
case 7: mar_reg = &DMA1_Stream7->M0AR; break;
}
if (mar_reg) {
return (uint64_t*)*mar_reg;
}
}
else if (DMAx == DMA2) {
volatile uint64_t* mar_reg = NULL;
switch (stream) {
case 0: mar_reg = &DMA2_Stream0->M0AR; break;
case 1: mar_reg = &DMA2_Stream1->M0AR; break;
case 2: mar_reg = &DMA2_Stream2->M0AR; break;
case 3: mar_reg = &DMA2_Stream3->M0AR; break;
case 4: mar_reg = &DMA2_Stream4->M0AR; break;
case 5: mar_reg = &DMA2_Stream5->M0AR; break;
case 6: mar_reg = &DMA2_Stream6->M0AR; break;
case 7: mar_reg = &DMA2_Stream7->M0AR; break;
}
if (mar_reg) {
return (uint64_t*)*mar_reg;
}
}
#endif
return NULL;
}
uint32_t DMA_Get_Buffer_Size(DMA_TypeDef* DMAx, uint32_t stream)
{
// Получаем размер буфера из регистров DMA
#ifdef STM32F1
if (DMAx == DMA1) {
switch (stream) {
case 0: return DMA1_Channel1->CNDTR;
case 1: return DMA1_Channel2->CNDTR;
case 2: return DMA1_Channel3->CNDTR;
case 3: return DMA1_Channel4->CNDTR;
case 4: return DMA1_Channel5->CNDTR;
case 5: return DMA1_Channel6->CNDTR;
case 6: return DMA1_Channel7->CNDTR;
}
}
#elif defined(STM32F4)
if (DMAx == DMA1) {
volatile uint64_t* mar_reg = NULL;
switch (stream) {
case 0: mar_reg = &DMA1_Stream0->NDTR; break;
case 1: mar_reg = &DMA1_Stream1->NDTR; break;
case 2: mar_reg = &DMA1_Stream2->NDTR; break;
case 3: mar_reg = &DMA1_Stream3->NDTR; break;
case 4: mar_reg = &DMA1_Stream4->NDTR; break;
case 5: mar_reg = &DMA1_Stream5->NDTR; break;
case 6: mar_reg = &DMA1_Stream6->NDTR; break;
case 7: mar_reg = &DMA1_Stream7->NDTR; break;
}
if (mar_reg) {
return (uint64_t*)*mar_reg;
}
}
else if (DMAx == DMA2) {
volatile uint64_t* mar_reg = NULL;
switch (stream) {
case 0: mar_reg = &DMA2_Stream0->NDTR; break;
case 1: mar_reg = &DMA2_Stream1->NDTR; break;
case 2: mar_reg = &DMA2_Stream2->NDTR; break;
case 3: mar_reg = &DMA2_Stream3->NDTR; break;
case 4: mar_reg = &DMA2_Stream4->NDTR; break;
case 5: mar_reg = &DMA2_Stream5->NDTR; break;
case 6: mar_reg = &DMA2_Stream6->NDTR; break;
case 7: mar_reg = &DMA2_Stream7->NDTR; break;
}
if (mar_reg) {
return (uint64_t*)*mar_reg;
}
}
#endif
return 0;
}
uint8_t DMA_Get_Circular_Mode(DMA_TypeDef* DMAx, uint32_t stream)
{
// Проверяем циклический режим
#ifdef STM32F1
if (DMAx == DMA1) {
switch (stream) {
case 0: return (DMA1_Channel1->CCR & DMA_CCR_CIRC) != 0;
case 1: return (DMA1_Channel2->CCR & DMA_CCR_CIRC) != 0;
case 2: return (DMA1_Channel3->CCR & DMA_CCR_CIRC) != 0;
case 3: return (DMA1_Channel4->CCR & DMA_CCR_CIRC) != 0;
case 4: return (DMA1_Channel5->CCR & DMA_CCR_CIRC) != 0;
case 5: return (DMA1_Channel6->CCR & DMA_CCR_CIRC) != 0;
case 6: return (DMA1_Channel7->CCR & DMA_CCR_CIRC) != 0;
}
}
if (DMAx == DMA1) {
switch (stream) {
case 0: return (DMA1_Stream1->CR & DMA_SxCR_CIRC) != 0;
case 1: return (DMA1_Stream11->CR & DMA_SxCR_CIRC) != 0;
case 2: return (DMA1_Stream13->CR & DMA_SxCR_CIRC) != 0;
case 3: return (DMA1_Stream14->CR & DMA_SxCR_CIRC) != 0;
case 4: return (DMA1_Stream15->CR & DMA_SxCR_CIRC) != 0;
case 5: return (DMA1_Stream16->CR & DMA_SxCR_CIRC) != 0;
case 6: return (DMA1_Stream17->CR & DMA_SxCR_CIRC) != 0;
}
}
#elif defined(STM32F4)
if (DMAx == DMA1 || DMAx == DMA2) {
volatile uint32_t* cr_reg = NULL;
switch (stream) {
case 0: return (DMA2_Stream1->CR & DMA_SxCR_CIRC) != 0;
case 1: return (DMA2_Stream1->CR & DMA_SxCR_CIRC) != 0;
case 2: return (DMA2_Stream3->CR & DMA_SxCR_CIRC) != 0;
case 3: return (DMA2_Stream4->CR & DMA_SxCR_CIRC) != 0;
case 4: return (DMA2_Stream5->CR & DMA_SxCR_CIRC) != 0;
case 5: return (DMA2_Stream6->CR & DMA_SxCR_CIRC) != 0;
case 6: return (DMA2_Stream7->CR & DMA_SxCR_CIRC) != 0;
}
}
#endif
return 0;
}
// функцию для определения размера данных DMA
uint32_t DMA_Get_DataSize(DMA_TypeDef* DMAx, uint32_t stream)
{
#ifdef STM32F4
if (DMAx == DMA1 || DMAx == DMA2) {
volatile uint32_t* cr_reg = NULL;
// Получаем регистр CR для соответствующего потока
if (DMAx == DMA1) {
switch (stream) {
case 0: cr_reg = &DMA1_Stream0->CR; break;
case 1: cr_reg = &DMA1_Stream1->CR; break;
case 2: cr_reg = &DMA1_Stream2->CR; break;
case 3: cr_reg = &DMA1_Stream3->CR; break;
case 4: cr_reg = &DMA1_Stream4->CR; break;
case 5: cr_reg = &DMA1_Stream5->CR; break;
case 6: cr_reg = &DMA1_Stream6->CR; break;
case 7: cr_reg = &DMA1_Stream7->CR; break;
}
}
else if (DMAx == DMA2) {
switch (stream) {
case 0: cr_reg = &DMA2_Stream0->CR; break;
case 1: cr_reg = &DMA2_Stream1->CR; break;
case 2: cr_reg = &DMA2_Stream2->CR; break;
case 3: cr_reg = &DMA2_Stream3->CR; break;
case 4: cr_reg = &DMA2_Stream4->CR; break;
case 5: cr_reg = &DMA2_Stream5->CR; break;
case 6: cr_reg = &DMA2_Stream6->CR; break;
case 7: cr_reg = &DMA2_Stream7->CR; break;
}
}
if (cr_reg) {
uint32_t psize = (*cr_reg & DMA_SxCR_PSIZE);
// Определяем размер данных на основе битов PSIZE
switch (psize) {
case DMA_PDATAALIGN_BYTE: // 00: Byte alignment (8-bit)
return 1;
case DMA_PDATAALIGN_HALFWORD: // 01: HalfWord alignment (16-bit)
return 2;
case DMA_PDATAALIGN_WORD: // 10: Word alignment (32-bit)
return 4;
default:
return 1; // По умолчанию байт
}
}
}
#elif defined(STM32F1)
// Для STM32F1 логика может отличаться
if (DMAx == DMA1) {
volatile uint32_t* ccr_reg = NULL;
switch (stream) {
case 0: ccr_reg = &DMA1_Channel1->CCR; break;
case 1: ccr_reg = &DMA1_Channel2->CCR; break;
case 2: ccr_reg = &DMA1_Channel3->CCR; break;
case 3: ccr_reg = &DMA1_Channel4->CCR; break;
case 4: ccr_reg = &DMA1_Channel5->CCR; break;
case 5: ccr_reg = &DMA1_Channel6->CCR; break;
case 6: ccr_reg = &DMA1_Channel7->CCR; break;
}
if (ccr_reg) {
// В STM32F1 размер определяется битами MSIZE[1:0] и PSIZE[1:0]
uint32_t size_bits = (*ccr_reg & (DMA_CCR_MSIZE | DMA_CCR_PSIZE));
// Упрощенная логика - обычно размеры памяти и периферии совпадают
if (size_bits & 0x0200) return 4; // Word (32-bit)
if (size_bits & 0x0100) return 2; // HalfWord (16-bit)
return 1; // Byte (8-bit)
}
}
#endif
return 1; // По умолчанию 1 байт
}
__weak void DMA1_Stream0_IRQHandler(void) {}
__weak void DMA1_Stream1_IRQHandler(void) {}
__weak void DMA1_Stream2_IRQHandler(void) {}
__weak void DMA1_Stream3_IRQHandler(void) {}
__weak void DMA1_Stream4_IRQHandler(void) {}
__weak void DMA1_Stream5_IRQHandler(void) {}
__weak void DMA1_Stream6_IRQHandler(void) {}
__weak void DMA1_Stream7_IRQHandler(void) {}
__weak void DMA2_Stream0_IRQHandler(void) {}
__weak void DMA2_Stream1_IRQHandler(void) {}
__weak void DMA2_Stream2_IRQHandler(void) {}
__weak void DMA2_Stream3_IRQHandler(void) {}
__weak void DMA2_Stream4_IRQHandler(void) {}
__weak void DMA2_Stream5_IRQHandler(void) {}
__weak void DMA2_Stream6_IRQHandler(void) {}
__weak void DMA2_Stream7_IRQHandler(void) {}
void DMA_Call_IRQHandller(DMA_TypeDef* DMAx, uint32_t stream)
{
struct DMA_Stream_Sim* stream_sim = DMA_Get_Stream_Sim(DMAx, stream);
if (stream_sim == NULL) return;
#ifdef STM32F4
// Определяем какой обработчик вызывать на основе DMAx и stream
if (DMAx == DMA1) {
switch (stream) {
case 0: DMA1_Stream0_IRQHandler(); break;
case 1: DMA1_Stream1_IRQHandler(); break;
case 2: DMA1_Stream2_IRQHandler(); break;
case 3: DMA1_Stream3_IRQHandler(); break;
case 4: DMA1_Stream4_IRQHandler(); break;
case 5: DMA1_Stream5_IRQHandler(); break;
case 6: DMA1_Stream6_IRQHandler(); break;
case 7: DMA1_Stream7_IRQHandler(); break;
}
}
else if (DMAx == DMA2) {
switch (stream) {
case 0: DMA2_Stream0_IRQHandler(); break;
case 1: DMA2_Stream1_IRQHandler(); break;
case 2: DMA2_Stream2_IRQHandler(); break;
case 3: DMA2_Stream3_IRQHandler(); break;
case 4: DMA2_Stream4_IRQHandler(); break;
case 5: DMA2_Stream5_IRQHandler(); break;
case 6: DMA2_Stream6_IRQHandler(); break;
case 7: DMA2_Stream7_IRQHandler(); break;
}
}
#elif defined(STM32F1)
if (DMAx == DMA1) {
switch (stream) {
case 0: DMA1_Channel0_IRQHandler(); break;
case 1: DMA1_Channel1_IRQHandler(); break;
case 2: DMA1_Channel2_IRQHandler(); break;
case 3: DMA1_Channel3_IRQHandler(); break;
case 4: DMA1_Channel4_IRQHandler(); break;
case 5: DMA1_Channel5_IRQHandler(); break;
case 6: DMA1_Channel6_IRQHandler(); break;
case 7: DMA1_Channel7_IRQHandler(); break;
}
}
#endif
}
/////////////////////////////---DEINITIALIZATION---/////////////////////////////
void DMA_SIM_DEINIT(void)
{
#ifdef USE_DMA1
memset(&dma1_stream0s, 0, sizeof(dma1_stream0s));
memset(&dma1_stream1s, 0, sizeof(dma1_stream1s));
memset(&dma1_stream2s, 0, sizeof(dma1_stream2s));
memset(&dma1_stream3s, 0, sizeof(dma1_stream3s));
memset(&dma1_stream4s, 0, sizeof(dma1_stream4s));
memset(&dma1_stream5s, 0, sizeof(dma1_stream5s));
memset(&dma1_stream6s, 0, sizeof(dma1_stream6s));
memset(&dma1_stream7s, 0, sizeof(dma1_stream7s));
#endif
#ifdef USE_DMA2
memset(&dma2_stream0s, 0, sizeof(dma2_stream0s));
memset(&dma2_stream1s, 0, sizeof(dma2_stream1s));
memset(&dma2_stream2s, 0, sizeof(dma2_stream2s));
memset(&dma2_stream3s, 0, sizeof(dma2_stream3s));
memset(&dma2_stream4s, 0, sizeof(dma2_stream4s));
memset(&dma2_stream5s, 0, sizeof(dma2_stream5s));
memset(&dma2_stream6s, 0, sizeof(dma2_stream6s));
memset(&dma2_stream7s, 0, sizeof(dma2_stream7s));
#endif
}

View File

@ -0,0 +1,40 @@
#ifndef _MATLAB_DMA_H_
#define _MATLAB_DMA_H_
#include "stm32_matlab_conf.h"
#ifdef DMA1
#define USE_DMA1
#endif
#ifdef DMA2
#define USE_DMA2
#endif
/////////////////////////////---STRUCTURES---///////////////////////////
struct DMA_Stream_Sim
{
uint32_t* peripheral_address;
uint32_t* memory_address;
uint32_t buffer_size;
uint32_t current_index;
uint32_t data_size;
uint8_t circular_mode;
uint8_t transfer_complete;
uint8_t enabled;
uint8_t transfer_enabled;
};
///////////////////////////////////////////////////////////////////////
///////////////////////////---FUNCTIONS---///////////////////////////
void DMA_Sim_Transfer(DMA_TypeDef* DMAx, uint32_t stream);
struct DMA_Stream_Sim* DMA_Get_Stream_Sim(DMA_TypeDef* DMAx, uint32_t stream);
uint8_t DMA_Is_Stream_Enabled(DMA_TypeDef* DMAx, uint32_t stream);
uint32_t* DMA_Get_Peripheral_Address(DMA_TypeDef* DMAx, uint32_t stream);
uint32_t* DMA_Get_Memory_Address(DMA_TypeDef* DMAx, uint32_t stream);
uint32_t DMA_Get_Buffer_Size(DMA_TypeDef* DMAx, uint32_t stream);
uint8_t DMA_Get_Circular_Mode(DMA_TypeDef* DMAx, uint32_t stream);
uint32_t DMA_Get_DataSize(DMA_TypeDef* DMAx, uint32_t stream);
///////////////////////////////////////////////////////////////////////
#endif // _MATLAB_DMA_H_

View File

@ -7,7 +7,7 @@
struct SlaveChannels Slave_Channels; // структура для связи и синхронизации таймеров
void TIM_Call_IRQHandller(TIM_TypeDef* TIMx);
//----------------------TIMER BASE FUNCTIONS-----------------------//
/* Базовая функция для симуляции таймера: она вызывается каждый шаг симуляции */
@ -24,6 +24,7 @@ switch (TIMx->SMCR & TIM_SMCR_SMS) // TIMER MODE
case(TIM_SLAVEMODE_DISABLE):// NORMAL MODE counting
TIMx_Count(TIMx, TIMS);
Channels_Simulation(TIMx, TIMS); // CaptureCompare and PWM channels simulation
Write_TRGO(TIMx, TIMS);
break;
@ -32,6 +33,7 @@ switch (TIMx->SMCR & TIM_SMCR_SMS) // TIMER MODE
Slave_Mode_Check_Source(TIMx, TIMS);
TIMx_Count(TIMx, TIMS);
Channels_Simulation(TIMx, TIMS); // CaptureCompare and PWM channels simulation
Write_TRGO(TIMx, TIMS);
break;
}
@ -48,12 +50,14 @@ void TIMx_Count(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS)
/* Проверка на переполнение и дальнейшая его обработка */
void Overflow_Check(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS)
{
TIMS->Updated = 0;
// Переполнение таймера: сброс таймера и вызов прерывания
if ((TIMx->CR1 & TIM_CR1_UDIS) == 0) // UPDATE enable
{
if ((TIMx->CR1 & TIM_CR1_ARPE) == 0) TIMS->RELOAD = TIMx->ARR; // PRELOAD disable - update ARR every itteration
if (TIMS->tx_cnt > TIMS->RELOAD || TIMS->tx_cnt < 0) // OVERFLOW
{
TIMS->Updated = 1;
TIMS->RELOAD = TIMx->ARR; // RELOAD ARR
if (TIMS->tx_cnt > TIMx->ARR) // reset COUNTER
@ -61,7 +65,10 @@ void Overflow_Check(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS)
else if (TIMS->tx_cnt < 0)
TIMS->tx_cnt += TIMS->RELOAD+1;
call_IRQHandller(TIMx); // call HANDLER
if(TIMS->tx_step > TIMS->RELOAD)
TIMS->tx_cnt = 0;
TIM_Call_IRQHandller(TIMx); // call HANDLER
}
}
}
@ -79,8 +86,6 @@ void Channels_Simulation(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS)
CC_PWM_Ch4_Simulation(TIMx, TIMS);
Write_OC_to_GPIO(TIMx, TIMS);
Write_OC_to_TRGO(TIMx, TIMS);
}
//-----------------CAPTURE COPMARE & PWM FUNCTIONS------------------//
/* Выбор режима CaptureCompare или PWM и симуляция для каждого канала */
@ -323,26 +328,38 @@ void Write_OC_to_GPIO(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS)
}
}
/* Запись результата compare в глабальную структуру с TRIGGER OUTPUT */
void Write_OC_to_TRGO(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS)
void Write_TRGO(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS)
{
// write trigger output from OCxREF pin if need
unsigned temp_trgo;
if ((TIMx->CR2 & TIM_CR2_MMS) == (0b100 << TIM_CR2_MMS_Pos))
if ((TIMx->CR2 & TIM_CR2_MMS) == (TIM_TRGO_OC1REF))
{
temp_trgo = TIMS->Channels.OC1REF;
}
else if ((TIMx->CR2 & TIM_CR2_MMS) == (0b101 << TIM_CR2_MMS_Pos))
else if ((TIMx->CR2 & TIM_CR2_MMS) == (TIM_TRGO_OC2REF))
{
temp_trgo = TIMS->Channels.OC2REF;
}
else if ((TIMx->CR2 & TIM_CR2_MMS) == (0b110 << TIM_CR2_MMS_Pos))
else if ((TIMx->CR2 & TIM_CR2_MMS) == (TIM_TRGO_OC3REF))
{
temp_trgo = TIMS->Channels.OC3REF;
}
else if ((TIMx->CR2 & TIM_CR2_MMS) == (0b111 << TIM_CR2_MMS_Pos))
else if ((TIMx->CR2 & TIM_CR2_MMS) == (TIM_TRGO_OC4REF))
{
temp_trgo = TIMS->Channels.OC4REF;
}
else if ((TIMx->CR2 & TIM_CR2_MMS) == (TIM_TRGO_UPDATE))
{
temp_trgo = TIMS->Updated;
}
else if ((TIMx->CR2 & TIM_CR2_MMS) == (TIM_TRGO_ENABLE))
{
temp_trgo = (TIMx->CR1 & TIM_CR1_CEN) ? 1: 0;
}
else if ((TIMx->CR2 & TIM_CR2_MMS) == (TIM_TRGO_RESET))
{
temp_trgo = 0;
}
// select TIMx TRGO
@ -585,7 +602,7 @@ void TIM_SIM_DEINIT(void)
//#endif
/* Вызов прерывания */
void call_IRQHandller(TIM_TypeDef* TIMx)
void TIM_Call_IRQHandller(TIM_TypeDef* TIMx)
{ // calling HANDLER
//if (TIMx == TIM1)
// TIM1_UP_IRQHandler();

View File

@ -42,7 +42,7 @@ struct SlaveChannels
unsigned TIM8_TRGO : 1;
};
extern struct SlaveChannels Slave_Channels; // структура для связи и синхронизации таймеров
/* Структура для моделирования каналов таймера */
struct Channels_Sim
{
@ -69,6 +69,7 @@ struct Channels_Sim
/* Структура для моделирования таймера */
struct TIM_Sim
{
int Updated; // счетчик таймера
double tx_cnt; // счетчик таймера
double tx_step; // шаг счета за один шаг симуляции
int RELOAD; // буфер, если PRELOAD = 1
@ -87,8 +88,6 @@ void TIM_Simulation(TIM_TypeDef *TIMx, struct TIM_Sim *TIMS);
void TIMx_Count(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS);
/* Проверка на переполнение и дальнейшая его обработка */
void Overflow_Check(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS);
/* Вызов прерывания */
void call_IRQHandller(TIM_TypeDef *TIMx);
//-----------------------------------------------------------------//
@ -104,7 +103,7 @@ void CC_PWM_Ch4_Simulation(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS);
/* Запись каналов таймера в порты GPIO */
void Write_OC_to_GPIO(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS);
/* Запись результата compare в глабальную структуру с TRIGGER OUTPUT */
void Write_OC_to_TRGO(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS);
void Write_TRGO(TIM_TypeDef* TIMx, struct TIM_Sim* TIMS);
//------------------------------------------------------------------//

View File

@ -5,6 +5,7 @@
**************************************************************************/
#include "stm32_matlab_conf.h"
#include "mcu_wrapper_conf.h"
#include "app_includes.h"
MCU_MemoryTypeDef MCU_MEM;
DBGMCU_TypeDef DEBUG_MCU;
@ -16,11 +17,21 @@ MCU_CortexMemoryTypeDef MCU_CORTEX_MEM;
void Initialize_Periph_Sim(void)
{
Init_TIM_SIM();
Init_ADC_SIM();
}
// MCU PERIPH SIM
void Simulate_Periph_Sim(void)
{
Simulate_TIMs();
Simulate_ADCs();
}
// MCU PERIPH DEINIT
void deInitialize_Periph_Sim(void)
{
TIM_SIM_DEINIT();
ADC_SIM_DEINIT();
}
// MCU DEINIT
void deInitialize_MCU(void)
@ -30,6 +41,17 @@ void deInitialize_MCU(void)
// обнуление структур, симулирующих память МК
memset(&MCU_MEM, 0, sizeof(MCU_MEM));
memset(&MCU_CORTEX_MEM, 0, sizeof(MCU_CORTEX_MEM));
memset(&htim1, 0, sizeof(htim1));
ClearStruct(htim1);
ClearStruct(htim3);
ClearStruct(htim8);
ClearStruct(htim11);
ClearStruct(htim12);
ClearStruct(htim13);
ClearStruct(hadc3);
ClearStruct(hdma_adc3);
}
/*------------------------------FUNCTIONS--------------------------------*/
@ -85,6 +107,7 @@ struct TIM_Sim tim14s;
void Init_TIM_SIM(void)
{
#ifdef USE_TIM1
memset(&tim1s, 0, sizeof(tim1s));
tim1s.tx_cnt = TIM1->CNT;
tim1s.tx_step = hmcu.sSimSampleTime * ABP2_TIMS_Value;
@ -98,6 +121,7 @@ void Init_TIM_SIM(void)
tim1s.Channels.OC4_PIN_SHIFT = 11;
#endif
#ifdef USE_TIM2
memset(&tim2s, 0, sizeof(tim2s));
tim2s.tx_cnt = TIM2->CNT;
tim2s.tx_step = hmcu.sSimSampleTime * ABP1_TIMS_Value;
@ -111,6 +135,7 @@ void Init_TIM_SIM(void)
tim2s.Channels.OC4_PIN_SHIFT = 3;
#endif
#ifdef USE_TIM3
memset(&tim3s, 0, sizeof(tim3s));
tim3s.tx_cnt = TIM3->CNT;
tim3s.tx_step = hmcu.sSimSampleTime * ABP1_TIMS_Value;
@ -124,6 +149,7 @@ void Init_TIM_SIM(void)
tim3s.Channels.OC4_PIN_SHIFT = 9;
#endif
#ifdef USE_TIM4
memset(&tim4s, 0, sizeof(tim4s));
tim4s.tx_cnt = TIM4->CNT;
tim4s.tx_step = hmcu.sSimSampleTime * ABP1_TIMS_Value;
@ -137,6 +163,7 @@ void Init_TIM_SIM(void)
tim4s.Channels.OC4_PIN_SHIFT = 9;
#endif
#ifdef USE_TIM5
memset(&tim5s, 0, sizeof(tim5s));
tim5s.tx_cnt = TIM5->CNT;
tim5s.tx_step = hmcu.sSimSampleTime * ABP1_TIMS_Value;
@ -149,8 +176,9 @@ void Init_TIM_SIM(void)
tim5s.Channels.OC4_GPIOx = GPIOA;
tim5s.Channels.OC4_PIN_SHIFT = 3;
#endif
#ifdef USE_TIMx
tim6s.tx_cnt = TIMx->CNT;
#ifdef USE_TIM6
memset(&tim6s, 0, sizeof(tim6s));
tim6s.tx_cnt = TIM6->CNT;
tim6s.tx_step = hmcu.sSimSampleTime * ABP1_TIMS_Value;
tim6s.Channels.OC1_GPIOx = GPIOA;
@ -162,6 +190,154 @@ void Init_TIM_SIM(void)
tim6s.Channels.OC4_GPIOx = GPIOA;
tim6s.Channels.OC4_PIN_SHIFT = 0;
#endif
#ifdef USE_TIM7
memset(&tim7s, 0, sizeof(tim7s));
tim7s.tx_cnt = TIM7->CNT;
tim7s.tx_step = hmcu.sSimSampleTime * ABP1_TIMS_Value;
tim7s.Channels.OC1_GPIOx = GPIOA;
tim7s.Channels.OC1_PIN_SHIFT = 0;
tim7s.Channels.OC2_GPIOx = GPIOA;
tim7s.Channels.OC2_PIN_SHIFT = 0;
tim7s.Channels.OC3_GPIOx = GPIOA;
tim7s.Channels.OC3_PIN_SHIFT = 0;
tim7s.Channels.OC4_GPIOx = GPIOA;
tim7s.Channels.OC4_PIN_SHIFT = 0;
#endif
#ifdef USE_TIM8
memset(&tim8s, 0, sizeof(tim8s));
tim8s.tx_cnt = TIM8->CNT;
tim8s.tx_step = hmcu.sSimSampleTime * ABP2_TIMS_Value;
tim8s.Channels.OC1_GPIOx = GPIOA;
tim8s.Channels.OC1_PIN_SHIFT = 0;
tim8s.Channels.OC2_GPIOx = GPIOA;
tim8s.Channels.OC2_PIN_SHIFT = 0;
tim8s.Channels.OC3_GPIOx = GPIOA;
tim8s.Channels.OC3_PIN_SHIFT = 0;
tim8s.Channels.OC4_GPIOx = GPIOA;
tim8s.Channels.OC4_PIN_SHIFT = 0;
#endif
#ifdef USE_TIM9
memset(&tim9s, 0, sizeof(tim9s));
tim9s.tx_cnt = TIM9->CNT;
tim9s.tx_step = hmcu.sSimSampleTime * ABP2_TIMS_Value;
tim9s.Channels.OC1_GPIOx = GPIOA;
tim9s.Channels.OC1_PIN_SHIFT = 0;
tim9s.Channels.OC2_GPIOx = GPIOA;
tim9s.Channels.OC2_PIN_SHIFT = 0;
tim9s.Channels.OC3_GPIOx = GPIOA;
tim9s.Channels.OC3_PIN_SHIFT = 0;
tim9s.Channels.OC4_GPIOx = GPIOA;
tim9s.Channels.OC4_PIN_SHIFT = 0;
#endif
#ifdef USE_TIM10
memset(&tim10s, 0, sizeof(tim10s));
tim10s.tx_cnt = TIM10->CNT;
tim10s.tx_step = hmcu.sSimSampleTime * ABP2_TIMS_Value;
tim10s.Channels.OC1_GPIOx = GPIOA;
tim10s.Channels.OC1_PIN_SHIFT = 0;
tim10s.Channels.OC2_GPIOx = GPIOA;
tim10s.Channels.OC2_PIN_SHIFT = 0;
tim10s.Channels.OC3_GPIOx = GPIOA;
tim10s.Channels.OC3_PIN_SHIFT = 0;
tim10s.Channels.OC4_GPIOx = GPIOA;
tim10s.Channels.OC4_PIN_SHIFT = 0;
#endif
#ifdef USE_TIM11
memset(&tim11s, 0, sizeof(tim11s));
tim11s.tx_cnt = TIM11->CNT;
tim11s.tx_step = hmcu.sSimSampleTime * ABP2_TIMS_Value;
tim11s.Channels.OC1_GPIOx = GPIOA;
tim11s.Channels.OC1_PIN_SHIFT = 0;
tim11s.Channels.OC2_GPIOx = GPIOA;
tim11s.Channels.OC2_PIN_SHIFT = 0;
tim11s.Channels.OC3_GPIOx = GPIOA;
tim11s.Channels.OC3_PIN_SHIFT = 0;
tim11s.Channels.OC4_GPIOx = GPIOA;
tim11s.Channels.OC4_PIN_SHIFT = 0;
#endif
#ifdef USE_TIM12
memset(&tim12s, 0, sizeof(tim12s));
tim12s.tx_cnt = TIM12->CNT;
tim12s.tx_step = hmcu.sSimSampleTime * ABP1_TIMS_Value;
tim12s.Channels.OC1_GPIOx = GPIOA;
tim12s.Channels.OC1_PIN_SHIFT = 0;
tim12s.Channels.OC2_GPIOx = GPIOA;
tim12s.Channels.OC2_PIN_SHIFT = 0;
tim12s.Channels.OC3_GPIOx = GPIOA;
tim12s.Channels.OC3_PIN_SHIFT = 0;
tim12s.Channels.OC4_GPIOx = GPIOA;
tim12s.Channels.OC4_PIN_SHIFT = 0;
#endif
#ifdef USE_TIM13
memset(&tim13s, 0, sizeof(tim13s));
tim13s.tx_cnt = TIM13->CNT;
tim13s.tx_step = hmcu.sSimSampleTime * ABP1_TIMS_Value;
tim13s.Channels.OC1_GPIOx = GPIOA;
tim13s.Channels.OC1_PIN_SHIFT = 0;
tim13s.Channels.OC2_GPIOx = GPIOA;
tim13s.Channels.OC2_PIN_SHIFT = 0;
tim13s.Channels.OC3_GPIOx = GPIOA;
tim13s.Channels.OC3_PIN_SHIFT = 0;
tim13s.Channels.OC4_GPIOx = GPIOA;
tim13s.Channels.OC4_PIN_SHIFT = 0;
#endif
#ifdef USE_TIM14
memset(&tim14s, 0, sizeof(tim14s));
tim14s.tx_cnt = TIM14->CNT;
tim14s.tx_step = hmcu.sSimSampleTime * ABP1_TIMS_Value;
tim14s.Channels.OC1_GPIOx = GPIOA;
tim14s.Channels.OC1_PIN_SHIFT = 0;
tim14s.Channels.OC2_GPIOx = GPIOA;
tim14s.Channels.OC2_PIN_SHIFT = 0;
tim14s.Channels.OC3_GPIOx = GPIOA;
tim14s.Channels.OC3_PIN_SHIFT = 0;
tim14s.Channels.OC4_GPIOx = GPIOA;
tim14s.Channels.OC4_PIN_SHIFT = 0;
#endif
}
/*-------------------------------TIMERS----------------------------------*/
//-----------------------------------------------------------------------//
//-----------------------------------------------------------------------//
/*---------------------------------ADC-----------------------------------*/
#ifdef USE_ADC1
struct ADC_Sim adc1s;
#endif
#ifdef USE_ADC2
struct ADC_Sim adc2s;
#endif
#ifdef USE_ADC3
struct ADC_Sim adc3s;
#endif
void Init_ADC_SIM(void)
{
#ifdef USE_ADC1
memset(&adc1s, 0, sizeof(adc1s));
adc1s.simulation_step = hmcu.sSimSampleTime;
adc1s.adc_clock_freq = ABP2_Value; // Частота APB2
#endif
#ifdef USE_ADC2
memset(&adc2s, 0, sizeof(adc2s));
adc2s.simulation_step = hmcu.sSimSampleTime;
adc2s.adc_clock_freq = ABP2_Value; // Частота APB2
#endif
#ifdef USE_ADC3
memset(&adc3s, 0, sizeof(adc3s));
adc3s.simulation_step = hmcu.sSimSampleTime;
adc3s.adc_clock_freq = ABP2_Value; // Частота APB2
#endif
}
/*---------------------------------ADC-----------------------------------*/
//-----------------------------------------------------------------------//

View File

@ -54,22 +54,21 @@
//-----------------------------------------------------------------------//
/*------------------------------FUNCTIONS--------------------------------*/
void deInitialize_Periph_Sim(void);
void Simulate_Periph_Sim(void);
void deInitialize_MCU(void);
void Initialize_Periph_Sim(void);
#include "stm32_matlab_rcc.h"
#include "stm32_matlab_gpio.h"
#include "stm32_matlab_dma.h"
//-----------------------------------------------------------------------//
/*-------------------------------TIMERS----------------------------------*/
//#if defined(USE_TIM1) || defined(USE_TIM2) || defined(USE_TIM3) || defined(USE_TIM4) || defined(USE_TIM5) || \
// defined(USE_TIM6) || defined(USE_TIM7) || defined(USE_TIM8) || defined(USE_TIM9) || defined(USE_TIM10) || \
// defined(USE_TIM11) || defined(USE_TIM12) || defined(USE_TIM13) || defined(USE_TIM14)
#include "stm32_matlab_tim.h"
// CODE
void Init_TIM_SIM(void);
#if defined(USE_TIM1) || defined(USE_TIM2) || defined(USE_TIM3) || defined(USE_TIM4) || defined(USE_TIM5) || \
defined(USE_TIM6) || defined(USE_TIM7) || defined(USE_TIM8) || defined(USE_TIM9) || defined(USE_TIM10) || \
defined(USE_TIM11) || defined(USE_TIM12) || defined(USE_TIM13) || defined(USE_TIM14)
#include "stm32_matlab_tim.h"
#ifdef USE_TIM1
extern struct TIM_Sim tim1s;
@ -113,7 +112,39 @@ extern struct TIM_Sim tim13s;
#ifdef USE_TIM14
extern struct TIM_Sim tim14s;
#endif
#endif
#ifndef TIM_ENABLE
static void Simulate_TIMs() {}
static void TIM_SIM_DEINIT() {}
#endif
/*-------------------------------TIMERS----------------------------------*/
//-----------------------------------------------------------------------//
//-----------------------------------------------------------------------//
/*---------------------------------ADC-----------------------------------*/
void Init_ADC_SIM(void);
#if defined(USE_ADC1) || defined(USE_ADC2) || defined(USE_ADC3)
#include "stm32_matlab_adc.h"
#ifdef USE_ADC1
extern struct ADC_Sim adc1s;
#endif
#ifdef USE_ADC2
extern struct ADC_Sim adc2s;
#endif
#ifdef USE_ADC3
extern struct ADC_Sim adc3s;
#endif
#endif
#ifndef ADC_ENABLE
static void Simulate_ADCs() {}
static void ADC_SIM_DEINIT() {}
#endif
/*---------------------------------ADC-----------------------------------*/
//-----------------------------------------------------------------------//
#endif // _MATLAB_SETUP_H_

View File

@ -16,8 +16,7 @@
],
"PeriphSimulation": [
"uwTick = hmcu.SystemClock / (MCU_CORE_CLOCK / 1000)",
"Simulate_TIMs()",
"Simulate_GPIO_BSRR()"
"Simulate_Periph_Sim()"
],
"PeriphDeinit": [
"deInitialize_Periph_Sim()"
@ -28,6 +27,7 @@
"Sources": [
"stm32_matlab_conf.c",
"Drivers/STM32_SIMULINK/stm32_matlab_gpio.c",
"Drivers/STM32_SIMULINK/stm32_matlab_dma.c",
"Drivers/STM32_SIMULINK/stm32_periph_registers.c"
],
"Defines": {
@ -49,12 +49,14 @@
},
"Tab_TIM_Enable": {
"Prompt": "Enable TIMs",
"Def": "TIM_ENABLE",
"Type": "checkbox",
"Default": true,
"NewRow": true
},
"Tab_ADC_Enable": {
"Prompt": "Enable ADCs",
"Def": "ADC_ENABLE",
"Type": "checkbox",
"Default": false,
"NewRow": true
@ -70,7 +72,7 @@
"Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c"
],
"Type": "checkbox",
"Default": true,
"Default": false,
"NewRow": true
},
"HAL_ADC": {
@ -500,7 +502,7 @@
"Prompt": "TIM8 Enable",
"Def": "USE_TIM8",
"Type": "checkbox",
"Default": false,
"Default": true,
"NewRow": true
},
"TIM6_Handler": {
@ -583,21 +585,31 @@
}
},
"ADC": {
"Sources": [
"Drivers/STM32_SIMULINK/stm32_matlab_adc.c"
],
"Defines": {
"ADC1_Enable": {
"Prompt": "ADC1 Enable",
"Def": "ADC1_ENABLE",
"Def": "USE_ADC1",
"Type": "checkbox",
"Default": false,
"NewRow": true
},
"ADC2_Enable": {
"Prompt": "ADC2 Enable",
"Def": "ADC2_ENABLE",
"Def": "USE_ADC2",
"Type": "checkbox",
"Default": false,
"NewRow": true
},
"ADC3_Enable": {
"Prompt": "ADC3 Enable",
"Def": "USE_ADC3",
"Type": "checkbox",
"Default": true,
"NewRow": true
},
"Sample_Rate": {
"Prompt": "Sample Rate (Hz)",
"Def": "SAMPLE_RATE",

View File

@ -197,24 +197,24 @@ static void mdlTerminate(SimStruct* S)
//// Простая версия - ждем завершения потока
// Ждем до 5 секунд
for (int i = 0; i < 50; i++) {
// Проверяем, завершился ли поток (упрощенная проверка)
DWORD exitCode;
if (GetExitCodeThread(hmcu.hMCUThread, &exitCode) && exitCode != STILL_ACTIVE) {
break; // поток завершился
}
Sleep(100); // ждем 100ms
}
//// Даем потоку шанс завершиться нормально
//DWORD waitResult = WaitForSingleObject(hmcu.hMCUThread, 3000);
//if (waitResult == WAIT_TIMEOUT) {
// // Поток не ответил - завершаем принудительно
// TerminateThread(hmcu.hMCUThread, 0);
//// Ждем до 5 секунд
//for (int i = 0; i < 50; i++) {
// // Проверяем, завершился ли поток (упрощенная проверка)
// DWORD exitCode;
// if (GetExitCodeThread(hmcu.hMCUThread, &exitCode) && exitCode != STILL_ACTIVE) {
// break; // поток завершился
// }
// Sleep(100); // ждем 100ms
//}
// Даем потоку шанс завершиться нормально
DWORD waitResult = WaitForSingleObject(hmcu.hMCUThread, 10000);
if (waitResult == WAIT_TIMEOUT) {
// Поток не ответил - завершаем принудительно
TerminateThread(hmcu.hMCUThread, 0);
}
CloseHandle(hmcu.hMCUThread);
hmcu.hMCUThread = NULL;
}

View File

@ -114,8 +114,7 @@ void MCU_Periph_Simulation(SimStruct* S)
{
// PERIPH SIM START
uwTick = hmcu.SystemClock / (MCU_CORE_CLOCK / 1000);
Simulate_TIMs();
Simulate_GPIO_BSRR();
Simulate_Periph_Sim();
// PERIPH SIM END
}

View File

@ -51,11 +51,11 @@
// INPUT/OUTPUTS PARAMS START
#define IN_PORT_NUMB 2
#define ADC_PORT_1_WIDTH 6
#define IN_PORT_2_WIDTH 16
#define IN_PORT_2_WIDTH 1
#define OUT_PORT_NUMB 2
#define THYR_PORT_1_WIDTH 6
#define OUT_PORT_2_WIDTH 16
#define OUT_PORT_2_WIDTH 6
// INPUT/OUTPUTS PARAMS END
/** WRAPPER_CONF

View File

@ -0,0 +1,156 @@
@echo off
:: Получаем аргументы из командной строки
:: %1 - includes_USER
:: %2 - code_USER
:: %3 - режим (например, debug)
:: Аргументы:
:: %1 — includes строка (в кавычках)
:: %2 — sources строка
:: %3 — defines строка
:: %4 — режим компиляции (debug/release)
:: Сохраняем как переменные
set filename=%~1
set includes_USER=%~2
set code_USER=%~3
set defines_USER=%~4
set defines_CONFIG=%~5
set compil_mode=%~6
:: Заменяем __EQ__ на =
set defines_USER=%defines_USER:__EQ__==%
set defines_CONFIG=%defines_CONFIG:__EQ__==%
set defines_WRAPPER=-D"MATLAB"^ -D"__sizeof_ptr=8"
:: -------------------------USERS PATHS AND CODE---------------------------
::-------------------------------------------------------------------------
:: -------------------------WRAPPER PATHS AND CODE---------------------------
:: оболочка, которая будет моделировать работу МК в симулинке
:: WRAPPER BAT START
set code_WRAPPER=.\MCU_Wrapper\MCU.c^
.\MCU_Wrapper\mcu_wrapper.c
set includes_WRAPPER= -I".\MCU_Wrapper\"
:: WRAPPER BAT END
:: APP WRAPPER BAT START
set code_APP_WRAPPER=.\app_wrapper\app_wrapper.c^
.\app_wrapper\app_init.c^
.\app_wrapper\app_io.c
set includes_APP_WRAPPER= -I".\app_wrapper\"
:: APP WRAPPER BAT END
set includes_WRAPPER= %includes_WRAPPER% %includes_APP_WRAPPER%
set code_WRAPPER= %code_WRAPPER% %code_APP_WRAPPER%
:: PERIPH BAT START
set code_PERIPH=.\MCU_STM32_Matlab\stm32_matlab_conf.c^
.\MCU_STM32_Matlab\Drivers\STM32_SIMULINK\stm32_matlab_gpio.c^
.\MCU_STM32_Matlab\Drivers\STM32_SIMULINK\stm32_matlab_dma.c^
.\MCU_STM32_Matlab\Drivers\STM32_SIMULINK\stm32_periph_registers.c^
.\MCU_STM32_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal.c^
.\MCU_STM32_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_adc.c^
.\MCU_STM32_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_adc_ex.c^
.\MCU_STM32_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cortex.c^
.\MCU_STM32_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma.c^
.\MCU_STM32_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_exti.c^
.\MCU_STM32_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_gpio.c^
.\MCU_STM32_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pwr.c^
.\MCU_STM32_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pwr_ex.c^
.\MCU_STM32_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc.c^
.\MCU_STM32_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc_ex.c^
.\MCU_STM32_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_tim.c^
.\MCU_STM32_Matlab\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_tim_ex.c^
.\MCU_STM32_Matlab\Drivers\STM32_SIMULINK\stm32_matlab_tim.c^
.\MCU_STM32_Matlab\Drivers\STM32_SIMULINK\stm32_matlab_adc.c
set includes_PERIPH=-I".\MCU_STM32_Matlab\."^
-I".\MCU_STM32_Matlab\Drivers\STM32_SIMULINK"^
-I".\MCU_STM32_Matlab\Drivers\CMSIS"^
-I".\MCU_STM32_Matlab\Drivers\CMSIS\Device\STM32F4xx"^
-I".\MCU_STM32_Matlab\Drivers\STM32F4xx_HAL_Driver\Inc"^
-I".\MCU_STM32_Matlab\Drivers\STM32F4xx_HAL_Driver\Inc\Legacy"
:: PERIPH BAT END
::-------------------------------------------------------------------------
:: ---------------------SET PARAMS FOR MEX COMPILING-----------------------
:: -------------ALL------------
set includes= %includes_WRAPPER% %includes_PERIPH% %includes_USER%
set codes= %code_USER% %code_WRAPPER% %code_PERIPH%
set defines= %defines_WRAPPER% %defines_CONFIG% %defines_USER%
:: -------OUTPUT FOLDER--------
set output= -outdir "." -output %filename%
:: если нужен дебаг, до запускаем run_mex с припиской debug
IF %compil_mode%==debug (set debug= -g)
::-------------------------------------------------------------------------
::------START COMPILING-------
if "%7"=="echo_enable" (
echo Compiling...
echo ===========================
echo =========INCLUDES==========
echo USER:
for %%f in (%includes_USER%) do (
echo %%f
)
echo INTERNAL:
for %%f in (%includes_WRAPPER%) do (
echo %%f
)
echo PERIPH:
for %%f in (%includes_PERIPH%) do (
echo %%f
)
echo ===========================
echo ==========SOURCES==========
echo USER:
for %%f in (%code_USER%) do (
echo %%f
)
echo INTERNAL:
for %%f in (%code_WRAPPER%) do (
echo %%f
)
echo PERIPH:
for %%f in (%code_PERIPH%) do (
echo %%f
)
echo ===========================
echo ==========DEFINES==========
echo USER:
for %%d in (%defines_USER%) do (
echo %%d
)
echo CONFIG:
for %%f in (%defines_CONFIG%) do (
echo %%f
)
echo INTERNAL:
for %%f in (%defines_WRAPPER%) do (
echo %%f
)
)
echo ===========================
echo MODE: %compil_mode%
echo ===========================
:: 1. ПРЕЖДЕ ЧЕМ КОМПИЛИРОВАТЬ - ВЫГРУЗИТЬ СТАРЫЙ ФАЙЛ
:: 2. Компиляция с флагами для MSVC
:: set LINK_EMBEDDED=/BASE:0x10000000 /FIXED:NO /FILEALIGN:0x1000 /FORCE:MULTIPLE /DYNAMICBASE:NO
set C_EMBEDDED="-w"
mex %output% %defines% %includes% %codes% %debug% CFLAGS="$CFLAGS %C_EMBEDDED%" LINKFLAGS="$LINKFLAGS %LINK_EMBEDDED%"
echo %DATE% %TIME%
exit /b %ERRORLEVEL%

View File

@ -10,9 +10,11 @@
// INCLUDES START
// Инклюды для доступа к коду МК в коде оболочке
//#include "stm32_matlab_conf.h"
#include "main.h"
#include "tim.h"
#include "adc.h"
#include "upp_main.h"
#include "adc_tools.h"
// INCLUDES END
#endif //_APP_INCLUDES_H_

View File

@ -17,10 +17,14 @@ void app_init(void) {
// Вызов разных функций в случае,
// если не используется отдельный поток для main().
HAL_Init();
MX_DMA_Init();
MX_TIM1_Init();
MX_TIM3_Init();
__HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_1, __HAL_TIM_GET_AUTORELOAD(&hpwm1)/2);
HAL_TIM_PWM_Start(&hpwm1, PWM_CHANNEL_1);
MX_TIM8_Init();
MX_ADC3_Init();
UPP_Init();
UPP_PreWhile();
// USER APP INIT END
}

View File

@ -32,6 +32,15 @@ void ThyristorWrite(real_T* Buffer)
*/
void app_readInputs(const real_T* Buffer) {
// USER APP INPUT START
ADC_Set_Channel_Value(ADC3, 4, ReadInputArray(0,0));
ADC_Set_Channel_Value(ADC3, 5, ReadInputArray(0,1));
ADC_Set_Channel_Value(ADC3, 6, ReadInputArray(0,2));
ADC_Set_Channel_Value(ADC3, 7, ReadInputArray(0,3));
ADC_Set_Channel_Value(ADC3, 8, ReadInputArray(0,4));
ADC_Set_Channel_Value(ADC3, 10, ReadInputArray(0,5));
__HAL_TIM_SET_AUTORELOAD(&adc_tim, ReadInputArray(1, 0));
// USER APP INPUT END
}
@ -43,6 +52,17 @@ void app_readInputs(const real_T* Buffer) {
*/
void app_writeOutputBuffer(real_T* Buffer) {
// USER APP OUTPUT START
ThyristorWrite(Buffer);
//ThyristorWrite(Buffer);
for (int i = 0; i < 2; i++)
{
WriteOutputArray(ZC_Detected[i], 0, i);
}
extern ADC_Period_t adc;
for(int i = 0; i < 6; i++)
{
WriteOutputArray(adc.Data[i], 1, i);
}
// USER APP OUTPUT END
}

Binary file not shown.

File diff suppressed because one or more lines are too long

@ -1 +1 @@
Subproject commit eff64709bccb8f8fa7297f4042f4ebb7c71a5a21
Subproject commit 3b162c9f8cdbcf8606d1b96ea2b26b23e2e9c290

View File

@ -13,7 +13,6 @@
#include "upp_config.h"
// user includes
#ifndef MATLAB
/**
* @addtogroup TRACE_CONFIG Trace configs
* @ingroup MYLIBS_CONFIG
@ -53,6 +52,26 @@
*/
/**
* @addtogroup FILTER_CONFIG Filter configs
* @ingroup MYLIBS_CONFIG
* @brief Конфигурация фильтров
* @{
*/
#define FILTERS_ENABLE ///< Включить библиотеку фильтров
//#define FILTER_MEDIAN_MAX_SIZE ///< Максимальный размер окна медианного фильтра (по умолчанию 5)
//#define FILTER_AVERAGE_MAX_SIZE ///< Максимальный размер окна усредняющего фильтра (по умолчанию 8)
//#define FILTER_POLY_MAX_ORDER ///< Максимальный порядок полинома (по умолчанию 4)
/** GEN_CONFIG
* @}
*/
/**
* @addtogroup GEN_CONFIG Genetic configs
* @ingroup MYLIBS_CONFIG
@ -93,6 +112,7 @@
* @{
*/
#ifndef MATLAB
#define local_time() uwTick ///< Локальное время
#define INCLUDE_GEN_OPTIMIZER ///< Подключить библиотеку для оптимизации параметров
@ -100,9 +120,22 @@
#define INCLUDE_TRACKERS_LIB ///< Подключить библиотеку с трекерами
#define INCLUDE_TRACE_LIB ///< Подключить библиотеку с трейсами
#define INCLUDE_GENERAL_PERIPH_LIBS ///< Подключить библиотеку с периферией
#define INCLUDE_BENCH_TIME ///< Подключить библиотеку с периферией
#define INCLUDE_BENCH_TIME ///< Подключить библиотеку с бенчмарком времени
#define INCLUDE_FILTERS ///< Подключить библиотеку с фильтрами
//#define FREERTOS_DELAY ///< Использовать FreeRTOS задержку, вместо HAL
#else
#define local_time() uwTick ///< Локальное время
//#define INCLUDE_GEN_OPTIMIZER ///< Подключить библиотеку для оптимизации параметров
#define INCLUDE_BIT_ACCESS_LIB ///< Подключить библиотеку с typedef с битовыми полями
#define INCLUDE_TRACKERS_LIB ///< Подключить библиотеку с трекерами
//#define INCLUDE_TRACE_LIB ///< Подключить библиотеку с трейсами
//#define INCLUDE_GENERAL_PERIPH_LIBS ///< Подключить библиотеку с периферией
//#define INCLUDE_BENCH_TIME ///< Подключить библиотеку с бенчмарком времени
#define INCLUDE_FILTERS ///< Подключить библиотеку с фильтрами
#endif //MATLAB
/** LIBS_CONFIG
* @}
*/
@ -110,5 +143,4 @@
/** MYLIBS_CONFIG
* @}
*/
#endif //MATLAB
#endif //__MYLIBS_CONFIG_H_

View File

@ -100,6 +100,52 @@
#define BenchTime_ResetStats(channel)
#endif //BENCH_TIME_ENABLE
#ifdef INCLUDE_FILTERS
#include "filters.h"
#else //INCLUDE_FILTERS
// Заглушки для float
#define FilterMedian_t void *
#define FilterExp_t void *
#define FilterAverage_t void *
#define FilterPoly_t void *
#define FilterLUT_t void *
#define FilterMedian_Init(filter, size)
#define FilterMedian_Process(filter, input) (input)
#define FilterExp_Init(filter, alpha)
#define FilterExp_Process(filter, input) (input)
#define FilterAverage_Init(filter, size)
#define FilterAverage_Process(filter, input) (input)
#define FilterPoly_Init(filter, coeffs, order) (0)
#define FilterPoly_Process(filter, input) (input)
#define FilterLUT_Init(filter, input_arr, output_arr, size, interpolation) (0)
#define FilterLUT_Process(filter, input) (input)
// Заглушки для int32_t
#define FilterMedianInt_t void *
#define FilterExpInt_t void *
#define FilterAverageInt_t void *
#define FilterPolyInt_t void *
#define FilterLUTInt_t void *
#define FilterMedianInt_Init(filter, size)
#define FilterMedianInt_Process(filter, input) (input)
#define FilterExpInt_Init(filter, alpha, scale)
#define FilterExpInt_Process(filter, input) (input)
#define FilterAverageInt_Init(filter, size)
#define FilterAverageInt_Process(filter, input) (input)
#define FilterPolyInt_Init(filter, coeffs, order, scale) (0)
#define FilterPolyInt_Process(filter, input) (input)
#define FilterLUTInt_Init(filter, input_arr, output_arr, size, interpolation) (0)
#define FilterLUTInt_Process(filter, input) (input)
#define FILTER_GET_STATE(_fltr_) dummy
#define FILTER_ENABLE 0
#define FILTER_DISABLE 0
#endif //INCLUDE_FILTERS
#ifdef INCLUDE_GENERAL_PERIPH_LIBS
#include "__general_flash.h"

View File

@ -35,7 +35,7 @@ extern "C" {
extern ADC_HandleTypeDef hadc3;
/* USER CODE BEGIN Private defines */
extern DMA_HandleTypeDef hdma_adc3;
/* USER CODE END Private defines */
void MX_ADC3_Init(void);

52
UPP/Core/Inc/dma.h Normal file
View File

@ -0,0 +1,52 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file dma.h
* @brief This file contains all the function prototypes for
* the dma.c file
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __DMA_H__
#define __DMA_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* DMA memory to memory transfer handles -------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_DMA_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __DMA_H__ */

View File

@ -57,24 +57,25 @@ extern "C" {
void Error_Handler(void);
/* USER CODE BEGIN EFP */
extern __IO uint32_t micros;
/* USER CODE END EFP */
/* Private defines -----------------------------------------------------------*/
#define mb_huart huart3
#define mbdbg_htim htim11
#define mb_htim htim12
#define mb_dbg_huart huart6
#define ustim htim13
#define mem_hspi hspi3
#define hpwm1 htim1
#define hpwm2 htim2
#define PWM_CHANNEL_1 TIM_CHANNEL_1
#define PWM_CHANNEL_2 TIM_CHANNEL_2
#define PWM_CHANNEL_3 TIM_CHANNEL_3
#define PWM_CHANNEL_4 TIM_CHANNEL_4
#define mem_hspi hspi3
#define PWM_CHANNEL_5 TIM_CHANNEL_3
#define PWM_CHANNEL_6 TIM_CHANNEL_4
#define mb_htim htim12
#define adc_tim htim8
#define hpwm2 htim2
#define mb_dbg_huart huart6
#define ustim htim13
#define hpwm1 htim1
#define UM_LED_GREEN2_Pin GPIO_PIN_2
#define UM_LED_GREEN2_GPIO_Port GPIOE
#define CEN_O_Pin GPIO_PIN_3

View File

@ -56,6 +56,7 @@ void DebugMon_Handler(void);
void PendSV_Handler(void);
void SysTick_Handler(void);
void TIM8_TRG_COM_TIM14_IRQHandler(void);
void DMA2_Stream0_IRQHandler(void);
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */

View File

@ -36,6 +36,8 @@ extern TIM_HandleTypeDef htim1;
extern TIM_HandleTypeDef htim3;
extern TIM_HandleTypeDef htim8;
extern TIM_HandleTypeDef htim11;
extern TIM_HandleTypeDef htim12;
@ -48,6 +50,7 @@ extern TIM_HandleTypeDef htim13;
void MX_TIM1_Init(void);
void MX_TIM3_Init(void);
void MX_TIM8_Init(void);
void MX_TIM11_Init(void);
void MX_TIM12_Init(void);
void MX_TIM13_Init(void);

View File

@ -0,0 +1,229 @@
/**
******************************************************************************
* @file adc_tools.c
* @brief Модуль считывающий данные с АЦП
******************************************************************************
* @details
******************************************************************************/
#include "adc_tools.h"
// Проверка корректности структуры АЦП
#define assert_adc(_adc_) check_null_ptr_2(_adc_, (_adc_)->f.Initialized)
static void ADC_EnableAllFilters(ADC_Period_t *adc)
{
for(int i = 0; i < ADC_NUMB_OF_CHANNELS; i++)
{
FILTER_GET_STATE(&adc->filter[i]) = FILTER_ENABLE;
}
}
static void ADC_InitAllFilters(ADC_Period_t *adc, int coef)
{
for(int i = 0; i < ADC_NUMB_OF_CHANNELS; i++)
{
FilterAverageInt_Init(&adc->filter[i], coef);
}
FilterLUTInt_Init(&adc->temp_filter[0],
(int32_t *)adc_temp_quants,
(int32_t *)adc_temp_vals,
sizeof(adc_temp_quants), 0);
FilterLUTInt_Init(&adc->temp_filter[1],
(int32_t *)adc_temp_quants,
(int32_t *)adc_temp_vals,
sizeof(adc_temp_quants), 0);
}
/**
* @brief Инициализация периодического АЦП.
* @param adc Указатель на кастомный хендл АЦП
* @param htim Указатель на HAL хендл таймера
* @param hadc Указатель на HAL хендл АЦП
* @return HAL Status.
*/
HAL_StatusTypeDef ADC_Init(ADC_Period_t *adc, TIM_HandleTypeDef *htim, ADC_HandleTypeDef *hadc)
{
HAL_StatusTypeDef res;
if(check_null_ptr_2(htim, hadc))
return HAL_ERROR;
adc->htim = htim;
adc->hadc = hadc;
ADC_InitAllFilters(adc, 10);
adc->f.AdcRunning = 0;
adc->f.DataReady = 0;
adc->f.Initialized = 1;
return HAL_OK;
}
/**
* @brief Конфигуарция канала АЦП.
* @param adc Указатель на кастомный хендл АЦП
* @param ChNumb Номер канала для конфигурации
* @param levelZero Нулевой уровень (в квантах АЦП)
* @param valueMax Максимальный уровень Единиц Измерения (в Вольтах/Амперах/Градусах)
* @param levelMax Максимальный уровень АЦП (в квантах АЦП)
* @return HAL Status.
*/
HAL_StatusTypeDef ADC_ConfigChannel(ADC_Period_t *adc, int ChNumb, uint16_t levelZero, float valueMax, uint16_t levelMax)
{
HAL_StatusTypeDef res;
if(assert_adc(adc))
return HAL_ERROR;
if((valueMax == 0) || (levelMax == 0))
return HAL_ERROR;
adc->Coefs[ChNumb].lMax = levelMax;
adc->Coefs[ChNumb].vMax = valueMax;
adc->Coefs[ChNumb].lZero = levelZero;
return HAL_OK;
}
/**
* @brief Запуск АЦП.
* @param adc Указатель на кастомный хендл АЦП
* @param Period Период таймера с какой частотой будет работать АЦП
* @return HAL Status.
* @details Запускает АЦП с частотой дискретизации на которую настроен таймер adc_tim.
*/
HAL_StatusTypeDef ADC_Start(ADC_Period_t *adc, uint16_t Period)
{
HAL_StatusTypeDef res;
if(assert_adc(adc))
return HAL_ERROR;
if(Period == 0)
return HAL_ERROR;
// Запускаем таймер который будет запускать опрос АЦП с заданным периодом
__HAL_TIM_SET_AUTORELOAD(adc->htim, Period);
res = HAL_TIM_Base_Start(adc->htim);
if(res != HAL_OK)
{
return res;
}
// Запускаем АЦП который будет перекидывать данные в ADC_DMA_Buffer
res = HAL_ADC_Start_DMA(adc->hadc, (uint32_t*)adc->RawData, 6); // Затем АЦП с DMA
if(res != HAL_OK)
{
return res;
}
//ADC_EnableAllFilters(adc);
FILTER_GET_STATE(&adc->temp_filter[0]) = FILTER_ENABLE;
FILTER_GET_STATE(&adc->temp_filter[1]) = FILTER_ENABLE;
return res;
}
/**
* @brief Остановка АЦП .
* @param adc Указатель на кастомный хендл АЦП
* @return HAL Status.
* @details По факту остановка таймера, который запускает АЦП. Сам АЦП продолжает работу.
*/
HAL_StatusTypeDef ADC_Stop(ADC_Period_t *adc)
{
if(assert_adc(adc))
return HAL_ERROR;
// Запускаем таймер который будет запускать опрос АЦП
return HAL_TIM_Base_Stop(adc->htim);
}
/**
* @brief Обработка АЦП.
* @return HAL Status.
* @details По факту остановка таймера, который запускает АЦП. Сам АЦП продолжает работу.
* @note Вызывается в DMA2_Stream0_IRQHandler() для обработки всего, что пришло по DMA.
*/
HAL_StatusTypeDef ADC_Handle(ADC_Period_t *adc)
{
if(assert_adc(adc))
return HAL_ERROR;
ADC_Coefs_t *coefs = adc->Coefs;
uint16_t *raw = adc->RawData;
float *data = adc->Data;
// Фильтрация от шумов для всех каналов
for(int i = 0; i < ADC_NUMB_OF_CHANNELS; i++)
{
if(FILTER_GET_STATE(&adc->filter[i]) == FILTER_ENABLE)
{
// заменяем сырое на отфильтровоное сырое
raw[i] = FilterAverageInt_Process(&adc->filter[i], raw[i]);
}
}
// Перерасчеты Напряжений/Токов в единицы измерения
for(int i = 0; i < ADC_TEMP_CHANNELS_START; i++)
{
ADC_Coefs_t *coefs = &adc->Coefs[i];
data[i] = ((float)(raw[i])-coefs->lZero) * coefs->vMax / (coefs->lMax-coefs->lZero);
}
// Преобразования температуры по таблице
for (int i = ADC_TEMP_CHANNELS_START; i < ADC_NUMB_OF_CHANNELS; i++)
{
data[i] = FilterLUTInt_Process(&adc->temp_filter[i-ADC_TEMP_CHANNELS_START], raw[i]);
}
adc->f.DataReady = 1;
return HAL_OK;
}
/**
* @brief Сбор статистики.
*/
void ADC_UpdateStatistics(ADC_Period_t *adc, uint8_t channel, float value)
{
if(assert_adc(adc))
return;
if (channel >= ADC_NUMB_OF_REGULAR_CHANNELS) return;
ADC_Statistics *stat = &adc->Stat[channel];
// Первая инициализация
if (stat->SampleCount == 0) {
stat->Max = value;
stat->Min = value;
stat->Sum = 0;
stat->SumSquares = 0;
}
// Обновление min/max
if (value > stat->Max) stat->Max = value;
if (value < stat->Min) stat->Min = value;
// Накопление для Avg/RMS
stat->Sum += value;
stat->SumSquares += value * value;
stat->SampleCount++;
// Расчет Avg/RMS (периодически или по запросу)
if (stat->SampleCount >= 1000) { // Пример: пересчет каждые 1000 samples
stat->Avg = stat->Sum / stat->SampleCount;
stat->RMS = sqrtf(stat->SumSquares / stat->SampleCount);
// Сброс накопителей
stat->Sum = 0;
stat->SumSquares = 0;
stat->SampleCount = 0;
}
}
/**
* @brief Сброс статистики.
*/
void ADC_ResetStatistics(ADC_Period_t *adc, uint8_t channel)
{
if (channel < ADC_NUMB_OF_REGULAR_CHANNELS) {
memset(&adc->Stat[channel], 0, sizeof(ADC_Statistics));
}
}

View File

@ -0,0 +1,110 @@
/**
******************************************************************************
* @file adc_tools.h
* @brief Модуль считывающий данные с АЦП
******************************************************************************
* @details
******************************************************************************/
#ifndef _ADC_TOOLS_H_
#define _ADC_TOOLS_H_
#include "main.h"
#define ADC_NUMB_OF_CHANNELS 6
#define ADC_NUMB_OF_REGULAR_CHANNELS 4
#define ADC_TEMP_CHANNELS_START ADC_NUMB_OF_REGULAR_CHANNELS
#define ADC_TEMPERATURES_QUANTS \
{ 2188, 2197, 2206, 2216, 2226, 2236, 2247, 2259, 2271, 2283, \
2296, 2310, 2324, 2338, 2354, 2369, 2385, 2402, 2419, 2437, \
2455, 2474, 2493, 2513, 2533, 2554, 2575, 2597, 2619, 2641, \
2664, 2688, 2711, 2735, 2759, 2784, 2809, 2833, 2859, 2884, \
2909, 2935, 2961, 2986, 3012, 3037, 3063, 3089, 3114, 3140, \
3165, 3190, 3215, 3239, 3263, 3288, 3312, 3335, 3359, 3381, \
3404, 3426, 3448, 3470, 3491, 3512, 3532, 3552, 3572, 3591, \
3610, 3628, 3646, 3663, 3681, 3697, 3714, 3729, 3745, 3760, \
3775, 3789, 3803, 3817, 3830, 3843, 3855, 3868, 3879, 3891, \
3902, 3913, 3924, 3934, 3944, 3954, 3963, 3972, 3981, 3989, \
3997, 4005, 4013, 4021, 4028, 4035, 4042, 4049, 4055, 4062, \
4068, 4074, 4079, 4085, 4091, 4096}
#define ADC_TEMPERATURES \
{ -25, -24, -23, -22, -21, -20, -19, -18, -17, -16, -15, -14, -13, -12, -11, \
-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, \
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, \
28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, \
46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, \
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, \
82, 83, 84, 85, 86, 87, 88, 89, 90}
static const int32_t adc_temp_vals[] = ADC_TEMPERATURES;
static const int32_t adc_temp_quants[] = ADC_TEMPERATURES_QUANTS;
/**
* @brief Коэфициенты канала АЦП для пересчета в единицы измерения
*/
typedef struct
{
uint16_t lZero; ///< Нулевой уровень (в квантах АЦП)
float vMax; ///< Максимальный уровень Единиц Измерения (в Вольтах/Амперах)
uint16_t lMax; ///< Максимальный уровень АЦП (в квантах АЦП)
}ADC_Coefs_t;
/**
* @brief Статистика АЦП
*/
typedef struct
{
float Max; ///< Пиковое значение
float Min; ///< Минимальное значение
float Avg; ///< Среднее арифметическое значение
float RMS; ///< Действующее значение
uint32_t SampleCount; ///< Для корректного расчета Avg/RMS
float Sum; ///< Накопитель для среднего
float SumSquares; ///< Накопитель для RMS
}ADC_Statistics;
/**
* @brief Хендл АЦП
*/
typedef struct
{
// Handles
TIM_HandleTypeDef *htim; ///< Хендл таймера, который запускает АЦП
ADC_HandleTypeDef *hadc; ///< Хендл АЦП
// Data and calculation
uint16_t RawData[ADC_NUMB_OF_CHANNELS]; ///< Сырые значения АЦП
ADC_Coefs_t Coefs[ADC_NUMB_OF_REGULAR_CHANNELS]; ///< Коэффициенты @ref ADC_Coefs_t для регулярных каналов (не температуры)
FilterAverageInt_t filter[ADC_NUMB_OF_CHANNELS]; ///< Фильтр от шумов АЦП
FilterLUTInt_t temp_filter[2]; ///< Коррекция нелинейности датчиков температуры
float Data[ADC_NUMB_OF_CHANNELS]; ///< Пересчитанные значения АЦП (в Вольтах/Амперах)
ADC_Statistics Stat[ADC_NUMB_OF_REGULAR_CHANNELS]; ///< Статистика для регулярных каналов (не температуры)
struct
{
unsigned Initialized:1;
unsigned AdcRunning:1;
unsigned DataReady:1;
}f; ///< Флаги
uint32_t LastTick; // Время последнего преобразования
}ADC_Period_t;
/* Инициализация периодического АЦП */
HAL_StatusTypeDef ADC_Init(ADC_Period_t *adc, TIM_HandleTypeDef *htim, ADC_HandleTypeDef *hadc);
/* Конфигуарция канала АЦП. */
HAL_StatusTypeDef ADC_ConfigChannel(ADC_Period_t *adc, int ChNumb, uint16_t levelZero, float valueMax, uint16_t levelMax);
/* Запуск АЦП. */
HAL_StatusTypeDef ADC_Start(ADC_Period_t *adc, uint16_t Period);
/* Остановка АЦП. */
HAL_StatusTypeDef ADC_Stop(ADC_Period_t *adc);
/* Остановка АЦП . */
HAL_StatusTypeDef ADC_Handle(ADC_Period_t *adc);
#endif //_ADC_TOOLS_H_

View File

@ -0,0 +1,333 @@
/**
******************************************************************************
* @file zero_cross.c
* @brief Модуль фиксирующий переход через ноль
******************************************************************************
* @details
******************************************************************************/
#include "zero_cross.h"
#include <string.h>
/**
* @brief Инициализация детектора нуля с индивидуальными настройками.
* @param zc Указатель на хендл детектора нуля
* @param num_channels Количество каналов для этого хендла
* @param hysteresis Гистерезис для избежания дребезга
* @param debounce_samples Количество samples для антидребезга
* @return HAL Status.
*/
HAL_StatusTypeDef ZC_Init(ZeroCross_Handle_t *zc, uint8_t num_channels,
float hysteresis, uint8_t debounce_samples)
{
if (zc == NULL || num_channels == 0 || num_channels > ZC_MAX_CHANNELS) {
return HAL_ERROR;
}
// Инициализация структуры
memset(zc, 0, sizeof(ZeroCross_Handle_t));
// Установка параметров хендла
zc->NumChannels = num_channels;
zc->Hysteresis = hysteresis;
zc->DebounceSamples = debounce_samples;
// Инициализация каналов
for (int i = 0; i < num_channels; i++) {
zc->Channel[i].CrossCount = 0;
zc->Channel[i].LastValue = 0.0f;
zc->Channel[i].CurrentValue = 0.0f;
zc->Channel[i].DebounceCounter = 0;
zc->Channel[i].StableState = 0;
zc->Channel[i].LastCrossTime = 0;
zc->Channel[i].Period = 0;
zc->Channel[i].Frequency = 0.0f;
zc->Channel[i].EdgeType = ZC_BOTH_EDGES;
}
zc->f.Initialized = 1;
zc->f.Monitoring = 1;
return HAL_OK;
}
/**
* @brief Настройка канала детектора.
* @param zc Указатель на хендл детектора нуля
* @param channel Номер канала для конфигурации
* @param edgeType Тип детектируемого перехода
* @return HAL Status.
*/
HAL_StatusTypeDef ZC_ConfigChannel(ZeroCross_Handle_t *zc, uint8_t channel,
ZC_EdgeType_t edgeType)
{
if (zc == NULL || !zc->f.Initialized) {
return HAL_ERROR;
}
if (channel >= zc->NumChannels) {
return HAL_ERROR;
}
zc->Channel[channel].EdgeType = edgeType;
// Сброс состояния канала при реконфигурации
zc->Channel[channel].LastValue = 0.0f;
zc->Channel[channel].DebounceCounter = 0;
zc->Channel[channel].StableState = 0;
zc->Channel[channel].LastCrossTime = 0;
zc->Channel[channel].Period = 0;
zc->Channel[channel].Frequency = 0.0f;
zc->Channel[channel].CrossCount = 0;
return HAL_OK;
}
/**
* @brief Основная функция обработки значения канала.
* @param zc Указатель на хендл детектора нуля
* @param channel Номер канала
* @param value Текущее значение сигнала
* @param timestamp Временная метка измерения в микросекундах
*/
void ZC_ProcessChannel(ZeroCross_Handle_t *zc, uint8_t channel, float value, uint32_t timestamp)
{
if (zc == NULL || !zc->f.Initialized || !zc->f.Monitoring) {
return;
}
if (channel >= zc->NumChannels) {
return;
}
ZC_Channel_t *zc_ch = &zc->Channel[channel];
zc_ch->CurrentValue = value;
// Детектирование rising edge (отрицательное -> положительное)
if ((zc_ch->LastValue <= -zc->Hysteresis) &&
(value >= zc->Hysteresis)) {
if (zc_ch->EdgeType == ZC_RISING_EDGE || zc_ch->EdgeType == ZC_BOTH_EDGES) {
// Переход подтвержден сразу (без дебаунса)
if (zc_ch->LastCrossTime != 0) {
// Расчет периода и частоты
zc_ch->Period = timestamp - zc_ch->LastCrossTime;
if (zc_ch->Period > 0) {
zc_ch->Frequency = 1000000.0f / zc_ch->Period;
}
}
zc_ch->LastCrossTime = timestamp;
zc_ch->CrossCount++;
zc_ch->StableState = 1;
}
}
// Детектирование falling edge (положительное -> отрицательное)
else if ((zc_ch->LastValue >= zc->Hysteresis) &&
(value <= -zc->Hysteresis)) {
if (zc_ch->EdgeType == ZC_FALLING_EDGE || zc_ch->EdgeType == ZC_BOTH_EDGES) {
// Переход подтвержден сразу (без дебаунса)
if (zc_ch->LastCrossTime != 0) {
// Расчет периода и частоты
zc_ch->Period = timestamp - zc_ch->LastCrossTime;
if (zc_ch->Period > 0) {
zc_ch->Frequency = 1000000.0f / zc_ch->Period;
}
}
zc_ch->LastCrossTime = timestamp;
zc_ch->CrossCount++;
zc_ch->StableState = 0;
}
}
// Сохраняем текущее значение для следующей итерации в случае если оно не в мертвой зоне
if((value > zc->Hysteresis) || (value < -zc->Hysteresis))
{
zc_ch->LastValue = value;
}
}
/**
* @brief Пакетная обработка всех каналов.
* @param zc Указатель на хендл детектора нуля
* @param values Массив значений сигналов
* @param timestamp Временная метка измерения
*/
void ZC_ProcessAllChannels(ZeroCross_Handle_t *zc, float values[], uint32_t timestamp)
{
if (zc == NULL || !zc->f.Initialized || !zc->f.Monitoring || values == NULL) {
return;
}
for (int ch = 0; ch < zc->NumChannels; ch++) {
ZC_ProcessChannel(zc, ch, values[ch], timestamp);
}
}
/**
* @brief Получение частоты сигнала.
* @param zc Указатель на хендл детектора нуля
* @param channel Номер канала
* @return Частота в Гц.
*/
float ZC_GetFrequency(ZeroCross_Handle_t *zc, uint8_t channel)
{
if (zc == NULL || !zc->f.Initialized || channel >= zc->NumChannels) {
return 0.0f;
}
return zc->Channel[channel].Frequency;
}
/**
* @brief Получение периода сигнала.
* @param zc Указатель на хендл детектора нуля
* @param channel Номер канала
* @return Период в тактах таймера.
*/
uint32_t ZC_GetPeriod(ZeroCross_Handle_t *zc, uint8_t channel)
{
if (zc == NULL || !zc->f.Initialized || channel >= zc->NumChannels) {
return 0;
}
return zc->Channel[channel].Period;
}
/**
* @brief Получение счетчика переходов.
* @param zc Указатель на хендл детектора нуля
* @param channel Номер канала
* @return Количество переходов.
*/
uint32_t ZC_GetCrossCount(ZeroCross_Handle_t *zc, uint8_t channel)
{
if (zc == NULL || !zc->f.Initialized || channel >= zc->NumChannels) {
return 0;
}
return zc->Channel[channel].CrossCount;
}
/**
* @brief Получение текущего состояния канала.
* @param zc Указатель на хендл детектора нуля
* @param channel Номер канала
* @return Состояние (0 - отрицательное, 1 - положительное).
*/
uint8_t ZC_GetStableState(ZeroCross_Handle_t *zc, uint8_t channel)
{
if (zc == NULL || !zc->f.Initialized || channel >= zc->NumChannels) {
return 0;
}
return zc->Channel[channel].StableState;
}
/**
* @brief Получение текущего значения канала.
* @param zc Указатель на хендл детектора нуля
* @param channel Номер канала
* @return Текущее значение сигнала.
*/
float ZC_GetCurrentValue(ZeroCross_Handle_t *zc, uint8_t channel)
{
if (zc == NULL || !zc->f.Initialized || channel >= zc->NumChannels) {
return 0.0f;
}
return zc->Channel[channel].CurrentValue;
}
/**
* @brief Включение/выключение мониторинга.
* @param zc Указатель на хендл детектора нуля
* @param enable Флаг включения (1 - вкл, 0 - выкл)
*/
void ZC_EnableMonitoring(ZeroCross_Handle_t *zc, uint8_t enable)
{
if (zc == NULL || !zc->f.Initialized) {
return;
}
zc->f.Monitoring = enable ? 1 : 0;
}
/**
* @brief Сброс статистики канала.
* @param zc Указатель на хендл детектора нуля
* @param channel Номер канала
*/
void ZC_Reset(ZeroCross_Handle_t *zc, uint8_t channel)
{
if (zc == NULL || !zc->f.Initialized) {
return;
}
if (channel < zc->NumChannels) {
zc->Channel[channel].LastValue = 0.0f;
zc->Channel[channel].CurrentValue = 0.0f;
zc->Channel[channel].DebounceCounter = 0;
zc->Channel[channel].StableState = 0;
zc->Channel[channel].LastCrossTime = 0;
zc->Channel[channel].Period = 0;
zc->Channel[channel].Frequency = 0.0f;
zc->Channel[channel].CrossCount = 0;
}
else {
// Сброс всех каналов
for (int i = 0; i < zc->NumChannels; i++) {
zc->Channel[i].LastValue = 0.0f;
zc->Channel[i].CurrentValue = 0.0f;
zc->Channel[i].DebounceCounter = 0;
zc->Channel[i].StableState = 0;
zc->Channel[i].LastCrossTime = 0;
zc->Channel[i].Period = 0;
zc->Channel[i].Frequency = 0.0f;
zc->Channel[i].CrossCount = 0;
}
}
}
/**
* @brief Установка гистерезиса для хендла.
* @param zc Указатель на хендл детектора нуля
* @param hysteresis Значение гистерезиса
*/
void ZC_SetHysteresis(ZeroCross_Handle_t *zc, float hysteresis)
{
if (zc == NULL || !zc->f.Initialized) {
return;
}
zc->Hysteresis = hysteresis;
}
/**
* @brief Установка дебаунс samples для хендла.
* @param zc Указатель на хендл детектора нуля
* @param debounce_samples Количество samples для антидребезга
*/
void ZC_SetDebounceSamples(ZeroCross_Handle_t *zc, uint8_t debounce_samples)
{
if (zc == NULL || !zc->f.Initialized) {
return;
}
zc->DebounceSamples = debounce_samples;
}
/**
* @brief Получение количества каналов хендла.
* @param zc Указатель на хендл детектора нуля
* @return Количество каналов.
*/
uint8_t ZC_GetNumChannels(ZeroCross_Handle_t *zc)
{
if (zc == NULL || !zc->f.Initialized) {
return 0;
}
return zc->NumChannels;
}

View File

@ -0,0 +1,166 @@
/**
******************************************************************************
* @file zero_cross.h
* @brief Модуль фиксирующий переход через ноль
******************************************************************************
* @addtogroup ZERO_CROSS Zero-cross detection
* @brief Библиотека для детектирования переходов сигнала через ноль
* @details
Поддерживает:
- Многоканальное детектирование (несколько независимых сигналов)
- Детектирование фронтов: rising, falling, both
- Антидребезг с настраиваемым количеством samples
- Расчет частоты и периода сигнала
- Гистерезис для устойчивого детектирования
- Независимость от источника данных (ADC, DAC, другие)
- Индивидуальные настройки для каждого хендла
@par Пример использования:
@code
#include "zero_cross.h"
// Объявление структур
ZeroCross_Handle_t zc_handle;
float adc_values[2] = {0};
uint32_t timestamp = 0;
// Инициализация с индивидуальными настройками
ZC_Init(&zc_handle, 2, 0.1f, 3); // 2 канала, гистерезис 0.1, дебаунс 3 samples
// Настройка каналов
ZC_ConfigChannel(&zc_handle, 0, ZC_RISING_EDGE); // Канал 0 - только rising edge
ZC_ConfigChannel(&zc_handle, 1, ZC_BOTH_EDGES); // Канал 1 - оба фронта
// В основном цикле обработки ADC
while (1) {
// Получение данных от ADC (пример)
adc_values[0] = read_adc_channel(0); // Фаза A
adc_values[1] = read_adc_channel(1); // Фаза B
timestamp = HAL_GetTick() * 1000; // Текущее время в микросекундах
// Обработка всех каналов
ZC_ProcessAllChannels(&zc_handle, adc_values, timestamp);
// Получение результатов
float freq_a = ZC_GetFrequency(&zc_handle, 0);
float freq_b = ZC_GetFrequency(&zc_handle, 1);
uint32_t period_a = ZC_GetPeriod(&zc_handle, 0);
uint32_t cross_count_a = ZC_GetCrossCount(&zc_handle, 0);
// Использование в логике управления
if (freq_a > 55.0f || freq_a < 45.0f) {
// Авария по частоте
handle_frequency_fault();
}
}
// Пример создания нескольких хендлов с разными настройками
ZeroCross_Handle_t zc_high_sensitivity;
ZeroCross_Handle_t zc_low_sensitivity;
// Высокая чувствительность - малый гистерезис
ZC_Init(&zc_high_sensitivity, 2, 0.01f, 5); // 0.01 гистерезис, 5 samples дебаунс
// Низкая чувствительность - большой гистерезис для зашумленных сигналов
ZC_Init(&zc_low_sensitivity, 2, 0.5f, 2); // 0.5 гистерезис, 2 samples дебаунс
@endcode
* @{
*****************************************************************************/
#ifndef _ZERO_CROSS_H_
#define _ZERO_CROSS_H_
#include "main.h"
#ifndef ZC_MAX_CHANNELS
#define ZC_MAX_CHANNELS 8 ///< Максимальное количество каналов на хендл
#endif
/**
* @brief Тип перехода через ноль
*/
typedef enum {
ZC_BOTH_EDGES = 0, ///< Детектирование обоих переходов
ZC_RISING_EDGE, ///< Переход от отрицательного к положительному
ZC_FALLING_EDGE, ///< Переход от положительного к отрицательному
} ZC_EdgeType_t;
/**
* @brief Структура канала детектора нуля
*/
typedef struct {
uint32_t CrossCount; ///< Счетчик переходов
float LastValue; ///< Предыдущее значение
float CurrentValue; ///< Текущее значение
uint8_t DebounceCounter; ///< Счетчик антидребезга
uint8_t StableState; ///< Стабильное состояние (0=отриц, 1=полож)
uint32_t LastCrossTime; ///< Время последнего перехода
uint32_t Period; ///< Период сигнала (в тактах таймера)
float Frequency; ///< Частота
ZC_EdgeType_t EdgeType; ///< Тип детектируемого перехода
} ZC_Channel_t;
/**
* @brief Хендл детектора нуля
*/
typedef struct {
ZC_Channel_t Channel[ZC_MAX_CHANNELS]; ///< Каналы @ref ZC_Channel_t
uint8_t NumChannels; ///< Количество используемых каналов для этого хендла
float Hysteresis; ///< Гистерезис для избежания дребезга
uint8_t DebounceSamples; ///< Количество samples для антидребезга
struct {
unsigned Initialized:1; ///< Флаг инициализации
unsigned Monitoring:1; ///< Флаг активности мониторинга
} f; ///< Флаги
} ZeroCross_Handle_t;
/* Инициализация детектора нуля с индивидуальными настройками */
HAL_StatusTypeDef ZC_Init(ZeroCross_Handle_t *zc, uint8_t num_channels,
float hysteresis, uint8_t debounce_samples);
/* Настройка канала детектора */
HAL_StatusTypeDef ZC_ConfigChannel(ZeroCross_Handle_t *zc, uint8_t channel,
ZC_EdgeType_t edgeType);
/* Обработка значения отдельного канала */
void ZC_ProcessChannel(ZeroCross_Handle_t *zc, uint8_t channel, float value,
uint32_t timestamp);
/* Пакетная обработка всех каналов */
void ZC_ProcessAllChannels(ZeroCross_Handle_t *zc, float values[],
uint32_t timestamp);
/* Получение частоты сигнала */
float ZC_GetFrequency(ZeroCross_Handle_t *zc, uint8_t channel);
/* Получение периода сигнала */
uint32_t ZC_GetPeriod(ZeroCross_Handle_t *zc, uint8_t channel);
/* Получение счетчика переходов */
uint32_t ZC_GetCrossCount(ZeroCross_Handle_t *zc, uint8_t channel);
/* Получение текущего состояния канала */
uint8_t ZC_GetStableState(ZeroCross_Handle_t *zc, uint8_t channel);
/* Получение текущего значения канала */
float ZC_GetCurrentValue(ZeroCross_Handle_t *zc, uint8_t channel);
/* Включение/выключение мониторинга */
void ZC_EnableMonitoring(ZeroCross_Handle_t *zc, uint8_t enable);
/* Сброс статистики канала */
void ZC_Reset(ZeroCross_Handle_t *zc, uint8_t channel);
/* Установка гистерезиса для хендла */
void ZC_SetHysteresis(ZeroCross_Handle_t *zc, float hysteresis);
/* Установка дебаунс samples для хендла */
void ZC_SetDebounceSamples(ZeroCross_Handle_t *zc, uint8_t debounce_samples);
/* Получение количества каналов хендла */
uint8_t ZC_GetNumChannels(ZeroCross_Handle_t *zc);
#endif /* _ZERO_CROSS_H_ */
/**
* @}
*/

View File

@ -21,10 +21,11 @@
#include "adc.h"
/* USER CODE BEGIN 0 */
#include "tim.h"
/* USER CODE END 0 */
ADC_HandleTypeDef hadc3;
DMA_HandleTypeDef hdma_adc3;
/* ADC3 init function */
void MX_ADC3_Init(void)
@ -45,15 +46,15 @@ void MX_ADC3_Init(void)
hadc3.Instance = ADC3;
hadc3.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc3.Init.Resolution = ADC_RESOLUTION_12B;
hadc3.Init.ScanConvMode = DISABLE;
hadc3.Init.ScanConvMode = ENABLE;
hadc3.Init.ContinuousConvMode = DISABLE;
hadc3.Init.DiscontinuousConvMode = DISABLE;
hadc3.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc3.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc3.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
hadc3.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T8_TRGO;
hadc3.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc3.Init.NbrOfConversion = 1;
hadc3.Init.NbrOfConversion = 6;
hadc3.Init.DMAContinuousRequests = DISABLE;
hadc3.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc3.Init.EOCSelection = ADC_EOC_SEQ_CONV;
if (HAL_ADC_Init(&hadc3) != HAL_OK)
{
Error_Handler();
@ -61,13 +62,58 @@ void MX_ADC3_Init(void)
/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_7;
sConfig.Channel = ADC_CHANNEL_4;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_5;
sConfig.Rank = 2;
if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_6;
sConfig.Rank = 3;
if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_7;
sConfig.Rank = 4;
if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_8;
sConfig.Rank = 5;
if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_10;
sConfig.Rank = 6;
if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC3_Init 2 */
/* USER CODE END ADC3_Init 2 */
@ -107,6 +153,25 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(AI_Temp2_GPIO_Port, &GPIO_InitStruct);
/* ADC3 DMA Init */
/* ADC3 Init */
hdma_adc3.Instance = DMA2_Stream0;
hdma_adc3.Init.Channel = DMA_CHANNEL_2;
hdma_adc3.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc3.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc3.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc3.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_adc3.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_adc3.Init.Mode = DMA_NORMAL;
hdma_adc3.Init.Priority = DMA_PRIORITY_LOW;
hdma_adc3.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_adc3) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(adcHandle,DMA_Handle,hdma_adc3);
/* USER CODE BEGIN ADC3_MspInit 1 */
/* USER CODE END ADC3_MspInit 1 */
@ -137,6 +202,8 @@ void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)
HAL_GPIO_DeInit(AI_Temp2_GPIO_Port, AI_Temp2_Pin);
/* ADC3 DMA DeInit */
HAL_DMA_DeInit(adcHandle->DMA_Handle);
/* USER CODE BEGIN ADC3_MspDeInit 1 */
/* USER CODE END ADC3_MspDeInit 1 */

55
UPP/Core/Src/dma.c Normal file
View File

@ -0,0 +1,55 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file dma.c
* @brief This file provides code for the configuration
* of all the requested memory to memory DMA transfers.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "dma.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/*----------------------------------------------------------------------------*/
/* Configure DMA */
/*----------------------------------------------------------------------------*/
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/**
* Enable DMA controller clock
*/
void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA2_CLK_ENABLE();
/* DMA interrupt init */
/* DMA2_Stream0_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
}
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */

View File

@ -20,6 +20,7 @@
#include "main.h"
#include "adc.h"
#include "can.h"
#include "dma.h"
#include "iwdg.h"
#include "rtc.h"
#include "spi.h"
@ -28,12 +29,12 @@
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "upp_main.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
__IO uint32_t micros;
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
@ -92,6 +93,7 @@ int main(void)
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_DMA_Init();
MX_ADC3_Init();
MX_USART3_UART_Init();
MX_CAN1_Init();
@ -104,25 +106,23 @@ int main(void)
MX_SPI3_Init();
MX_TIM11_Init();
MX_TIM12_Init();
MX_TIM8_Init();
/* USER CODE BEGIN 2 */
#else
MX_TIM1_Init();
MX_TIM3_Init();
#endif
__HAL_TIM_SET_COMPARE(&hpwm1, PWM_CHANNEL_1, __HAL_TIM_GET_AUTORELOAD(&hpwm1)/2);
HAL_TIM_PWM_Start(&hpwm1, PWM_CHANNEL_1);
#else //MATLAB
#endif //MATLAB
UPP_Init();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
UPP_PreWhile();
while (1)
{
UPP_While();
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
int A = 0;
return A;
/* USER CODE END 3 */
}

View File

@ -22,6 +22,7 @@
#include "stm32f4xx_it.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "upp_main.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
@ -55,6 +56,8 @@
/* USER CODE END 0 */
/* External variables --------------------------------------------------------*/
extern DMA_HandleTypeDef hdma_adc3;
extern TIM_HandleTypeDef htim8;
extern TIM_HandleTypeDef htim14;
/* USER CODE BEGIN EV */
@ -207,12 +210,27 @@ void TIM8_TRG_COM_TIM14_IRQHandler(void)
/* USER CODE BEGIN TIM8_TRG_COM_TIM14_IRQn 0 */
#ifndef MATLAB
/* USER CODE END TIM8_TRG_COM_TIM14_IRQn 0 */
HAL_TIM_IRQHandler(&htim8);
HAL_TIM_IRQHandler(&htim14);
/* USER CODE BEGIN TIM8_TRG_COM_TIM14_IRQn 1 */
#endif
/* USER CODE END TIM8_TRG_COM_TIM14_IRQn 1 */
}
/**
* @brief This function handles DMA2 stream0 global interrupt.
*/
void DMA2_Stream0_IRQHandler(void)
{
/* USER CODE BEGIN DMA2_Stream0_IRQn 0 */
/* USER CODE END DMA2_Stream0_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_adc3);
/* USER CODE BEGIN DMA2_Stream0_IRQn 1 */
UPP_ADC_Handle();
/* USER CODE END DMA2_Stream0_IRQn 1 */
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */

View File

@ -26,6 +26,7 @@
TIM_HandleTypeDef htim1;
TIM_HandleTypeDef htim3;
TIM_HandleTypeDef htim8;
TIM_HandleTypeDef htim11;
TIM_HandleTypeDef htim12;
TIM_HandleTypeDef htim13;
@ -169,6 +170,47 @@ void MX_TIM3_Init(void)
/* USER CODE END TIM3_Init 2 */
HAL_TIM_MspPostInit(&htim3);
}
/* TIM8 init function */
void MX_TIM8_Init(void)
{
/* USER CODE BEGIN TIM8_Init 0 */
/* USER CODE END TIM8_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
/* USER CODE BEGIN TIM8_Init 1 */
/* USER CODE END TIM8_Init 1 */
htim8.Instance = TIM8;
htim8.Init.Prescaler = 0;
htim8.Init.CounterMode = TIM_COUNTERMODE_UP;
htim8.Init.Period = 1000;
htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim8.Init.RepetitionCounter = 0;
htim8.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim8) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim8, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim8, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM8_Init 2 */
/* USER CODE END TIM8_Init 2 */
}
/* TIM11 init function */
void MX_TIM11_Init(void)
@ -281,6 +323,21 @@ void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
/* USER CODE END TIM3_MspInit 1 */
}
else if(tim_baseHandle->Instance==TIM8)
{
/* USER CODE BEGIN TIM8_MspInit 0 */
/* USER CODE END TIM8_MspInit 0 */
/* TIM8 clock enable */
__HAL_RCC_TIM8_CLK_ENABLE();
/* TIM8 interrupt Init */
HAL_NVIC_SetPriority(TIM8_TRG_COM_TIM14_IRQn, 15, 0);
HAL_NVIC_EnableIRQ(TIM8_TRG_COM_TIM14_IRQn);
/* USER CODE BEGIN TIM8_MspInit 1 */
/* USER CODE END TIM8_MspInit 1 */
}
else if(tim_baseHandle->Instance==TIM11)
{
/* USER CODE BEGIN TIM11_MspInit 0 */
@ -392,6 +449,20 @@ void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
/* USER CODE END TIM3_MspDeInit 1 */
}
else if(tim_baseHandle->Instance==TIM8)
{
/* USER CODE BEGIN TIM8_MspDeInit 0 */
/* USER CODE END TIM8_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM8_CLK_DISABLE();
/* TIM8 interrupt Deinit */
HAL_NVIC_DisableIRQ(TIM8_TRG_COM_TIM14_IRQn);
/* USER CODE BEGIN TIM8_MspDeInit 1 */
/* USER CODE END TIM8_MspDeInit 1 */
}
else if(tim_baseHandle->Instance==TIM11)
{
/* USER CODE BEGIN TIM11_MspDeInit 0 */

80
UPP/Core/UPP/upp_main.c Normal file
View File

@ -0,0 +1,80 @@
/**
******************************************************************************
* @file upp_main.c
* @brief Инициализация и самые базовые вещи по работе УПП
******************************************************************************
* @details
******************************************************************************/
#include "main.h" // либы из AllLibs и вербальные имена из CubeMX
#include "upp_main.h" // всё остальное по работе с УПП
#include "adc.h"
#include "tim.h"
#include "adc_tools.h"
#include "zero_cross.h"
ADC_Period_t adc;
ZeroCross_Handle_t hzc;
uint32_t ZC_Detected[ZC_MAX_CHANNELS] = {0};
#define ADC_CHANNEL_UBA 0
#define ADC_CHANNEL_UAC 1
#define ADC_CHANNEL_IC 2
#define ADC_CHANNEL_IA 3
#define ADC_CHANNEL_TEMP1 4
#define ADC_CHANNEL_TEMP2 5
/**
* @brief Инициализация УПП.
* @return 0 - если ОК, >1 если ошибка.
*/
int UPP_Init(void)
{
ADC_Init(&adc, &adc_tim, &hadc3);
ADC_ConfigChannel(&adc, ADC_CHANNEL_UBA, 2048, 1216, 4095);
ADC_ConfigChannel(&adc, ADC_CHANNEL_UAC, 2048, 1216, 4095);
ADC_ConfigChannel(&adc, ADC_CHANNEL_IC, 2048, 53, 4095);
ADC_ConfigChannel(&adc, ADC_CHANNEL_IA, 2048, 53, 4095);
ADC_ConfigChannel(&adc, ADC_CHANNEL_TEMP1, 2554, 90, 4095);
ADC_ConfigChannel(&adc, ADC_CHANNEL_TEMP2, 2554, 90, 4095);
ZC_Init(&hzc, ZC_MAX_CHANNELS, 10, 3);
ZC_ConfigChannel(&hzc, 0, ZC_BOTH_EDGES);
ZC_ConfigChannel(&hzc, 1, ZC_BOTH_EDGES);
return 0;
}
/**
* @brief Инициализация основного цикла УПП.
* @return 0 - если ОК, >1 если ошибка.
*/
int UPP_PreWhile(void)
{
ADC_Start(&adc, 100);
return 0;
}
/**
* @brief Основной цикл УПП.
* @return 0 - если ОК, >1 если ошибка.
*/
int UPP_While(void)
{
return 0;
}
void UPP_ADC_Handle(void)
{
static uint32_t last_zc_cnt[ZC_MAX_CHANNELS] = {0};
ADC_Handle(&adc);
ZC_ProcessAllChannels(&hzc, adc.Data, uwTick);
for(int i = 0; i < ZC_MAX_CHANNELS; i++)
{
if(last_zc_cnt[i] != ZC_GetCrossCount(&hzc, i))
{
last_zc_cnt[i] = ZC_GetCrossCount(&hzc, i);
ZC_Detected[i] = !ZC_Detected[i];
}
}
}

23
UPP/Core/UPP/upp_main.h Normal file
View File

@ -0,0 +1,23 @@
/**
******************************************************************************
* @file modbus_data.h
* @brief Определения структур данных Modbus устройства
******************************************************************************
* @details
******************************************************************************/
#ifndef _UPP_MAIN_H
#define _UPP_MAIN_H
#include "upp_config.h"
/* Инициализация УПП */
int UPP_Init(void);
/* Инициализация основного цикла УПП. */
int UPP_PreWhile(void);
/* Основной цикл УПП. */
int UPP_While(void);
void UPP_ADC_Handle(void);
extern uint32_t ZC_Detected[];
#endif //_UPP_MAIN_H

View File

@ -298,7 +298,7 @@
</Group>
<Group>
<GroupName>Application/User/Core</GroupName>
<GroupName>UPP/Main</GroupName>
<tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
@ -310,14 +310,110 @@
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Core/Src/main.c</PathWithFileName>
<FilenameWithoutPath>main.c</FilenameWithoutPath>
<PathWithFileName>..\Core\UPP\upp_main.c</PathWithFileName>
<FilenameWithoutPath>upp_main.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>11</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\Core\UPP\upp_main.h</PathWithFileName>
<FilenameWithoutPath>upp_main.h</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group>
<Group>
<GroupName>PowerMonitor</GroupName>
<tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>12</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\Core\PowerMonitor\adc_tools.c</PathWithFileName>
<FilenameWithoutPath>adc_tools.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>13</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\Core\PowerMonitor\adc_tools.h</PathWithFileName>
<FilenameWithoutPath>adc_tools.h</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>14</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\Core\PowerMonitor\zero_cross.c</PathWithFileName>
<FilenameWithoutPath>zero_cross.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>15</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\Core\PowerMonitor\zero_cross.h</PathWithFileName>
<FilenameWithoutPath>zero_cross.h</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group>
<Group>
<GroupName>Thyristors</GroupName>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
</Group>
<Group>
<GroupName>Application/User/Core</GroupName>
<tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>16</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Core/Src/main.c</PathWithFileName>
<FilenameWithoutPath>main.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>17</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -328,8 +424,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>12</FileNumber>
<GroupNumber>5</GroupNumber>
<FileNumber>18</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -340,8 +436,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>13</FileNumber>
<GroupNumber>5</GroupNumber>
<FileNumber>19</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -352,8 +448,20 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>14</FileNumber>
<GroupNumber>5</GroupNumber>
<FileNumber>20</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>../Core/Src/dma.c</PathWithFileName>
<FilenameWithoutPath>dma.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>21</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -364,8 +472,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>15</FileNumber>
<GroupNumber>5</GroupNumber>
<FileNumber>22</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -376,8 +484,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>16</FileNumber>
<GroupNumber>5</GroupNumber>
<FileNumber>23</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -388,8 +496,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>17</FileNumber>
<GroupNumber>5</GroupNumber>
<FileNumber>24</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -400,8 +508,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>18</FileNumber>
<GroupNumber>5</GroupNumber>
<FileNumber>25</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -412,8 +520,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>19</FileNumber>
<GroupNumber>5</GroupNumber>
<FileNumber>26</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -424,8 +532,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>20</FileNumber>
<GroupNumber>5</GroupNumber>
<FileNumber>27</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -436,8 +544,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>21</FileNumber>
<GroupNumber>5</GroupNumber>
<FileNumber>28</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -451,13 +559,13 @@
<Group>
<GroupName>MyLibs</GroupName>
<tvExp>0</tvExp>
<tvExp>1</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>22</FileNumber>
<GroupNumber>6</GroupNumber>
<FileNumber>29</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -468,8 +576,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>23</FileNumber>
<GroupNumber>6</GroupNumber>
<FileNumber>30</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -480,8 +588,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>24</FileNumber>
<GroupNumber>6</GroupNumber>
<FileNumber>31</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -492,8 +600,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>25</FileNumber>
<GroupNumber>6</GroupNumber>
<FileNumber>32</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -504,8 +612,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>26</FileNumber>
<GroupNumber>6</GroupNumber>
<FileNumber>33</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -516,8 +624,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>27</FileNumber>
<GroupNumber>6</GroupNumber>
<FileNumber>34</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -527,6 +635,30 @@
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>35</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\AllLibs\MyLibs\MyLibs\Src\filters.c</PathWithFileName>
<FilenameWithoutPath>filters.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>36</FileNumber>
<FileType>5</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>..\AllLibs\MyLibs\MyLibs\Inc\filters.h</PathWithFileName>
<FilenameWithoutPath>filters.h</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group>
<Group>
@ -536,8 +668,8 @@
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>28</FileNumber>
<GroupNumber>7</GroupNumber>
<FileNumber>37</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -548,8 +680,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>29</FileNumber>
<GroupNumber>7</GroupNumber>
<FileNumber>38</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -560,8 +692,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>30</FileNumber>
<GroupNumber>7</GroupNumber>
<FileNumber>39</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -572,8 +704,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>31</FileNumber>
<GroupNumber>7</GroupNumber>
<FileNumber>40</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -584,8 +716,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>32</FileNumber>
<GroupNumber>7</GroupNumber>
<FileNumber>41</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -596,8 +728,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>33</FileNumber>
<GroupNumber>7</GroupNumber>
<FileNumber>42</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -608,8 +740,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>34</FileNumber>
<GroupNumber>7</GroupNumber>
<FileNumber>43</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -620,8 +752,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>35</FileNumber>
<GroupNumber>7</GroupNumber>
<FileNumber>44</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -632,8 +764,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>36</FileNumber>
<GroupNumber>7</GroupNumber>
<FileNumber>45</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -644,8 +776,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>37</FileNumber>
<GroupNumber>7</GroupNumber>
<FileNumber>46</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -656,8 +788,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>38</FileNumber>
<GroupNumber>7</GroupNumber>
<FileNumber>47</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -668,8 +800,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>39</FileNumber>
<GroupNumber>7</GroupNumber>
<FileNumber>48</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -688,8 +820,8 @@
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>40</FileNumber>
<GroupNumber>8</GroupNumber>
<FileNumber>49</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -700,8 +832,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>41</FileNumber>
<GroupNumber>8</GroupNumber>
<FileNumber>50</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -720,8 +852,8 @@
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>42</FileNumber>
<GroupNumber>9</GroupNumber>
<FileNumber>51</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -732,8 +864,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>43</FileNumber>
<GroupNumber>9</GroupNumber>
<FileNumber>52</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -744,8 +876,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>44</FileNumber>
<GroupNumber>9</GroupNumber>
<FileNumber>53</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -756,8 +888,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>45</FileNumber>
<GroupNumber>9</GroupNumber>
<FileNumber>54</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -768,8 +900,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>46</FileNumber>
<GroupNumber>9</GroupNumber>
<FileNumber>55</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -788,8 +920,8 @@
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>47</FileNumber>
<GroupNumber>10</GroupNumber>
<FileNumber>56</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -800,8 +932,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>48</FileNumber>
<GroupNumber>10</GroupNumber>
<FileNumber>57</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -812,8 +944,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>49</FileNumber>
<GroupNumber>10</GroupNumber>
<FileNumber>58</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -824,8 +956,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>50</FileNumber>
<GroupNumber>10</GroupNumber>
<FileNumber>59</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -836,8 +968,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>51</FileNumber>
<GroupNumber>10</GroupNumber>
<FileNumber>60</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -848,8 +980,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>52</FileNumber>
<GroupNumber>10</GroupNumber>
<FileNumber>61</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -860,8 +992,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>53</FileNumber>
<GroupNumber>10</GroupNumber>
<FileNumber>62</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -872,8 +1004,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>54</FileNumber>
<GroupNumber>10</GroupNumber>
<FileNumber>63</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -884,8 +1016,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>55</FileNumber>
<GroupNumber>10</GroupNumber>
<FileNumber>64</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -896,8 +1028,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>56</FileNumber>
<GroupNumber>10</GroupNumber>
<FileNumber>65</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -908,8 +1040,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>57</FileNumber>
<GroupNumber>10</GroupNumber>
<FileNumber>66</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -920,8 +1052,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>58</FileNumber>
<GroupNumber>10</GroupNumber>
<FileNumber>67</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -932,8 +1064,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>59</FileNumber>
<GroupNumber>10</GroupNumber>
<FileNumber>68</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -944,8 +1076,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>60</FileNumber>
<GroupNumber>10</GroupNumber>
<FileNumber>69</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -956,8 +1088,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>61</FileNumber>
<GroupNumber>10</GroupNumber>
<FileNumber>70</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -968,8 +1100,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>62</FileNumber>
<GroupNumber>10</GroupNumber>
<FileNumber>71</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -980,8 +1112,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>63</FileNumber>
<GroupNumber>10</GroupNumber>
<FileNumber>72</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -992,8 +1124,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>64</FileNumber>
<GroupNumber>10</GroupNumber>
<FileNumber>73</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1004,8 +1136,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>65</FileNumber>
<GroupNumber>10</GroupNumber>
<FileNumber>74</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1016,8 +1148,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>66</FileNumber>
<GroupNumber>10</GroupNumber>
<FileNumber>75</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1028,8 +1160,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>67</FileNumber>
<GroupNumber>10</GroupNumber>
<FileNumber>76</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1040,8 +1172,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>68</FileNumber>
<GroupNumber>10</GroupNumber>
<FileNumber>77</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1052,8 +1184,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>69</FileNumber>
<GroupNumber>10</GroupNumber>
<FileNumber>78</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1064,8 +1196,8 @@
<bShared>0</bShared>
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>70</FileNumber>
<GroupNumber>10</GroupNumber>
<FileNumber>79</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1084,8 +1216,8 @@
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>71</FileNumber>
<GroupNumber>11</GroupNumber>
<FileNumber>80</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1104,8 +1236,8 @@
<cbSel>0</cbSel>
<RteFlg>0</RteFlg>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>72</FileNumber>
<GroupNumber>12</GroupNumber>
<FileNumber>81</FileNumber>
<FileType>2</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>

View File

@ -341,7 +341,7 @@
<MiscControls></MiscControls>
<Define>USE_HAL_DRIVER,STM32F427xx</Define>
<Undefine></Undefine>
<IncludePath>../Core/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32F4xx/Include;../Drivers/CMSIS/Include;../AllLibs/ExtMemory/Inc;../AllLibs/Modbus/Inc;../AllLibs/MyLibs/MyLibs/Inc;../AllLibs/MyLibs/RTT;../AllLibs/PeriphGeneral/Inc;../Core/Configs</IncludePath>
<IncludePath>../Core/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32F4xx/Include;../Drivers/CMSIS/Include;../AllLibs/ExtMemory/Inc;../AllLibs/Modbus/Inc;../AllLibs/MyLibs/MyLibs/Inc;../AllLibs/MyLibs/RTT;../AllLibs/PeriphGeneral/Inc;../Core/Configs;../Core/PowerMonitor;../Core/Thyristors;../Core/UPP</IncludePath>
</VariousControls>
</Cads>
<Aads>
@ -432,6 +432,49 @@
</File>
</Files>
</Group>
<Group>
<GroupName>UPP/Main</GroupName>
<Files>
<File>
<FileName>upp_main.c</FileName>
<FileType>1</FileType>
<FilePath>..\Core\UPP\upp_main.c</FilePath>
</File>
<File>
<FileName>upp_main.h</FileName>
<FileType>5</FileType>
<FilePath>..\Core\UPP\upp_main.h</FilePath>
</File>
</Files>
</Group>
<Group>
<GroupName>PowerMonitor</GroupName>
<Files>
<File>
<FileName>adc_tools.c</FileName>
<FileType>1</FileType>
<FilePath>..\Core\PowerMonitor\adc_tools.c</FilePath>
</File>
<File>
<FileName>adc_tools.h</FileName>
<FileType>5</FileType>
<FilePath>..\Core\PowerMonitor\adc_tools.h</FilePath>
</File>
<File>
<FileName>zero_cross.c</FileName>
<FileType>1</FileType>
<FilePath>..\Core\PowerMonitor\zero_cross.c</FilePath>
</File>
<File>
<FileName>zero_cross.h</FileName>
<FileType>5</FileType>
<FilePath>..\Core\PowerMonitor\zero_cross.h</FilePath>
</File>
</Files>
</Group>
<Group>
<GroupName>Thyristors</GroupName>
</Group>
<Group>
<GroupName>Application/User/Core</GroupName>
<Files>
@ -455,6 +498,62 @@
<FileType>1</FileType>
<FilePath>../Core/Src/can.c</FilePath>
</File>
<File>
<FileName>dma.c</FileName>
<FileType>1</FileType>
<FilePath>../Core/Src/dma.c</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>1</IncludeInBuild>
<AlwaysBuild>2</AlwaysBuild>
<GenerateAssemblyFile>2</GenerateAssemblyFile>
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
<Cads>
<interw>2</interw>
<Optim>0</Optim>
<oTime>2</oTime>
<SplitLS>2</SplitLS>
<OneElfS>2</OneElfS>
<Strict>2</Strict>
<EnumInt>2</EnumInt>
<PlainCh>2</PlainCh>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<wLevel>0</wLevel>
<uThumb>2</uThumb>
<uSurpInc>2</uSurpInc>
<uC99>2</uC99>
<uGnu>2</uGnu>
<useXO>2</useXO>
<v6Lang>0</v6Lang>
<v6LangP>0</v6LangP>
<vShortEn>2</vShortEn>
<vShortWch>2</vShortWch>
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
<File>
<FileName>iwdg.c</FileName>
<FileType>1</FileType>
@ -530,6 +629,16 @@
<FileType>5</FileType>
<FilePath>..\AllLibs\MyLibs\MyLibs\Inc\trackers.h</FilePath>
</File>
<File>
<FileName>filters.c</FileName>
<FileType>1</FileType>
<FilePath>..\AllLibs\MyLibs\MyLibs\Src\filters.c</FilePath>
</File>
<File>
<FileName>filters.h</FileName>
<FileType>5</FileType>
<FilePath>..\AllLibs\MyLibs\MyLibs\Inc\filters.h</FilePath>
</File>
</Files>
</Group>
<Group>

View File

@ -1,9 +1,28 @@
#MicroXplorer Configuration settings - do not modify
ADC3.Channel-15\#ChannelRegularConversion=ADC_CHANNEL_7
ADC3.IPParameters=Rank-15\#ChannelRegularConversion,Channel-15\#ChannelRegularConversion,SamplingTime-15\#ChannelRegularConversion,NbrOfConversionFlag
ADC3.Channel-15\#ChannelRegularConversion=ADC_CHANNEL_4
ADC3.Channel-16\#ChannelRegularConversion=ADC_CHANNEL_5
ADC3.Channel-17\#ChannelRegularConversion=ADC_CHANNEL_6
ADC3.Channel-18\#ChannelRegularConversion=ADC_CHANNEL_7
ADC3.Channel-19\#ChannelRegularConversion=ADC_CHANNEL_8
ADC3.Channel-20\#ChannelRegularConversion=ADC_CHANNEL_10
ADC3.EOCSelection=ADC_EOC_SEQ_CONV
ADC3.ExternalTrigConv=ADC_EXTERNALTRIGCONV_T8_TRGO
ADC3.IPParameters=Rank-15\#ChannelRegularConversion,Channel-15\#ChannelRegularConversion,SamplingTime-15\#ChannelRegularConversion,NbrOfConversionFlag,NbrOfConversion,ScanConvMode,Rank-16\#ChannelRegularConversion,Channel-16\#ChannelRegularConversion,SamplingTime-16\#ChannelRegularConversion,Rank-17\#ChannelRegularConversion,Channel-17\#ChannelRegularConversion,SamplingTime-17\#ChannelRegularConversion,Rank-18\#ChannelRegularConversion,Channel-18\#ChannelRegularConversion,SamplingTime-18\#ChannelRegularConversion,Rank-19\#ChannelRegularConversion,Channel-19\#ChannelRegularConversion,SamplingTime-19\#ChannelRegularConversion,Rank-20\#ChannelRegularConversion,Channel-20\#ChannelRegularConversion,SamplingTime-20\#ChannelRegularConversion,ExternalTrigConv,EOCSelection
ADC3.NbrOfConversion=6
ADC3.NbrOfConversionFlag=1
ADC3.Rank-15\#ChannelRegularConversion=1
ADC3.Rank-16\#ChannelRegularConversion=2
ADC3.Rank-17\#ChannelRegularConversion=3
ADC3.Rank-18\#ChannelRegularConversion=4
ADC3.Rank-19\#ChannelRegularConversion=5
ADC3.Rank-20\#ChannelRegularConversion=6
ADC3.SamplingTime-15\#ChannelRegularConversion=ADC_SAMPLETIME_3CYCLES
ADC3.SamplingTime-16\#ChannelRegularConversion=ADC_SAMPLETIME_3CYCLES
ADC3.SamplingTime-17\#ChannelRegularConversion=ADC_SAMPLETIME_3CYCLES
ADC3.SamplingTime-18\#ChannelRegularConversion=ADC_SAMPLETIME_3CYCLES
ADC3.SamplingTime-19\#ChannelRegularConversion=ADC_SAMPLETIME_3CYCLES
ADC3.SamplingTime-20\#ChannelRegularConversion=ADC_SAMPLETIME_3CYCLES
ADC3.ScanConvMode=ENABLE
CAD.formats=
CAD.pinconfig=
CAD.provider=
@ -14,6 +33,18 @@ CAN1.CalculateTimeBit=4000
CAN1.CalculateTimeQuantum=222.22222222222223
CAN1.IPParameters=CalculateTimeQuantum,CalculateTimeBit,CalculateBaudRate,BS1,BS2,Prescaler
CAN1.Prescaler=10
Dma.ADC3.0.Direction=DMA_PERIPH_TO_MEMORY
Dma.ADC3.0.FIFOMode=DMA_FIFOMODE_DISABLE
Dma.ADC3.0.Instance=DMA2_Stream0
Dma.ADC3.0.MemDataAlignment=DMA_MDATAALIGN_HALFWORD
Dma.ADC3.0.MemInc=DMA_MINC_ENABLE
Dma.ADC3.0.Mode=DMA_NORMAL
Dma.ADC3.0.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD
Dma.ADC3.0.PeriphInc=DMA_PINC_DISABLE
Dma.ADC3.0.Priority=DMA_PRIORITY_LOW
Dma.ADC3.0.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode
Dma.Request0=ADC3
Dma.RequestsNb=1
File.Version=6
GPIO.groupedBy=Group By Peripherals
IWDG.IPParameters=Prescaler
@ -23,20 +54,22 @@ Mcu.CPN=STM32F427ZGT6
Mcu.Family=STM32F4
Mcu.IP0=ADC3
Mcu.IP1=CAN1
Mcu.IP10=TIM11
Mcu.IP11=TIM12
Mcu.IP12=TIM13
Mcu.IP13=USART3
Mcu.IP14=USART6
Mcu.IP2=IWDG
Mcu.IP3=NVIC
Mcu.IP4=RCC
Mcu.IP5=RTC
Mcu.IP6=SPI3
Mcu.IP7=SYS
Mcu.IP8=TIM1
Mcu.IP9=TIM3
Mcu.IPNb=15
Mcu.IP10=TIM3
Mcu.IP11=TIM8
Mcu.IP12=TIM11
Mcu.IP13=TIM12
Mcu.IP14=TIM13
Mcu.IP15=USART3
Mcu.IP16=USART6
Mcu.IP2=DMA
Mcu.IP3=IWDG
Mcu.IP4=NVIC
Mcu.IP5=RCC
Mcu.IP6=RTC
Mcu.IP7=SPI3
Mcu.IP8=SYS
Mcu.IP9=TIM1
Mcu.IPNb=17
Mcu.Name=STM32F427Z(G-I)Tx
Mcu.Package=LQFP144
Mcu.Pin0=PE2
@ -94,20 +127,22 @@ Mcu.Pin55=VP_RTC_VS_RTC_Calendar
Mcu.Pin56=VP_SYS_VS_tim14
Mcu.Pin57=VP_TIM1_VS_ClockSourceINT
Mcu.Pin58=VP_TIM3_VS_ClockSourceINT
Mcu.Pin59=VP_TIM11_VS_ClockSourceINT
Mcu.Pin59=VP_TIM8_VS_ClockSourceINT
Mcu.Pin6=PC14/OSC32_IN
Mcu.Pin60=VP_TIM12_VS_ClockSourceINT
Mcu.Pin61=VP_TIM13_VS_ClockSourceINT
Mcu.Pin60=VP_TIM11_VS_ClockSourceINT
Mcu.Pin61=VP_TIM12_VS_ClockSourceINT
Mcu.Pin62=VP_TIM13_VS_ClockSourceINT
Mcu.Pin7=PC15/OSC32_OUT
Mcu.Pin8=PF6
Mcu.Pin9=PF7
Mcu.PinsNb=62
Mcu.PinsNb=63
Mcu.ThirdPartyNb=0
Mcu.UserConstants=mb_huart,huart3;mbdbg_htim,htim11;mb_htim,htim12;mb_dbg_huart,huart6;ustim,htim13;mem_hspi,hspi3;hpwm1,htim1;hpwm2,htim2;PWM_CHANNEL_1,TIM_CHANNEL_1;PWM_CHANNEL_2,TIM_CHANNEL_2;PWM_CHANNEL_3,TIM_CHANNEL_3;PWM_CHANNEL_4,TIM_CHANNEL_4;PWM_CHANNEL_5,TIM_CHANNEL_3;PWM_CHANNEL_6,TIM_CHANNEL_4
Mcu.UserConstants=mb_huart,huart3;mbdbg_htim,htim11;PWM_CHANNEL_1,TIM_CHANNEL_1;PWM_CHANNEL_2,TIM_CHANNEL_2;PWM_CHANNEL_3,TIM_CHANNEL_3;PWM_CHANNEL_4,TIM_CHANNEL_4;mem_hspi,hspi3;PWM_CHANNEL_5,TIM_CHANNEL_3;PWM_CHANNEL_6,TIM_CHANNEL_4;mb_htim,htim12;adc_tim,htim8;hpwm2,htim2;mb_dbg_huart,huart6;ustim,htim13;hpwm1,htim1
Mcu.UserName=STM32F427ZGTx
MxCube.Version=6.12.1
MxDb.Version=DB.6.0.121
NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.DMA2_Stream0_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true
NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.ForceEnableDMAVector=true
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
@ -359,7 +394,7 @@ ProjectManager.ToolChainLocation=
ProjectManager.UAScriptAfterPath=
ProjectManager.UAScriptBeforePath=
ProjectManager.UnderRoot=false
ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-true-HAL-true,3-MX_ADC3_Init-ADC3-false-HAL-true,4-MX_USART3_UART_Init-USART3-false-HAL-true,5-MX_CAN1_Init-CAN1-false-HAL-true,6-MX_IWDG_Init-IWDG-false-HAL-true,7-MX_TIM13_Init-TIM13-false-HAL-true,8-MX_RTC_Init-RTC-false-HAL-true,9-MX_TIM1_Init-TIM1-false-HAL-true,10-MX_TIM3_Init-TIM3-false-HAL-true,11-MX_USART6_UART_Init-USART6-false-HAL-true,12-MX_SPI3_Init-SPI3-false-HAL-true,13-MX_TIM11_Init-TIM11-false-HAL-true,14-MX_TIM12_Init-TIM12-false-HAL-true
ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-true-HAL-true,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_ADC3_Init-ADC3-false-HAL-true,5-MX_USART3_UART_Init-USART3-false-HAL-true,6-MX_CAN1_Init-CAN1-false-HAL-true,7-MX_IWDG_Init-IWDG-false-HAL-true,8-MX_TIM13_Init-TIM13-false-HAL-true,9-MX_RTC_Init-RTC-false-HAL-true,10-MX_TIM1_Init-TIM1-false-HAL-true,11-MX_TIM3_Init-TIM3-false-HAL-true,12-MX_USART6_UART_Init-USART6-false-HAL-true,13-MX_SPI3_Init-SPI3-false-HAL-true,14-MX_TIM11_Init-TIM11-false-HAL-true,15-MX_TIM12_Init-TIM12-false-HAL-true,16-MX_TIM8_Init-TIM8-false-HAL-true
RCC.48MHZClocksFreq_Value=90000000
RCC.AHBFreq_Value=180000000
RCC.APB1CLKDivider=RCC_HCLK_DIV4
@ -438,6 +473,11 @@ TIM13.Prescaler=90-1
TIM3.Channel-PWM\ Generation3\ CH3=TIM_CHANNEL_3
TIM3.Channel-PWM\ Generation4\ CH4=TIM_CHANNEL_4
TIM3.IPParameters=Channel-PWM Generation3 CH3,Channel-PWM Generation4 CH4
TIM8.IPParameters=Prescaler,Period,TIM_MasterSlaveMode,TIM_MasterOutputTrigger
TIM8.Period=1000
TIM8.Prescaler=0
TIM8.TIM_MasterOutputTrigger=TIM_TRGO_UPDATE
TIM8.TIM_MasterSlaveMode=TIM_MASTERSLAVEMODE_DISABLE
USART3.IPParameters=VirtualMode
USART3.VirtualMode=VM_ASYNC
USART6.IPParameters=VirtualMode
@ -460,4 +500,6 @@ VP_TIM1_VS_ClockSourceINT.Mode=Internal
VP_TIM1_VS_ClockSourceINT.Signal=TIM1_VS_ClockSourceINT
VP_TIM3_VS_ClockSourceINT.Mode=Internal
VP_TIM3_VS_ClockSourceINT.Signal=TIM3_VS_ClockSourceINT
VP_TIM8_VS_ClockSourceINT.Mode=Internal
VP_TIM8_VS_ClockSourceINT.Signal=TIM8_VS_ClockSourceINT
board=custom

View File

@ -0,0 +1,204 @@
import numpy as np
import matplotlib.pyplot as plt
# Данные: ADC -> Temperature
adc_values = [2188, 2197, 2206, 2216, 2226, 2236, 2247, 2259, 2271, 2283,
2296, 2310, 2324, 2338, 2354, 2369, 2385, 2402, 2419, 2437,
2455, 2474, 2493, 2513, 2533, 2554, 2575, 2597, 2619, 2641,
2664, 2688, 2711, 2735, 2759, 2784, 2809, 2833, 2859, 2884,
2909, 2935, 2961, 2986, 3012, 3037, 3063, 3089, 3114, 3140,
3165, 3190, 3215, 3239, 3263, 3288, 3312, 3335, 3359, 3381,
3404, 3426, 3448, 3470, 3491, 3512, 3532, 3552, 3572, 3591,
3610, 3628, 3646, 3663, 3681, 3697, 3714, 3729, 3745, 3760,
3775, 3789, 3803, 3817, 3830, 3843, 3855, 3868, 3879, 3891,
3902, 3913, 3924, 3934, 3944, 3954, 3963, 3972, 3981, 3989,
3997, 4005, 4013, 4021, 4028, 4035, 4042, 4049, 4055, 4062,
4068, 4074, 4079, 4085, 4091, 4096]
temperatures = [-25, -24, -23, -22, -21, -20, -19, -18, -17, -16, -15, -14, -13, -12, -11,
-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
82, 83, 84, 85, 86, 87, 88, 89, 90]
# Параметры ограничений
MIN_COEFF_ABS = 1e-5 # Минимальное абсолютное значение коэффициента
MAX_CONDITION_NUMBER = 1e10 # Максимальное число обусловленности
# Аппроксимация полиномами разных степеней
degrees = [2, 3, 4, 5]
coefficients = {}
filtered_coefficients = {}
plt.figure(figsize=(16, 12))
# График 1: Сравнение аппроксимаций
plt.subplot(2, 3, 1)
plt.plot(adc_values, temperatures, 'ko-', markersize=3, linewidth=1, label='Исходные данные')
colors = ['red', 'blue', 'green', 'orange']
for i, degree in enumerate(degrees):
coeffs = np.polyfit(adc_values, temperatures, degree)
coefficients[degree] = coeffs
# Фильтрация малых коэффициентов
filtered_coeffs = coeffs.copy()
small_coeffs_mask = np.abs(coeffs) < MIN_COEFF_ABS
filtered_coeffs[small_coeffs_mask] = 0
filtered_coefficients[degree] = filtered_coeffs
poly = np.poly1d(coeffs)
adc_continuous = np.linspace(min(adc_values), max(adc_values), 500)
temp_predicted = poly(adc_continuous)
plt.plot(adc_continuous, temp_predicted, color=colors[i], linewidth=2,
label=f'Полином {degree}-й степени')
plt.xlabel('Значение АЦП')
plt.ylabel('Температура (°C)')
plt.title('Аппроксимация зависимости АЦП → Температура')
plt.legend()
plt.grid(True, alpha=0.3)
# График 2: Ошибки аппроксимации
plt.subplot(2, 3, 2)
for i, degree in enumerate(degrees):
poly = np.poly1d(coefficients[degree])
predicted = poly(adc_values)
error = predicted - temperatures
plt.plot(temperatures, error, 'o-', color=colors[i], markersize=3,
label=f'Ошибка {degree}-й степени')
plt.xlabel('Температура (°C)')
plt.ylabel('Ошибка (°C)')
plt.title('Ошибки аппроксимации по температуре')
plt.legend()
plt.grid(True, alpha=0.3)
# График 3: Статистика ошибок
plt.subplot(2, 3, 3)
max_errors = []
rms_errors = []
for degree in degrees:
poly = np.poly1d(coefficients[degree])
predicted = poly(adc_values)
max_error = np.max(np.abs(predicted - temperatures))
rms_error = np.sqrt(np.mean((predicted - temperatures)**2))
max_errors.append(max_error)
rms_errors.append(rms_error)
x_pos = np.arange(len(degrees))
width = 0.35
plt.bar(x_pos - width/2, max_errors, width, label='Макс. ошибка', alpha=0.7)
plt.bar(x_pos + width/2, rms_errors, width, label='СКО', alpha=0.7)
plt.xlabel('Степень полинома')
plt.ylabel('Ошибка (°C)')
plt.title('Статистика ошибок аппроксимации')
plt.xticks(x_pos, degrees)
plt.legend()
plt.grid(True, alpha=0.3)
# График 4: Сравнение коэффициентов до/после фильтрации
plt.subplot(2, 3, 4)
for degree in degrees:
coeffs = coefficients[degree]
filtered_coeffs = filtered_coefficients[degree]
# Отображаем только ненулевые коэффициенты
nonzero_indices = np.where(filtered_coeffs != 0)[0]
if len(nonzero_indices) > 0:
plt.semilogy(nonzero_indices, np.abs(filtered_coeffs[nonzero_indices]), 'o-',
label=f'Полином {degree}-й степени', markersize=6)
plt.axhline(y=MIN_COEFF_ABS, color='r', linestyle='--', alpha=0.7, label=f'Порог {MIN_COEFF_ABS:.0e}')
plt.xlabel('Индекс коэффициента')
plt.ylabel('Абсолютное значение коэффициента')
plt.title('Коэффициенты после фильтрации (логарифмическая шкала)')
plt.legend()
plt.grid(True, alpha=0.3)
# График 5: Влияние фильтрации на ошибку
plt.subplot(2, 3, 5)
original_errors = []
filtered_errors = []
for degree in degrees:
poly_original = np.poly1d(coefficients[degree])
poly_filtered = np.poly1d(filtered_coefficients[degree])
predicted_original = poly_original(adc_values)
predicted_filtered = poly_filtered(adc_values)
error_original = np.max(np.abs(predicted_original - temperatures))
error_filtered = np.max(np.abs(predicted_filtered - temperatures))
original_errors.append(error_original)
filtered_errors.append(error_filtered)
x_pos = np.arange(len(degrees))
width = 0.35
plt.bar(x_pos - width/2, original_errors, width, label='Оригинальные коэф.', alpha=0.7)
plt.bar(x_pos + width/2, filtered_errors, width, label='После фильтрации', alpha=0.7)
plt.xlabel('Степень полинома')
plt.ylabel('Максимальная ошибка (°C)')
plt.title('Влияние фильтрации коэффициентов на точность')
plt.xticks(x_pos, degrees)
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# Вывод численных результатов
print("=" * 80)
print("РЕЗУЛЬТАТЫ АППРОКСИМАЦИИ С ФИЛЬТРАЦИЕЙ КОЭФФИЦИЕНТОВ")
print("=" * 80)
for degree in degrees:
coeffs = coefficients[degree]
filtered_coeffs = filtered_coefficients[degree]
poly_original = np.poly1d(coeffs)
poly_filtered = np.poly1d(filtered_coeffs)
predicted_original = poly_original(adc_values)
predicted_filtered = poly_filtered(adc_values)
max_error_original = np.max(np.abs(predicted_original - temperatures))
rms_error_original = np.sqrt(np.mean((predicted_original - temperatures)**2))
max_error_filtered = np.max(np.abs(predicted_filtered - temperatures))
rms_error_filtered = np.sqrt(np.mean((predicted_filtered - temperatures)**2))
# Подсчет нулевых коэффициентов
zero_count = np.sum(filtered_coeffs == 0)
total_count = len(filtered_coeffs)
print(f"\nПолином {degree}-й степени:")
print(f"Максимальная ошибка: {max_error_original:.3f}°C -> {max_error_filtered:.3f}°C")
print(f"Среднеквадратичная ошибка: {rms_error_original:.3f}°C -> {rms_error_filtered:.3f}°C")
print(f"Обнулено коэффициентов: {zero_count}/{total_count}")
print("Коэффициенты после фильтрации:")
for i, coeff in enumerate(filtered_coeffs):
power = len(filtered_coeffs) - i - 1
status = "" if coeff != 0 else "✗ (обнулен)"
print(f" a_{power} = {coeff:.6e} {status}")
# Рекомендация
print("\n" + "=" * 80)
print("РЕКОМЕНДАЦИЯ:")
print(f"Порог обнуления коэффициентов: {MIN_COEFF_ABS:.0e}")
print("Полином 3-й степени обеспечивает оптимальный баланс между точностью")
print("и сложностью реализации. Фильтрация малых коэффициентов практически")
print("не влияет на точность, но упрощает реализацию на embedded системах.")
print("=" * 80)