petrdynin

Mik32+ADC+Timer32_IRQ+DMA+2xBuffer

Sep 18th, 2025 (edited)
19
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.76 KB | Source Code | 0 0
  1. #include "mik32_hal.h"
  2. #include "mik32_hal_irq.h"
  3. #include "mik32_hal_adc.h"
  4. #include "mik32_hal_timer32.h"
  5. #include "mik32_hal_dma.h"
  6.  
  7.  
  8. /* Пример работы запуска преобразований ADC по таймеру, полученные данные по DMA
  9.  * складываются в текущий буфер, при заполнении текущего буфера в прерывании от DMA
  10.  * переключаемся на свободный буфер и DMA начинает складывать новые данные в него,
  11.  * а в это время программа может обработать заполненный буфер.
  12.  */
  13.  
  14.  
  15. ADC_HandleTypeDef hadc;
  16. TIMER32_HandleTypeDef htimer32_1;
  17. DMA_InitTypeDef hdma;
  18. DMA_ChannelHandleTypeDef hdma_ch0;
  19.  
  20.  
  21. void SystemClock_Config(void);
  22. void GPIO_Init();
  23. static void ADC_Init(void);
  24. static void Timer32_1_Init(void);
  25. static void DMA_Init(void);
  26. static void DMA_CH0_Init(DMA_InitTypeDef *hdma);
  27.  
  28. #define BUFF_SIZE  32  // размер должен быть степенью двойки
  29.  
  30. volatile uint16_t adc_value = 0;
  31. volatile uint8_t flag_dma = 0, CurBuf = 0,  buf_ready = 0, buff_fill = 0;
  32. volatile uint16_t buff[2][BUFF_SIZE];
  33.  
  34. int main()
  35. {
  36.     HAL_Init();
  37.  
  38.     SystemClock_Config();
  39.  
  40.     GPIO_Init();
  41.  
  42.     DMA_Init();
  43.  
  44.     Timer32_1_Init();
  45.  
  46.     ADC_Init();
  47.  
  48.     HAL_EPIC_MaskLevelSet(HAL_EPIC_TIMER32_1_MASK);
  49.     HAL_IRQ_EnableInterrupts();
  50.  
  51.     /* Запуск таймера и прерываний в продолжительном режиме */
  52.     HAL_Timer32_Start_IT(&htimer32_1, TIMER32_INT_OVERFLOW_M);
  53.  
  54.     ANALOG_REG->ADC_SINGLE = 1;
  55.     HAL_DMA_Start(&hdma_ch0, (void *)&ANALOG_REG->ADC_VALUE, (void *)buff[CurBuf], sizeof(buff[0])- 1);
  56.  
  57.     while (1)
  58.        {
  59.  
  60.         if(flag_dma){
  61.             flag_dma = 0;
  62.             HAL_DMA_Start(&hdma_ch0, (void *)&ANALOG_REG->ADC_VALUE, (void *)buff[CurBuf], sizeof(buff[0])- 1);
  63.             buf_ready = 1;
  64.         }
  65.  
  66.         if(buf_ready){
  67.             buf_ready = 0;
  68.             // тут можно обрабатывать заполненный буфер buff[buff_fill], пока текущий buff[CurBuf] наполняется данными
  69.             HAL_GPIO_TogglePin(GPIO_0, GPIO_PIN_9);
  70.         }
  71.  
  72.  
  73.        }
  74. }
  75.  
  76. void SystemClock_Config(void)
  77. {
  78.     PCC_InitTypeDef PCC_OscInit = {0};
  79.  
  80.     PCC_OscInit.OscillatorEnable = PCC_OSCILLATORTYPE_ALL;
  81.     PCC_OscInit.FreqMon.OscillatorSystem = PCC_OSCILLATORTYPE_OSC32M;
  82.     PCC_OscInit.FreqMon.ForceOscSys = PCC_FORCE_OSC_SYS_UNFIXED;
  83.     PCC_OscInit.FreqMon.Force32KClk = PCC_FREQ_MONITOR_SOURCE_OSC32K;
  84.     PCC_OscInit.AHBDivider = 0;
  85.     PCC_OscInit.APBMDivider = 0;
  86.     PCC_OscInit.APBPDivider = 0;
  87.     PCC_OscInit.HSI32MCalibrationValue = 128;
  88.     PCC_OscInit.LSI32KCalibrationValue = 8;
  89.     PCC_OscInit.RTCClockSelection = PCC_RTC_CLOCK_SOURCE_AUTO;
  90.     PCC_OscInit.RTCClockCPUSelection = PCC_CPU_RTC_CLOCK_SOURCE_OSC32K;
  91.     HAL_PCC_Config(&PCC_OscInit);
  92. }
  93.  
  94. void GPIO_Init()
  95. {
  96.     GPIO_InitTypeDef GPIO_InitStruct = {0};
  97.     __HAL_PCC_GPIO_0_CLK_ENABLE();
  98.     __HAL_PCC_GPIO_1_CLK_ENABLE();
  99.     __HAL_PCC_GPIO_2_CLK_ENABLE();
  100.  
  101.     GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10 ;
  102.     GPIO_InitStruct.Mode = HAL_GPIO_MODE_GPIO_OUTPUT;
  103.     GPIO_InitStruct.Pull = HAL_GPIO_PULL_NONE;
  104.     HAL_GPIO_Init(GPIO_0, &GPIO_InitStruct);
  105.  
  106. }
  107.  
  108. void __attribute__((section(".ram_text"))) trap_handler(void)
  109. {
  110.  
  111.     if(EPIC_CHECK_DMA()){
  112.         HAL_DMA_ClearIrq(&hdma);
  113.         buff_fill = CurBuf;
  114.         CurBuf = 1 - CurBuf;
  115.         flag_dma = 1;
  116.  
  117.     }
  118.  
  119.     if (EPIC_CHECK_TIMER32_1())
  120.         {
  121.             uint32_t interrupt_status = TIMER32_1->INT_FLAGS;
  122.             uint32_t interrupt_mask = TIMER32_1->INT_MASK;
  123.            
  124.             if ((interrupt_status & TIMER32_INT_OVERFLOW_M) & interrupt_mask)
  125.             {
  126.                  while (!(ANALOG_REG->ADC_VALID))
  127.                         ;
  128.                  adc_value = ANALOG_REG->ADC_VALUE;
  129.                  ANALOG_REG->ADC_SINGLE = 1;
  130.                  GPIO_0->OUTPUT ^= GPIO_PIN_10;
  131.             }
  132.  
  133.             HAL_TIMER32_INTERRUPTFLAGS_CLEAR(&htimer32_1); /* Сброс всех флагов */
  134.         }
  135.  
  136.     /* Сброс прерываний */
  137.     //HAL_EPIC_Clear(0xFFFFFFFF);
  138. }
  139.  
  140. static void ADC_Init(void)
  141. {
  142.     hadc.Instance = ANALOG_REG;
  143.  
  144.     hadc.Init.Sel    = ADC_CHANNEL0;
  145.     hadc.Init.EXTRef = ADC_EXTREF_OFF;    /* Выбор источника опорного напряжения: «1» - внешний; «0» - встроенный */
  146.     hadc.Init.EXTClb = ADC_EXTCLB_ADCREF; /* Выбор источника внешнего опорного напряжения: «1» - внешний вывод; «0» - настраиваемый ОИН */
  147.  
  148.     HAL_ADC_Init(&hadc);
  149. }
  150.  
  151.  
  152. static void Timer32_1_Init(void)
  153. {
  154.     htimer32_1.Instance = TIMER32_1;
  155.     htimer32_1.Top = 3200000;
  156.     htimer32_1.Clock.Source = TIMER32_SOURCE_PRESCALER;
  157.     htimer32_1.Clock.Prescaler = 0;
  158.     htimer32_1.InterruptMask = TIMER32_INT_OVERFLOW_M;
  159.     htimer32_1.CountMode = TIMER32_COUNTMODE_FORWARD;
  160.     HAL_Timer32_Init(&htimer32_1);
  161. }
  162.  
  163. static void DMA_Init(void)
  164. {
  165.  
  166.     /* Настройки DMA */
  167.     hdma.Instance = DMA_CONFIG;
  168.     hdma.CurrentValue = DMA_CURRENT_VALUE_ENABLE;
  169.     HAL_DMA_Init(&hdma);
  170.     HAL_DMA_GlobalIRQEnable(&hdma, DMA_IRQ_ENABLE);
  171.     /* Инициализация канала */
  172.     DMA_CH0_Init(&hdma);
  173.     HAL_DMA_LocalIRQEnable(&hdma_ch0, DMA_IRQ_ENABLE);
  174. }
  175.  
  176. static void DMA_CH0_Init(DMA_InitTypeDef *hdma)
  177. {
  178.     hdma_ch0.dma = hdma;
  179.  
  180.     /* Настройки канала */
  181.     hdma_ch0.ChannelInit.Channel = DMA_CHANNEL_0;
  182.     hdma_ch0.ChannelInit.Priority = DMA_CHANNEL_PRIORITY_VERY_HIGH;
  183.  
  184.     hdma_ch0.ChannelInit.ReadMode = DMA_CHANNEL_MODE_PERIPHERY;
  185.     hdma_ch0.ChannelInit.ReadInc = DMA_CHANNEL_INC_DISABLE;
  186.     hdma_ch0.ChannelInit.ReadSize = DMA_CHANNEL_SIZE_HALFWORD; /* data_len должно быть кратно read_size */
  187.     hdma_ch0.ChannelInit.ReadBurstSize = 1;                    /* read_burst_size должно быть кратно read_size */
  188.     hdma_ch0.ChannelInit.ReadRequest = DMA_CHANNEL_TIMER32_1_REQUEST;
  189.     hdma_ch0.ChannelInit.ReadAck = DMA_CHANNEL_ACK_ENABLE;
  190.  
  191.     hdma_ch0.ChannelInit.WriteMode = DMA_CHANNEL_MODE_MEMORY;
  192.     hdma_ch0.ChannelInit.WriteInc = DMA_CHANNEL_INC_ENABLE;
  193.     hdma_ch0.ChannelInit.WriteSize = DMA_CHANNEL_SIZE_HALFWORD; /* data_len должно быть кратно write_size */
  194.     hdma_ch0.ChannelInit.WriteBurstSize = 1;                /* write_burst_size должно быть кратно read_size */
  195.     hdma_ch0.ChannelInit.WriteRequest = DMA_CHANNEL_TIMER32_1_REQUEST;
  196.     hdma_ch0.ChannelInit.WriteAck = DMA_CHANNEL_ACK_ENABLE;
  197. }
  198.  
  199.  
  200.  
Add Comment
Please, Sign In to add comment