Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить

CH32V и лента WS2812

Вт май 16, 2023 11:05:43

Всем привет!

Пытаюсь реализовать управление WS2812 с RISC-V контроллера CH32V307 (потом перенесу код на CH32V003) по образу и подобию с руководства по STM32: здесь.

Тактирование 96 МГц, выдать пачку импульсов не удается, прерывания по DMA не выдаются. По логическому анализатору импульс выдается на сбросе.
Подскажите, что не так

Код под спойлером



Добавлено after 42 minutes 54 seconds:
Настроил логический анализатор на большую частоту выборок. При настройке Pulse выдается ШИМ, норм
Но DMA не работает

Re: CH32V и лента WS2812

Ср май 17, 2023 08:51:29

TIM1 точно на DMA1 Chanel11 заведён?

Re: CH32V и лента WS2812

Ср май 17, 2023 13:05:45

Может у них тоже чертовщина всякая с запросами ПДП настраивается в SYSCFG? Ну или что у них там в качестве аналога.

Re: CH32V и лента WS2812

Ср май 17, 2023 13:07:02

Так, теперь прерывание приходит, но один раз

И принцип, я так понимаю, такой: на таймере надо включить выход запроса DMA с определенного канала, с которого выдается ШИМ, активировать сам DMA, написать обработчик, а связь между запросом DMA и каналом таймера задана уже в железе

Код обработчика прерываний DMA
Код:
void DMA1_Channel2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void DMA1_Channel2_IRQHandler(void)
{

    if(DMA_GetITStatus(DMA1_IT_TC2) != RESET) {
        DMA_ClearITPendingBit(DMA1_IT_TC2);
    }

    if (TIM_GetITStatus(TIM1, TIM_IT_CC1) != RESET) {
        TIM_ClearITPendingBit(TIM1, TIM_IT_CC1);
    }

    // Вставить настройку таймера для нового запроса
//    time_base_init.TIM_Period = 126;
    TIM1->CNT = 0;


    DMA_Cmd(DMA1_Channel2, DISABLE);
    TIM_DMACmd(TIM1, TIM_DMA_CC1, DISABLE);
    TIM_Cmd(TIM1, DISABLE);
    TIM_ITConfig(TIM1, TIM_IT_CC1, DISABLE);

    TIM_CCxCmd(TIM1, TIM_Channel_1, TIM_CCx_Disable);
    x++;
}


Запуск вывода
Код:
void ws2812_show() {
    TIM_DMACmd(TIM1, TIM_DMA_CC1, ENABLE);
    TIM_CCxCmd(TIM1, TIM_Channel_1, TIM_CCx_Enable);
    TIM_Cmd(TIM1, ENABLE);
    NVIC_EnableIRQ(DMA1_Channel2_IRQn);
    DMA_Cmd(DMA1_Channel2, ENABLE);
}

Re: CH32V и лента WS2812

Ср май 17, 2023 17:30:47

А где вы его включаете, чтобы оно много раз происходило?

Re: CH32V и лента WS2812

Ср май 17, 2023 17:42:38

DMA должно включаться каждый раз, когда вызываю ws2812_show(), вызывается каждые 100 мс

Re: CH32V и лента WS2812

Чт май 18, 2023 11:57:34

Помогло от одноразовой отправки вот что: перед отправкой семплов сбрасываю счетчик отправленных данных DMA
DMA_SetCurrDataCounter(DMA1_Channel2, LED_ARRAY_LEN);

Re: CH32V и лента WS2812

Чт май 18, 2023 12:20:56

Только не сбрасываете, а задаёте количество передаваемых данных.

Re: CH32V и лента WS2812

Сб май 20, 2023 01:10:11

Теперь другая проблема: посылка не отправляется в нужном формате
Решил проверить работу ШИМ, заодно и подкорректировать значения ШИМ для 0 и 1.
В итоге, засовываю в регистр CH1CVR значение для низкого уровня, получаю такую картину:
https://disk.yandex.ru/i/-wFed6Js7Ke30g
Код для инициализации таймера:
Код:
// Init Timer for PWM (PA8)
void Timer_PWM_Init() {

    GPIO_InitTypeDef GPIO_PWMInitStructure={0};
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_TIM1, ENABLE );

    GPIO_PWMInitStructure.GPIO_Pin = GPIO_Pin_8;
    GPIO_PWMInitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_PWMInitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init( GPIOA, &GPIO_PWMInitStructure );
    GPIO_PinRemapConfig(AFIO_PCFR1_TIM1_REMAP_FULLREMAP, ENABLE);

    time_base_init.TIM_ClockDivision = TIM_CKD_DIV4;
    time_base_init.TIM_Period = 99;
    time_base_init.TIM_CounterMode = TIM_CounterMode_Up;
    time_base_init.TIM_Prescaler = 0;
    time_base_init.TIM_RepetitionCounter = 0;

    TIM_TimeBaseInit(TIM1, &time_base_init);

    timer_output_cfg.TIM_OCMode = TIM_OCMode_PWM1;
    timer_output_cfg.TIM_OutputState = TIM_OutputState_Enable;
    timer_output_cfg.TIM_OCPolarity = TIM_OCPolarity_Low;
    timer_output_cfg.TIM_OCIdleState = 0;
//    timer_output_cfg.TIM_OCNIdleState = 0;
    timer_output_cfg.TIM_Pulse = 10; // Если выставлять больше, уровень будет резко меняться, в конечном итоге выставится сплошной уровень по выходу ШИМ. HIGH 0x8F5C LOW 0x47AE

//    TIM_DMAConfig(TIM1, TIM_DMABase_CCR1, TIM_DMABurstLength_1Transfer);
//    TIM_DMACmd(TIM1, TIM_DMA_CC1, DISABLE);

    TIM_OC1Init(TIM1, &timer_output_cfg);
    TIM_CtrlPWMOutputs(TIM1, ENABLE );
    TIM_OC1PreloadConfig( TIM1, TIM_OCPreload_Disable );
    TIM_ARRPreloadConfig( TIM1, ENABLE );
    TIM_CCxCmd(TIM1, TIM_Channel_1, TIM_CCx_Enable);
    TIM_ITConfig(TIM1, TIM_IT_CC1, ENABLE);
    NVIC_EnableIRQ(TIM1_CC_IRQn);

    TIM_Cmd( TIM1, ENABLE );
}

Re: CH32V и лента WS2812

Сб май 20, 2023 17:54:16

Здесь верно?
dma_leds.DMA_PeripheralBaseAddr = (u32)TIM1->DMAADR;

Re: CH32V и лента WS2812

Ср май 31, 2023 20:59:37

Здесь верно?
dma_leds.DMA_PeripheralBaseAddr = (u32)TIM1->DMAADR;

Поправил на адрес на CH1CVR для TIM1. Теперь судя по всему, посылки передаются, но не получается выдержать тайминги
Ответить