[研电赛技术支持] GD32F303RET6驱动WS2812灯阵动图显示

[复制链接]
 楼主| 八层楼 发表于 2025-7-8 18:16 | 显示全部楼层 |阅读模式
1.MCU资源分配
灯阵规格32*32,配置4个buffer存储每个灯的RGB数据,每个buffer存储8行灯的RGB数据。

#define PIXEL_NUM 256                                    // 8行*32
#define LED_DATA_SIZE ((PIXEL_NUM+3) * 3)                // 每个 LED 3 字节(RGB)

uint8_t flat_data[LED_DATA_SIZE*8];                      // 每字节对应 8 位占空比
uint8_t flat_data2[LED_DATA_SIZE*8];
uint8_t flat_data3[LED_DATA_SIZE*8];
uint8_t flat_data4[LED_DATA_SIZE*8];


每个buffer有独立的DMA通道将数据发送至输出端的外部比较寄存器,实现PWM信号的输出。

此外,需要配置串口,从主板RK3588接收图片的RGB数据。

mcu资源分配:

8041686c963ab22da.png

19922686c96340f737.png

12114686c962d6c2f3.png

90248686c961c7d18c.png


2.输出配置 DMA+PWM
void DMA_config() //PA8 TIMER0CH0 DMA0CH1
{
                timer_oc_parameter_struct timer_ocintpara;  
                timer_parameter_struct timer_initpara;      
                dma_parameter_struct dma_init_struct;      
               
                        //打开时钟
                rcu_periph_clock_enable(RCU_DMA0);
                rcu_periph_clock_enable(RCU_GPIOA);
                rcu_periph_clock_enable(RCU_AF);
                rcu_periph_clock_enable(RCU_TIMER0);
       
                 //GPIO配置
                rcu_periph_clock_enable(RCU_GPIOA);
                gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_8);
                       
                        //TIME 初始化 80K
                timer_deinit(TIMER0);
                timer_initpara.prescaler         = 0;                                                          //预分频器配置为0
                timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;          //边缘对齐方式
                timer_initpara.counterdirection  = TIMER_COUNTER_UP;            //向上计数
                timer_initpara.period            = 89;                          //自动重装载寄存器的值  72mhz/800khz
                timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;            //时钟分频
                timer_initpara.repetitioncounter = 0;                           //重复计数
                timer_init(TIMER0,&timer_initpara);                             //初始化            
                       
                        //通道输出控制
                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_LOW;     //空闲状态下比较输出状态
                timer_ocintpara.ocnidlestate     = TIMER_OCN_IDLE_STATE_LOW;    //空闲状态下互补输出状态
    timer_channel_output_config(TIMER0,TIMER_CH_0,&timer_ocintpara);//初始化比较输出
               
                //PWM0
                timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_0,0);                 //初始化比较输出寄存器的值
    timer_channel_output_shadow_config(TIMER0,TIMER_CH_0,TIMER_OC_SHADOW_ENABLE); //使能影子寄存器
    timer_channel_output_mode_config(TIMER0,TIMER_CH_0,TIMER_OC_MODE_PWM0);       //PWM0模式
               
//                printf("TIMER1 Channel 2 Compare Value: 0x%08X\n", TIMER_CH0CV(TIMER0));
//                 
//                printf("Periph Addr: %p\n", (void*)&TIMER_CH0CV(TIMER0));
//                printf("Memory Addr: %p\n", (void*)flat_data);

                dma_deinit(DMA0, DMA_CH1);
//                dma_init_struct.periph_addr  = (uint32_t)(&TIMER_DMATB(TIMER1));  //外设数据寄存器的地址
                dma_init_struct.periph_addr  = (uint32_t)(&TIMER_CH0CV(TIMER0));  //外设数据寄存器的地址
                dma_init_struct.periph_inc   = DMA_PERIPH_INCREASE_DISABLE;       //外设寄存器地址不自增
                dma_init_struct.memory_addr  = (uint32_t)(flat_data4);             //内部存储器地址
                dma_init_struct.memory_inc   = DMA_MEMORY_INCREASE_ENABLE;        //内存地址自增
                dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_32BIT;        //外设数据宽度
                dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;             //内存数据宽度
                dma_init_struct.direction    = DMA_MEMORY_TO_PERIPHERAL;          //传输方向为内存到外设
                dma_init_struct.number       = LED_DATA_SIZE*8;                   //DMA需要输出的次数
                dma_init_struct.priority     = DMA_PRIORITY_ULTRA_HIGH;           //DMA优先级
                dma_init(DMA0, DMA_CH1,&dma_init_struct);                               //DMA通道初始化
               
                dma_circulation_disable(DMA0, DMA_CH1);                       
                dma_memory_to_memory_disable(DMA0, DMA_CH1);            
               
                timer_primary_output_config(TIMER0,ENABLE);                       //定时器输出使能
                       
                timer_dma_transfer_config(TIMER0, TIMER_DMACFG_DMATA_CH0CV, TIMER_DMACFG_DMATC_1TRANSFER);
                timer_dma_enable(TIMER0,TIMER_DMA_CH0D);
                timer_channel_dma_request_source_select(TIMER0,TIMER_DMAREQUEST_UPDATEEVENT);
//                timer_channel_dma_request_source_select(TIMER1, TIMER_DMAREQUEST_CHANNELEVENT);
                timer_auto_reload_shadow_enable(TIMER0);
               
                dma_channel_disable(DMA0, DMA_CH1);
                timer_enable(TIMER0);
                       
                dma_interrupt_enable(DMA0, DMA_CH1,DMA_INT_FTF);                         
                nvic_irq_enable(DMA0_Channel1_IRQn, 2, 1);
//               
//               
                printf("DMA Channel 1 Control Register: 0x%08X\n", DMA_CHCTL(DMA0, DMA_CH1));
                printf("DMA Channel 1 Peripheral Address: 0x%08X\n", DMA_CHPADDR(DMA0, DMA_CH1));
                printf("DMA Channel 1 Memory Address: 0x%08X\n", DMA_CHMADDR(DMA0, DMA_CH1));
                printf("DMA Channel 1 Count Register: 0x%08X\n", DMA_CHCNT(DMA0, DMA_CH1));
               
}



以上为第一通道配置,其他通道以此类推,不需要对TIMER0重复配置,如下

void DMA_config2() //PA9 TIMER0CH1 DMA0CH2
{
                timer_oc_parameter_struct timer_ocintpara;
//                timer_parameter_struct timer_initpara;      
                dma_parameter_struct dma_init_struct;      
       
                 //GPIO配置
                rcu_periph_clock_enable(RCU_GPIOA);
                gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);                        
                       
                //通道输出控制
                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_LOW;     //空闲状态下比较输出状态
                timer_ocintpara.ocnidlestate     = TIMER_OCN_IDLE_STATE_LOW;    //空闲状态下互补输出状态
    timer_channel_output_config(TIMER0,TIMER_CH_1,&timer_ocintpara);//初始化比较输出
               
                //PWM0
                timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_1,0);                 //初始化比较输出寄存器的值
    timer_channel_output_shadow_config(TIMER0,TIMER_CH_1,TIMER_OC_SHADOW_ENABLE); //使能影子寄存器
    timer_channel_output_mode_config(TIMER0,TIMER_CH_1,TIMER_OC_MODE_PWM0);       //PWM0模式
               
                // 打印定时器1通道1比较寄存器的值
//                printf("TIMER0 Channel 1 Compare Value: 0x%08X\n", TIMER_CH1CV(TIMER0));
//                 
//                //打印 DMA配置
//                printf("Periph Addr: %p\n", (void*)&TIMER_CH1CV(TIMER0));
//                printf("Memory Addr: %p\n", (void*)flat_data);

                dma_deinit(DMA0, DMA_CH2);
//                dma_init_struct.periph_addr  = (uint32_t)(&TIMER_DMATB(TIMER1));  //外设数据寄存器的地址
                dma_init_struct.periph_addr  = (uint32_t)(&TIMER_CH1CV(TIMER0));  //外设数据寄存器的地址
                dma_init_struct.periph_inc   = DMA_PERIPH_INCREASE_DISABLE;       //外设寄存器地址不自增
                dma_init_struct.memory_addr  = (uint32_t)(flat_data);             //内部存储器地址
                dma_init_struct.memory_inc   = DMA_MEMORY_INCREASE_ENABLE;        //内存地址自增
                dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_32BIT;        //外设数据宽度
                dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;             //内存数据宽度
                dma_init_struct.direction    = DMA_MEMORY_TO_PERIPHERAL;          //传输方向为内存到外设
                dma_init_struct.number       = LED_DATA_SIZE*8;                   //DMA需要输出的次数
                dma_init_struct.priority     = DMA_PRIORITY_ULTRA_HIGH;           //DMA优先级
                dma_init(DMA0, DMA_CH2,&dma_init_struct);                               //DMA通道初始化
               
                dma_circulation_disable(DMA0, DMA_CH2);                  
                dma_memory_to_memory_disable(DMA0, DMA_CH2);          
               
                timer_primary_output_config(TIMER0,ENABLE);                       //定时器输出使能
                       
                timer_dma_transfer_config(TIMER0, TIMER_DMACFG_DMATA_CH1CV, TIMER_DMACFG_DMATC_1TRANSFER);
                timer_dma_enable(TIMER0,TIMER_DMA_CH1D);
                timer_channel_dma_request_source_select(TIMER0,TIMER_DMAREQUEST_UPDATEEVENT);
//                timer_channel_dma_request_source_select(TIMER1, TIMER_DMAREQUEST_CHANNELEVENT);
                timer_auto_reload_shadow_enable(TIMER0);
               
                dma_channel_disable(DMA0, DMA_CH2);
                timer_enable(TIMER0);
                       
                dma_interrupt_enable(DMA0, DMA_CH2,DMA_INT_FTF);                        //DMA中断使能                       
                nvic_irq_enable(DMA0_Channel2_IRQn, 2, 1);
               
//                printf("DMA Channel 2 Control Register: 0x%08X\n", DMA_CHCTL(DMA0, DMA_CH2));
//                printf("DMA Channel 2 Peripheral Address: 0x%08X\n", DMA_CHPADDR(DMA0, DMA_CH2));
//                printf("DMA Channel 2 Memory Address: 0x%08X\n", DMA_CHMADDR(DMA0, DMA_CH2));
//                printf("DMA Channel 2 Count Register: 0x%08X\n", DMA_CHCNT(DMA0, DMA_CH2));
//               
}

void DMA_config3() //PA10 TIMER0CH2 DMA0CH5
{
                timer_oc_parameter_struct timer_ocintpara;
//                timer_parameter_struct timer_initpara;      
                dma_parameter_struct dma_init_struct;      
       
                 //GPIO配置
                rcu_periph_clock_enable(RCU_GPIOA);
                gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10);         
                       
                        //通道输出控制
                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_LOW;     //空闲状态下比较输出状态
                timer_ocintpara.ocnidlestate     = TIMER_OCN_IDLE_STATE_LOW;    //空闲状态下互补输出状态
    timer_channel_output_config(TIMER0,TIMER_CH_2,&timer_ocintpara);//初始化比较输出
               
                //PWM0
                timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_2,0);                 //初始化比较输出寄存器的值
    timer_channel_output_shadow_config(TIMER0,TIMER_CH_2,TIMER_OC_SHADOW_ENABLE); //使能影子寄存器
    timer_channel_output_mode_config(TIMER0,TIMER_CH_2,TIMER_OC_MODE_PWM0);       //PWM0模式
               
//                printf("TIMER0 Channel 2 Compare Value: 0x%08X\n", TIMER_CH2CV(TIMER0));
//                 
//                printf("Periph Addr: %p\n", (void*)&TIMER_CH2CV(TIMER0));
//                printf("Memory Addr: %p\n", (void*)flat_data);

                dma_deinit(DMA0, DMA_CH5);
//                dma_init_struct.periph_addr  = (uint32_t)(&TIMER_DMATB(TIMER1));  //外设数据寄存器的地址
                dma_init_struct.periph_addr  = (uint32_t)(&TIMER_CH2CV(TIMER0));  //外设数据寄存器的地址
                dma_init_struct.periph_inc   = DMA_PERIPH_INCREASE_DISABLE;       //外设寄存器地址不自增
                dma_init_struct.memory_addr  = (uint32_t)(flat_data3);             //内部存储器地址
                dma_init_struct.memory_inc   = DMA_MEMORY_INCREASE_ENABLE;        //内存地址自增
                dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_32BIT;        //外设数据宽度
                dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;             //内存数据宽度
                dma_init_struct.direction    = DMA_MEMORY_TO_PERIPHERAL;          //传输方向为内存到外设
                dma_init_struct.number       = LED_DATA_SIZE*8;                   //DMA需要输出的次数
                dma_init_struct.priority     = DMA_PRIORITY_ULTRA_HIGH;           //DMA优先级
                dma_init(DMA0, DMA_CH5,&dma_init_struct);                               //DMA通道初始化
               
                dma_circulation_disable(DMA0, DMA_CH5);                     
                dma_memory_to_memory_disable(DMA0, DMA_CH5);          
               
                timer_primary_output_config(TIMER0,ENABLE);                       //定时器输出使能
                       
                timer_dma_transfer_config(TIMER0, TIMER_DMACFG_DMATA_CH2CV, TIMER_DMACFG_DMATC_1TRANSFER);//定时器DMA输出配置
                timer_dma_enable(TIMER0,TIMER_DMA_CH2D);
                timer_channel_dma_request_source_select(TIMER1,TIMER_DMAREQUEST_UPDATEEVENT);
//                timer_channel_dma_request_source_select(TIMER1, TIMER_DMAREQUEST_CHANNELEVENT);
                timer_auto_reload_shadow_enable(TIMER1);
               
                dma_channel_disable(DMA0, DMA_CH5);
                timer_enable(TIMER0);
                       
                dma_interrupt_enable(DMA0, DMA_CH5,DMA_INT_FTF);                         //DMA中断使能                       
                nvic_irq_enable(DMA0_Channel5_IRQn, 2, 1);
               
//                printf("DMA Channel 5 Control Register: 0x%08X\n", DMA_CHCTL(DMA0, DMA_CH5));
//                printf("DMA Channel 5 Peripheral Address: 0x%08X\n", DMA_CHPADDR(DMA0, DMA_CH5));
//                printf("DMA Channel 5 Memory Address: 0x%08X\n", DMA_CHMADDR(DMA0, DMA_CH5));
//                printf("DMA Channel 5 Count Register: 0x%08X\n", DMA_CHCNT(DMA0, DMA_CH5));
//               
}

void DMA_config4() //PA11 TIMER0CH3 DMA0CH3
{
                timer_oc_parameter_struct timer_ocintpara;  
//                timer_parameter_struct timer_initpara;   
                dma_parameter_struct dma_init_struct;      
       
                 //GPIO配置
                rcu_periph_clock_enable(RCU_GPIOA);
                gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_11);                                     
                       
                        //通道输出控制
                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_LOW;     //空闲状态下比较输出状态
                timer_ocintpara.ocnidlestate     = TIMER_OCN_IDLE_STATE_LOW;    //空闲状态下互补输出状态
    timer_channel_output_config(TIMER0,TIMER_CH_3,&timer_ocintpara);//初始化比较输出
               
                //PWM0
                timer_channel_output_pulse_value_config(TIMER0,TIMER_CH_3,0);                 //初始化比较输出寄存器的值
    timer_channel_output_shadow_config(TIMER0,TIMER_CH_3,TIMER_OC_SHADOW_ENABLE); //使能影子寄存器
    timer_channel_output_mode_config(TIMER0,TIMER_CH_3,TIMER_OC_MODE_PWM0);       //PWM0模式
               
//                printf("TIMER0 Channel 3 Compare Value: 0x%08X\n", TIMER_CH3CV(TIMER0));
//                 
//                printf("Periph Addr: %p\n", (void*)&TIMER_CH3CV(TIMER0));
//                printf("Memory Addr: %p\n", (void*)flat_data);

                dma_deinit(DMA0, DMA_CH3);
//                dma_init_struct.periph_addr  = (uint32_t)(&TIMER_DMATB(TIMER1));  //外设数据寄存器的地址
                dma_init_struct.periph_addr  = (uint32_t)(&TIMER_CH3CV(TIMER0));  //外设数据寄存器的地址
                dma_init_struct.periph_inc   = DMA_PERIPH_INCREASE_DISABLE;       //外设寄存器地址不自增
                dma_init_struct.memory_addr  = (uint32_t)(flat_data2);             //内部存储器地址
                dma_init_struct.memory_inc   = DMA_MEMORY_INCREASE_ENABLE;        //内存地址自增
                dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_32BIT;        //外设数据宽度
                dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;             //内存数据宽度
                dma_init_struct.direction    = DMA_MEMORY_TO_PERIPHERAL;          //传输方向为内存到外设
                dma_init_struct.number       = LED_DATA_SIZE*8;                   //DMA需要输出的次数
                dma_init_struct.priority     = DMA_PRIORITY_ULTRA_HIGH;           //DMA优先级
                dma_init(DMA0, DMA_CH3,&dma_init_struct);                               //DMA通道初始化
               
                dma_circulation_disable(DMA0, DMA_CH3);                        
                dma_memory_to_memory_disable(DMA0, DMA_CH3);             
               
                timer_primary_output_config(TIMER0,ENABLE);  
                       
                timer_dma_transfer_config(TIMER0, TIMER_DMACFG_DMATA_CH3CV, TIMER_DMACFG_DMATC_1TRANSFER);
                timer_dma_enable(TIMER0,TIMER_DMA_CH3D);//
                timer_channel_dma_request_source_select(TIMER0,TIMER_DMAREQUEST_UPDATEEVENT);
//                timer_channel_dma_request_source_select(TIMER1, TIMER_DMAREQUEST_CHANNELEVENT);
                timer_auto_reload_shadow_enable(TIMER0);
               
                dma_channel_disable(DMA0, DMA_CH3);
                timer_enable(TIMER0);
                       
                dma_interrupt_enable(DMA0, DMA_CH3,DMA_INT_FTF);        
                nvic_irq_enable(DMA0_Channel3_IRQn, 2, 1);
//               
//                printf("DMA Channel 3 Control Register: 0x%08X\n", DMA_CHCTL(DMA0, DMA_CH3));
//                printf("DMA Channel 3 Peripheral Address: 0x%08X\n", DMA_CHPADDR(DMA0, DMA_CH3));
//                printf("DMA Channel 3 Memory Address: 0x%08X\n", DMA_CHMADDR(DMA0, DMA_CH3));
//                printf("DMA Channel 3 Count Register: 0x%08X\n", DMA_CHCNT(DMA0, DMA_CH3));
//               
}



DMA中断函数:

void DMA0_Channel1_IRQHandler(void) //
{
    if (dma_flag_get(DMA0, DMA_CH1, DMA_FLAG_FTF)) {
        dma_flag_clear(DMA0, DMA_CH1, DMA_FLAG_FTF);
                               
        dma_channel_disable(DMA0, DMA_CH1);
        dma_transfer_number_config(DMA0, DMA_CH1, LED_DATA_SIZE*8);  
                                timer_disable(TIMER0);
    }else printf("err");
}

void DMA0_Channel2_IRQHandler(void) //
{
    if (dma_flag_get(DMA0, DMA_CH2, DMA_FLAG_FTF)) {
        dma_flag_clear(DMA0, DMA_CH2, DMA_FLAG_FTF);
                               
        dma_channel_disable(DMA0, DMA_CH2);
        dma_transfer_number_config(DMA0, DMA_CH2, LED_DATA_SIZE*8);         
                                timer_disable(TIMER0);
    }else printf("err");
}

void DMA0_Channel3_IRQHandler(void) //
{
    if (dma_flag_get(DMA0, DMA_CH3, DMA_FLAG_FTF)) {
        dma_flag_clear(DMA0, DMA_CH3, DMA_FLAG_FTF);               
                       
        dma_channel_disable(DMA0, DMA_CH3);
        dma_transfer_number_config(DMA0, DMA_CH3, LED_DATA_SIZE*8);  
                                timer_disable(TIMER0);
    }else printf("err");
}

void DMA0_Channel5_IRQHandler(void) //
{
    if (dma_flag_get(DMA0, DMA_CH5, DMA_FLAG_FTF)) {
        dma_flag_clear(DMA0, DMA_CH5, DMA_FLAG_FTF);               
                       
        dma_channel_disable(DMA0, DMA_CH5);
        dma_transfer_number_config(DMA0, DMA_CH5, LED_DATA_SIZE*8);  
                                timer_disable(TIMER0);
    }else printf("err");
}



3.串口接受并刷写(配合主板发送)
通讯协议:

99131686c960453b54.png

串口配置:

            gd_eval_com_init(EVAL_COM0);  
            usart_interrupt_enable(USART0, USART_INT_RBNE);
                nvic_irq_enable(USART0_IRQn, 2, 0);


串口中断:

#define PACKET_TOTAL_LEN 775                             // 串口接收 2+2+1+1+768+1 = 775字节
uint8_t uart_rx_buf[PACKET_TOTAL_LEN];
uint16_t uart_rx_index = 0;
uint8_t in_packet = 0;       
volatile uint8_t packet_ready = 0;         
uint8_t packet_buf[PACKET_TOTAL_LEN];


void USART0_IRQHandler(void)
{
    if (usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE)) {                       
                                uint8_t ch = usart_data_receive(USART0);
//                                usart_data_transmit(USART0, ch);

        if (!in_packet) {
            if (uart_rx_index == 0 && ch == 0x4D) {
                uart_rx_buf[uart_rx_index++] = ch;
            } else if (uart_rx_index == 1 && ch == 0x4D) {
                uart_rx_buf[uart_rx_index++] = ch;
                in_packet = 1;
            } else {
                uart_rx_index = 0;
            }
        } else {
            uart_rx_buf[uart_rx_index++] = ch;

            if (uart_rx_index == 4) {
                uint16_t length = uart_rx_buf[2] | (uart_rx_buf[3] << 8);
                if (length != 0x0302) {
                    uart_rx_index = 0;
                    in_packet = 0;
                }
            }

            if (uart_rx_index == PACKET_TOTAL_LEN) {
                for (int i = 0; i < PACKET_TOTAL_LEN; ++i)
                    packet_buf = uart_rx_buf;
                packet_ready = 1;

                uart_rx_index = 0;
                in_packet = 0;
            }
        }
    }
}


主函数实现:

int main(void)
{
    systick_config();      

        gd_eval_com_init(EVAL_COM0);  
        usart_interrupt_enable(USART0, USART_INT_RBNE);
        nvic_irq_enable(USART0_IRQn, 2, 0);
               
        DMA_config();
        DMA_config2();
        DMA_config3();
        DMA_config4();
               
        Fixed_Color_Display(0x000000);         
               
    while (1){
                       
                //串口接收数据后DMA显示
                if (packet_ready) {
                        packet_ready = 0;

                        uint8_t cmd = packet_buf[4];
                        uint8_t checksum = packet_buf[PACKET_TOTAL_LEN - 1];
                        uint8_t sum = cmd;

                        for (int i = 0; i < 769; ++i) sum += packet_buf[5 + i];
                        sum &= 0xFF;

                        if (sum == checksum && cmd == 0x30) {
                                uint8_t segment = packet_buf[5];
                                const uint8_t* grb_data = &packet_buf[6];
                                Set_Row_Color_From_Payload(segment, grb_data);
                        }
                }
    }
}


功能函数:

static uint8_t segment_received_flags = 0;

void Set_Row_Color_From_Payload(uint8_t segment, const uint8_t* payload)
{
    if (segment < 1 || segment > 4) return;

    uint8_t* target_buffer = NULL;
    switch(segment) {
        case 1: target_buffer = flat_data; break;
        case 2: target_buffer = flat_data2; break;
        case 3: target_buffer = flat_data3; break;
        case 4: target_buffer = flat_data4; break;
    }

    // 将 payload 中 GRB 数据填充到目标 flat_dataX 中
    for (int i = 0; i < 768; ++i) {
        uint8_t grb = payload;
        for (int b = 0; b < 8; ++b) {
            target_buffer[i * 8 + b] = (grb & (1 << (7 - b))) ? 61 : 29;
        }
    }

    // 标记该段完成
    segment_received_flags |= (1 << (segment - 1));

    // 如果全部四段都接收完毕,触发 DMA 显示
    if ((segment_received_flags & 0x0F) == 0x0F) {
        segment_received_flags = 0; // 重置

                dma_channel_enable(DMA0, DMA_CH1);
                dma_channel_enable(DMA0, DMA_CH2);
                dma_channel_enable(DMA0, DMA_CH3);
                dma_channel_enable(DMA0, DMA_CH5);
               
                timer_enable(TIMER0);
    }
}


————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/m0_60013390/article/details/148744193

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

本版积分规则

113

主题

4338

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部

113

主题

4338

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部