GD32F450 rgb移植调试

直接照着上个项目的GD32F407的RGB驱动移植就行。

 1 /*!**************************************************************************************************
 2 \brief        ch0 - rgb0 - pa0(af2)
 3             ch1 - rgb1 - pa1(af2)
 4 ****************************************************************************************************/
 5 void Timer4_init(void)
 6 {
 7     rcu_periph_clock_enable(RCU_TIMER4);
 8     rcu_periph_clock_enable(RCU_GPIOA);
 9     rcu_periph_clock_enable(RCU_GPIOC);
10     rcu_periph_clock_enable(RCU_DMA0);
11 
12     dma_single_data_parameter_struct dma_data_parameter;
13     timer_oc_parameter_struct timer_ocintpara;
14     timer_parameter_struct timer_initpara;
15 
16     //rgb_pwn
17     gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_PIN_14);
18     gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_14);
19 
20     gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_0|GPIO_PIN_1);
21     gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0|GPIO_PIN_1);
22     gpio_af_set(GPIOA, GPIO_AF_2, GPIO_PIN_0|GPIO_PIN_1);
23 
24     /* TIMER4 configuration */
25     timer_initpara.prescaler         = 9;            //时钟预分频数 (200)M/10/25 = 0.8mHz = 800KHz
26     timer_initpara.alignedmode         = TIMER_COUNTER_EDGE;        //向上&向下都是边沿对齐
27     timer_initpara.counterdirection  = TIMER_COUNTER_UP;
28     timer_initpara.period             = 24;                    /* 自动重装载寄存器周期的值(计数值) */
29     timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
30     timer_initpara.repetitioncounter = 0;
31     timer_init(TIMER4, &timer_initpara);
32 
33     /* TIMER1 channel3 configuration in PWM mode */
34     timer_ocintpara.outputstate  = TIMER_CCX_ENABLE;
35     timer_ocintpara.ocpolarity     = TIMER_OC_POLARITY_HIGH;
36     timer_channel_output_config(TIMER4, TIMER_CH_0, &timer_ocintpara);
37     timer_channel_output_config(TIMER4, TIMER_CH_1, &timer_ocintpara);
38 
39     timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_0, 0); //占空比 = TIMERx_CHxCV / TIMERx_CAR
40     timer_channel_output_mode_config(TIMER4, TIMER_CH_0, TIMER_OC_MODE_PWM0);
41     timer_channel_output_shadow_config(TIMER4, TIMER_CH_0, TIMER_OC_SHADOW_ENABLE);//TIMER_OC_SHADOW_ENABLE
42 
43     timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_1, 0); //占空比 = TIMERx_CHxCV / TIMERx_CAR
44     timer_channel_output_mode_config(TIMER4, TIMER_CH_1, TIMER_OC_MODE_PWM0);
45     timer_channel_output_shadow_config(TIMER4, TIMER_CH_1, TIMER_OC_SHADOW_ENABLE);//TIMER_OC_SHADOW_ENABLE
46 
47     timer_auto_reload_shadow_disable(TIMER4);
48 
49 ////RGB0--(Timer4_Ch0)--(DMA0_ch2_stream6)-pa0
50     dma_deinit(DMA0,DMA_CH2);
51 
52     /* initialize DMA single data mode */
53     dma_data_parameter.periph_addr    = (uint32_t)TIMER4_CCR0_Address;
54     dma_data_parameter.periph_inc    = DMA_PERIPH_INCREASE_DISABLE;
55     dma_data_parameter.memory0_addr = (uint32_t)LED_BYTE_Buffer;
56     dma_data_parameter.memory_inc    = DMA_MEMORY_INCREASE_ENABLE;
57     dma_data_parameter.periph_memory_width = DMA_PERIPH_WIDTH_16BIT;
58     dma_data_parameter.direction    = DMA_MEMORY_TO_PERIPH;
59     dma_data_parameter.number        = 42;
60     dma_data_parameter.priority     = DMA_PRIORITY_HIGH;  
61 
62     dma_single_data_mode_init(DMA0, DMA_CH2, &dma_data_parameter);    
63     dma_channel_subperipheral_select(DMA0, DMA_CH2, DMA_SUBPERI6);
64     dma_circulation_disable(DMA0, DMA_CH2);
65     timer_dma_enable(TIMER4,TIMER_DMA_CH0D);
66     dma_channel_disable(DMA0, DMA_CH2); 
67 
68 ////RGB1--(Timer4_Ch1)--(DMA0_ch4_stream6)-pa1
69     dma_deinit(DMA0,DMA_CH4);
70 
71     /* initialize DMA single data mode */
72     dma_data_parameter.periph_addr    = (uint32_t)TIMER4_CCR1_Address;
73     dma_data_parameter.periph_inc    = DMA_PERIPH_INCREASE_DISABLE;
74     dma_data_parameter.memory0_addr = (uint32_t)LED_BYTE_Buffer;
75     dma_data_parameter.memory_inc    = DMA_MEMORY_INCREASE_ENABLE;
76     dma_data_parameter.periph_memory_width = DMA_PERIPH_WIDTH_16BIT;
77     dma_data_parameter.direction    = DMA_MEMORY_TO_PERIPH;
78     dma_data_parameter.number        = 42;
79     dma_data_parameter.priority     = DMA_PRIORITY_HIGH;  
80 
81     dma_single_data_mode_init(DMA0, DMA_CH4, &dma_data_parameter);    
82     dma_channel_subperipheral_select(DMA0, DMA_CH4, DMA_SUBPERI6);
83     dma_circulation_disable(DMA0, DMA_CH4);
84     timer_dma_enable(TIMER4,TIMER_DMA_CH1D);
85     dma_channel_disable(DMA0, DMA_CH4); 
86 
87     timer_disable(TIMER4);
88 
89 }
 1 /****************************************************************************
 2 *函数名:Timer2_init
 3 *输  入:无
 4 *输  出:无
 5 *功  能:TIM2时钟初始化函数,以及DMA初始化函数:PWM,单色LED控制
 6 *作  者:xj
 7 ****************************************************************************/
 8 void Timer2_init(void)
 9 {    
10     /* 结构体定义 */
11     dma_single_data_parameter_struct dma_data_parameter;
12     timer_oc_parameter_struct timer_ocintpara;
13     timer_parameter_struct timer_initpara;
14 
15     rcu_periph_clock_enable(RCU_GPIOB);
16     rcu_periph_clock_enable(RCU_DMA0);
17     rcu_periph_clock_enable(RCU_TIMER2);
18 
19     gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_1);//GPIO_MODE_OUTPUT//GPIO_MODE_AF
20     gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_1);
21     gpio_af_set(GPIOB, GPIO_AF_2, GPIO_PIN_1);
22 
23     /*
24         备注:从STM32F4的内部时钟树可知,当APB1和APB2分频数为1的时候,
25         TIM1、TIM8~TIM11的时钟为APB2的时钟,TIM2~TIM7、TIM12~TIM14的时钟为APB1的时钟;
26         而如果APB1和APB2分频数不为1,那么TIM1、TIM8~TIM11的时钟为APB2的时钟的两倍,
27         TIMER1~TIM7、TIM12~TIM14的时钟为APB1的时钟的两倍。
28         故:APB1:42MHz 对应的TIM 时钟翻倍;APB2:84MHz,同理
29         */
30 
31     /* TIMER2 configuration */    
32     timer_initpara.prescaler         = 9;            //时钟预分频数 (200)M/10/25 = 0.8mHz = 800KHz
33     timer_initpara.alignedmode         = TIMER_COUNTER_EDGE;        //向上&向下都是边沿对齐
34     timer_initpara.counterdirection  = TIMER_COUNTER_UP;
35     timer_initpara.period             = 24;                    /* 自动重装载寄存器周期的值(计数值) */
36     timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
37     timer_initpara.repetitioncounter = 0;
38     timer_init(TIMER2, &timer_initpara);
39 
40     /* TIMER1 channel3 configuration in PWM mode */
41     timer_ocintpara.outputstate  = TIMER_CCX_ENABLE;
42     timer_ocintpara.ocpolarity   = TIMER_OC_POLARITY_HIGH;
43     timer_channel_output_config(TIMER2, TIMER_CH_3, &timer_ocintpara);
44 
45     timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_3, 0);    //占空比 = TIMERx_CHxCV / TIMERx_CAR
46     timer_channel_output_mode_config(TIMER2, TIMER_CH_3, TIMER_OC_MODE_PWM0);
47     timer_channel_output_shadow_config(TIMER2, TIMER_CH_3, TIMER_OC_SHADOW_ENABLE);//TIMER_OC_SHADOW_ENABLE
48 
49     timer_auto_reload_shadow_disable(TIMER2);
50 
51     ////RGB2-(Timer2_Ch3)-(DMA0_ch2_stream5)(gd的通道和流与ST的相反)
52     dma_deinit(DMA0,DMA_CH2);
53     
54     /* initialize DMA single data mode */
55     dma_data_parameter.periph_addr    = (uint32_t)TIMER2_CCR3_Address;
56     dma_data_parameter.periph_inc    = DMA_PERIPH_INCREASE_DISABLE;
57     dma_data_parameter.memory0_addr    = (uint32_t)LED_BYTE_Buffer;
58     dma_data_parameter.memory_inc    = DMA_MEMORY_INCREASE_ENABLE;
59     dma_data_parameter.periph_memory_width = DMA_PERIPH_WIDTH_16BIT;
60     dma_data_parameter.direction    = DMA_MEMORY_TO_PERIPH;
61     dma_data_parameter.number        = 42;
62     dma_data_parameter.priority     = DMA_PRIORITY_HIGH;  
63 
64     dma_single_data_mode_init(DMA0, DMA_CH2, &dma_data_parameter);  
65     dma_channel_subperipheral_select(DMA0, DMA_CH2, DMA_SUBPERI5);
66     dma_circulation_disable(DMA0, DMA_CH2);
67     timer_dma_enable(TIMER2,TIMER_DMA_UPD);
68     dma_channel_disable(DMA0, DMA_CH2);        
69     
70     timer_disable(TIMER2);
71 }

RGB的驱动代码如下:

 1 void KeyLampProc(void)
 2 { 
 3     memset(RGB1_buf,    0xFF, sizeof(RGB1_buf));
 4     memset(RGB2_buf,    0xFF, sizeof(RGB2_buf));
 5     memset(RGB3_buf,    0xFF, sizeof(RGB3_buf));    
 7 
 8     WS2812_send(RGB1_buf, 17,RGB1); 
 9     
10     WS2812_send(RGB2_buf, 10,RGB2);
11     
12     WS2812_send(RGB3_buf, 17,RGB3);    //长度需+1,否则最后一个filter2不亮 
13 
14 }
  1 void WS2812_send( uint8_t (*color)[ 3 ], uint16_t len,uint8_t PWM_CHANNEL )
  2 {
  3     uint8_t  j;
  4     uint8_t led = 0;
  5     uint16_t memaddr= 0;
  6     uint16_t buffersize = 0;
  7     buffersize = ( len * 24 ) + 42; // number of bytes needed is #LEDs * 24 bytes + 42 trailing bytes
  8 
  9     while ( len )
 10     {
 11     // GREEN data
 12       for ( j = 0; j < 8; j++ )         
 13       {
 14         if ( ( color[ led ][ 1 ] << j ) & 0x80 ) // data sent MSB first, j = 0 is MSB j = 7 is LSB
 15         {
 16             if(memaddr<500)
 17             {
 18                 LED_BYTE_Buffer[ memaddr ] = 17;  // compare value for logical 1
 19             }
 20             if((memaddr ==1) && (PWM_CHANNEL != 1 && PWM_CHANNEL != 5))    //timer3不会丢失波形,timer2和timer0会丢失第2bit的波形,所以此处要冗余一次bit2
 21             {
 22                 LED_BYTE_Buffer[ ++memaddr ] = 17;
 23             }
 24             else if((memaddr ==DecrsNm) && (PWM_CHANNEL == 1))
 25             {
 26                 LED_BYTE_Buffer[ ++memaddr ] = 17;
 27             }
 28           }
 29         else
 30         {
 31             if(memaddr<500)
 32             {
 33                 LED_BYTE_Buffer[ memaddr ] = 9; // compare value for logical 0 9
 34             }
 35             
 36             if((memaddr ==1) && (PWM_CHANNEL != 1&& PWM_CHANNEL != 5))    //timer3不会丢失波形,timer2和timer0会丢失第2bit的波形,所以此处要冗余一次bit2
 37             {
 38                 LED_BYTE_Buffer[ ++memaddr ] = 9;
 39             }
 40             else if((memaddr ==DecrsNm) && (PWM_CHANNEL == 1))
 41             {
 42                 LED_BYTE_Buffer[ ++memaddr ] = 9;
 43             }
 44         }
 45             memaddr++;
 46       }
 47     //RED data
 48     for ( j = 0; j < 8; j++ )
 49     {
 50         if ( ( color[ led ][ 0 ] << j ) & 0x80 ) // data sent MSB first, j = 0 is MSB j = 7 is LSB
 51         {
 52             if(memaddr<500)
 53             {
 54                 LED_BYTE_Buffer[ memaddr ] = 17;  // compare value for logical 1
 55             }
 56         }
 57         else
 58         {
 59             if(memaddr<500)
 60             {
 61                 LED_BYTE_Buffer[ memaddr ] = 9; // compare value for logical 0
 62             }
 63         }
 64         memaddr++;
 65     }
 66        
 67     // BLUE data
 68     for ( j = 0; j < 8; j++ )         
 69     {
 70       if ( ( color[ led ][ 2 ] << j ) & 0x80 ) // data sent MSB first, j = 0 is MSB j = 7 is LSB
 71       {
 72           if(memaddr<500)
 73           {
 74               LED_BYTE_Buffer[ memaddr ] = 17;  // compare value for logical 1
 75           }
 76       }
 77       else
 78       {
 79           if(memaddr<500)
 80           {
 81               LED_BYTE_Buffer[ memaddr ] = 9; // compare value for logical 0
 82           }
 83       }
 84       memaddr++;
 85     }
 86      led++;
 87      len--;
 88     }
 89 
 90     if(PWM_CHANNEL==1)  timer_channel_output_pulse_value_config(TIMER4,TIMER_CH_0,0);//此设置可以让TIM对应channel的输出为高电平,
 91 
 92     if(PWM_CHANNEL==2)  timer_channel_output_pulse_value_config(TIMER4,TIMER_CH_1,0);//此设置可以让TIM 预想的情况下,输出为高电平而不需要把TIM关掉
 93 
 94     if(PWM_CHANNEL==3)  timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_3,0);//此设置可以让TIM 预想的情况下,输出为高电平而不需要把TIM关掉    
 95 
 96     while ( memaddr < buffersize )
 97     {
 98         if(memaddr<500)
 99         {       
100             LED_BYTE_Buffer[ memaddr ] = 0;       
101         }
102         memaddr++;
103     }
104  
105        
106     if(PWM_CHANNEL==1) //TIM4_CH0
107     { 
108      //   Timer4CH0_init_DMA();
109         
110           dma_transfer_number_config(DMA0, DMA_CH2, buffersize);
111        
112         dma_channel_enable(DMA0, DMA_CH2);        
113 
114         timer_enable(TIMER4);
115         
116         while ( !dma_flag_get( DMA0, DMA_CH2,DMA_FLAG_FTF ) ) //DMA channl2的中断
117         ;   // wait until transfer complete
118 
119         dma_channel_disable(DMA0, DMA_CH2); 
120         
121         dma_flag_clear( DMA0, DMA_CH2,DMA_FLAG_FTF);
122 
123         timer_disable(TIMER4);
124     }
125     if(PWM_CHANNEL==2) //TIM4CH1
126     { 
127           dma_transfer_number_config(DMA0, DMA_CH4, buffersize);
128        
129         dma_channel_enable(DMA0, DMA_CH4);
130 
131         timer_enable(TIMER4);
132         
133         while ( !dma_flag_get( DMA0, DMA_CH4,DMA_FLAG_FTF ) ) //DMA channl4中断
134         ;   // wait until transfer complete
135 
136         dma_channel_disable(DMA0, DMA_CH4); 
137         
138         dma_flag_clear( DMA0, DMA_CH4,DMA_FLAG_FTF);
139 
140         timer_disable(TIMER4);
141     }
142     if(PWM_CHANNEL==3) //TIM2_CH3
143    {
144     //       Tim2CH3_init_DMA();
145     
146         dma_transfer_number_config(DMA0, DMA_CH2, buffersize);
147        
148         dma_channel_enable(DMA0, DMA_CH2);
149 
150         timer_enable(TIMER2); 
151         
152         while ( !dma_flag_get( DMA0, DMA_CH2,DMA_FLAG_FTF ) ) //DMA channl2的中断
153         ;   // wait until transfer complete         
154         
155         dma_channel_disable(DMA0, DMA_CH2); 
156         
157         dma_flag_clear( DMA0, DMA_CH2,DMA_FLAG_FTF );
158 
159         timer_disable(TIMER2);
160     }
161 }

然后运行的时候发现RGB2和RGB3都能正常执行,而RGB1却在while处出不来。

代码都没问题,而根据RGB2和RGB3都能正常执行,推测是RGB1的配置出了问题。翻看下F407的代码,发现有这段代码

   然后再看下450的DMA通道配置信息:

  发现TIMER4_CH0 和 TIMER2_CH3共用了DMA0_CH2通道。而我的代码是先运行的timer4init(),后运行的timer2init(),这样timer2就把timer4的DMA通道配置给覆盖了。所以解决方案也很简单,照着上面配置下就可以了。

 1 void Tim2CH3_init_DMA(void)
 2 {
 3     dma_single_data_parameter_struct dma_data_parameter;
 4     
 5 ////RGB2-Timer2_Ch0--DMA0_ch4_stream5
 6     dma_deinit(DMA0,DMA_CH2);
 7     
 8     /* initialize DMA single data mode */
 9     dma_data_parameter.periph_addr    = (uint32_t)TIMER2_CCR3_Address;
10     dma_data_parameter.periph_inc    = DMA_PERIPH_INCREASE_DISABLE;
11     dma_data_parameter.memory0_addr = (uint32_t)LED_BYTE_Buffer;
12     dma_data_parameter.memory_inc    = DMA_MEMORY_INCREASE_ENABLE;
13     dma_data_parameter.periph_memory_width = DMA_PERIPH_WIDTH_16BIT;
14     dma_data_parameter.direction    = DMA_MEMORY_TO_PERIPH;
15     dma_data_parameter.number        = 42;
16     dma_data_parameter.priority     = DMA_PRIORITY_HIGH; 
17     
18     dma_single_data_mode_init(DMA0, DMA_CH2, &dma_data_parameter);
19     dma_channel_subperipheral_select(DMA0, DMA_CH2, DMA_SUBPERI5);
20     dma_circulation_disable(DMA0, DMA_CH2);
21 }
22 
23 void Timer4CH0_init_DMA(void)
24 {
25     dma_single_data_parameter_struct dma_data_parameter;
26     
27 ////RGB2-Timer2_Ch0--DMA0_ch4_stream5
28     dma_deinit(DMA0,DMA_CH2);
29     
30     /* initialize DMA single data mode */
31     dma_data_parameter.periph_addr    = (uint32_t)TIMER4_CCR0_Address;
32     dma_data_parameter.periph_inc    = DMA_PERIPH_INCREASE_DISABLE;
33     dma_data_parameter.memory0_addr = (uint32_t)LED_BYTE_Buffer;
34     dma_data_parameter.memory_inc    = DMA_MEMORY_INCREASE_ENABLE;
35     dma_data_parameter.periph_memory_width = DMA_PERIPH_WIDTH_16BIT;
36     dma_data_parameter.direction    = DMA_MEMORY_TO_PERIPH;
37     dma_data_parameter.number        = 42;
38     dma_data_parameter.priority     = DMA_PRIORITY_HIGH; 
39     
40     dma_single_data_mode_init(DMA0, DMA_CH2, &dma_data_parameter);
41     dma_channel_subperipheral_select(DMA0, DMA_CH2, DMA_SUBPERI6);
42     dma_circulation_disable(DMA0, DMA_CH2);
43 }

然后在每次使用DMA的时候重新配置下DMA_CH2即可。

  这样就能成功的运行了。但是RGB灯还是不亮。

===============↓↓↓↓2021-12-6更新↓↓↓=================

 将TIMRT4作为定时器,在其中断中翻转IO模拟PWM,是可以正常输出的

 1 /*!**************************************************************************************************
 2 \brief        初始化
 3 ****************************************************************************************************/
 4 void SystemTimer_Init(void)
 5 {
 6     rcu_periph_clock_enable(RCU_GPIOA);    
 7     rcu_periph_clock_enable(RCU_TIMER4);
 8 
 9     timer4_IrqPriority_Init();
10     
11     /* 复位TIMER4定时器,并选择内部时钟200M */
12     timer_deinit(TIMER4);
13 //    timer_internal_clock_config(TIMER4);
14 
15     gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_PIN_1);
16     gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_1);
17 
18     /* TIMER4 configuration */
19     timer_parameter_struct timer_initpara;
20     timer_initpara.prescaler         = (4);//200/200/1000
21     timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;//根据prescaler,clockdivision最终该定时器时钟频率为1M
22     timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;//触发方式设置根据边沿决定
23     timer_initpara.counterdirection  = TIMER_COUNTER_UP;//设置为上升沿触发
24     timer_initpara.period            = 49;//设置0.1ms定时
25     timer_initpara.repetitioncounter = 0;
26     timer_init(TIMER4, &timer_initpara);
27 
28     /* TIMER4 enable */
29     timer_enable(TIMER4);
30     
31     timer_interrupt_enable(TIMER4,TIMER_INT_UP);
32 }

然后关闭Timer4其中一路,只实验一路输出,减少变量的干扰,但是还是不行

 1 /*!**************************************************************************************************
 2 \brief        ch0 - rgb0 - pa0(af2)
 3             ch1 - rgb1 - pa1(af2)
 4 ****************************************************************************************************/
 5 void Timer4_init(void)
 6 {
 7     rcu_periph_clock_enable(RCU_TIMER4);
 8     rcu_periph_clock_enable(RCU_GPIOA);
 9     rcu_periph_clock_enable(RCU_GPIOC);
10     rcu_periph_clock_enable(RCU_DMA0);
11 
12     dma_single_data_parameter_struct dma_data_parameter;
13     timer_oc_parameter_struct timer_ocintpara;
14     timer_parameter_struct timer_initpara;
15 
16     //rgb_power
17     gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_PIN_14);
18     gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, GPIO_PIN_14);
19 
20     gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_0|GPIO_PIN_1);
21     gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0|GPIO_PIN_1);
22     gpio_af_set(GPIOA, GPIO_AF_2, GPIO_PIN_0|GPIO_PIN_1);
23 
24     /* TIMER4 configuration */
25     timer_initpara.prescaler         = 4;            //时钟预分频数 (100)M/10/25 = 0.8mHz = 800KHz
26     timer_initpara.alignedmode         = TIMER_COUNTER_EDGE;        //向上&向下都是边沿对齐
27     timer_initpara.counterdirection  = TIMER_COUNTER_UP;
28     timer_initpara.period             = 49;                    /* 自动重装载寄存器周期的值(计数值) */
29     timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
30     timer_initpara.repetitioncounter = 0;
31     timer_init(TIMER4, &timer_initpara);
32 
33     /* TIMER1 channel3 configuration in PWM mode */
34     timer_ocintpara.outputstate  = TIMER_CCX_ENABLE;
35     timer_ocintpara.outputnstate = TIMER_CCXN_DISABLE;
36     timer_ocintpara.ocpolarity     = TIMER_OC_POLARITY_HIGH;
37     timer_ocintpara.ocnpolarity  = TIMER_OCN_POLARITY_HIGH;
38     timer_ocintpara.ocidlestate  = TIMER_OC_IDLE_STATE_LOW;
39     timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;
40     timer_channel_output_config(TIMER4, TIMER_CH_0, &timer_ocintpara);
41 //    timer_channel_output_config(TIMER4, TIMER_CH_1, &timer_ocintpara);
42 
43     timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_0, 0); //占空比 = TIMERx_CHxCV / TIMERx_CAR
44     timer_channel_output_mode_config(TIMER4, TIMER_CH_0, TIMER_OC_MODE_PWM0);
45     timer_channel_output_shadow_config(TIMER4, TIMER_CH_0, TIMER_OC_SHADOW_DISABLE);//TIMER_OC_SHADOW_ENABLE
46 
47 //    timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_1, 0); //占空比 = TIMERx_CHxCV / TIMERx_CAR
48 //    timer_channel_output_mode_config(TIMER4, TIMER_CH_1, TIMER_OC_MODE_PWM0);
49 //    timer_channel_output_shadow_config(TIMER4, TIMER_CH_1, TIMER_OC_SHADOW_DISABLE);//TIMER_OC_SHADOW_ENABLE
50 
51     timer_primary_output_config(TIMER4,ENABLE);
52     timer_auto_reload_shadow_enable(TIMER4);
53 
54 ////RGB0--(Timer4_Ch0)--(DMA0_ch2_stream6)-pa0
55     dma_deinit(DMA0,DMA_CH2);
56 
57     /* initialize DMA single data mode */
58     dma_data_parameter.periph_addr    = (uint32_t)TIMER4_CCR0_Address;
59     dma_data_parameter.periph_inc    = DMA_PERIPH_INCREASE_DISABLE;
60     dma_data_parameter.memory0_addr = (uint32_t)LED_BYTE_Buffer;
61     dma_data_parameter.memory_inc    = DMA_MEMORY_INCREASE_ENABLE;
62     dma_data_parameter.periph_memory_width = DMA_PERIPH_WIDTH_16BIT;
63     dma_data_parameter.direction    = DMA_MEMORY_TO_PERIPH;
64     dma_data_parameter.number        = 42;
65     dma_data_parameter.priority     = DMA_PRIORITY_HIGH;  
66 
67     dma_single_data_mode_init(DMA0, DMA_CH2, &dma_data_parameter);    
68     dma_channel_subperipheral_select(DMA0, DMA_CH2, DMA_SUBPERI6);
69     dma_circulation_disable(DMA0, DMA_CH2);
70     timer_dma_enable(TIMER4,TIMER_DMA_CH0D);
71     dma_channel_disable(DMA0, DMA_CH2); 
72 
73 ////RGB1--(Timer4_Ch1)--(DMA0_ch4_stream6)-pa1
74 //    dma_deinit(DMA0,DMA_CH4);
75 //
76 //    /* initialize DMA single data mode */
77 //    dma_data_parameter.periph_addr    = (uint32_t)TIMER4_CCR1_Address;
78 //    dma_data_parameter.periph_inc    = DMA_PERIPH_INCREASE_DISABLE;
79 //    dma_data_parameter.memory0_addr = (uint32_t)LED_BYTE_Buffer;
80 //    dma_data_parameter.memory_inc    = DMA_MEMORY_INCREASE_ENABLE;
81 //    dma_data_parameter.periph_memory_width = DMA_PERIPH_WIDTH_16BIT;
82 //    dma_data_parameter.direction    = DMA_MEMORY_TO_PERIPH;
83 //    dma_data_parameter.number        = 42;
84 //    dma_data_parameter.priority     = DMA_PRIORITY_HIGH;  
85 //
86 //    dma_single_data_mode_init(DMA0, DMA_CH4, &dma_data_parameter);    
87 //    dma_channel_subperipheral_select(DMA0, DMA_CH4, DMA_SUBPERI6);
88 //    dma_circulation_disable(DMA0, DMA_CH4);
89 //    timer_dma_enable(TIMER4,TIMER_DMA_CH1D);
90 //    dma_channel_disable(DMA0, DMA_CH4); 
91 
92     timer_disable(TIMER4);
93 
94 }

其输出的波形如下:500Hz的不知道什么的波形

  由此推断,TIMER4没问题,问题应该出在DMA上。需要在DMA上做实验验证。

----------------------------2021-12-8-------------------------------------------------

经过原厂的手把手教学,今天终于找到了问题的所在!

首先原厂确认他们的芯片有一个问题,在DMA传输数据有0的时候,它会把后面的第1或者第2个数据丢失(类似往CCR里扔0,就会导致定时器重启,有个反应时间,所以会丢失后面的几个数据?)。这是一个大坑,不过这个坑我没踩到。

另外一个没注意到的地方(2坑)是定时器的比较寄存器有差异。

这个系列的芯片虽然定时器1234都属于L0组的通用定时器,我们一般会想当然的认为用法都一样。但是其实有很大的差异。下面图里能看到,1,4的CH1CV是个32位的寄存器

 

 而2,3的CHCV却是16位的寄存器。

 

 而这个跟我们配置的DMA的传输方式和传输的数据格式息息相关!

我们传输的数据是16位的数据

  而我们DMA的传输方式选择的也是16位

  这样的配置就导致我们把一个16位的数据传递给了32位的寄存器,按照不能正常运行的结果看,显然它是把16位的数据放在了比较寄存器的高16位了,那么这个比较值就是17<<16 = 1114112。

而我们定时器的自动重载值才是35,永远到不了比较值,那么输出的就是全是低电平了。

 因此需要把它们改成32位的即可。

定时器的DMA请求使能更新方式和其通道的关系

定时器的DMA请求使能方式有以下7种。

 

 一般我们是按照DMA外设请求表来填写。就像上面最开始的代码那样。

而timer 的TIMER_DMA_UPD更新方式跟具体的某个timer的通道没关系,它会启动所有通道的更新。而update更新方式,就可以避免上面说的那个大坑!

因此需要对上面的代码进行修改:

 

 timer4_ch0 采用update更新,使用DMA0_CH0;

 timer4_ch1 采用update更新,使用DMA0_CH6;

如此配置后,WS2811的RGB灯珠即可成功稳定的点亮。

而如果采用通道更新的话,灯珠就会乱闪,很明显就是他们说的数据丢失的问题。这也验证了我在做407的时候为什么固定第二个bit丢失数据的问题。

出了问题还是要找他们原厂的人,售后的人基本解决不了任何问题。

posted @ 2021-11-30 10:38  xjxcxjx  阅读(1052)  评论(0编辑  收藏  举报