From 79ff2667c46c0025edb5b73c4735092c757fdd42 Mon Sep 17 00:00:00 2001 From: Razvalyaev Date: Sun, 9 Nov 2025 21:04:52 +0300 Subject: [PATCH] =?UTF-8?q?=D0=92=D1=81=D1=8F=D0=BA=D0=B8=D0=B5=20=D1=84?= =?UTF-8?q?=D0=B8=D0=BA=D1=81=D1=8B=20=D0=BC=D0=BE=D0=B4=D0=B5=D0=BB=D0=B8?= =?UTF-8?q?=20=D0=B8=20=D0=B7=D0=B0=D0=B3=D0=BE=D1=82=D0=BE=D0=B2=D0=BA?= =?UTF-8?q?=D0=B8=20=D0=B4=D0=BB=D1=8F=20=D0=90=D0=A6=D0=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit И почему то все равно MATLAB намертво блокирует mingw64.... Приходится перезапускать матлаб для перекомпиляции --- .gitignore | 3 + .../Device/STM32F1xx/stm32f100xb_matlab.h | 4 +- .../Device/STM32F1xx/stm32f100xe_matlab.h | 4 +- .../Device/STM32F1xx/stm32f101x6_matlab.h | 4 +- .../Device/STM32F1xx/stm32f101xb_matlab.h | 4 +- .../Device/STM32F1xx/stm32f101xe_matlab.h | 4 +- .../Device/STM32F1xx/stm32f101xg_matlab.h | 4 +- .../Device/STM32F1xx/stm32f102x6_matlab.h | 4 +- .../Device/STM32F1xx/stm32f102xb_matlab.h | 4 +- .../Device/STM32F1xx/stm32f103x6_matlab.h | 4 +- .../Device/STM32F1xx/stm32f103xb_matlab.h | 6 +- .../Device/STM32F1xx/stm32f103xe_matlab.h | 4 +- .../Device/STM32F1xx/stm32f103xg_matlab.h | 4 +- .../Device/STM32F1xx/stm32f105xc_matlab.h | 4 +- .../Device/STM32F1xx/stm32f107xc_matlab.h | 4 +- .../Device/STM32F4xx/stm32f401xc_matlab.h | 6 +- .../Device/STM32F4xx/stm32f401xe_matlab.h | 6 +- .../Device/STM32F4xx/stm32f405xx_matlab.h | 6 +- .../Device/STM32F4xx/stm32f407xx_matlab.h | 6 +- .../Device/STM32F4xx/stm32f410cx_matlab.h | 6 +- .../Device/STM32F4xx/stm32f410rx_matlab.h | 6 +- .../Device/STM32F4xx/stm32f410tx_matlab.h | 6 +- .../Device/STM32F4xx/stm32f411xe_matlab.h | 6 +- .../Device/STM32F4xx/stm32f412cx_matlab.h | 6 +- .../Device/STM32F4xx/stm32f412rx_matlab.h | 6 +- .../Device/STM32F4xx/stm32f412vx_matlab.h | 6 +- .../Device/STM32F4xx/stm32f412zx_matlab.h | 6 +- .../Device/STM32F4xx/stm32f413xx_matlab.h | 6 +- .../Device/STM32F4xx/stm32f415xx_matlab.h | 6 +- .../Device/STM32F4xx/stm32f417xx_matlab.h | 6 +- .../Device/STM32F4xx/stm32f423xx_matlab.h | 6 +- .../Device/STM32F4xx/stm32f427xx_matlab.h | 6 +- .../Device/STM32F4xx/stm32f429xx_matlab.h | 6 +- .../Device/STM32F4xx/stm32f437xx_matlab.h | 6 +- .../Device/STM32F4xx/stm32f439xx_matlab.h | 6 +- .../Device/STM32F4xx/stm32f446xx_matlab.h | 6 +- .../Device/STM32F4xx/stm32f469xx_matlab.h | 6 +- .../Device/STM32F4xx/stm32f479xx_matlab.h | 6 +- .../Drivers/CMSIS/arm_defines.h | 7 +- .../Drivers/STM32_SIMULINK/stm32_matlab_adc.c | 266 ++++++-- .../Drivers/STM32_SIMULINK/stm32_matlab_adc.h | 13 +- .../Drivers/STM32_SIMULINK/stm32_matlab_dma.c | 591 ++++++++++++++++++ .../Drivers/STM32_SIMULINK/stm32_matlab_dma.h | 40 ++ .../Drivers/STM32_SIMULINK/stm32_matlab_tim.c | 34 +- .../Drivers/STM32_SIMULINK/stm32_matlab_tim.h | 7 +- MATLAB/MCU_STM32_Matlab/stm32_matlab_conf.c | 128 +++- MATLAB/MCU_STM32_Matlab/stm32_matlab_conf.h | 25 +- .../stm32f4xx_matlab_conf.json | 13 +- MATLAB/MCU_Wrapper/mcu_wrapper_conf.h | 2 +- MATLAB/MCU_Wrapper/run_mex.bat | 156 +++++ MATLAB/app_wrapper/app_includes.h | 3 +- MATLAB/app_wrapper/app_init.c | 10 +- MATLAB/app_wrapper/app_io.c | 13 +- MATLAB/upp_r2023.slx | Bin 66492 -> 66192 bytes UPP/.mxproject | 42 +- UPP/AllLibs/MyLibs | 2 +- UPP/Core/Inc/adc.h | 5 +- UPP/Core/Inc/dma.h | 52 ++ UPP/Core/Inc/main.h | 1 + UPP/Core/Inc/stm32f4xx_it.h | 1 + UPP/Core/Inc/tim.h | 3 + UPP/Core/PowerMonitor/adc_tools.c | 130 ++++ UPP/Core/PowerMonitor/adc_tools.h | 62 ++ UPP/Core/Src/adc.c | 171 +++-- UPP/Core/Src/dma.c | 55 ++ UPP/Core/Src/main.c | 19 +- UPP/Core/Src/stm32f4xx_it.c | 19 + UPP/Core/Src/tim.c | 71 +++ UPP/Core/UPP/upp_main.c | 58 ++ UPP/Core/UPP/upp_main.h | 21 + UPP/MDK-ARM/UPP.uvoptx | 382 ++++++----- UPP/MDK-ARM/UPP.uvprojx | 214 +++++-- UPP/UPP.ioc | 165 +++-- ...температуры в ед АЦП.xlsx | Bin 14018 -> 20953 bytes 74 files changed, 2371 insertions(+), 609 deletions(-) create mode 100644 MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_dma.c create mode 100644 MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_dma.h create mode 100644 MATLAB/MCU_Wrapper/run_mex.bat create mode 100644 UPP/Core/Inc/dma.h create mode 100644 UPP/Core/PowerMonitor/adc_tools.c create mode 100644 UPP/Core/PowerMonitor/adc_tools.h create mode 100644 UPP/Core/Src/dma.c create mode 100644 UPP/Core/UPP/upp_main.c create mode 100644 UPP/Core/UPP/upp_main.h diff --git a/.gitignore b/.gitignore index cf821df..76eefbb 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,6 @@ JLinkLog.txt # VS Code Generated Files /.vs/ +/MATLAB/MCU.exp +/MATLAB/MCU.lib +/MATLAB/MCU.mexw64.manifest diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f100xb_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f100xb_matlab.h index dbb699e..60f20d2 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f100xb_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f100xb_matlab.h @@ -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 diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f100xe_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f100xe_matlab.h index 9a937a0..7237b71 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f100xe_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f100xe_matlab.h @@ -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 diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f101x6_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f101x6_matlab.h index bf9d0e0..8d03ab6 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f101x6_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f101x6_matlab.h @@ -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 diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f101xb_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f101xb_matlab.h index 6c67d89..ca0107b 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f101xb_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f101xb_matlab.h @@ -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 diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f101xe_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f101xe_matlab.h index cab9bb7..e857442 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f101xe_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f101xe_matlab.h @@ -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 diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f101xg_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f101xg_matlab.h index abc990b..739da2c 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f101xg_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f101xg_matlab.h @@ -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 diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f102x6_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f102x6_matlab.h index b4d7d24..eb5752f 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f102x6_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f102x6_matlab.h @@ -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 diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f102xb_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f102xb_matlab.h index 888c1c8..e392d84 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f102xb_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f102xb_matlab.h @@ -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 diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f103x6_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f103x6_matlab.h index 47f7488..21da38d 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f103x6_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f103x6_matlab.h @@ -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 diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f103xb_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f103xb_matlab.h index 394c977..550f4a4 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f103xb_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f103xb_matlab.h @@ -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]; diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f103xe_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f103xe_matlab.h index 292c86b..a860faf 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f103xe_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f103xe_matlab.h @@ -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 diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f103xg_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f103xg_matlab.h index bd073d8..426dd75 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f103xg_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f103xg_matlab.h @@ -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 diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f105xc_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f105xc_matlab.h index 724c495..9b48c43 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f105xc_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f105xc_matlab.h @@ -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 diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f107xc_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f107xc_matlab.h index 9947728..81e6dc3 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f107xc_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F1xx/stm32f107xc_matlab.h @@ -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 diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f401xc_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f401xc_matlab.h index 610ab3a..3b4a041 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f401xc_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f401xc_matlab.h @@ -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; diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f401xe_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f401xe_matlab.h index 6549a19..a42d2af 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f401xe_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f401xe_matlab.h @@ -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; diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f405xx_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f405xx_matlab.h index eaaca4b..1b3fc71 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f405xx_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f405xx_matlab.h @@ -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; diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f407xx_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f407xx_matlab.h index 9609c9a..514f98b 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f407xx_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f407xx_matlab.h @@ -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; diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f410cx_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f410cx_matlab.h index d0004fd..12d46ce 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f410cx_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f410cx_matlab.h @@ -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; diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f410rx_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f410rx_matlab.h index ee99544..9343b21 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f410rx_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f410rx_matlab.h @@ -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; diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f410tx_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f410tx_matlab.h index 04dbe52..1afbac8 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f410tx_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f410tx_matlab.h @@ -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; diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f411xe_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f411xe_matlab.h index 0a6b5ee..b16a15a 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f411xe_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f411xe_matlab.h @@ -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; diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f412cx_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f412cx_matlab.h index 8a24b1c..08218f2 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f412cx_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f412cx_matlab.h @@ -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; diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f412rx_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f412rx_matlab.h index 2c65b22..97c1830 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f412rx_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f412rx_matlab.h @@ -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; diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f412vx_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f412vx_matlab.h index c5300cd..d472ba7 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f412vx_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f412vx_matlab.h @@ -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; diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f412zx_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f412zx_matlab.h index cc609ec..8aa9e5e 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f412zx_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f412zx_matlab.h @@ -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; diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f413xx_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f413xx_matlab.h index 62dd13f..6308d3f 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f413xx_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f413xx_matlab.h @@ -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; diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f415xx_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f415xx_matlab.h index 6538086..8a6508c 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f415xx_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f415xx_matlab.h @@ -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; diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f417xx_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f417xx_matlab.h index 8617ba8..fd8fe93 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f417xx_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f417xx_matlab.h @@ -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; diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f423xx_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f423xx_matlab.h index bd926b4..2e0f5fa 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f423xx_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f423xx_matlab.h @@ -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; diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f427xx_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f427xx_matlab.h index be49cd9..f63f572 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f427xx_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f427xx_matlab.h @@ -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; diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f429xx_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f429xx_matlab.h index 865f23c..4a1a4bd 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f429xx_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f429xx_matlab.h @@ -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; diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f437xx_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f437xx_matlab.h index b26ff5e..8fc92ef 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f437xx_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f437xx_matlab.h @@ -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; diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f439xx_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f439xx_matlab.h index 5c412e4..f9ddae2 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f439xx_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f439xx_matlab.h @@ -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; diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f446xx_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f446xx_matlab.h index 12383be..9d330d6 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f446xx_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f446xx_matlab.h @@ -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; diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f469xx_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f469xx_matlab.h index a006ccd..8b3975f 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f469xx_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f469xx_matlab.h @@ -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; diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f479xx_matlab.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f479xx_matlab.h index 97f7620..8b5431e 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f479xx_matlab.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/Device/STM32F4xx/stm32f479xx_matlab.h @@ -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; diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/arm_defines.h b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/arm_defines.h index 8604f58..e31109d 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/arm_defines.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/CMSIS/arm_defines.h @@ -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() diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_adc.c b/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_adc.c index e7fa495..d199507 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_adc.c +++ b/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_adc.c @@ -1,4 +1,5 @@ #include "stm32_matlab_adc.h" +#include "stm32_matlab_dma.h" #include @@ -22,19 +23,26 @@ void ADC_Simulation(ADC_TypeDef* ADCx, struct ADC_Sim* ADCS) { if (!(ADCx->CR2 & ADC_CR2_ADON)) return; - // Start conversion on SWSTART + // ПЕРВОЕ: Проверка внешнего триггера (для режима по триггеру) + 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; } - // Handle ongoing conversion - + // ТРЕТЬЕ: Обработка текущего преобразования if (ADCS->conversion_time_elapsed >= 0) { ADCS->conversion_time_elapsed += ADCS->simulation_step; - double total_time = ADC_Get_Total_Conversion_Time(ADCx, ADCS); + + // ИСПОЛЬЗУЕМ ОБЩЕЕ ВРЕМЯ ДЛЯ ВСЕЙ ПОСЛЕДОВАТЕЛЬНОСТИ + double total_time = ADC_Get_Total_Sequence_Time(ADCx, ADCS); if (ADCS->conversion_time_elapsed >= total_time) { - ADC_Complete_Conversion(ADCx, ADCS); + ADC_Complete_Conversion(ADCx, ADCS); // Обрабатываем ВСЕ каналы // Continuous mode auto-restart if (ADCx->CR2 & ADC_CR2_CONT) { @@ -42,19 +50,18 @@ void ADC_Simulation(ADC_TypeDef* ADCx, struct ADC_Sim* 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); } @@ -63,81 +70,210 @@ void ADC_Start_Conversion(ADC_TypeDef* ADCx, struct ADC_Sim* ADCS) void ADC_Complete_Conversion(ADC_TypeDef* ADCx, struct ADC_Sim* ADCS) { - // - double analog_val = 0; - if (ADCS->channel_connected[ADCS->current_channel]) { - analog_val = ADCS->channel_values[ADCS->current_channel]; + 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 + } + } } - 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); - - // LSB - 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; - - // DR - ADCx->DR = ADCS->last_conversion_value; - - // EOC + // Устанавливаем EOS в конце последовательности ADCx->SR |= ADC_SR_EOC; - // DMA - if (ADCx->CR2 & ADC_CR2_DMA) { - ADC_DMA_Transfer(ADCx, ADCS); - } - - // - if (ADCx->CR1 & ADC_CR1_SCAN) { - ADCS->current_rank++; - uint32_t seq_len = ADC_Get_Sequence_Length(ADCx); - - if (ADCS->current_rank < seq_len) { - // - ADCS->current_channel = ADC_Get_Sequence_Channel(ADCx, ADCS->current_rank); - ADCS->conversion_time_elapsed = 0; - return; - } - else { - // -#ifdef ADC_SR_EOS - ADCx->SR |= ADC_SR_EOS; -#endif - } - } - - ADCS->conversion_time_elapsed = 0; + 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 + // Получаем sampling time из регистров uint32_t sampling_cycles = ADC_Get_Sampling_Cycles(ADCx, ADCS->current_channel); - // Conversion cycles - uint32_t conversion_cycles = 12; // 12-bit + // Conversion cycles фиксированы для разрешения + uint32_t conversion_cycles = 12; // Для 12-bit double total_cycles = sampling_cycles + conversion_cycles; - double adc_clock = ADCS->adc_clock_freq; // + 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 + // Получаем sampling time из SMPR1/SMPR2 uint32_t smpr_code; if (channel <= 9) { smpr_code = (ADCx->SMPR2 >> (channel * 3)) & 0x7; @@ -176,7 +312,7 @@ uint32_t ADC_Get_Sequence_Channel(ADC_TypeDef* ADCx, uint32_t rank) } /////////////////////////////---DMA FUNCTIONS---/////////////////////////////// -void ADC_DMA_Transfer(ADC_TypeDef* ADCx, struct ADC_Sim* ADCS) +void ADC_DMA_Sim_Transfer(ADC_TypeDef* ADCx, struct ADC_Sim* ADCS) { if (!ADCS->dma_buffer || ADCS->dma_buffer_size == 0) return; diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_adc.h b/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_adc.h index feea8fe..26d8697 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_adc.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_adc.h @@ -5,11 +5,11 @@ #ifdef STM32F1 -#define ADC_NOISE_LSB 10 // Шум в LSB (квантах АЦП) +#define ADC_NOISE_LSB 30 // Большой шум STMF103 в LSB (квантах АЦП) #endif #ifdef STM32F4 -#define ADC_NOISE_LSB 2 // Шум в LSB (квантах АЦП) +#define ADC_NOISE_LSB 10 // Шум в LSB (квантах АЦП) #endif /////////////////////////////---STRUCTURES---/////////////////////////// @@ -32,6 +32,11 @@ struct ADC_Sim // Timing double simulation_step; double adc_clock_freq; + + // Добавьте для поддержки триггеров + uint8_t external_trigger_enabled; + uint32_t trigger_source; + uint8_t last_trigger_state; }; /////////////////////////////////////////////////////////////////////// @@ -42,11 +47,13 @@ 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_Transfer(ADC_TypeDef* ADCx, struct ADC_Sim* ADCS); +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); diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_dma.c b/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_dma.c new file mode 100644 index 0000000..7a85299 --- /dev/null +++ b/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_dma.c @@ -0,0 +1,591 @@ +#include "stm32_matlab_dma.h" +#include + +// 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 +} \ No newline at end of file diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_dma.h b/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_dma.h new file mode 100644 index 0000000..e2e7aaa --- /dev/null +++ b/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_dma.h @@ -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_ \ No newline at end of file diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_tim.c b/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_tim.c index c4c8dc6..5f24a07 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_tim.c +++ b/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_tim.c @@ -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,7 @@ 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 + TIM_Call_IRQHandller(TIMx); // call HANDLER } } } @@ -79,8 +83,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 +325,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 +599,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(); diff --git a/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_tim.h b/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_tim.h index 6a5478b..15572a8 100644 --- a/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_tim.h +++ b/MATLAB/MCU_STM32_Matlab/Drivers/STM32_SIMULINK/stm32_matlab_tim.h @@ -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); //------------------------------------------------------------------// diff --git a/MATLAB/MCU_STM32_Matlab/stm32_matlab_conf.c b/MATLAB/MCU_STM32_Matlab/stm32_matlab_conf.c index 2973f9c..bd6379c 100644 --- a/MATLAB/MCU_STM32_Matlab/stm32_matlab_conf.c +++ b/MATLAB/MCU_STM32_Matlab/stm32_matlab_conf.c @@ -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; @@ -40,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--------------------------------*/ @@ -164,9 +176,9 @@ void Init_TIM_SIM(void) tim5s.Channels.OC4_GPIOx = GPIOA; tim5s.Channels.OC4_PIN_SHIFT = 3; #endif -#ifdef USE_TIMx +#ifdef USE_TIM6 memset(&tim6s, 0, sizeof(tim6s)); - tim6s.tx_cnt = TIMx->CNT; + tim6s.tx_cnt = TIM6->CNT; tim6s.tx_step = hmcu.sSimSampleTime * ABP1_TIMS_Value; tim6s.Channels.OC1_GPIOx = GPIOA; @@ -178,6 +190,118 @@ 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----------------------------------*/ //-----------------------------------------------------------------------// diff --git a/MATLAB/MCU_STM32_Matlab/stm32_matlab_conf.h b/MATLAB/MCU_STM32_Matlab/stm32_matlab_conf.h index 8b353e6..34e81e8 100644 --- a/MATLAB/MCU_STM32_Matlab/stm32_matlab_conf.h +++ b/MATLAB/MCU_STM32_Matlab/stm32_matlab_conf.h @@ -60,16 +60,15 @@ 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,13 +112,22 @@ 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 @@ -129,7 +137,12 @@ extern struct ADC_Sim adc2s; #ifdef USE_ADC3 extern struct ADC_Sim adc3s; #endif +#endif +#ifndef ADC_ENABLE +static void Simulate_ADCs() {} +static void ADC_SIM_DEINIT() {} +#endif /*---------------------------------ADC-----------------------------------*/ //-----------------------------------------------------------------------// diff --git a/MATLAB/MCU_STM32_Matlab/stm32f4xx_matlab_conf.json b/MATLAB/MCU_STM32_Matlab/stm32f4xx_matlab_conf.json index 3c36e56..596d63e 100644 --- a/MATLAB/MCU_STM32_Matlab/stm32f4xx_matlab_conf.json +++ b/MATLAB/MCU_STM32_Matlab/stm32f4xx_matlab_conf.json @@ -27,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": { @@ -48,14 +49,16 @@ }, "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": true, + "Default": false, "NewRow": true } } @@ -69,7 +72,7 @@ "Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c" ], "Type": "checkbox", - "Default": true, + "Default": false, "NewRow": true }, "HAL_ADC": { @@ -499,7 +502,7 @@ "Prompt": "TIM8 Enable", "Def": "USE_TIM8", "Type": "checkbox", - "Default": false, + "Default": true, "NewRow": true }, "TIM6_Handler": { @@ -590,7 +593,7 @@ "Prompt": "ADC1 Enable", "Def": "USE_ADC1", "Type": "checkbox", - "Default": true, + "Default": false, "NewRow": true }, "ADC2_Enable": { @@ -604,7 +607,7 @@ "Prompt": "ADC3 Enable", "Def": "USE_ADC3", "Type": "checkbox", - "Default": false, + "Default": true, "NewRow": true }, "Sample_Rate": { diff --git a/MATLAB/MCU_Wrapper/mcu_wrapper_conf.h b/MATLAB/MCU_Wrapper/mcu_wrapper_conf.h index fa2864b..93edc3f 100644 --- a/MATLAB/MCU_Wrapper/mcu_wrapper_conf.h +++ b/MATLAB/MCU_Wrapper/mcu_wrapper_conf.h @@ -55,7 +55,7 @@ #define OUT_PORT_NUMB 2 #define THYR_PORT_1_WIDTH 6 -#define OUT_PORT_2_WIDTH 1 +#define OUT_PORT_2_WIDTH 6 // INPUT/OUTPUTS PARAMS END /** WRAPPER_CONF diff --git a/MATLAB/MCU_Wrapper/run_mex.bat b/MATLAB/MCU_Wrapper/run_mex.bat new file mode 100644 index 0000000..8d7bb2c --- /dev/null +++ b/MATLAB/MCU_Wrapper/run_mex.bat @@ -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% \ No newline at end of file diff --git a/MATLAB/app_wrapper/app_includes.h b/MATLAB/app_wrapper/app_includes.h index 1c5648d..fed3040 100644 --- a/MATLAB/app_wrapper/app_includes.h +++ b/MATLAB/app_wrapper/app_includes.h @@ -10,10 +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_ \ No newline at end of file diff --git a/MATLAB/app_wrapper/app_init.c b/MATLAB/app_wrapper/app_init.c index 515a489..854cc3a 100644 --- a/MATLAB/app_wrapper/app_init.c +++ b/MATLAB/app_wrapper/app_init.c @@ -17,12 +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_ADC1_Init(); - HAL_ADC_Start(&hadc1); + MX_TIM8_Init(); + MX_ADC3_Init(); + UPP_Init(); + UPP_PreWhile(); + // USER APP INIT END } diff --git a/MATLAB/app_wrapper/app_io.c b/MATLAB/app_wrapper/app_io.c index 46f50ea..bbd7a47 100644 --- a/MATLAB/app_wrapper/app_io.c +++ b/MATLAB/app_wrapper/app_io.c @@ -32,7 +32,12 @@ void ThyristorWrite(real_T* Buffer) */ void app_readInputs(const real_T* Buffer) { // USER APP INPUT START -ADC_Set_Channel_Value(ADC1, 0, ReadInputArray(1,0)); +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)); // USER APP INPUT END } @@ -44,6 +49,10 @@ ADC_Set_Channel_Value(ADC1, 0, ReadInputArray(1,0)); void app_writeOutputBuffer(real_T* Buffer) { // USER APP OUTPUT START ThyristorWrite(Buffer); - WriteOutputArray(ADC1->DR, 1, 0); + extern ADC_Period_t adc; + for(int i = 0; i < 6; i++) + { + WriteOutputArray(adc.Data[i], 1, i); + } // USER APP OUTPUT END } \ No newline at end of file diff --git a/MATLAB/upp_r2023.slx b/MATLAB/upp_r2023.slx index d9915853767404eb7514ded05466e006e0438fd7..1ebf0c03611b4e40cdb769df5963a54adb506d4f 100644 GIT binary patch delta 55042 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 delta 55397 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 XK_K$~3j5+T#R3h?j#+m5&-MQR6DL4B diff --git a/UPP/.mxproject b/UPP/.mxproject index 6a3e639..76a640e 100644 --- a/UPP/.mxproject +++ b/UPP/.mxproject @@ -2,40 +2,42 @@ LibFiles=Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_adc.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_adc_ex.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_ll_adc.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_rcc.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_rcc_ex.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_ll_bus.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_ll_rcc.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_ll_system.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_ll_utils.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_flash.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_flash_ex.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_flash_ramfunc.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_gpio.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_gpio_ex.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_ll_gpio.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_dma_ex.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_dma.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_ll_dma.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_ll_dmamux.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_pwr.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_pwr_ex.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_ll_pwr.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_cortex.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_ll_cortex.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal.h;Drivers\STM32F4xx_HAL_Driver\Inc\Legacy\stm32_hal_legacy.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_def.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_exti.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_ll_exti.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_can.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_iwdg.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_ll_iwdg.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_rtc.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_ll_rtc.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_rtc_ex.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_spi.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_ll_spi.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_tim.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_tim_ex.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_ll_tim.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_uart.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_ll_usart.h;Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_adc.c;Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_adc_ex.c;Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_ll_adc.c;Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc.c;Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc_ex.c;Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash.c;Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash_ex.c;Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash_ramfunc.c;Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_gpio.c;Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma_ex.c;Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma.c;Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pwr.c;Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pwr_ex.c;Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cortex.c;Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal.c;Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_exti.c;Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_can.c;Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_iwdg.c;Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rtc.c;Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rtc_ex.c;Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_spi.c;Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_tim.c;Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_tim_ex.c;Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_uart.c;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_adc.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_adc_ex.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_ll_adc.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_rcc.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_rcc_ex.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_ll_bus.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_ll_rcc.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_ll_system.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_ll_utils.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_flash.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_flash_ex.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_flash_ramfunc.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_gpio.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_gpio_ex.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_ll_gpio.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_dma_ex.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_dma.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_ll_dma.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_ll_dmamux.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_pwr.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_pwr_ex.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_ll_pwr.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_cortex.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_ll_cortex.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal.h;Drivers\STM32F4xx_HAL_Driver\Inc\Legacy\stm32_hal_legacy.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_def.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_exti.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_ll_exti.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_can.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_iwdg.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_ll_iwdg.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_rtc.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_ll_rtc.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_rtc_ex.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_spi.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_ll_spi.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_tim.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_tim_ex.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_ll_tim.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_hal_uart.h;Drivers\STM32F4xx_HAL_Driver\Inc\stm32f4xx_ll_usart.h;Drivers\CMSIS\Device\ST\STM32F4xx\Include\stm32f427xx.h;Drivers\CMSIS\Device\ST\STM32F4xx\Include\stm32f4xx.h;Drivers\CMSIS\Device\ST\STM32F4xx\Include\system_stm32f4xx.h;Drivers\CMSIS\Device\ST\STM32F4xx\Include\system_stm32f4xx.h;Drivers\CMSIS\Device\ST\STM32F4xx\Source\Templates\system_stm32f4xx.c;Drivers\CMSIS\Include\cachel1_armv7.h;Drivers\CMSIS\Include\cmsis_armcc.h;Drivers\CMSIS\Include\cmsis_armclang.h;Drivers\CMSIS\Include\cmsis_armclang_ltm.h;Drivers\CMSIS\Include\cmsis_compiler.h;Drivers\CMSIS\Include\cmsis_gcc.h;Drivers\CMSIS\Include\cmsis_iccarm.h;Drivers\CMSIS\Include\cmsis_version.h;Drivers\CMSIS\Include\core_armv81mml.h;Drivers\CMSIS\Include\core_armv8mbl.h;Drivers\CMSIS\Include\core_armv8mml.h;Drivers\CMSIS\Include\core_cm0.h;Drivers\CMSIS\Include\core_cm0plus.h;Drivers\CMSIS\Include\core_cm1.h;Drivers\CMSIS\Include\core_cm23.h;Drivers\CMSIS\Include\core_cm3.h;Drivers\CMSIS\Include\core_cm33.h;Drivers\CMSIS\Include\core_cm35p.h;Drivers\CMSIS\Include\core_cm4.h;Drivers\CMSIS\Include\core_cm55.h;Drivers\CMSIS\Include\core_cm7.h;Drivers\CMSIS\Include\core_cm85.h;Drivers\CMSIS\Include\core_sc000.h;Drivers\CMSIS\Include\core_sc300.h;Drivers\CMSIS\Include\core_starmc1.h;Drivers\CMSIS\Include\mpu_armv7.h;Drivers\CMSIS\Include\mpu_armv8.h;Drivers\CMSIS\Include\pac_armv81.h;Drivers\CMSIS\Include\pmu_armv8.h;Drivers\CMSIS\Include\tz_context.h; [PreviousUsedKeilFiles] -SourceFiles=..\Core\Src\main.c;..\Core\Src\gpio.c;..\Core\Src\adc.c;..\Core\Src\can.c;..\Core\Src\iwdg.c;..\Core\Src\rtc.c;..\Core\Src\spi.c;..\Core\Src\tim.c;..\Core\Src\usart.c;..\Core\Src\stm32f4xx_it.c;..\Core\Src\stm32f4xx_hal_msp.c;..\Core\Src\stm32f4xx_hal_timebase_tim.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_adc.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_adc_ex.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_ll_adc.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc_ex.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash_ex.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash_ramfunc.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_gpio.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma_ex.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pwr.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pwr_ex.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cortex.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_exti.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_can.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_iwdg.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rtc.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rtc_ex.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_spi.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_tim.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_tim_ex.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_uart.c;..\Drivers\CMSIS\Device\ST\STM32F4xx\Source\Templates\system_stm32f4xx.c;..\Core\Src\system_stm32f4xx.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_adc.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_adc_ex.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_ll_adc.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc_ex.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash_ex.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash_ramfunc.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_gpio.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma_ex.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pwr.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pwr_ex.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cortex.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_exti.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_can.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_iwdg.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rtc.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rtc_ex.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_spi.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_tim.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_tim_ex.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_uart.c;..\Drivers\CMSIS\Device\ST\STM32F4xx\Source\Templates\system_stm32f4xx.c;..\Core\Src\system_stm32f4xx.c;;; +SourceFiles=..\Core\Src\main.c;..\Core\Src\gpio.c;..\Core\Src\adc.c;..\Core\Src\can.c;..\Core\Src\dma.c;..\Core\Src\iwdg.c;..\Core\Src\rtc.c;..\Core\Src\spi.c;..\Core\Src\tim.c;..\Core\Src\usart.c;..\Core\Src\stm32f4xx_it.c;..\Core\Src\stm32f4xx_hal_msp.c;..\Core\Src\stm32f4xx_hal_timebase_tim.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_adc.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_adc_ex.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_ll_adc.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc_ex.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash_ex.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash_ramfunc.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_gpio.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma_ex.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pwr.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pwr_ex.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cortex.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_exti.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_can.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_iwdg.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rtc.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rtc_ex.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_spi.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_tim.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_tim_ex.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_uart.c;..\Drivers\CMSIS\Device\ST\STM32F4xx\Source\Templates\system_stm32f4xx.c;..\Core\Src\system_stm32f4xx.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_adc.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_adc_ex.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_ll_adc.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rcc_ex.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash_ex.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_flash_ramfunc.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_gpio.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma_ex.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_dma.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pwr.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_pwr_ex.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_cortex.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_exti.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_can.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_iwdg.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rtc.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_rtc_ex.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_spi.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_tim.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_tim_ex.c;..\Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal_uart.c;..\Drivers\CMSIS\Device\ST\STM32F4xx\Source\Templates\system_stm32f4xx.c;..\Core\Src\system_stm32f4xx.c;;; HeaderPath=..\Drivers\STM32F4xx_HAL_Driver\Inc;..\Drivers\STM32F4xx_HAL_Driver\Inc\Legacy;..\Drivers\CMSIS\Device\ST\STM32F4xx\Include;..\Drivers\CMSIS\Include;..\Core\Inc; CDefines=USE_HAL_DRIVER;STM32F427xx;USE_HAL_DRIVER;USE_HAL_DRIVER; [PreviousGenFiles] AdvancedFolderStructure=true -HeaderFileListSize=11 +HeaderFileListSize=12 HeaderFiles#0=..\Core\Inc\gpio.h HeaderFiles#1=..\Core\Inc\adc.h HeaderFiles#2=..\Core\Inc\can.h -HeaderFiles#3=..\Core\Inc\iwdg.h -HeaderFiles#4=..\Core\Inc\rtc.h -HeaderFiles#5=..\Core\Inc\spi.h -HeaderFiles#6=..\Core\Inc\tim.h -HeaderFiles#7=..\Core\Inc\usart.h -HeaderFiles#8=..\Core\Inc\stm32f4xx_it.h -HeaderFiles#9=..\Core\Inc\stm32f4xx_hal_conf.h -HeaderFiles#10=..\Core\Inc\main.h +HeaderFiles#3=..\Core\Inc\dma.h +HeaderFiles#4=..\Core\Inc\iwdg.h +HeaderFiles#5=..\Core\Inc\rtc.h +HeaderFiles#6=..\Core\Inc\spi.h +HeaderFiles#7=..\Core\Inc\tim.h +HeaderFiles#8=..\Core\Inc\usart.h +HeaderFiles#9=..\Core\Inc\stm32f4xx_it.h +HeaderFiles#10=..\Core\Inc\stm32f4xx_hal_conf.h +HeaderFiles#11=..\Core\Inc\main.h HeaderFolderListSize=1 HeaderPath#0=..\Core\Inc HeaderFiles=; -SourceFileListSize=12 +SourceFileListSize=13 SourceFiles#0=..\Core\Src\gpio.c SourceFiles#1=..\Core\Src\adc.c SourceFiles#2=..\Core\Src\can.c -SourceFiles#3=..\Core\Src\iwdg.c -SourceFiles#4=..\Core\Src\rtc.c -SourceFiles#5=..\Core\Src\spi.c -SourceFiles#6=..\Core\Src\tim.c -SourceFiles#7=..\Core\Src\usart.c -SourceFiles#8=..\Core\Src\stm32f4xx_it.c -SourceFiles#9=..\Core\Src\stm32f4xx_hal_msp.c -SourceFiles#10=..\Core\Src\stm32f4xx_hal_timebase_tim.c -SourceFiles#11=..\Core\Src\main.c +SourceFiles#3=..\Core\Src\dma.c +SourceFiles#4=..\Core\Src\iwdg.c +SourceFiles#5=..\Core\Src\rtc.c +SourceFiles#6=..\Core\Src\spi.c +SourceFiles#7=..\Core\Src\tim.c +SourceFiles#8=..\Core\Src\usart.c +SourceFiles#9=..\Core\Src\stm32f4xx_it.c +SourceFiles#10=..\Core\Src\stm32f4xx_hal_msp.c +SourceFiles#11=..\Core\Src\stm32f4xx_hal_timebase_tim.c +SourceFiles#12=..\Core\Src\main.c SourceFolderListSize=1 SourcePath#0=..\Core\Src SourceFiles=; diff --git a/UPP/AllLibs/MyLibs b/UPP/AllLibs/MyLibs index eff6470..60629aa 160000 --- a/UPP/AllLibs/MyLibs +++ b/UPP/AllLibs/MyLibs @@ -1 +1 @@ -Subproject commit eff64709bccb8f8fa7297f4042f4ebb7c71a5a21 +Subproject commit 60629aaa3bb3a068cbfe5a93f43f676bd154e85b diff --git a/UPP/Core/Inc/adc.h b/UPP/Core/Inc/adc.h index 34c0965..208562f 100644 --- a/UPP/Core/Inc/adc.h +++ b/UPP/Core/Inc/adc.h @@ -32,15 +32,12 @@ extern "C" { /* USER CODE END Includes */ -extern ADC_HandleTypeDef hadc1; - extern ADC_HandleTypeDef hadc3; /* USER CODE BEGIN Private defines */ - +extern DMA_HandleTypeDef hdma_adc3; /* USER CODE END Private defines */ -void MX_ADC1_Init(void); void MX_ADC3_Init(void); /* USER CODE BEGIN Prototypes */ diff --git a/UPP/Core/Inc/dma.h b/UPP/Core/Inc/dma.h new file mode 100644 index 0000000..493d98e --- /dev/null +++ b/UPP/Core/Inc/dma.h @@ -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__ */ + diff --git a/UPP/Core/Inc/main.h b/UPP/Core/Inc/main.h index 72e8f7e..a705fae 100644 --- a/UPP/Core/Inc/main.h +++ b/UPP/Core/Inc/main.h @@ -75,6 +75,7 @@ void Error_Handler(void); #define PWM_CHANNEL_4 TIM_CHANNEL_4 #define PWM_CHANNEL_5 TIM_CHANNEL_3 #define PWM_CHANNEL_6 TIM_CHANNEL_4 +#define adc_tim htim8 #define UM_LED_GREEN2_Pin GPIO_PIN_2 #define UM_LED_GREEN2_GPIO_Port GPIOE #define CEN_O_Pin GPIO_PIN_3 diff --git a/UPP/Core/Inc/stm32f4xx_it.h b/UPP/Core/Inc/stm32f4xx_it.h index f706d99..52044da 100644 --- a/UPP/Core/Inc/stm32f4xx_it.h +++ b/UPP/Core/Inc/stm32f4xx_it.h @@ -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 */ diff --git a/UPP/Core/Inc/tim.h b/UPP/Core/Inc/tim.h index 48522b1..2dfa292 100644 --- a/UPP/Core/Inc/tim.h +++ b/UPP/Core/Inc/tim.h @@ -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); diff --git a/UPP/Core/PowerMonitor/adc_tools.c b/UPP/Core/PowerMonitor/adc_tools.c new file mode 100644 index 0000000..a5ad350 --- /dev/null +++ b/UPP/Core/PowerMonitor/adc_tools.c @@ -0,0 +1,130 @@ +/** +****************************************************************************** +* @file adc_tools.c +* @brief Функции доступа к данным Modbus +****************************************************************************** +* @details +******************************************************************************/ +#include "adc_tools.h" + + +// Проверка корректности структуры АЦП +#define assert_adc(_adc_) check_null_ptr_2(_adc_, (_adc_)->f.Initialized) + + +/** + * @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->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; + } + + 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 Вызывается в . + */ +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++) + { + ADC_Coefs_t *coefs = &adc->Coefs[i]; + data[i] = ((float)(raw[i])-coefs->lZero) * coefs->vMax / (coefs->lMax-coefs->lZero); + } + adc->f.DataReady = 1; + + return HAL_OK; +} \ No newline at end of file diff --git a/UPP/Core/PowerMonitor/adc_tools.h b/UPP/Core/PowerMonitor/adc_tools.h new file mode 100644 index 0000000..a5923a3 --- /dev/null +++ b/UPP/Core/PowerMonitor/adc_tools.h @@ -0,0 +1,62 @@ +/** +****************************************************************************** +* @file adc_tools.h +* @brief Определения структур данных Modbus устройства +****************************************************************************** +* @details +******************************************************************************/ + +#ifndef _ADC_TOOLS_H_ +#define _ADC_TOOLS_H_ +#include "main.h" + +#define ADC_NUMB_OF_CHANNELS 6 + +/** + * @brief Коэфициенты канала АЦП для пересчета в единицы измерения + */ +typedef struct +{ + uint16_t lZero; ///< Нулевой уровень (в квантах АЦП) + float vMax; ///< Максимальный уровень Единиц Измерения (в Вольтах/Амперах/Градусах) + uint16_t lMax; ///< Максимальный уровень АЦП (в квантах АЦП) +}ADC_Coefs_t; + +/** + * @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_CHANNELS]; ///< Коэффициенты @ref ADC_Coefs_t + float Data[ADC_NUMB_OF_CHANNELS]; ///< Пересчитанные значения АЦП (в Вольтах/Амперах/Градусах) + + struct + { + unsigned Initialized:1; + unsigned AdcRunning:1; + unsigned DataReady:1; + }f; +}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_ diff --git a/UPP/Core/Src/adc.c b/UPP/Core/Src/adc.c index 87bdb83..603f877 100644 --- a/UPP/Core/Src/adc.c +++ b/UPP/Core/Src/adc.c @@ -21,59 +21,12 @@ #include "adc.h" /* USER CODE BEGIN 0 */ - +#include "tim.h" /* USER CODE END 0 */ -ADC_HandleTypeDef hadc1; ADC_HandleTypeDef hadc3; +DMA_HandleTypeDef hdma_adc3; -/* ADC1 init function */ -void MX_ADC1_Init(void) -{ - - /* USER CODE BEGIN ADC1_Init 0 */ - - /* USER CODE END ADC1_Init 0 */ - - ADC_ChannelConfTypeDef sConfig = {0}; - - /* USER CODE BEGIN ADC1_Init 1 */ - - /* USER CODE END ADC1_Init 1 */ - - /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) - */ - hadc1.Instance = ADC1; - hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; - hadc1.Init.Resolution = ADC_RESOLUTION_12B; - hadc1.Init.ScanConvMode = DISABLE; - hadc1.Init.ContinuousConvMode = ENABLE; - hadc1.Init.DiscontinuousConvMode = DISABLE; - hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; - hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; - hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; - hadc1.Init.NbrOfConversion = 1; - hadc1.Init.DMAContinuousRequests = DISABLE; - hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV; - if (HAL_ADC_Init(&hadc1) != 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_0; - sConfig.Rank = 1; - sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES; - if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) - { - Error_Handler(); - } - /* USER CODE BEGIN ADC1_Init 2 */ - - /* USER CODE END ADC1_Init 2 */ - -} /* ADC3 init function */ void MX_ADC3_Init(void) { @@ -93,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(); @@ -109,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 */ @@ -126,28 +124,7 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; - if(adcHandle->Instance==ADC1) - { - /* USER CODE BEGIN ADC1_MspInit 0 */ - - /* USER CODE END ADC1_MspInit 0 */ - /* ADC1 clock enable */ - __HAL_RCC_ADC1_CLK_ENABLE(); - - __HAL_RCC_GPIOA_CLK_ENABLE(); - /**ADC1 GPIO Configuration - PA0/WKUP ------> ADC1_IN0 - */ - GPIO_InitStruct.Pin = GPIO_PIN_0; - GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; - GPIO_InitStruct.Pull = GPIO_NOPULL; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - - /* USER CODE BEGIN ADC1_MspInit 1 */ - - /* USER CODE END ADC1_MspInit 1 */ - } - else if(adcHandle->Instance==ADC3) + if(adcHandle->Instance==ADC3) { /* USER CODE BEGIN ADC3_MspInit 0 */ @@ -176,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 */ @@ -185,24 +181,7 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle) void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle) { - if(adcHandle->Instance==ADC1) - { - /* USER CODE BEGIN ADC1_MspDeInit 0 */ - - /* USER CODE END ADC1_MspDeInit 0 */ - /* Peripheral clock disable */ - __HAL_RCC_ADC1_CLK_DISABLE(); - - /**ADC1 GPIO Configuration - PA0/WKUP ------> ADC1_IN0 - */ - HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0); - - /* USER CODE BEGIN ADC1_MspDeInit 1 */ - - /* USER CODE END ADC1_MspDeInit 1 */ - } - else if(adcHandle->Instance==ADC3) + if(adcHandle->Instance==ADC3) { /* USER CODE BEGIN ADC3_MspDeInit 0 */ @@ -223,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 */ diff --git a/UPP/Core/Src/dma.c b/UPP/Core/Src/dma.c new file mode 100644 index 0000000..3f5fab8 --- /dev/null +++ b/UPP/Core/Src/dma.c @@ -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 */ + diff --git a/UPP/Core/Src/main.c b/UPP/Core/Src/main.c index ec5e420..0e2747f 100644 --- a/UPP/Core/Src/main.c +++ b/UPP/Core/Src/main.c @@ -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,7 +29,7 @@ /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ - +#include "upp_main.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -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,26 +106,23 @@ int main(void) MX_SPI3_Init(); MX_TIM11_Init(); MX_TIM12_Init(); - MX_ADC1_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 */ } diff --git a/UPP/Core/Src/stm32f4xx_it.c b/UPP/Core/Src/stm32f4xx_it.c index a7ab8ff..c199d34 100644 --- a/UPP/Core/Src/stm32f4xx_it.c +++ b/UPP/Core/Src/stm32f4xx_it.c @@ -55,6 +55,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 +209,29 @@ 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 */ +#include "adc_tools.h" + extern ADC_Period_t adc; + ADC_Handle(&adc); + /* USER CODE END DMA2_Stream0_IRQn 0 */ + HAL_DMA_IRQHandler(&hdma_adc3); + /* USER CODE BEGIN DMA2_Stream0_IRQn 1 */ + + /* USER CODE END DMA2_Stream0_IRQn 1 */ +} + /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ diff --git a/UPP/Core/Src/tim.c b/UPP/Core/Src/tim.c index fb00a90..04ec18c 100644 --- a/UPP/Core/Src/tim.c +++ b/UPP/Core/Src/tim.c @@ -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 = 180-1; + 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 */ diff --git a/UPP/Core/UPP/upp_main.c b/UPP/Core/UPP/upp_main.c new file mode 100644 index 0000000..d95628b --- /dev/null +++ b/UPP/Core/UPP/upp_main.c @@ -0,0 +1,58 @@ +/** +****************************************************************************** +* @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" +ADC_Period_t adc; +#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); + + return 0; +} + +/** + * @brief Инициализация основного цикла УПП. + * @return 0 - если ОК, >1 если ошибка. + */ +int UPP_PreWhile(void) +{ + ADC_Start(&adc, 1000); + return 0; +} + +/** + * @brief Основной цикл УПП. + * @return 0 - если ОК, >1 если ошибка. + */ +int UPP_While(void) +{ + + return 0; +} \ No newline at end of file diff --git a/UPP/Core/UPP/upp_main.h b/UPP/Core/UPP/upp_main.h new file mode 100644 index 0000000..3d72e8b --- /dev/null +++ b/UPP/Core/UPP/upp_main.h @@ -0,0 +1,21 @@ +/** +****************************************************************************** +* @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); + +#endif //_UPP_MAIN_H \ No newline at end of file diff --git a/UPP/MDK-ARM/UPP.uvoptx b/UPP/MDK-ARM/UPP.uvoptx index 13cdd2d..66f3b96 100644 --- a/UPP/MDK-ARM/UPP.uvoptx +++ b/UPP/MDK-ARM/UPP.uvoptx @@ -1,4 +1,4 @@ - + 1.0 @@ -45,7 +45,7 @@ 79 66 8 - + 1 @@ -104,16 +104,16 @@ 0 0 6 - - - - - - - - - - + + + + + + + + + + STLink\ST-LINKIII-KEIL_SWO.dll @@ -128,7 +128,7 @@ -U-O142 -O2190 -S0 -C0 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC800 -FN1 -FF0STM32F4xx_1024.FLM -FS08000000 -FL0100000 -FP0($$Device:STM32F427ZGTx$CMSIS\Flash\STM32F4xx_1024.FLM) - + 0 @@ -158,19 +158,19 @@ 0 0 - - + + 0 0 0 - - - - - - - - + + + + + + + + 1 1 @@ -298,7 +298,7 @@ - Application/User/Core + UPP/Main 1 0 0 @@ -310,14 +310,86 @@ 0 0 0 - ../Core/Src/main.c - main.c + ..\Core\UPP\upp_main.c + upp_main.c 0 0 2 11 + 5 + 0 + 0 + 0 + ..\Core\UPP\upp_main.h + upp_main.h + 0 + 0 + + + + + PowerMonitor + 1 + 0 + 0 + 0 + + 3 + 12 + 1 + 0 + 0 + 0 + ..\Core\PowerMonitor\adc_tools.c + adc_tools.c + 0 + 0 + + + 3 + 13 + 5 + 0 + 0 + 0 + ..\Core\PowerMonitor\adc_tools.h + adc_tools.h + 0 + 0 + + + + + Thyristors + 0 + 0 + 0 + 0 + + + + Application/User/Core + 1 + 0 + 0 + 0 + + 5 + 14 + 1 + 0 + 0 + 0 + ../Core/Src/main.c + main.c + 0 + 0 + + + 5 + 15 1 0 0 @@ -328,8 +400,8 @@ 0 - 2 - 12 + 5 + 16 1 0 0 @@ -340,8 +412,8 @@ 0 - 2 - 13 + 5 + 17 1 0 0 @@ -352,8 +424,20 @@ 0 - 2 - 14 + 5 + 18 + 1 + 0 + 0 + 0 + ../Core/Src/dma.c + dma.c + 0 + 0 + + + 5 + 19 1 0 0 @@ -364,8 +448,8 @@ 0 - 2 - 15 + 5 + 20 1 0 0 @@ -376,8 +460,8 @@ 0 - 2 - 16 + 5 + 21 1 0 0 @@ -388,8 +472,8 @@ 0 - 2 - 17 + 5 + 22 1 0 0 @@ -400,8 +484,8 @@ 0 - 2 - 18 + 5 + 23 1 0 0 @@ -412,8 +496,8 @@ 0 - 2 - 19 + 5 + 24 1 0 0 @@ -424,8 +508,8 @@ 0 - 2 - 20 + 5 + 25 1 0 0 @@ -436,8 +520,8 @@ 0 - 2 - 21 + 5 + 26 1 0 0 @@ -451,13 +535,13 @@ MyLibs - 0 + 1 0 0 0 - 3 - 22 + 6 + 27 5 0 0 @@ -468,8 +552,8 @@ 0 - 3 - 23 + 6 + 28 5 0 0 @@ -480,8 +564,8 @@ 0 - 3 - 24 + 6 + 29 5 0 0 @@ -492,8 +576,8 @@ 0 - 3 - 25 + 6 + 30 5 0 0 @@ -504,8 +588,8 @@ 0 - 3 - 26 + 6 + 31 5 0 0 @@ -516,8 +600,8 @@ 0 - 3 - 27 + 6 + 32 5 0 0 @@ -536,8 +620,8 @@ 0 0 - 4 - 28 + 7 + 33 1 0 0 @@ -548,8 +632,8 @@ 0 - 4 - 29 + 7 + 34 1 0 0 @@ -560,8 +644,8 @@ 0 - 4 - 30 + 7 + 35 1 0 0 @@ -572,8 +656,8 @@ 0 - 4 - 31 + 7 + 36 1 0 0 @@ -584,8 +668,8 @@ 0 - 4 - 32 + 7 + 37 1 0 0 @@ -596,8 +680,8 @@ 0 - 4 - 33 + 7 + 38 1 0 0 @@ -608,8 +692,8 @@ 0 - 4 - 34 + 7 + 39 1 0 0 @@ -620,8 +704,8 @@ 0 - 4 - 35 + 7 + 40 1 0 0 @@ -632,8 +716,8 @@ 0 - 4 - 36 + 7 + 41 1 0 0 @@ -644,8 +728,8 @@ 0 - 4 - 37 + 7 + 42 1 0 0 @@ -656,8 +740,8 @@ 0 - 4 - 38 + 7 + 43 1 0 0 @@ -668,8 +752,8 @@ 0 - 4 - 39 + 7 + 44 1 0 0 @@ -688,8 +772,8 @@ 0 0 - 5 - 40 + 8 + 45 1 0 0 @@ -700,8 +784,8 @@ 0 - 5 - 41 + 8 + 46 1 0 0 @@ -720,8 +804,8 @@ 0 0 - 6 - 42 + 9 + 47 1 0 0 @@ -732,8 +816,8 @@ 0 - 6 - 43 + 9 + 48 1 0 0 @@ -744,8 +828,8 @@ 0 - 6 - 44 + 9 + 49 1 0 0 @@ -756,8 +840,8 @@ 0 - 6 - 45 + 9 + 50 1 0 0 @@ -768,8 +852,8 @@ 0 - 6 - 46 + 9 + 51 1 0 0 @@ -788,8 +872,8 @@ 0 0 - 7 - 47 + 10 + 52 1 0 0 @@ -800,8 +884,8 @@ 0 - 7 - 48 + 10 + 53 1 0 0 @@ -812,8 +896,8 @@ 0 - 7 - 49 + 10 + 54 1 0 0 @@ -824,8 +908,8 @@ 0 - 7 - 50 + 10 + 55 1 0 0 @@ -836,8 +920,8 @@ 0 - 7 - 51 + 10 + 56 1 0 0 @@ -848,8 +932,8 @@ 0 - 7 - 52 + 10 + 57 1 0 0 @@ -860,8 +944,8 @@ 0 - 7 - 53 + 10 + 58 1 0 0 @@ -872,8 +956,8 @@ 0 - 7 - 54 + 10 + 59 1 0 0 @@ -884,8 +968,8 @@ 0 - 7 - 55 + 10 + 60 1 0 0 @@ -896,8 +980,8 @@ 0 - 7 - 56 + 10 + 61 1 0 0 @@ -908,8 +992,8 @@ 0 - 7 - 57 + 10 + 62 1 0 0 @@ -920,8 +1004,8 @@ 0 - 7 - 58 + 10 + 63 1 0 0 @@ -932,8 +1016,8 @@ 0 - 7 - 59 + 10 + 64 1 0 0 @@ -944,8 +1028,8 @@ 0 - 7 - 60 + 10 + 65 1 0 0 @@ -956,8 +1040,8 @@ 0 - 7 - 61 + 10 + 66 1 0 0 @@ -968,8 +1052,8 @@ 0 - 7 - 62 + 10 + 67 1 0 0 @@ -980,8 +1064,8 @@ 0 - 7 - 63 + 10 + 68 1 0 0 @@ -992,8 +1076,8 @@ 0 - 7 - 64 + 10 + 69 1 0 0 @@ -1004,8 +1088,8 @@ 0 - 7 - 65 + 10 + 70 1 0 0 @@ -1016,8 +1100,8 @@ 0 - 7 - 66 + 10 + 71 1 0 0 @@ -1028,8 +1112,8 @@ 0 - 7 - 67 + 10 + 72 1 0 0 @@ -1040,8 +1124,8 @@ 0 - 7 - 68 + 10 + 73 1 0 0 @@ -1052,8 +1136,8 @@ 0 - 7 - 69 + 10 + 74 1 0 0 @@ -1064,8 +1148,8 @@ 0 - 7 - 70 + 10 + 75 1 0 0 @@ -1084,8 +1168,8 @@ 0 0 - 8 - 71 + 11 + 76 1 0 0 @@ -1104,8 +1188,8 @@ 0 0 - 9 - 72 + 12 + 77 2 0 0 diff --git a/UPP/MDK-ARM/UPP.uvprojx b/UPP/MDK-ARM/UPP.uvprojx index 13644f1..b8ac044 100644 --- a/UPP/MDK-ARM/UPP.uvprojx +++ b/UPP/MDK-ARM/UPP.uvprojx @@ -1,7 +1,10 @@ - - + + + 2.1 +
### uVision Project, (C) Keil Software
+ UPP @@ -17,28 +20,28 @@ Keil.STM32F4xx_DFP.2.16.0 http://www.keil.com/pack/ IRAM(0x20000000-0x2002FFFF) IRAM2(0x10000000-0x1000FFFF) IROM(0x8000000-0x80FFFFF) CLOCK(25000000) FPU2 CPUTYPE("Cortex-M4") TZ - - - + + + 0 - - - - - - - - - - + + + + + + + + + + $$Device:STM32F427ZGTx$CMSIS\SVD\STM32F427x.svd 0 0 - - - - - + + + + + 0 0 @@ -53,15 +56,15 @@ 1 1 1 - + 1 0 0 0 0 - - + + 0 0 0 @@ -70,8 +73,8 @@ 0 0 - - + + 0 0 0 @@ -80,15 +83,15 @@ 0 1 - - + + 0 0 0 0 1 - + 0 @@ -102,8 +105,8 @@ 0 0 3 - - + + 0 @@ -136,11 +139,11 @@ 1 BIN\UL2V8M.DLL - - - - - + + + + + 0 @@ -173,7 +176,7 @@ 0 0 "Cortex-M4" - + 0 0 0 @@ -308,7 +311,7 @@ 0x10000 - + 1 @@ -335,10 +338,10 @@ 0 0 - + USE_HAL_DRIVER,STM32F427xx - - ../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/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 @@ -353,10 +356,10 @@ 0 1 - - - - + + + + @@ -366,15 +369,15 @@ 0 1 0 - - - - - - - - - + + + + + + + + + @@ -429,6 +432,39 @@
+ + UPP/Main + + + upp_main.c + 1 + ..\Core\UPP\upp_main.c + + + upp_main.h + 5 + ..\Core\UPP\upp_main.h + + + + + PowerMonitor + + + adc_tools.c + 1 + ..\Core\PowerMonitor\adc_tools.c + + + adc_tools.h + 5 + ..\Core\PowerMonitor\adc_tools.h + + + + + Thyristors + Application/User/Core @@ -452,6 +488,62 @@ 1 ../Core/Src/can.c
+ + dma.c + 1 + ../Core/Src/dma.c + + + 2 + 0 + 0 + 0 + 0 + 1 + 2 + 2 + 2 + 2 + 11 + + + 1 + + + + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 0 + 2 + 2 + 2 + 2 + 2 + 0 + 0 + 2 + 2 + 2 + 2 + 2 + + + + + + + + + + iwdg.c 1 @@ -793,24 +885,26 @@ + - + - + - + - + - + - + + @@ -819,5 +913,5 @@ - + diff --git a/UPP/UPP.ioc b/UPP/UPP.ioc index b810d65..817c3bc 100644 --- a/UPP/UPP.ioc +++ b/UPP/UPP.ioc @@ -1,17 +1,28 @@ #MicroXplorer Configuration settings - do not modify -ADC1.Channel-1\#ChannelRegularConversion=ADC_CHANNEL_0 -ADC1.ContinuousConvMode=ENABLE -ADC1.IPParameters=Rank-1\#ChannelRegularConversion,master,Channel-1\#ChannelRegularConversion,SamplingTime-1\#ChannelRegularConversion,NbrOfConversionFlag,ContinuousConvMode -ADC1.NbrOfConversionFlag=1 -ADC1.Rank-1\#ChannelRegularConversion=1 -ADC1.SamplingTime-1\#ChannelRegularConversion=ADC_SAMPLETIME_3CYCLES -ADC1.master=1 -ADC3.Channel-15\#ChannelRegularConversion=ADC_CHANNEL_7 -ADC3.IPParameters=Rank-15\#ChannelRegularConversion,Channel-15\#ChannelRegularConversion,SamplingTime-15\#ChannelRegularConversion,NbrOfConversionFlag,NbrOfConversion -ADC3.NbrOfConversion=1 +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= @@ -22,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 @@ -29,15 +52,16 @@ IWDG.Prescaler=IWDG_PRESCALER_32 KeepUserPlacement=false Mcu.CPN=STM32F427ZGT6 Mcu.Family=STM32F4 -Mcu.IP0=ADC1 -Mcu.IP1=ADC3 +Mcu.IP0=ADC3 +Mcu.IP1=CAN1 Mcu.IP10=TIM3 -Mcu.IP11=TIM11 -Mcu.IP12=TIM12 -Mcu.IP13=TIM13 -Mcu.IP14=USART3 -Mcu.IP15=USART6 -Mcu.IP2=CAN1 +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 @@ -45,7 +69,7 @@ Mcu.IP6=RTC Mcu.IP7=SPI3 Mcu.IP8=SYS Mcu.IP9=TIM1 -Mcu.IPNb=16 +Mcu.IPNb=17 Mcu.Name=STM32F427Z(G-I)Tx Mcu.Package=LQFP144 Mcu.Pin0=PE2 @@ -56,54 +80,54 @@ Mcu.Pin12=PF10 Mcu.Pin13=PH0/OSC_IN Mcu.Pin14=PH1/OSC_OUT Mcu.Pin15=PC0 -Mcu.Pin16=PA0/WKUP -Mcu.Pin17=PA4 -Mcu.Pin18=PA5 -Mcu.Pin19=PA6 +Mcu.Pin16=PA4 +Mcu.Pin17=PA5 +Mcu.Pin18=PA6 +Mcu.Pin19=PB0 Mcu.Pin2=PE4 -Mcu.Pin20=PB0 -Mcu.Pin21=PB1 -Mcu.Pin22=PF11 -Mcu.Pin23=PB10 -Mcu.Pin24=PB11 -Mcu.Pin25=PB13 -Mcu.Pin26=PG6 -Mcu.Pin27=PC6 -Mcu.Pin28=PC7 -Mcu.Pin29=PC8 +Mcu.Pin20=PB1 +Mcu.Pin21=PF11 +Mcu.Pin22=PB10 +Mcu.Pin23=PB11 +Mcu.Pin24=PB13 +Mcu.Pin25=PG6 +Mcu.Pin26=PC6 +Mcu.Pin27=PC7 +Mcu.Pin28=PC8 +Mcu.Pin29=PC9 Mcu.Pin3=PE5 -Mcu.Pin30=PC9 -Mcu.Pin31=PA8 -Mcu.Pin32=PA9 -Mcu.Pin33=PA10 -Mcu.Pin34=PA11 -Mcu.Pin35=PA12 -Mcu.Pin36=PA13 -Mcu.Pin37=PA14 -Mcu.Pin38=PA15 -Mcu.Pin39=PC10 +Mcu.Pin30=PA8 +Mcu.Pin31=PA9 +Mcu.Pin32=PA10 +Mcu.Pin33=PA11 +Mcu.Pin34=PA12 +Mcu.Pin35=PA13 +Mcu.Pin36=PA14 +Mcu.Pin37=PA15 +Mcu.Pin38=PC10 +Mcu.Pin39=PC11 Mcu.Pin4=PE6 -Mcu.Pin40=PC11 -Mcu.Pin41=PC12 -Mcu.Pin42=PD2 -Mcu.Pin43=PD3 -Mcu.Pin44=PD6 -Mcu.Pin45=PG12 -Mcu.Pin46=PG15 -Mcu.Pin47=PB3 -Mcu.Pin48=PB6 -Mcu.Pin49=PB7 +Mcu.Pin40=PC12 +Mcu.Pin41=PD2 +Mcu.Pin42=PD3 +Mcu.Pin43=PD6 +Mcu.Pin44=PG12 +Mcu.Pin45=PG15 +Mcu.Pin46=PB3 +Mcu.Pin47=PB6 +Mcu.Pin48=PB7 +Mcu.Pin49=PB8 Mcu.Pin5=PC13 -Mcu.Pin50=PB8 -Mcu.Pin51=PB9 -Mcu.Pin52=PE0 -Mcu.Pin53=PE1 -Mcu.Pin54=VP_IWDG_VS_IWDG -Mcu.Pin55=VP_RTC_VS_RTC_Activate -Mcu.Pin56=VP_RTC_VS_RTC_Calendar -Mcu.Pin57=VP_SYS_VS_tim14 -Mcu.Pin58=VP_TIM1_VS_ClockSourceINT -Mcu.Pin59=VP_TIM3_VS_ClockSourceINT +Mcu.Pin50=PB9 +Mcu.Pin51=PE0 +Mcu.Pin52=PE1 +Mcu.Pin53=VP_IWDG_VS_IWDG +Mcu.Pin54=VP_RTC_VS_RTC_Activate +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_TIM8_VS_ClockSourceINT Mcu.Pin6=PC14/OSC32_IN Mcu.Pin60=VP_TIM11_VS_ClockSourceINT Mcu.Pin61=VP_TIM12_VS_ClockSourceINT @@ -113,11 +137,12 @@ Mcu.Pin8=PF6 Mcu.Pin9=PF7 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;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;adc_tim,htim8 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 @@ -131,7 +156,6 @@ NVIC.TIM8_TRG_COM_TIM14_IRQn=true\:15\:0\:false\:false\:true\:false\:true\:true NVIC.TimeBase=TIM8_TRG_COM_TIM14_IRQn NVIC.TimeBaseIP=TIM14 NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false -PA0/WKUP.Signal=ADCx_IN0 PA10.GPIOParameters=GPIO_Label PA10.GPIO_Label=PWM3 PA10.Locked=true @@ -370,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 @@ -415,8 +439,6 @@ RTC.IPParameters=WeekDay,Year,Date,Month,Hours RTC.Month=RTC_MONTH_JANUARY RTC.WeekDay=RTC_WEEKDAY_MONDAY RTC.Year=25 -SH.ADCx_IN0.0=ADC1_IN0,IN0 -SH.ADCx_IN0.ConfNb=1 SH.ADCx_IN10.0=ADC3_IN10,IN10 SH.ADCx_IN10.ConfNb=1 SH.S_TIM1_CH1.0=TIM1_CH1,PWM Generation1 CH1 @@ -451,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=180-1 +TIM8.TIM_MasterOutputTrigger=TIM_TRGO_UPDATE +TIM8.TIM_MasterSlaveMode=TIM_MASTERSLAVEMODE_DISABLE USART3.IPParameters=VirtualMode USART3.VirtualMode=VM_ASYNC USART6.IPParameters=VirtualMode @@ -473,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 diff --git a/Информация для программиста (УПП СП СЭД)/Значения температуры в ед АЦП.xlsx b/Информация для программиста (УПП СП СЭД)/Значения температуры в ед АЦП.xlsx index 9ebd825e3cc119432bdf104029a5357c7f3f36c5..392e4758e1dd795523a11a9a764ca9595e4d6c05 100644 GIT binary patch delta 16620 zcmb`vWndh;vIb~ojG394nVFd(F*7rcnR(0<#~fqK%*-4!b4)SEyiU&BoBPh&pF2M^ z8mYQkRbO>WRV7WY-Esjawz3>J1Ud*52n+}a2nk3NSEf}DCj4w!zaJp8i5Rb z20X2HVNpC^3dOM+>h6q9FpM)X=}jHwdRPZfI}J(^xP{Z6xR8k zG!#E@aYM}_wjL(v3nfuEivcY$vP|>%d&{1_ByK+;awX@jBaZi=%zrGaIJNB!*-$Bc zkKXZqF^Db;iJH-=jEEh@au5`eG~%qom7ktMluN@#qYmZ(;i!rkVPz2jL8S^4wKt=5 z^u(?oE882kMXdQ;8B%SpUQ*e4{8L+eaO!Po(=t6vb`76mZBNvRg5`SxYjyd`+ z(I%yvAEo->VGByo`u-QQOh+T8sfW{ZvxlgF{sbYcnIPie-Wd!0`OxIRX88K2CW`6> zm$lquNURV3!CzcH@g)j83XdM2WHz-2Qq^o6o$t6rwIH;t532LqyWI zbLH4&-SZ{t9nIi~trj4rGuURl!4^A!09jzs>n6Y{z~OL??}vflARziMKqXjAfToWb2-Nu;l1xV-zID+UJd$#Iu;7f;sNxyup5P^t|gt)(sF!Ksd zg;?#T5ZA}d!2C%L9^rz?=4B9QoD6Y(M7kf8J%n=CYg-T+Pz^3L7tmv!3xFt#m7<_W z;Xh<+0iX6hyODe@{*rajflklq@{J&=65e}29dXeR_At|6gHg0;F z&?i1Nyz!85$1&(N*&vB{o`55Su||5S90=nZ6B!9v^7X^75QJ4bkNT4uOHZiKVFf0S zemxMOgJAw570gN96o(J#!!Q`6=i6WS)_Gpef2|(RSh8o!e~ufPyIQ=e-k;hJ-$&km zx-x&r_igiy9Oc^Q<9I=wMc%i;b`X9dbQNL*&^knUt!P!ssZ6bV;?(nH;lNJ zZHwM|96pp59w#*L)_T7u zWevh6SPcVjIK>-fBz0W+fh!9`P>6rB?StgiASUR`&avhq-L;y7VT0ELk zWuBfMV4ua3z7RHIq-T3|PS@S9J_zZcqb0@%Cr3F5e z+h^-#ZidcA))chk>q_lPoAr&>Y=fgFyyip4BI|igiKvdw+hPyZPtv&K)bJM|1M)c$ zfg(~9zYlYEcFu=K4Ld=cN+ig@V*Am2E&#&aD-aa}11QOcR0}Nu23L`QgTIRe0#Nxy;jZSJvKT2(N0}-z+)7^7S2S>)gZMEK#)T;92uLV;|`>hIOd)J)4&de!6#$r z+YF=J9TL>hdBoMK^UO3WxO5G|K2+-Q!lrPa#CtixccHvRuvHuCewe;M4!;bcsM{t0 zGkO#GQ5x%X5IV^*Kf}Jk>jH_v}1&iM%e-m8zFhHq8ST7UauRBYpsw&X= z`g(PB`!ZBb^qHvZ`9#Q}lRu~Tc;ci>==HMo^?2RY`+74$$lv>Z^=+f8-QW9R_hinB zd+74!`PXsr%LAo9Z_!*9$IsT+lcvL;fL}k)9xk`hs2LR!BT1bH+@4|r=>#j_eEoZu z`ru;bXTZ@cknzs^7OK9_Ls zUEOVmBMbF+AvnDGKCSNd9j>||JZ0o1WHH0Ve#O z@meD94d%@tn6@_1C*H^Hs`ik{Lwa9_J7%{^y^102WPH?#lhX226jeX zOdE@~)LVv6vV23Ti2&W4=X6!gi-vxrlsqD4W@Lz(_A+K*=uERwTbDHh%1 zYNZmA>m@h#WpSSK#?t|dlP;`B%wWOe)JLoy2fTNjX(q7(d%gjuKFbhqx)>Fcqbxk;I_tVpX0O`E8x4WHLnkj@i$l-Ai zluiCvaMe*Y4G+pZ+z3#&w(rl4(V4#zK*Ze7Zml3s;B>adC+B7!S=iOX-YejQG;lr- zEzhE`qOM@zM3lXp?>f+J=S0Y*;M)xgY@A1$hr5@_z>=k_nDXYmRpe(%RG4R-0BPZQ zymBO>;U~y9ZyqCXu+F|H#1gG{Nn`((OR`u*+|)9%6Xv33u?9FapQILMOvE!Gv0u}i zCjKS^td)%V%~NNzWrW*nv?Zk5J1l*$`c_LQ$JU+|$rE0UYVFYcxPZNPcy7on#(hfp zN-9%lUnk>~l%vlQS`wAmk%shmdCQJ|KOsETS*N4^t z&^bJgrZ~pA@*jc}V-iphsOrTkC|pz#PMT$MGiF{I>pc6lh(S4QgQ1f)S@w>^Pk0U1 zD$Y2D8Xnd>e8MPSEtcDfnX^1*@fln2tIGI}ian(e0gTydrVUuj?LVorci6X7gOmhNgRq*r@?=nVF7S+Zj|GfYBT< zq;5EsB+%ACZ%Q7d688uFd_k(TL6p<^-9|Nh$3`BjTj#VoiXXPDs{zD8R~*mg!vxHY zI^`AsinJOHj>k|}&ItF@Nc7iF(*%x&j`5wWm&EER2e|Gn8O{D$vc%x1Qcv#gJ}^}NdN8Gw%( zWR2q|?>DP^r=DO!1SWA>q&;YG7|UG;TMlg$PM|b-yWmC{lNO9UmEnpM-HV`$M6Z>B z2Fl<@aMd93x1Ls&C8`&@qns7;jQwDSv7N23rHy55dsj({JM@eqZTSUCBM+6?wqWaX zWm%%yBc6Do%UX8HQng|gP2P7vKBF9-6%QPl#hqv?DlU-T4JCZ z)>m}hj9q#3-^Fv~eiyozF6gQqr&Qszu#!qLt?ykxhe_iZ69E0Cev|)?Xd^SS!Ku1UBB7}5xb_w)Ds29>)(1lct@Sld=si6)*zYVWzV_yH*E-t-O@3C z0+~_eFc=t+9a%Qf%-PFGgY4^#Xawn3?ru_5^>?sVzI2S3#r(zydK9=O?CeGaDKbV^hNvy z-vyV0C{zDVXW@m9q>bgL%CS*e{rN9Ix*){V<2e_);w`xgF3>s1)Op$BU1#-55qA#M z3al4kfeO5|g>_>r<+w6MCZhE~bDhtfLEV%&9I9zDll8>3Xx;GQiLR#56NOE|D}&#m zPEJ`zem^6WuqyqO(41K^LEYpz^>ayeW8}YC$h@s3>z8AV>m>jaomJ6ne9OaoXG4HIy=k0I2? z@dvaJ^PG*1yg3GpItv6oYx-V!hkSEhJA7$b553fp#vb1%jmH^>e&YvAChlW1b%**v zIjd5@=C*Bl-%|td4$0-a&7ie8lP~(d+nCILkOJX=8Q?coukRi3LJ;%^{O=Iz&g_+RD>Z4ukB#_AfIQBcu{_%<^fbBOtWVz!fMM)AN|Q*ib3{wCZ%rAhtBXKv?t}c{ zL@dp(O-|~sE>|*>`yrtR(Wc~0ZqVX-(FfPv4n4NKy`WU|IwvrURP;Bd2+N^RwwX_r zOV6*L$0xUS+-+_zoDu$={zSi8h?N=In1} zsCw_LQL`L+ZNDKGMnt>w0{)Bj$9=nRv27><7~1uE0l$ax{ysw!tp}J$89pcB?d3J{ z$*4x1MUP?q?qCu{uc_k!4O$tb93VbOiXNjVZ#4l%IoIL6tGGVn8VP$h-ylr;_d_F1 zt0o>nYQ+N2k=KZ)T~0>NX!6^T24QC6a-cLDH(V`Dlu)I3)sL+ITK5a2lybC+ z6^Plpg6M0Y1Dr~JFC#Q^#4!evRl4>QO6qpnCmqYCUF4Nt5IbfVV;?mLC$-(Cp-lS( zK4g1h7(K~??b6fSp;lU=L8Y;9@-()(4iXM(GM(P_A4K`S?2o2M3V%FVm8Bs;V05u{ z7T@fA{DNaBb%@nGa%Wqvbzh=GK#81L8Qx=-pb&R73n1~qo(cAXDjBo8DYe}W?J-Mw zZ_ct=yR~{zG#5NHJx{tTIm@Gq6vft;T;3z-7#_7oHYvBLtDWBGY<1@+M_@dBzf0Qp z<-Q2P3@L`zHOZ;bb1iJ&wBvI8nIgZ&l0>AwkNov53dl;UB8vxZcg`7p;AReKBur|7 zUO62A1M{$3pM#MkrNE&lnKzG3uTJT_I=ENJ<&c>ypJ z6u<)QvpycESz<4{aWt)$({?<34c!9%q2hibkHV@bqT7($1*Bs??2JHY?-M}E!N~U3 zbmNCjm+zE9L-gIrgZZLyVuy=lZmHqN*THpwYw~KqiBt3o1RJvMCHcHoA9pKPTUaxT z@?Cz$Eru`9YqRs^sv}HulR@<(#jbG4p|;FG`#q{Iz+mQKKXAeq=Ax!Xs#x>MO3D=f zsGeAEQrW|`m22dqFHCfWH@QXi7cM4%cXQYJ)j!_H9~VSCRspV;86~v(!vO%~JCS&D zu@6?2cTl1{P-G(HSh{C!6{ctXNzn7+7LsgTne1>`z={=lbpkfqS)L&)`LjS!TXaS{ zE=8}f?lFk{hZ?B$>BaTLQv>}TQQoU?{_LJeRx>e^5yGfan%YVL782nNuKTyt;GJHc z*R#$QdsM&i$l)-iKO+GLa>63RtuN_PEWU>(lfi$x#Q;`DPdnS}q!H`B-+pmuXYllT z;u$?Vr6P66^qQ=dkJg?Oy|IjBQl0YSIRVcESW5`Z*%%jFCV+LdJkz#^*UD89XebYB zX$1Fmk>}-6Uz{nKd&;fHrhudb+R>HM&p-1tX1y7%8;#sDZEp05(qudm4&6gwE?^Ki zt34n9U_8rg83bc$l`1p0!jDhiQJo_rsk>*E*O3KvA=8CiAtJ%FKA!<-jSS{k%B}^g zt=X?oevssd&>qo!6oW1jkF;(1K6s@O>vRDG#WHoMDPDS{Vq1TWrJ#8Ch?6_RP2F!E zIGpJ* zP%DahX!swys!ESLMnq{-yF6wpbLP12Jfwbe(Q^4v-^^-`hLmbahNQJTu`W?E;2{S` z?WOmGT;~JcQpFDkh#(9@w-_)&Qp{^anUf2beteG`{*O~yOEW30z~Cf9FEihy^WOZo zU0Po0R)Jo2YMf4USVn=aMuT;lO-q$}RDLR;M(zr}JHJ>KPUeAv;-Q7vP}161)*3a! zqM|S%_47xt-J{jzqqIXTGc1e3;?yP3KVeHa&^#OImH!uPLO^!XrcE$2%FrhC6Orf! zhxKYrR3n0{&gS6KUGAWom;$NHDe~a!eU7^wv>#1M`o}cibH@9L1D}Ni25qX?Nh^HG z*ZasMmG0dYY?S`JOf3Wi`8TnDr@Dn&|=8g z)Zaie+70LfYyz?RC>FkvN9FzlbVJi0pyA1Q{{W49&f>2%_Wd`|LGM7fa-v8!L}-sm zKK6mU1MR9|W%AJ4(|&)M4qw}}^x;{GimUH6h3XH`g5s=vgT6Vh$qG1F7PD@zTt+)A zb>C9_K$%MSIumwAGE($E6#)2*lq|I0^f}K=6X!0DF5n$wo*3as=X;s?mi>?D>Bu#k zr~W|wL5*_^>e5$csRiINYvW`$Ud&Z7Ej3SMre%>9jJZiqlecHEyE$==VXEPS{t7{M zDwmBJ4#^$3A}XIQpKt^JUy%NV8XQFHzuNzQhq^a>^~w(l1Y{8p*b0vakaNJ}`V*Tb zzRNu_l4*8E0BP`8@D(UC^IISABwBrC|Nv)PLq-Bu@aSsO|LWwr_pW)TmAw zPERtFI+-?^@wE_@P!SL0={j^>+-wv#LDF>x-P+a_n^;RMK)4Y^Z0O_?%`2NUt)?t7 zh3`&S&lFn>t6F}6y`)fNWSzOUZH$}Mh$9aBS2Aobj>fK-FZAFg3@oPoY`8NonREOJ zWqKJ);p@<_T-pNg1dqZ|7?QI*n>J)B5e$#vUcKvG1nJbA+=fRN@8h3kk49Bm(Ai<^ zL2f<*)pjt}o_w_zU`NZ5@`<YV$wugZ zaKAB;&mrK3S|OY@z~Jj%RU7wh=5&hnP!cA&1a*)nl!S!& z8fKGfoMji0UxoWJ@pLx?1JNJ8e2HrBRXs#PUyJr9z*QVuYMmr;w&^eq#1CGvEAorG z*Lr7Pabz@lRGc5XgVAL4FoWQEKleyG>l{0yu~32uj7p4q%T5mH~_- zA8iidnWfJHO~)^=8`OrgYtIlp@fNJn5I1h<1BAPK6>*18j--EOXLY%VnTeuw)HJ6n zzZk4AF5;cBt+K`-%cMz&vvx`8`8-zEv$K{ty-$1;+dYc-z6w2Me)=RCwsP(+`ME`+ zu2UIn1RGiAoUHP`HlB7+rcOH}G;v7EyO@7K3esLd;f|m=XFx{6y#Z}$qWzxHFcWbW z9>8>rFPIuf&p=5fH)BL+`MvxWB$V3*k_pQ%ajcDG4zzX2kb`nLQD%JQZXWSd`@F+|=1Z20W#u7?>W zy=F0(#t$0%Of8>n#ZX=#BG`9uWZi z&a6=;fJ-8>&97QRY>G9S6xpd3p>b6=mSoC9f~ErLWM)1IK*L(a0Ol~o%!0ber^(&UJtaZIelfjBW)0!VZw)0xLCIEF7x8??CbHL zEcmWjK@nSi%SP0Iqfbln0zD~2D+-X5$36jXn7YqvB=xK|TBUBkm{K1pw~(MM_FE4{0A)c=Y5Ie1P20w_`cHdv}JN}^|Cc{`Mv7w*OZIfg*w{bIGbC*|`<(dh(+6<0YD1EtHpOkz+aN z_RN4UAgZzUz4rG-jEbhn+p|5d`vK0$u{pwqlN>3m!jS8G98y2}*I14R&b1K~L4k(Y zvbM7o=eF6aot6?$h%c!33Z={jVW6fv%|JHm^LyZk9t_GRL`{KR7*zrLTZtZ!wS=bF$mNgA2=5{1{hEXmeZK^k-^=77}d$Cr;cEews} z`K7@P4*L!c>h_!DqBEW#A_#zGQc2!K4h~@qGI?H^!6iM<$QMu=m;`Zq%e>wS(C%2+ z+k&3C#ls!YvC^@17>tx=VI4o1%^II&S9s=@Nn+1_G+L7A!bxS*nN3Z_iED#sE?~AD zUQ~X?gPQh#V+&S6A{`dtRhZ=tQ1>*NrTEn~)e{-Gs}RJjV8OQeY7UU$ZNPX%2Qy$0 z_QxxdLj z$c=L0eLHX!KiP~Ws(S%JmWI;LW)%*1#$s+82FB}&-Yi#X0`g3?FZhJQs#rg6w2-Cj z0y8C({3w@zHwhh3tk1trb{&+6a{axYcaQsaFC1$SSVgl0b{&N~h;_ReS6%Qt8#Q7( zGTNYcyug1@R1W86JanU(q@ChajqNd zjAQJlQd7B3Yv%+w)um=6nxfTS;f(c}`1XW#$D|t5PkVpD4&>K?lRTeEVUx%0_U)fx z(_-JiAKK~|`U+%}y4tD&?$Uj5`!}=_FL)m2uXC6wBZ2*M!y{xu+C$qvI7bUm?~hWd zVWw_hUImOtq+I%NAok@6ZQLrRm*6CVjzfvpOeof_^_(84{&)vKYYvn;6&g}dfX%dC zjW8Gp$T|cF2=+gZsj0J(hn2mB3)BBpSpN8l>IT-U!YKYsH%MchbdNRUtG%iTc3&Z6 zGsEvd#;na?3k~YpA_+wE!jDA2{6@r(w>L`L%2P}}V6A*gkYdYqFz<92j2`pb4CL#T z7_)?Xfky@tWhn>fw#sZbRTr@Z3rmaB&9lg=dMZJ*j|=*1pVH-?_Gf}a3QOc0sx3*k zDClc#h22Q&e`EMUtIM`Q_SNuVu#$U)=BU%<_p@5F522AyB3=~^Q}201U@2ftGcIr8 zJfvB8;v9uH2(2}tBcz?~rqk?r3$eluJNip?F+=E{^a6lAONh2_o2CHW#3}W8L>z^7{n}eLR?DJ=P-Ke^&x@3R4ksHf>Lf&?bbCoWY32j#4q#~>OVEKcUO4m z7&N8F$Q5c1BO8#lT0M|N9QOD&(q>b~kx?;ewy24RT2o$KeL9=E@=XyE<)4e`E#qkU{N?$Mw9YI&!#F- z9K7hwPqkS@pEk5a_{@W+cRy3^xb}`ah;-Vrk^; z>caHr>yMe8W^FpJ4q^;m@XdLAVre;0 zlV@C6Jc_?H{taK3M{K%RVXy*pl9%yPa`(Xu&gi z?)ab??BAA^GGcDrJ1CVza#^)i=$e@s9EW-o=v|x?2)%Aw2~IK974xl{x8y2QY4A;9 zZI~_E9oFe&ef**DUGQsDYrfA(>#`|Bli&lgK`zRNJA+Nq;YK#UZh zPOtInTW^EC$HGYuJOj5EYFq<=IRUCAQ?%WQ_gHW#D$#8-%~i4eiQ7GSHCJ6H8yC$F zdKe4-aoP%x(WJq|iLoD(p&4!Yi#9nPOe>Qysgh=& z3(u>c2q#Y#CQi&}=W}!b^D=D{O3}qn)H8H|?e%rVf|*fctI}QK z#A++OCREys@m+&qszQ828d4rkGch$D?0d#sVr+50H!619P3U+nfm{0;`?mspy4U0==rN6v9*^?1;Ma+RTKG$Z1_s z`_uBTn(jIF%N@6zgN;PYp1b^yp!Hl?*O?m_gYo+kz_eBXk-MHRHm3)-KDKhaj$-QJ z-e83Rz!c2=mlbs{^cnIUt00~3%1eC}V0gIx+N)u;ea7b6%I{`O2=K624S2gH>iOKs z`zkwr{Fyi+)@tc#-Z^7N@|)dRmYq)Z%?wxOv%BVs`BVA)W}{w`%>@)Rwzxo%9oH9% zGY=g>fCoDOayar3!GE16FmO z{D2bHI>`}D?p2VHhAWbocenr46FesE0V=_vI{+Mp`%^C{xqP)I7hweVr$JCtc}?~k za2#j^99AT3R#SXt(_w99lL&2QW7{5iY%ok8w6G_@rztE>Cr=Xn?X6yl4{;3omfO=i z%iOgnk*=Rew2qs52NIF!^o@>7McEROXzMwS(~YB35HM6z;%GO7W{n0`m3gZ?x#*xV z`5^a)p-?KFEuTF4{0L=v8bL$K@%2v`QVQtuMrft9gj=KRFrNVLm2!=^ssM95-qv5S zn7n{iuvtU`15gGoS69fw_eQW4`=cXS>Gz)${!F~BA7&AkDTG_U6wr~Z56`4b(}~Ab zg}9PQX^FNb{!d$i{oWBRJ`;B<+-xkq0pzh{Tvd=O*;&Jki#gKLy}#^>+=nYnphye+H4{KZTR;@ljZU{mzl(|9A1@cgN@@SYZ}# zD{5RD!8**W!v7T5zia<4EIo3H!np@&0xqzr zxPd^n!R?MpHjcX4g`rvz6E$ zgIbIp-8+lC4U{3=%)laZ?Sl2s!k~=31%Z$Rp~3_oM-zuK^BAHDPD<(v8IxBWaFX?q zG~vJkoSG+w_0m^k+98`KBCvKiO$Mi8XHm=DV)vx4rb;Q|dY9`%`$6$n8xww2P7E@T z-yP6P!|>EP@Ia~vx|3&zP-lOrp(jC)`=pbOLhGxYi2}z5=;_yZ{Kiirnw=NMYRSAQA)OyGWAlOr4* zYK4g=gd0NiSr*%F_hIs-&dxk7LQXMW4k{`_>5I|UhpTb#2a7;(N}BxeUUK%6Mj%{v z>p&%Ts}0@Ok#()LksjMO4CJVQ1;=p%=*pTICBOk*0vQYB3J zNwI6RBBeqg?r2&3v+B4>O-_%s2@@mZ_d`0G!xv6M_B$YK3h0xDA?O_Ffy#~%MMQVB zu$Y+Iw282jK05S?u#HZsa;8ziDwy)7Q6{{p@8#}ga%742n%S~=G297&-*%TK4oQbM zk!C}cK6m&A^(s>SveN`K6gPGl)pn0&BL_5^TD_Z@wBg&}kN9Vq)KGL;Zpl4FOJKKWleq#L<)DXvyip=GT)^o;-FNqUerz~kL_AV9X)2)pLe|Kaur7$7Wn6$O-{-A4VsBG z(&3UIGqkw_i`{ND(4o;cmh!&_^WChF>^qfq^Oct5^A_&fu&J!!rF>F}T?n;O=Ym9B z`0jbPyN)ogHiXOo|GF!% zGih<2kD>j`R-`QS34u;;bbjkByPV#<8Er*rbd!X?ne3W3Ah!`=riyK5h>OoVq9Xl^ zmg&C3Nn3-N2Q9Zk%PIh=rJ2a<*@v{N>zgYsBI7pTYd8DL_~R^-Talju%>u33i>D92 zx{EIIu)lrtS7;BDABt~fSv_}WE>o`eh9{#uH5fc+J&`qH;<=aKtDj$UYo2#-CUC-; za-FvQE@Oa7fU@?t9h@4Ab__h-`})z;72GbHC07wDp++^g_kW?Ts76LC(^jx zA^;zi)gF}v#pQTf6BCuku>%^D$b&zpZX*aLFg-HLMF-Om-ufBOZ00!IJ%1-f<)JKQL* zbg2MgaM$BT4YjX})j=s-8=JHh**e z-7Mjc&@TDopUnqoyyIFx0`D%@()U)bU71T*W-M3$@X7P6tQLVW0yq-%d4{FKNs$>` zxCl}k-k8}6Vz_m~A#lIM$u;C-1cBD6Q>ZTKW{%qfA+RypN4qm6pq(9o`-v9CU2J_{ z@tiJWC4ctT#X~Q-N~4d`OCkzn|S=<{(L3uqltZ3}WviBTOy|56G2 zdTPuMz;0$rvOxjF=BxYWMt988H*pct^UHSaf5)CZS_O(e4h)I$AwPNV0dwg5 z5MKYo_eCbfm;}--$F>(@!t84o(Rd$Q7hRi`eI*=s!vsqXV$Rri;J^ztE0mG?83nal zoo1%M)zRTo_KG%@2RyjA6|1xCtu#){0sy@7rwnUNhR{kp2=59dpF};?&jEfIicT&wgaJ1oCzFmp5XRFITPfQXZ#@L9`M?$S|5_O7d|08 z^_h{&hFG!w8a+@v*y6O?u4W4^#qI$48gQ0KEe-huelGCR7FZ>Bzp*ohB#l?E1q!Hz z&_f)B)e&(O^~O-5D7*qy1BEV|Jq>;I%qGBzdV3x~k42C4aan&>t_7Z~pj^qif0u4R z+G^3rqxat&xv8HrDVSNzz zX=FBL+*4elA{9u{7b;76=5(J^(G0i{`=ny`mCy^W*+we2(viUg*248`oR!Zh-jV>X zEu8}+uMv?tNXrc~i%Wa=mSat=@i@_rWrARJ@lP=0?O~KTDyV>0(vG}1 z^_*%q`DS*iMVW8DK&CYvTB2;BY;~!^3MtKtS#_2&r4G7#cct=T3*P6vdVlK5u;Pc5 z*459p@vc8wk%|bL&V;#_lP#^;4lDc|JeG9*3IbNn<~o0T=}_N2wF}@<>)n7GfvvY9 zjL0ongujs$k_KXAmseUr8$gPG1M4KSRJ?OH$R`tTJZhCzEXrG0)?2$Eh!h~aT3qUb z%!GVtZm3-@%D-=KQ018a(E2FlGP+UA2&`Ja+J5}7a@O@vfCC@Br1a%Iuwnlm_Qv?% z0S*US2WOW*Z?Zz5i2eJf5Q*v!4*;DxxkI1{l;l8{0OxL~5iw54` zNdZ_MmWIUDcg;)#(>~AwDiSB&_nsgGTm*Lp&vdxY_F)$&GMP-DtOx{H&_(Ky;>qbP zHhuP>rZ4(7X8$PiS@6r*xlQgo6=qx{eSIrv=$={xySAr*U^S6&4L6*4XG?@9REr^Av%-~QwTztkdIUR!Ft8 z;LuuRJmn#ms;oEjlFoR-&q;6TiF<=^XizqqCXq|BkIP z{%#40pZL95DC8pO0_Dzr)*B_UxFce^d>&eR_6)gEW>~Vu!66R|vS;oa-zgWL#BC5v&RCj?oSMhk@EK5=nq+ z)Pyiwt!u8WGcT5Tj1@x1mF4*oaK&O-Bvc71`J=o_6Rzm`0deL)$=;joqFce2I=1)> z+h^1-;{ha;#9_JlP&A8()k$MF^rf}RANNPO{xSRjytTmDcQNDN#U=Vj-2aK}{Uhw( z_}(8;D-wES`+x5_dKdM;e(qF6oO3;x_*7#N8s@kjG0U`99_8t-7^@~)DxR(H%}>aM z->;}tFp)yJ@lz`yy1A0ca9wEp*hwE6^;gDtMpa1wJRMwi*i+jso}`wZbgHsAhb$(% zT;;xw%_Te~6#>Th87nH4*6MH_%U*VxJC(`(t8MxvUHDBJwwiL%t1uv5npU5~pCsw@qKV2kI-GvJ zZ@YK{?lYqT=@^b+jdASOyWe$i2z+D42BeNDzVED(xR-tw+Y{(_;47tpC+`FiB$h?2 zOqNO!hj}FowhYX*B{ky}B;0Jtb#-~$@EFj`Jm}+|7hRWCDf~j<5x(7kIi(cOrGkDv zi_lh#7p@*1&mR4BcDqn)*Lr8Pi62Ia7S@9KWX7|RvcGn&wmIIk%Yyijmge*$3qaAO zSiSF?ty-6LPs8A+WliI^Y!R?zzhYcAP=Gl=vPc|texmalLNrd3&Gmq$Ia_%+B>(Fm z8Q3YZ@S+s+k?244Fgbigffz7+PQ$>GyTZ0To^dh6ZaMrM6axhCCEC zRiaF!A$QvQHCY3+eP3YW%okhWs@j@{C@8Og{T3 zNdik21dz;qhqJWKmzEe5;F~n@o&rG+y$@{yXrb~dRHm05@DQYu1Siww` zG&aXwY0Wm5@1ET8M5Iav3G=x;yga&8xOFsS~l@#@ za)v*dl)2vewn-s_E`ITncg7X$|81<7)25+IGb8t*oF^^R7cb@1&Ug%2Eaa{)o<2gG zZiTc8R3_)?p(}+S?9V}6G{!|RY)~+U_vFI=J&Xg9*&$ zK>0tZy}z{Qbbs>k|Cy5hJJF{s_rF#6@2t&VE~bosxcr|S&i`-#{0D`9J9vLtxbXfr zi@)yPzX$Q}mDOJkqC)@8!Q}5cOPTIpg8XOg@jr9&UmniF!0ZncKm~Rb{(n#0e~IEm z{_2a>_v|j}|GL^y@;%5-1{CJRrInBY0WozjQFeB4 ebYU`bbo_@AR) delta 9818 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