OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4963|回复: 0

gd32f303驱动ws2812,只能驱动部分灯珠

[复制链接]

1

主题

3

帖子

0

精华

新手入门

积分
8
金钱
8
注册时间
2022-9-6
在线时间
2 小时
发表于 2022-9-26 21:07:27 | 显示全部楼层 |阅读模式
7金钱
最近弄个ws2812,而且还是gd32系列的,所以一点整的我一点头痛了都,就是一块灯板上一共有423个灯珠,是用pwm+dma来驱动,但是现在只能控制前面的93个灯珠,却不能控制后面的那些灯珠,只要过了第93个灯珠,后面的灯珠就不受控了,颜色是随机显示的,希望哪位大佬帮我看看问题的所在,,指点指点
#include "gd32f30x.h"
#include "systick.h"
#include <stdio.h>
#include "main.h"
#include "gd32f307c_eval.h"

#define T1H#define T0H        160 //65

// LED灯珠数量
#define LED_NUM  105        //500个bit的时候,可以亮18颗,每增加100就可以亮多四颗。//11是开始的亮一颗,15就三个灯珠亮,17的话就四个灯珠亮,所以每加亮一颗就需要在11的基础上加2

// TIMER0_CH0, 这个查对照表
#define TIMER3_CH0CV     ((uint32_t)0x40000834)

#define TRANSFER_NUM     ((24 * LED_NUM)+6000)
uint8_t  LEDlen;

uint16_t dma_ws2812_buffer[TRANSFER_NUM];


void gpio_config(void);
void timer_config(void);
void dma_config(void);


        void gpio_config(void)
{
    rcu_periph_clock_enable(RCU_GPIOB);
    rcu_periph_clock_enable(RCU_AF);

    /*configure PA8(TIMER0 CH0) as alternate function*/
    gpio_init(GPIOB,GPIO_MODE_AF_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_6);
}
/*!
    \brief      main function
    \param[in]  none
    \param[out] none
    \retval     none
*/
void dma_config(void)
{
       
    dma_parameter_struct dma_init_struct;

    /* enable DMA clock */
    rcu_periph_clock_enable(RCU_DMA0);

    /* initialize DMA channel5 */
    dma_deinit(DMA0,DMA_CH0);

    /* DMA channel5 initialize */
    dma_init_struct.periph_addr = (uint32_t)TIMER3_CH0CV;                        //外设的基地址
    dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;        //不设置递增,每一次传输地址不加一
    dma_init_struct.memory_addr = (uint32_t)dma_ws2812_buffer;                                //内存基地址
    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;        //内存的基地址,每一次传输地址加一
    dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;//外设的数据宽度为半字(16bit)传输
    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;                        //内存的数据宽度为半字(16bit)传输
    dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL;                        //传输方向为内存向外设传输数据
    dma_init_struct.number =         TRANSFER_NUM;                                                                                                                                //这个为每次传输的数据量大小,比如ws2815为(24*有多少个灯珠+复位时间)
    dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;                                //这个是dma被中断后的响应优先级               
       
    dma_init(DMA0,DMA_CH0,&dma_init_struct);

    dma_circulation_enable(DMA0,DMA_CH0);
               
                dma_memory_width_config(DMA0,DMA_CH0,DMA_MEMORY_WIDTH_8BIT);
               
                dma_memory_to_memory_disable(DMA0,DMA_CH0);
    /* enable DMA channel5 */
    dma_channel_enable(DMA0,DMA_CH0);
}

void timer_config(void)
{
                timer_oc_parameter_struct timer_ocintpara;
    timer_parameter_struct timer_initpara;

    rcu_periph_clock_enable(RCU_TIMER3);

    timer_deinit(TIMER3);
       
                timer_struct_para_init(&timer_initpara);
    /* TIMER0 configuration */
    timer_initpara.prescaler         = 0;
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;
    timer_initpara.period            = 245;
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0;
    timer_init(TIMER3,&timer_initpara);

    /* CH0 configuration in PWM1 mode */
    timer_ocintpara.outputstate  = TIMER_CCX_ENABLE;
    timer_ocintpara.outputnstate = TIMER_CCXN_DISABLE;
    timer_ocintpara.ocpolarity   = TIMER_OC_POLARITY_HIGH;
    timer_ocintpara.ocnpolarity  = TIMER_OCN_POLARITY_HIGH;
    timer_ocintpara.ocidlestate  = TIMER_OC_IDLE_STATE_HIGH;
    timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;
    timer_channel_output_config(TIMER3,TIMER_CH_0,&timer_ocintpara);

    timer_channel_output_pulse_value_config(TIMER3,TIMER_CH_0,0);
               
    timer_channel_output_mode_config(TIMER3,TIMER_CH_0,TIMER_OC_MODE_PWM0);
               
    timer_channel_output_shadow_config(TIMER3,TIMER_CH_0,TIMER_OC_SHADOW_DISABLE);

    /* TIMER0 primary output enable */
    timer_primary_output_config(TIMER3,ENABLE);

    /* TIMER0 update DMA request enable */
               
    /* auto-reload preload enable */         
                timer_dma_transfer_config(TIMER3,TIMER_DMACFG_DMATA_CH0CV,TIMER_DMACFG_DMATC_10TRANSFER);
               
                timer_dma_enable(TIMER3, TIMER_DMA_CH0D);
               
                  timer_auto_reload_shadow_enable(TIMER3);
    /* TIMER0 counter enable */
    timer_enable(TIMER3);
}


AUAR  AuarTable;


void WS6812_ledsingle_send2(uint8_t color[][3], uint16_t len)//第一个是定义的数组是确定是哪一个灯的哪一个颜色,第二个是灯珠的数量
{
        uint16_t  i=0;
        uint16_t  j=0;

        uint16_t memaddr =0;
        uint16_t  AuarRGBTableBuf[3];
        AuarTable.Dimmer=255;
       
                        if(memaddr < 300 )//ws2812,开始需要300us的低电平来复位
                                {
                                        dma_ws2812_buffer[memaddr] = 00;
                                        memaddr++;        
                                }
                 
                 for(j=0;j<len;j++)
                 {

                                 AuarRGBTableBuf[0]=color[j][0]*AuarTable.Dimmer/255;
                                 AuarRGBTableBuf[1]=color[j][1]*AuarTable.Dimmer/255;
                                 AuarRGBTableBuf[2]=color[j][2]*AuarTable.Dimmer/255;
                                        
                                 for(i=0; i<8; i++) // GREEN data
                                 {
                                        dma_ws2812_buffer[memaddr] = ((AuarRGBTableBuf[1]<<i) & 0x0080) ? T1H:T0H;
                                        memaddr++;
                                 }
                                 for(i=0; i<8; i++) // RED
                                 {
                                        dma_ws2812_buffer[memaddr] = ((AuarRGBTableBuf[0]<<i) & 0x0080) ? T1H:T0H;
                                        memaddr++;
                                 }
                                 for(i=0; i<8; i++) // BLUE
                                 {
                                        dma_ws2812_buffer[memaddr] = ((AuarRGBTableBuf[2]<<i) & 0x0080) ? T1H:T0H;
                                        memaddr++;
                                 }
                         }

                 
                 if(memaddr<TRANSFER_NUM)//后面结束时不知道为什么会是高电平,所以加一个低电平
                        {                       
                        dma_ws2812_buffer[memaddr] = 0;
                                 memaddr++;       
                        }
        }               



void  DealAuarDate(AUAR *AUARTa)
{
       
         uint16_t number = 110;
         uint16_t  i=0,j=0;
       
                                         

                for(i=0;i<number;i++)
                {
                        AUARTa->RGBTable[i][0]=250;//255;//AUARTa->Blue;//Effect_Table.HSIRGB[0]; blue  0;//green//
                        AUARTa->RGBTable[i][1]=0;//255;//AUARTa->RED;//Effect_Table.HSIRGB[1];red255;//red//
                       AUARTa->RGBTable[i][2]=0;//255;// AUARTa->Green;//Effect_Table.HSIRGB[2];        green0;//blue//
                                       
                 }
        WS6812_ledsingle_send2(AUARTa->RGBTable,number);       
       
}



int main(void)
{

                rcu_ahb_clock_config(RCU_AHB_CKSYS_DIV1);
                systick_config();
                gpio_config();
                dma_config();
               timer_config();

    while (1)
                {

                                DealAuarDate(&AuarTable);

                 }
}

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-26 03:05

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表