21ic问答首页 - 为什么我的 PWM DMA 不起作用 是那里配置错了吗
为什么我的 PWM DMA 不起作用 是那里配置错了吗
这是代码 DMA一直没更新成功 buf
#include "bsp_pwm.h"
//#include "ws2812.h"
#include "gd32f4xx.h"
uint16_t LED_Buff[RGB_LEN];
void Tim4CH2_init_DMA(uint32_t number);
#define TIMER4_CH2CV (TIMER4+0x3C) /* 通道2 */
void Timer4_init(void)
{
rcu_periph_clock_enable(RCU_TIMER4);
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_DMA0);
dma_single_data_parameter_struct dma_data_parameter;
timer_oc_parameter_struct timer_ocintpara;
timer_parameter_struct timer_initpara;
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_2);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2);
gpio_af_set(GPIOA, GPIO_AF_2, GPIO_PIN_2);
/* TIMER4 configuration */
timer_initpara.prescaler = 299; //时钟预分频数 (200)M/10/25 = 0.8mHz = 800KHz
timer_initpara.alignedmode = TIMER_COUNTER_EDGE; //向上&向下都是边沿对齐
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 999; /* 自动重装载寄存器周期的值(计数值) */
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter = 0;
timer_init(TIMER4, &timer_initpara);
/* TIMER1 channel3 configuration in PWM mode */
timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
timer_channel_output_config(TIMER4, TIMER_CH_2, &timer_ocintpara);
timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_2, 500); //占空比 = TIMERx_CHxCV / TIMERx_CAR
timer_channel_output_mode_config(TIMER4, TIMER_CH_2, TIMER_OC_MODE_PWM0);
timer_channel_output_shadow_config(TIMER4, TIMER_CH_2, TIMER_OC_SHADOW_DISABLE);//TIMER_OC_SHADOW_ENABLE
timer_auto_reload_shadow_disable(TIMER4);
// timer_dma_transfer_config
// timer_dma_enable(TIMER4,TIMER_DMA_UPD);
// timer_disable(TIMER4);
timer_primary_output_config(TIMER4,ENABLE);
timer_dma_enable(TIMER4,TIMER_DMA_UPD);/*此处选择定时器更新事件*/
timer_auto_reload_shadow_enable(TIMER4);
timer_enable(TIMER4);
}
static void WS2812_send_internal(uint8_t (*color)[3], uint16_t len, uint8_t PWM_CHANNEL)
{
uint16_t buffersize = (len * 24) + 42;
if(buffersize >= RGB_LEN) {
return;
}
// 准备数据
uint16_t memaddr = 0;
for(uint16_t led = 0; led < len; led++) {
// 准备RGB数据
for(uint8_t j = 0; j < 8; j++) {
LED_Buff[memaddr++] = ((color[led][1]<<j) & 0x80) ? RGB_LOGICAL_H : RGB_LOGICAL_L;
}
for(uint8_t j = 0; j < 8; j++) {
LED_Buff[memaddr++] = ((color[led][0]<<j) & 0x80) ? RGB_LOGICAL_H : RGB_LOGICAL_L;
}
for(uint8_t j = 0; j < 8; j++) {
LED_Buff[memaddr++] = ((color[led][2]<<j) & 0x80) ? RGB_LOGICAL_H : RGB_LOGICAL_L;
}
}
// 填充剩余缓冲区
while(memaddr < buffersize) {
LED_Buff[memaddr++] = 0;
}
Tim4CH2_init_DMA(buffersize);
dma_channel_enable(DMA0, DMA_CH0);
timer_enable(TIMER4);
}
void WS2812_send(uint8_t (*color)[3], uint16_t len, uint8_t PWM_CHANNEL)
{
WS2812_send_internal(color, len, PWM_CHANNEL);
}
void rgb_dma_complete_callback(uint8_t channel)
{
dma_channel_disable(DMA0, DMA_CH0);
timer_disable(TIMER4);
// rgb_state.is_refreshing = false;
}
// DMA中断处理函数
void DMA0_Channel0_IRQHandler(void)
{
if(dma_flag_get(DMA0, DMA_CH0, DMA_INTF_FTFIF)) {
dma_flag_clear(DMA0, DMA_CH0, DMA_INTF_FTFIF);
// 由于DMA2被通道0和2共享,我们需要知道当前是哪个通道在使用
// 这里我们假设通道0和2是交替使用的
// rgb_dma_complete_callback(0);
dma_channel_disable(DMA0, DMA_CH0);
timer_disable(TIMER4);
}
}
void Tim4CH2_init_DMA(uint32_t number)
{
dma_single_data_parameter_struct dma_data_parameter;
rcu_periph_clock_enable(RCU_DMA0);
dma_deinit(DMA0,DMA_CH0);
/* initialize DMA single data mode */
dma_data_parameter.periph_addr = (uint32_t)TIMER4_CH2CV;//(uint32_t)(&TIMER_CH2CV(TIMER4));
dma_data_parameter.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_data_parameter.memory0_addr = (uint32_t)LED_Buff;
dma_data_parameter.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_data_parameter.periph_memory_width = DMA_PERIPH_WIDTH_32BIT;
dma_data_parameter.direction = DMA_MEMORY_TO_PERIPH;
dma_data_parameter.number = number;
dma_data_parameter.priority = DMA_PRIORITY_HIGH;
dma_single_data_mode_init(DMA0, DMA_CH0, &dma_data_parameter);
dma_channel_subperipheral_select(DMA0, DMA_CH0, DMA_SUBPERI5);
dma_circulation_disable(DMA0, DMA_CH0);
timer_dma_enable(TIMER4,TIMER_DMA_UPD);
// dma_channel_disable(DMA0, DMA_CH0);
dma_interrupt_enable(DMA0, DMA_CH0, DMA_CHXCTL_FTFIE);
nvic_irq_enable(DMA0_Channel0_IRQn, 2, 0);
dma_channel_enable(DMA0, DMA_CH0); //
/* enable DMA channel5 */
// dma_channel_enable(DMA0,DMA_CH5);
}
int demo_test(void)
{
Timer4_init();
// 定义8个灯珠的RGB颜色(GRB顺序)
uint8_t led_colors[3][3] = {
{0x00, 0xFF, 0x00}, // 绿色 (G=0, R=255, B=0) -> 实际显示为绿色
{0xFF, 0x00, 0x00}, // 红色
{0x00, 0x00, 0xFF}, // 蓝色
};
// 无限循环:交替显示颜色
while (1) {
// 发送数据(8个灯珠,使用Timer2_CH3通道)
WS2812_send(led_colors, 3, 0);
delay_1ms(1000);
}
}
#include "bsp_pwm.h"
//#include "ws2812.h"
#include "gd32f4xx.h"
uint16_t LED_Buff[RGB_LEN];
void Tim4CH2_init_DMA(uint32_t number);
#define TIMER4_CH2CV (TIMER4+0x3C) /* 通道2 */
void Timer4_init(void)
{
rcu_periph_clock_enable(RCU_TIMER4);
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_DMA0);
dma_single_data_parameter_struct dma_data_parameter;
timer_oc_parameter_struct timer_ocintpara;
timer_parameter_struct timer_initpara;
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_2);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2);
gpio_af_set(GPIOA, GPIO_AF_2, GPIO_PIN_2);
/* TIMER4 configuration */
timer_initpara.prescaler = 299; //时钟预分频数 (200)M/10/25 = 0.8mHz = 800KHz
timer_initpara.alignedmode = TIMER_COUNTER_EDGE; //向上&向下都是边沿对齐
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 999; /* 自动重装载寄存器周期的值(计数值) */
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter = 0;
timer_init(TIMER4, &timer_initpara);
/* TIMER1 channel3 configuration in PWM mode */
timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
timer_channel_output_config(TIMER4, TIMER_CH_2, &timer_ocintpara);
timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_2, 500); //占空比 = TIMERx_CHxCV / TIMERx_CAR
timer_channel_output_mode_config(TIMER4, TIMER_CH_2, TIMER_OC_MODE_PWM0);
timer_channel_output_shadow_config(TIMER4, TIMER_CH_2, TIMER_OC_SHADOW_DISABLE);//TIMER_OC_SHADOW_ENABLE
timer_auto_reload_shadow_disable(TIMER4);
// timer_dma_transfer_config
// timer_dma_enable(TIMER4,TIMER_DMA_UPD);
// timer_disable(TIMER4);
timer_primary_output_config(TIMER4,ENABLE);
timer_dma_enable(TIMER4,TIMER_DMA_UPD);/*此处选择定时器更新事件*/
timer_auto_reload_shadow_enable(TIMER4);
timer_enable(TIMER4);
}
static void WS2812_send_internal(uint8_t (*color)[3], uint16_t len, uint8_t PWM_CHANNEL)
{
uint16_t buffersize = (len * 24) + 42;
if(buffersize >= RGB_LEN) {
return;
}
// 准备数据
uint16_t memaddr = 0;
for(uint16_t led = 0; led < len; led++) {
// 准备RGB数据
for(uint8_t j = 0; j < 8; j++) {
LED_Buff[memaddr++] = ((color[led][1]<<j) & 0x80) ? RGB_LOGICAL_H : RGB_LOGICAL_L;
}
for(uint8_t j = 0; j < 8; j++) {
LED_Buff[memaddr++] = ((color[led][0]<<j) & 0x80) ? RGB_LOGICAL_H : RGB_LOGICAL_L;
}
for(uint8_t j = 0; j < 8; j++) {
LED_Buff[memaddr++] = ((color[led][2]<<j) & 0x80) ? RGB_LOGICAL_H : RGB_LOGICAL_L;
}
}
// 填充剩余缓冲区
while(memaddr < buffersize) {
LED_Buff[memaddr++] = 0;
}
Tim4CH2_init_DMA(buffersize);
dma_channel_enable(DMA0, DMA_CH0);
timer_enable(TIMER4);
}
void WS2812_send(uint8_t (*color)[3], uint16_t len, uint8_t PWM_CHANNEL)
{
WS2812_send_internal(color, len, PWM_CHANNEL);
}
void rgb_dma_complete_callback(uint8_t channel)
{
dma_channel_disable(DMA0, DMA_CH0);
timer_disable(TIMER4);
// rgb_state.is_refreshing = false;
}
// DMA中断处理函数
void DMA0_Channel0_IRQHandler(void)
{
if(dma_flag_get(DMA0, DMA_CH0, DMA_INTF_FTFIF)) {
dma_flag_clear(DMA0, DMA_CH0, DMA_INTF_FTFIF);
// 由于DMA2被通道0和2共享,我们需要知道当前是哪个通道在使用
// 这里我们假设通道0和2是交替使用的
// rgb_dma_complete_callback(0);
dma_channel_disable(DMA0, DMA_CH0);
timer_disable(TIMER4);
}
}
void Tim4CH2_init_DMA(uint32_t number)
{
dma_single_data_parameter_struct dma_data_parameter;
rcu_periph_clock_enable(RCU_DMA0);
dma_deinit(DMA0,DMA_CH0);
/* initialize DMA single data mode */
dma_data_parameter.periph_addr = (uint32_t)TIMER4_CH2CV;//(uint32_t)(&TIMER_CH2CV(TIMER4));
dma_data_parameter.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_data_parameter.memory0_addr = (uint32_t)LED_Buff;
dma_data_parameter.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_data_parameter.periph_memory_width = DMA_PERIPH_WIDTH_32BIT;
dma_data_parameter.direction = DMA_MEMORY_TO_PERIPH;
dma_data_parameter.number = number;
dma_data_parameter.priority = DMA_PRIORITY_HIGH;
dma_single_data_mode_init(DMA0, DMA_CH0, &dma_data_parameter);
dma_channel_subperipheral_select(DMA0, DMA_CH0, DMA_SUBPERI5);
dma_circulation_disable(DMA0, DMA_CH0);
timer_dma_enable(TIMER4,TIMER_DMA_UPD);
// dma_channel_disable(DMA0, DMA_CH0);
dma_interrupt_enable(DMA0, DMA_CH0, DMA_CHXCTL_FTFIE);
nvic_irq_enable(DMA0_Channel0_IRQn, 2, 0);
dma_channel_enable(DMA0, DMA_CH0); //
/* enable DMA channel5 */
// dma_channel_enable(DMA0,DMA_CH5);
}
int demo_test(void)
{
Timer4_init();
// 定义8个灯珠的RGB颜色(GRB顺序)
uint8_t led_colors[3][3] = {
{0x00, 0xFF, 0x00}, // 绿色 (G=0, R=255, B=0) -> 实际显示为绿色
{0xFF, 0x00, 0x00}, // 红色
{0x00, 0x00, 0xFF}, // 蓝色
};
// 无限循环:交替显示颜色
while (1) {
// 发送数据(8个灯珠,使用Timer2_CH3通道)
WS2812_send(led_colors, 3, 0);
delay_1ms(1000);
}
}

问答
您需要登录后才可以回复 登录 | 注册