CH32V и лента WS2812
Добавлено: Вт май 16, 2023 11:05:43
Всем привет!
Пытаюсь реализовать управление WS2812 с RISC-V контроллера CH32V307 (потом перенесу код на CH32V003) по образу и подобию с руководства по STM32: здесь.
Тактирование 96 МГц, выдать пачку импульсов не удается, прерывания по DMA не выдаются. По логическому анализатору импульс выдается на сбросе.
Подскажите, что не так
Код под спойлером
ws2812.c
ws2812.h
Добавлено after 42 minutes 54 seconds:
Настроил логический анализатор на большую частоту выборок. При настройке Pulse выдается ШИМ, норм
Но DMA не работает
Пытаюсь реализовать управление WS2812 с RISC-V контроллера CH32V307 (потом перенесу код на CH32V003) по образу и подобию с руководства по STM32: здесь.
Тактирование 96 МГц, выдать пачку импульсов не удается, прерывания по DMA не выдаются. По логическому анализатору импульс выдается на сбросе.
Подскажите, что не так
Код под спойлером
Спойлер
main.cКод: Выделить всё
/********************************** (C) COPYRIGHT *******************************
* File Name : main.c
* Author : WCH
* Version : V1.0.0
* Date : 2021/06/06
* Description : Main program body.
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
/*
*@Note
USART Print debugging routine:
USART1_Tx(PA9).
This example demonstrates using USART1(PA9) as a print debug port output.
*/
#include "debug.h"
#include "ws2812.h"
/* Global typedef */
/* Global define */
/* Global Variable */
//TIM_TypeDef timer_handle;
TIM_TimeBaseInitTypeDef time_base_init = {0};
TIM_OCInitTypeDef timer_output_cfg = {0};
DMA_InitTypeDef dma_leds = {0};
void Timer_PWM_Init();
void DMA_LEDs_Init();
/*********************************************************************
* @fn main
*
* @brief Main program.
*
* @return none
*/
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
SystemCoreClockUpdate();
Delay_Init();
USART_Printf_Init(115200);
printf("SystemClk:%d\r\n",SystemCoreClock);
printf( "ChipID:%08x\r\n", DBGMCU_GetCHIPID() );
printf("This is printf example\r\n");
Timer_PWM_Init();
DMA_LEDs_Init();
// while(DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET);
ws2812_init(TIM1);
ws2812_set_pixel(0, 0, 0, 0);
ws2812_show();
int i = 0;
while(1)
{
printf("OK\r\n");
Delay_Ms(1000);
ws2812_set_pixel(0, i++, 0, 0);
ws2812_show();
}
}
// 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_PD01_REMAP, DISABLE);
time_base_init.TIM_ClockDivision = TIM_CKD_DIV1;
time_base_init.TIM_Period = 126;
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_High;
// timer_output_cfg.TIM_OCIdleState = 0;
// timer_output_cfg.TIM_OCNIdleState = 0;
timer_output_cfg.TIM_Pulse = 0;
// TIM_DMAConfig(TIM1, TIM_DMABase, TIM_DMABurstLength)
TIM_OC1Init(TIM1, &timer_output_cfg);
TIM_CtrlPWMOutputs(TIM1, ENABLE );
TIM_OC1PreloadConfig( TIM1, TIM_OCPreload_Disable );
TIM_ARRPreloadConfig( TIM1, ENABLE );
TIM_Cmd( TIM1, ENABLE );
}
void DMA_LEDs_Init() {
RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1, ENABLE );
NVIC_SetPriority(DMA1_Channel1_IRQn,0xE0);
NVIC_EnableIRQ(DMA1_Channel1_IRQn);
dma_leds.DMA_PeripheralBaseAddr = (u32)TIM1->DMAADR;
dma_leds.DMA_MemoryBaseAddr = (u32)get_ws2812b_array_ptr();
dma_leds.DMA_DIR = DMA_DIR_PeripheralDST;
dma_leds.DMA_BufferSize = LED_ARRAY_LEN*2;
dma_leds.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
dma_leds.DMA_MemoryInc = DMA_MemoryInc_Enable;
dma_leds.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
dma_leds.DMA_MemoryDataSize = DMA_PeripheralDataSize_HalfWord;
dma_leds.DMA_Mode = DMA_Mode_Normal;
dma_leds.DMA_Priority = DMA_Priority_High;
dma_leds.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &dma_leds);
DMA_ITConfig(DMA1_Channel1,DMA_IT_TC,ENABLE);
DMA_ClearFlag(DMA1_FLAG_TC1);
DMA_Cmd(DMA1_Channel1, ENABLE);
}
/*********************************************************************
* @fn DMA1_Channel1_IRQHandler
*
* @brief This function DMA1 Channel1 exception.
*
* @return none
*/
void DMA1_Channel1_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void DMA1_Channel1_IRQHandler(void)
{
if(DMA_GetITStatus(DMA1_IT_TC1))
{
// TIM_Cmd(TIM1, DISABLE);
// TIM_DMACmd(TIM1, DMA1_Channel1, NewState)
DMA_ClearITPendingBit(DMA1_IT_TC1|DMA1_IT_GL1|DMA1_IT_HT1);
}
}
Код: Выделить всё
/*
* ws2812.c
*
* Created on: May 4, 2023
* Author: dmitr
*/
#include "ws2812.h"
uint16_t BUF_DMA[LED_ARRAY_LEN] = {0};
TIM_TypeDef * timer_handle = NULL;
int ws2812_init(TIM_TypeDef * th)
{
if (!th) return -1;
else timer_handle = th;
ws2812_clear_buffer();
return 0;
}
void ws2812_clear_buffer() {
for(int i=0;i<(LED_ARRAY_LEN-DELAY_LEN);i++) BUF_DMA[i] = LOW;
}
uint32_t * get_ws2812b_array_ptr() {
return &BUF_DMA;
}
void byte_to_sequence(uint8_t byte_to_convert, uint16_t * seq) {
for (int i = 7; i <= 0; i--) {
if (((byte_to_convert>>i) & 1) == 0) seq[i] = LOW;
else seq[i] = HIGH;
}
}
void copy_sequence_to_position(uint32_t position, int sp_offset, uint16_t * seq, uint16_t * led_array) {
if (position > LED_COUNT) position = LED_COUNT;
if (sp_offset > 2) sp_offset = 2;
if (sp_offset < 0) sp_offset = 0;
for (int i = 0; i < 8; i++) led_array[position+8*sp_offset+i] = seq[i];
}
void ws2812_set_pixel(uint32_t pixel_num, uint8_t r, uint8_t g, uint8_t b) {
if (pixel_num > LED_COUNT) pixel_num = LED_COUNT;
uint16_t tmp[8];
byte_to_sequence(r, &tmp);
copy_sequence_to_position(pixel_num, 0, &tmp, &BUF_DMA);
byte_to_sequence(g, &tmp);
copy_sequence_to_position(pixel_num, 1, &tmp, &BUF_DMA);
byte_to_sequence(b, &tmp);
copy_sequence_to_position(pixel_num, 2, &tmp, &BUF_DMA);
}
void ws2812_show() {
DMA_Cmd(DMA1_Channel1, ENABLE);
}
Код: Выделить всё
/*
* ws2812.h
*
* Created on: May 4, 2023
* Author: dmitr
*/
#ifndef USER_WS2812_H_
#define USER_WS2812_H_
#include "stdio.h"
#include "stdint.h"
#include "ch32v30x.h"
#include "ch32v30x_tim.h"
#include "ch32v30x_dma.h"
//--------------------------------------------------
#define DELAY_LEN 48
#define LED_COUNT 8
#define LED_ARRAY_LEN DELAY_LEN + LED_COUNT*24
#define HIGH 0x8A3D // 54%
#define LOW 0x3AE1 // 23%
int ws2812_init(TIM_TypeDef * th);
uint32_t * get_ws2812b_array_ptr();
void ws2812_set_pixel(uint32_t pixel_num, uint8_t r, uint8_t g, uint8_t b);
void ws2812_clear_buffer();
void ws2812_show();
#endif /* USER_WS2812_H_ */
Настроил логический анализатор на большую частоту выборок. При настройке Pulse выдается ШИМ, норм
Но DMA не работает