Кто любит RISC в жизни, заходим, не стесняемся.
Ответить

Re: stm32h7**

Пн янв 10, 2022 14:42:14

linkov1959 писал(а):Переменка имеет много измерений и каждый прибор имеет свое об этом представление, особенно трурмс. Хочу измерять трурмс по своим представлениям, как среднеквадратичное всех точек за известное мне время. У меня много вольтметров и я должен знать, что они измеряют. 26 мегасимплов на Н743 будет достаточно

Бред безграмотного пионЭра.
За последние 3 дня это уже третий пациент с этого форуме с воспалённой потребностью измерения СКЗ при полном отсутствии понимания чё и как делать-считать. Блин, ну неужели так сложно прочитать учебник с теорией, а?
Какие приборы и как измеряют, и почему их показания расходятся не вызывает вопросов у тех, кто в теме. Всё, опять же, изложено в теории, которую не читали.
КРАМ, когда последний раз тестировали измеритель СКЗ, в сети была постоянка около 10В. Видимо, у какой-то мощной нагрузки был неисправен выпрямитель.
Вообще, измерять нужно период, среднеквадратическое и среднее значения за период. По этим параметрам хорошо видно, что творится в сети. Даже измерители показателей качества электроэнергии дальше 41-ой гармоники не смотрят, а ГОСТ, если не ошибаюсь, нормирует значения до 19-ой, ибо всё, что выше, режется ёмкостью линий передачи. Так что базар за 26мегасэмплов- полный бред.

Re: stm32h7**

Пн янв 10, 2022 19:56:39

tonyk, Какой системы амперметр посоветуете для зарядного?

Re: stm32h7**

Пн янв 10, 2022 20:00:12

tonyk, Какой системы амперметр посоветуете для зарядного?

Ессно, тот, который показывает среднее значение.

Re: stm32h7**

Пн янв 10, 2022 20:56:51

tonyk, Сработаемся!
Теперь по H743.
Там проблема с DMA, не доступен массив, в которые хочем писать данные ADC. В новом проце периферия ограничена доменами памяти.Решил проблему с помощью указателей и в известной области памяти хранятся эти самые данные ADC, но массив еще не объявлен. Нужно объявить массив по известному адесу и работать с этими данными, как с массивом. Пока решил так:
for (i = 0; i < 2000; ++i) {
ptr1 = 0x30003000 +i;//заносим в указатель адреса.
adc[i]= *ptr1;//заполняем массив.
Реально работает, но должно быть более изящное решение, массив фактически существует, но без определения. Зачем каждое значение присваивать?

Re: stm32h7**

Пн янв 10, 2022 21:30:27

А чё тут сложного? Осваивай скрипт линкёра. Вот пример скрипта для STM32F411 под GCC. Смысл скрипта в том, чтобы уложить параметры ПЛК и байт-код его программы в массивы, которые расположены по адресам сегментов флэш.
Вот так описываем сегменты флэш. Заметь, у флэш этого МК нет страниц, толлько сегменты:
Спойлер
Код:
/**
 ******************************************************************************
 * @file      LinkerScript.ld
 * @author    Auto-generated by STM32CubeIDE
 *  Abstract    : Linker script for NUCLEO-F411RE Board embedding STM32F411RETx
 *                device from stm32f4 series
 
                512Kbytes FLASH
 *              128Kbytes RAM
 *
 *            Set heap size, stack size and stack location according
 *            to application requirements.
 *
 *            Set memory bank area and size if external memory is used
 ******************************************************************************
 * @attention
 *
 * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
 * All rights reserved.</center></h2>
 *
 * This software component is licensed by ST under BSD 3-Clause license,
 * the "License"; You may not use this file except in compliance with the
 * License. You may obtain a copy of the License at:
 *                        opensource.org/licenses/BSD-3-Clause
 *
 ******************************************************************************
 */

/* Entry Point */
ENTRY(Reset_Handler)

/* Highest address of the user mode stack */
_estack = ORIGIN(RAM) + LENGTH(RAM);   /* end of "RAM" Ram type memory */

_Min_Heap_Size = 512;   /* required amount of heap  */
_Min_Stack_Size = 2K;   /* required amount of stack */

/* Memories definition */
MEMORY
{
    RAM                 (xrw)   : ORIGIN = 0x20000000, LENGTH = 128K
   
    SECTOR_0            (rx)    : ORIGIN = 0x08000000, LENGTH = 16K
    SECTOR_1_2          (rx)    : ORIGIN = 0x08004000, LENGTH = 32K
    SECTOR_3            (rx)    : ORIGIN = 0x0800C000, LENGTH = 16K 
    SECTOR_4            (rx)    : ORIGIN = 0x08010000, LENGTH = 64K 
    SECTOR_5_7          (rx)    : ORIGIN = 0x08020000, LENGTH = 384K 
}

/* Sections */
SECTIONS
{
  /* The startup code into "FLASH" Rom type memory */
  .isr_vector_FLASH :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector_FLASH)) /* Startup code */
    . = ALIGN(4);
  } >SECTOR_0

  .plc_params :
  {
    . = ALIGN(2);
   
    KEEP (*(.plc_params))
                   
    /*. = ALIGN(2);*/
  } >SECTOR_1_2
 
  .plc_prog :
  {
    /*. = ALIGN(2);*/
    KEEP (*(.plc_prog))
                   
    . = ALIGN(2);
  } >SECTOR_1_2
     
  .plc_D8xxx :
  {
    . = ALIGN(2);
   
    KEEP (*(.plc_D8xxx))
                   
    . = ALIGN(2);
  } >SECTOR_1_2
       
  .plc_data_regs :
  {
    . = ALIGN(2);
   
    KEEP (*(.plc_data_regs))
                   
    . = ALIGN(2);
  } >SECTOR_3
       
  /* The program code and other data into "FLASH" Rom type memory */
  .text :
  {
    . = ALIGN(4);
    *(.text)           /* .text sections (code) */
    *(.text*)          /* .text* sections (code) */
    *(.glue_7)         /* glue arm to thumb code */
    *(.glue_7t)        /* glue thumb to arm code */
    *(.eh_frame)

    KEEP (*(.init))
    KEEP (*(.fini))

    . = ALIGN(4);
    _etext = .;        /* define a global symbols at end of code */
  } >SECTOR_5_7

  /* Constant data into "FLASH" Rom type memory */
  .rodata :
  {
    . = ALIGN(4);
    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
    . = ALIGN(4);
  } >SECTOR_5_7

  .ARM.extab   : {
    . = ALIGN(4);
    *(.ARM.extab* .gnu.linkonce.armextab.*)
    . = ALIGN(4);
  } >SECTOR_5_7
 
  .ARM : {
    . = ALIGN(4);
    __exidx_start = .;
    *(.ARM.exidx*)
    __exidx_end = .;
    . = ALIGN(4);
  } >SECTOR_5_7

  .preinit_array     :
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
    . = ALIGN(4);
  } >SECTOR_5_7
 
  .init_array :
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
    . = ALIGN(4);
  } >SECTOR_5_7
 
  .fini_array :
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT(.fini_array.*)))
    KEEP (*(.fini_array*))
    PROVIDE_HIDDEN (__fini_array_end = .);
    . = ALIGN(4);
  } >SECTOR_5_7
 
  _sidata = LOADADDR(.data);

  /* Initialized data sections into "RAM" Ram type memory */
  .isr_vector_RAM :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector_RAM))
    PROVIDE_HIDDEN ( __isr_vector_RAM = .);
    . = ALIGN(4);
  } >RAM

 
  .data :
  {
    . = ALIGN(4);
    _sdata = .;        /* create a global symbol at data start */
    *(.data)           /* .data sections */
    *(.data*)          /* .data* sections */

    . = ALIGN(4);
    _edata = .;        /* define a global symbol at data end */
   
  } >RAM AT> SECTOR_5_7

  /* Uninitialized data section into "RAM" Ram type memory */
  . = ALIGN(4);
  .bss :
  {
    /* This is used by the startup in order to initialize the .bss section */
    _sbss = .;         /* define a global symbol at bss start */
    __bss_start__ = _sbss;
    *(.bss)
    *(.bss*)
    *(COMMON)

    . = ALIGN(4);
    _ebss = .;         /* define a global symbol at bss end */
    __bss_end__ = _ebss;
  } >RAM

  /* User_heap_stack section, used to check that there is enough "RAM" Ram  type memory left */
  ._user_heap_stack :
  {
    . = ALIGN(8);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(8);
  } >RAM

  /* Remove information from the compiler libraries */
  /DISCARD/ :
  {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
  }

  .ARM.attributes 0 : { *(.ARM.attributes) }
}


А вот объявляем массивы, чтоб они легли в нужное нам место:
Спойлер
Код:
const uint8 __PLC_params[ SIZE_BYTE_PARAMS ] \
    __attribute__ ( (section( ".plc_params" ), used ) ) =
{
    MAX_STEP / 1000, 0x00,  // 00 0x0000 -- SIZE IN STEP 16000
    0x00, 0x00,             // 02        --
    0x00, 0x00,             // 04        --
    0x00, 0x00,             // 06        --

    0x20, 0x20,             // 08 0x0008 -- PASSWORD 0
    0x20, 0x20,             // 10        -- PASSWORD 1
    0x20, 0x20,             // 12        -- PASSWORD 2
    0x20, 0x20,             // 14        -- PASSWORD 3

    'S', 'K',               // 16 0x0010 -- PLC NAME 0
    '2', 'N',               // 18        -- PLC NAME 1
    '-', 'F',               // 20        -- PLC NAME 2
    '4', '1',               // 22        -- PLC NAME 3
    '1', 'R',               // 24        -- PLC NAME 4
    'E', '-',               // 26        -- PLC NAME 5
    'B', 'o',               // 28        -- PLC NAME 6
    'k', 'r',               // 30        -- PLC NAME 7
    'a',  0,                // 32        -- PLC NAME 8
     0,   0,                // 34        -- PLC NAME 9
     0,   0,                // 36        -- PLC NAME A
     0,   0,                // 38        -- PLC NAME B
     0,   0,                // 40        -- PLC NAME C
     0,   0,                // 42        -- PLC NAME D
     0,   0,                // 44        -- PLC NAME E
     0,   0,                // 46        -- PLC NAME F

    0x00,0x08,              // 48 0x0030 -- M   Latch Start 0
    0xFF,0x0B,              // 50        -- M   Latch End   1023
    0x00,0x00,              // 52        -- S   Latch Start 0
    0xE7,0x03,              // 54        -- S   Latch End   999
    0x00,0x0E,              // 56        -- C16 Latch Start /
    0xC7,0x0E,              // 58        -- C16 Latch End   /
    0xC8,0x0E,              // 60        -- C32 Latch Start /
    0xFF,0x0E,              // 62        -- C32 Latch End   /

    0x00,0x00,              // 64 0x0040 -- D   Latch Start /
    0xFE,0x03,              // 66        -- D   Latch End   /
    0x00,0x00,              // 68        --
    0x00,0x00,              // 70        --
    0x00,0x00,              // 72        -- File register address
    0x00,0x00,              // 74        -- File register capaity blocks
    0x00,0x00,              // 76        -- Comments address
    0x00,0x00,              // 78        -- Comments capaity blocks

    0x00,0x00,              // 80 0x0050 -- 0x80 ( RUN X007 -- X000 ) 0x40 -- PLC system 1/2
    0x00,0x00,              // 82        --
    0x00,0x00,              // 84        --
    0x00,0x00,              // 86        --
    0x00,0x00,              // 88        --
    0x00,0x00,              // 90        --
};
const uint16 __PLC_prog[ MAX_STEP ] \
    __attribute__ ( (section( ".plc_prog" ), used ) ) =
{
    0x2800, 0xC801, 0x001C, // -|M0|-(M1)-
    0xFFFF,                 // ----[FEND]-
    0x000F                  // -----[END]-
};

const uint16 __PLC_D8XXX[ 256 ] \
    __attribute__ ( (section( ".plc_D8xxx" ), used ) ) =
{
    0x00C8,             // D8000 - WDT 200ms
    PLC_TYPE,           // D8001 -
    MAX_STEP / 1000,    // D8002 - 16000 Steps
    0x0000,             // D8003 - Internal ( 0x10 - CPURAM, 0x00 - RAM, 0x01 - EPROM, 0x02 - EEPROM )
    0x0000,             // D8004 - Error
    0x0025,             // D8005 - Battery 3.7
    0x001E,             // D8006 - Low Battery 3.0
    0x0000,             // D8007 -
    0xFFFF,             // D8008 -
    0x0000,             // D8009 -
    0x0000,             // D8010 - scan current value
    0x0000,             // D8011 - scan minimum time ( 0.1MS )
    0x0000,             // D8012 - maximum scan time ( 0.1MS )
    0x0000,             // D8013 - Time Sec
    0x0000,             // D8014 - Time Min
    0x0000,             // D8015 - Time Hour
    0x0000,             // D8016 - Time Date
    0x0000,             // D8017 - Time Mounth
    0x0000,             // D8018 - Time Year
    0x0000,             // D8019 - Time Day

.....

    0x0000                  // D8255 -
};


const uint16 __PLC_storredRegisters[ STORRED_REGS_NUM ] \
    __attribute__ ( (section( ".plc_data_regs" ), used ) ) =
{
   0
};

Поэтому, открываешь карту памяти Н7, разбираешься, чё-куда класть, описываешь должным образом и наслаждаешься результатом. Сие не сложнее, чем понимание отличия среднего от среднеквадратического значения. ;)

Re: stm32h7**

Пн янв 10, 2022 21:41:53

tonyk, Сработаемся!
Решил проблему с помощью указателей и в известной области памяти хранятся эти самые данные ADC, но массив еще не объявлен. Нужно объявить массив по известному адесу и работать с этими данными, как с массивом. Пока решил так:
for (i = 0; i < 2000; ++i) {
ptr1 = 0x30003000 +i;//заносим в указатель адреса.
adc[i]= *ptr1;//заполняем массив.
Реально работает, но должно быть более изящное решение, массив фактически существует, но без определения. Зачем каждое значение присваивать?

Не ясно, как оно у вас работает. Покажите объявление переменных ptr1, adc, i - после этого можно будет понять как оно у вас работает и почему.
Обычно это делается как-то так:
Код:
#include <stdint.h>
typedef uint16_t adc_sample_t;  // тип отсчета АЦП
#define ADC_SAMPLE ((const adc_sample_t *)0x30003000)
// вычисляем сумму 2000 отсчетов АЦП
uint32_t sum = 0;
for (uint16_t i = 0; i != 2000; ++i) {
  sum += ADC_SAMPLE[i];
}

Re: stm32h7**

Пн янв 10, 2022 21:59:13

Professor Chaos писал(а):Обычно это делается как-то так:

Обычно это делается через скрипт линкёра, а не "как-то так". Линкёр палюбас лучше всяких профессоров разместит переменные по нужным адресам, сам вычислит и подставит эти адреса в переменные в программе. А способ "как-то так" мы оставим пионЭрам, которые за неимением жены пусть занимаются секасом со своим мозХом.

Re: stm32h7**

Пн янв 10, 2022 22:20:03

tonyk писал(а):Обычно это делается через скрипт линкёра, а не "как-то так".

То то же я смотрю, что вся периферия МК у всех производителей описывается скриптами линкёра, а не указателями на структуры :))
Так что как-то так - это в CMSIS-стиле.

Re: stm32h7**

Пн янв 10, 2022 22:42:04

То то же я смотрю, что вся периферия МК у всех производителей описывается скриптами линкёра, а не указателями на структуры :))
А скольких "производителей" Вы видели? :)
Или видели только одного (STM32) и сразу оптом судите обо всех? :)))
Замечу, что например TI как раз в скрипте компоновщика описывает периферию:
Спойлер
Код:
//!Description of the memory areas.
MEMORY
{
  PAGE 0: //!<RAM
  RAM_PRU_DATA0 (RW):  o = 0x01C30000  l = 0x00000200 //!<PRUSS data RAM0
  RAM_PRU_DATA1 (RW):  o = 0x01C32000  l = 0x00000200 //!<PRUSS data RAM1
  RAM_PRU_CODE0 (RW):  o = 0x01C38000  l = 0x00001000 //!<PRU0 code RAM
  RAM_PRU_CODE1 (RW):  o = 0x01C3C000  l = 0x00001000 //!<PRU1 code RAM
  ROM_DSP (RX):        o = 0x11700000  l = 0x00100000 //!<DSP L2 ROM
  RAM_L1P (RWX):       o = 0x11E00000  l = 0x00008000 //!<DSP L1P RAM
  RAM_L1D (RWX):       o = 0x11F00000  l = 0x00008000 //!<DSP L1D RAM
  ROM_ARM (RX):        o = 0xFFFD0000  l = 0x00010000 //!<ARM local ROM
  RAM_ARM (RWX):       o = 0xFFFF0000  l = 0x00002000 //!<ARM local RAM
  RAM_L2 (RWX):          o = RAM_L2_DSP_BEGIN  l = RAM_L2_DSP_LEN          //!<internal RAM for DSP (code & data)
  ...
  PAGE 2: //!<peripheral memory
  MMR_INTCD (RWI):     o = 0x01800000  l = 0x0200
  MMR_PDC (RWI):       o = 0x01810000  l = 0x0200
  MMR_IDMA (RWI):      o = 0x01820000  l = 0x0200
  MMR_CACHE (RWI):     o = 0x01840000  l = 0x8400 //!<only DSP-accessable
  MMR_EDMA3CC (RWI):   o = 0x01C00000  l = 0x5000
  MMR_EDMA3TC (RWI):   o = 0x01C08000  l = 0x0800
  MMR_PSC0 (RWI):      o = 0x01C10000  l = 0x1000
  MMR_PLL (RWI):       o = 0x01C11000  l = 0x0200
  MMR_SYSCFG (RWI):    o = 0x01C14000  l = 0x0200
  MMR_TMR (RWI):       o = 0x01C20000  l = 0x2000
  MMR_I2C0 (RWI):      o = 0x01C22000  l = 0x1000
  MMR_RTC (RWI):       o = 0x01C23000  l = 0x1000
  MMR_PRU (RWI):       o = 0x01C37000  l = 0x1000
  MMR_SPI0 (RWI):      o = 0x01C41000  l = 0x1000
  MMR_UART0 (RWI):     o = 0x01C42000  l = 0x1000
  MMR_MCASP (RWI):     o = 0x01D00000  l = 0xC000
  MMR_UART1 (RWI):     o = 0x01D0C000  l = 0x1000
  MMR_UART2 (RWI):     o = 0x01D0D000  l = 0x1000
  MMR_USB0 (RWI):      o = 0x01E00000  l = 0x7000
  MMR_SPI1 (RWI):      o = 0x01E12000  l = 0x1000
  MMR_MPU1 (RWI):      o = 0x01E14000  l = 0x1000
  MMR_MPU2 (RWI):      o = 0x01E15000  l = 0x1000
  MMR_GPIO (RWI):      o = 0x01E26000  l = 0x1000
  MMR_PSC1 (RWI):      o = 0x01E27000  l = 0x1000
  MMR_I2C1 (RWI):      o = 0x01E28000  l = 0x1000
  MMR_EMIFB (RWI):     o = 0xB0000000  l = 0x8000
  MMR_INTCA (RWI):     o = 0xFFFEE000  l = 0x2000
}

TI для Вас авторитет надеюсь? 8)

Re: stm32h7**

Пн янв 10, 2022 22:45:39

Professor Chaos, Работает! Этот ADC_SAMPLE массив или указатель? В дебаге не открывается, как массив. С ним можно работать, как с массивом?

Re: stm32h7**

Пн янв 10, 2022 22:57:53

Professor Chaos, Работает! Этот ADC_SAMPLE массив или указатель? В дебаге не открывается, как массив. С ним можно работать, как с массивом?
В си любой массив - это суть указатель.
Но объявлять лучше всё-таки как массив. А не константой. Для правильного резервирования памяти компоновщиком.

Добавлено after 2 minutes 3 seconds:
массив фактически существует, но без определения. Зачем каждое значение присваивать?
В чём тогда проблема описать его правильно - как массив?

Re: stm32h7**

Пн янв 10, 2022 23:03:17

jcxz, проблема в том, что я в СИ один месяц.:)
Если объвить массив, как обычно, то он определяется в другом, недоступном для DMA домене. 0x24000000.

Re: stm32h7**

Пн янв 10, 2022 23:13:54

jcxz, проблема в том, что я в СИ один месяц.:)
Если объвить массив, как обычно, то он определяется в другом, недоступном для DMA домене. 0x24000000.

Так Вы определите его "как обычно", а потом добавьте суффикс (или префикс) переопределения секции данных. А потом этот сегмент положите скриптом компоновщика в нужный регион ОЗУ.
Например для IAR .cpp-файл:
Код:
__no_init struct AdcRaw {
  u16 refint, usupply, u5v, temp, uaudio, u3v;
} static adcRaw[2][8] @ ".dma";  //помещаем массив AdcRaw в секцию ".dma"

Скрипт компоновщика (.icf):
Код:
define region RAM_regionC     = mem:[from 0x20020000 size 0x0F000]; //main SRAM (bit-band)
...
do not initialize  {section .dma};
...
place in RAM_regionC {section .dma};
Описываем регион памяти RAM_regionC. Компонуем секцию ".dma" в RAM_regionC.
И по .map-файлу можно поверить реальное попадание adcRaw в нужные адреса.

Re: stm32h7**

Пн янв 10, 2022 23:26:31

То то же я смотрю, что вся периферия МК у всех производителей описывается скриптами линкёра, а не указателями на структуры :))
Периферия прибита к своим адресам намертво, поэтому к ней проще обращаться по фиксированному адресу. Способы адресации в ARM позволяют делать доступ со смещением от базового адреса, что делает "бесплатным" доступ к элементам структуры по её адресу. Расположение же массива для данных лучше отдать на откуп линкеру, это его работа.

Re: stm32h7**

Пн янв 10, 2022 23:51:57

Всё это хорошо, но лучше выложить рабочий пример ADC DMA в CubeIDE c комментариями. Мой вариант пока сырой.

Re: stm32h7**

Вт янв 11, 2022 06:16:56

Для начала найди раскладку памяти для своего МК и опиши её линковщику. У разных МК даже внутри одной линейки раскладка памяти разная.
С Н7 не работал, Кубом не пользуюсь. Судя по картинкам, разная периферия имеет через ПДП доступ к разным областям ОЗУ, посему без настройки скрипта линковщика не обойтись. Такое разнесение сделано для того, чтобы несколько периферийных устройств внутри МК могли одновременно писать данные в разные области ОЗУ. В Инете достаточно примеров, чтобы разобраться с настройкой линковщика.

Re: stm32h7**

Ср янв 12, 2022 21:15:08

******************************************************************************
*/ADC DMA интерлив.
/* USER CODE END Header */
/* Includes ----------*/
#include "main.h"

/* Private includes ----------*/
/* USER CODE BEGIN Includes */
#include <stdint.h>
/* USER CODE END Includes */

/* Private typedef ----------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ----------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro ----------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ----------*/
ADC_HandleTypeDef hadc1;
ADC_HandleTypeDef hadc2;
DMA_HandleTypeDef hdma_adc1;
DMA_HandleTypeDef hdma_adc2;

TIM_HandleTypeDef htim2;

/* USER CODE BEGIN PV */

extern uint16_t flag =0;
uint32_t i =0;
typedef uint8_t t; // тип отсчета АЦП
#define ADC ((const t *)0x30003000)
uint32_t sum = 0;
/* USER CODE END PV */

/* Private function prototypes ----------*/
void SystemClock_Config(void);
void PeriphCommonClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_ADC1_Init(void);
static void MX_TIM2_Init(void);
static void MX_ADC2_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ----------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */

/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/* MCU Configuration--------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();

/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* Configure the system clock */
SystemClock_Config();

/* Configure the peripherals common clocks */
PeriphCommonClock_Config();

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC1_Init();
MX_TIM2_Init();
MX_ADC2_Init();
/* USER CODE BEGIN 2 */
HAL_ADCEx_Calibration_Start(&hadc1, ADC_CALIB_OFFSET_LINEARITY , ADC_SINGLE_ENDED);
HAL_ADCEx_Calibration_Start(&hadc2, ADC_CALIB_OFFSET_LINEARITY , ADC_SINGLE_ENDED);
HAL_TIM_Base_Start_IT(&htim2);
HAL_ADC_Start(&hadc2);
HAL_ADCEx_MultiModeStart_DMA(&hadc1, ADC, 2000);
/* USER CODE END 2 */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if (flag==1) {
HAL_ADC_Stop_DMA(&hadc1);
for ( i = 0; i != 2000; ++i)
{
sum += ADC[i];
}
flag=0;
}
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
Весь проект.
https://drive.google.com/file/d/1sm-cZQ ... sp=sharing

Re: stm32h7**

Чт янв 13, 2022 08:07:45

А зачем останавливаешь оцифровку? Обрабатывай прерывание по заполнению половину буфера, а сам ПДП включи в кольцевой режим.

Похоже, ты не учёл ещё две вещи. Первая- это измерение периода, а вторая- буферные ОУ на входе АЦП.

Re: stm32h7**

Чт янв 13, 2022 14:41:54

tonyk, останавливал, что бы посмотреть результат, пример учебный.
ОУ буфер нужен однозначно, попробую использовать внутренние ОУ.
Период - это другая тема.

Re: stm32h7**

Чт янв 13, 2022 19:18:09

linkov1959 писал(а):останавливал, что бы посмотреть результат, пример учебный.

Хм, так ты его в обработчике прерывания мог посмотреть.
ОУ буфер нужен однозначно, попробую использовать внутренние ОУ.

Не помню, чтобы в Н7 на входе были буферные усилители.
Период - это другая тема.

Эта-эта! Нафиг тебе тогда 26 мегавыборок, если ты измеряешь 50Гц? Такая частота выборки, по-моему, адекватна измерению входных сигналов частотой в несколько десятков килогерц. И тут тебе понадобятся оооочень хорошие буферные усилители. А ещё тебе придётся решать задачу измерения периода.
Ответить