Задать вопрос
@HikKira

Проблема со связкой ЦАП + DMA в циклическом режиме на gd32f303zet6. Как убрать 0 между циклами?

Я настроил на gd32f303zet6 цап на генерацию сигнала. Делаю я это посредством dma из заранее заготовленного буфера. Циклический режим dma для проверки настроил таким образом, чтобы ТОЧНО не вылазить за рамки буфера. Проблема заключается в том, что при достижении конца цикла, dma подсовывает цап нулевое значение. В результате один отсчет между циклами всегда нулевой. Может я не в том порядке настроил? Просто вроде много чего перепробовал и идеи закончились.
Исполняемый код:

#include "gd32f30x.h"
#include "systick.h"
#include "gd32f30x_dac.h"
#include "math.h"
#include "main.h"
#include "stddef.h"

//uint16_t buff_dac[4] = {500, 1000, 2024, 4000};
//uint16_t buff_dac[4] = {4000, 2000, 500, 500};// последний элемент не учитывается
uint16_t buff_dac[600] = {500, 1000, 2000, 1000, 3000};
uint8_t test_flag = 1;


// Функция по генерации синуса
uint32_t gen_sin(float f, uint8_t A)
{
    double f_s = 1000000;
    double f_sig = 45;
    double t = 0;

    for(uint16_t i = 0; i < 500; i++)
    {
        t = (double)i * (f_sig/f_s);
        buff_dac[i] = (uint16_t)(4095* (1 + sin(2*3.14*f_sig*t))/2);
        // buff_dac[i] = i*100;
    }
    return 100;
}

// Функция для тестирования пина
void delay_ms(uint32_t ms)
{
    for(uint32_t i = 0; i < ms * 8000; i++)
    {
        __NOP(); // пропуск операций
    }

}

void rcc_conf(void)
{
    rcu_periph_clock_enable(RCU_GPIOF);
    rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_DAC);

    rcu_periph_clock_enable(RCU_DMA0);
    rcu_periph_clock_enable(RCU_DMA1);
    rcu_periph_clock_enable(RCU_TIMER5);
}

void dac_config(void)
{
    dac_deinit();
    /* configure the DAC0 */
    dac_wave_mode_config(DAC0, DAC_WAVE_DISABLE);
    dac_output_buffer_disable(DAC0);

    
    dac_trigger_source_config(DAC1, DAC_TRIGGER_T5_TRGO);
    //dac_trigger_source_config(DAC0, DAC_TRIGGER_SOFTWARE);
    dac_dma_enable(DAC0);
    dac_output_buffer_enable(DAC0);
    dac_trigger_enable(DAC0);
    dac_enable(DAC0);
    delay_1ms(100);
    timer_enable(TIMER5);
    delay_1ms(100);

    
}

void timer_config(void)
{
    /* TIMER0 configuration: generate PWM signals with different duty cycles:
       TIMER0CLK = SystemCoreClock / 12000 = 10kHz */
    timer_oc_parameter_struct timer_ocintpara;
    timer_parameter_struct timer_initpara;
    timer_deinit(TIMER5);

    /* TIMER0 configuration */
    //timer_initpara.prescaler         = 59;
    timer_initpara.prescaler         = 119;
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;
    //timer_initpara.period            = 1;
    timer_initpara.period            = 250;
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0;
    timer_init(TIMER5, &timer_initpara);


    //timer_channel_output_pulse_value_config(TIMER5,TIMER_CH_0,250);
    //timer_channel_output_mode_config(TIMER5,TIMER_CH_0,TIMER_OC_MODE_PWM0);
   // timer_channel_output_shadow_config(TIMER5,TIMER_CH_0,TIMER_OC_SHADOW_DISABLE);
    timer_master_output_trigger_source_select(TIMER5, TIMER_TRI_OUT_SRC_UPDATE);
    timer_update_source_config(TIMER5, TIMER_UPDATE_SRC_GLOBAL); // БЕЗ ЭТОЙ СТРОЧКИ ТРИГГЕР от таймера НЕ РАБОТАЕТ и не поступает на ЦАП!!!!!!!!!
    //timer_primary_output_config(TIMER5,ENABLE);
    /* auto-reload preload enable */
    timer_auto_reload_shadow_enable(TIMER5);
    //timer_interrupt_enable(TIMER5, TIMER_INT_UP);
    //nvic_irq_enable(TIMER5_IRQn, 2, 0);
}

void dac_dma_config(void)
{
    //dma_interrupt_flag_clear(DMA1, DMA_CH2, DMA_INT_FLAG_G);
    dma_parameter_struct dma_init_struct;
    /* deinitialize DMA channel3 */
    dma_deinit(DMA1, DMA_CH2);
    dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL;
    //dma_init_struct.memory_addr = (uint32_t)&buff_dac;
    dma_init_struct.memory_addr   = (uint32_t)_binary_C__data_for_MC_2_bin_start + 20;
    dma_init_struct.memory_inc    = DMA_MEMORY_INCREASE_ENABLE;
    dma_init_struct.memory_width  = DMA_MEMORY_WIDTH_16BIT;
    dma_init_struct.number        = 250; // выше 500 отсчетов не работает
    dma_init_struct.periph_addr   = (uint32_t)&DAC0_R12DH;
    dma_init_struct.periph_inc    = DMA_PERIPH_INCREASE_DISABLE;
    dma_init_struct.periph_width  = DMA_PERIPHERAL_WIDTH_16BIT;

    dma_init(DMA1, DMA_CH2, &dma_init_struct);
    /* configure DMA mode */
    //uint32_t adrr_DMA01 = DMA_CHCNT(DMA1, DMA_CH2);  
    //*adrr_DMA01 = _binary_C___data_for_MC_2_bin_start[20];
    dma_circulation_enable(DMA1, DMA_CH2);
    //dma_channel_enable(DMA1, DMA_CH2);
    //dma_interrupt_enable(DMA1, DMA_CH2, DMA_INT_HTF);
    //nvic_irq_enable(DMA1_Channel2_IRQn, 2, 0);
    
}

void DMA1_Channel2_IRQHandler(void)
{
    if(dma_interrupt_flag_get(DMA1, DMA_CH2, DMA_INT_HTF))
    {
        
        dma_channel_disable(DMA1, DMA_CH2);
        DMA_CHCNT(DMA1, DMA_CH2) = _binary_C__data_for_MC_2_bin_start[20];
        DAC0_R12DH = _binary_C__data_for_MC_2_bin_start[20];
        //dma_channel_enable(DMA1, DMA_CH2);
        dma_interrupt_flag_clear(DMA1, DMA_CH2, DMA_INT_HTF);
    }

}
void TIMER5_IRQHandler(void)
{
    if(timer_interrupt_flag_get(TIMER5, TIMER_INT_FLAG_UP) == SET)
    {
        timer_interrupt_flag_clear(TIMER5, TIMER_INT_FLAG_UP);
    }
    if(test_flag == 1)
    {
        gpio_bit_set(GPIOF, GPIO_PIN_2);
        test_flag = 0;
    }    
    else
    {
        gpio_bit_reset(GPIOF, GPIO_PIN_2);
        test_flag = 1;
    }
}
int main(void) {

    gen_sin(100, 1);
    systick_config();
    rcc_conf();
    gpio_init(GPIOF, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_1);
    gpio_init(GPIOF, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2);
    dac_dma_config();
    timer_config();
    dac_config();

    // После определения - вечный цикл моргания
    while(1) 
    {
        
        gpio_bit_reset(GPIOF, GPIO_PIN_1);   
        delay_1ms(500);

        gpio_bit_set(GPIOF, GPIO_PIN_1);

        delay_1ms(500);

    
    }

}
  • Вопрос задан
  • 90 просмотров
Подписаться 1 Средний Комментировать
Помогут разобраться в теме Все курсы
  • Нетология
    1C-программист: расширенный курс
    18 месяцев
    Далее
  • Академия Эдюсон
    Python-разработчик
    9 месяцев
    Далее
  • Skillbox
    Профессия Графический дизайнер PRO
    12 месяцев
    Далее
Решения вопроса 1
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
Проблема заключается в том, что при достижении конца цикла, dma подстовывает цап нулевое значение.

А есть уверенность, что это именно последнее значение из цикла DMA?

Вот это место в коде как-то подозрительно выглядит:
dma_init_struct.memory_addr   = (uint32_t)_binary_C__data_for_MC_2_bin_start + 20;

с учётом того, что ни определения этого массива нет в приведённом коде, ни как он заполняется не видно.
Два предложения:
- проверить, что в этом массиве всё на месте
- уменьшить dma_init_struct.number на 1, а потом увеличить dma_init_struct.memory_addr на 2 и понаблюдать за тем, не исчезает ли эффект.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы