应该是搞定了,问题就是文档没有看仔细,TIMER1是32位的定时器,所以发送给TIMER1的数据要用32位的格式,同时初始化DMA的时候也得将外设地址宽度设置为32位,下面分享配置代码
[C] 纯文本查看 复制代码 #define TIMER1_CH0CV ((uint32_t)TIMER1 + 0x34)
uint32_t buffer[10] = {144, 81, 144, 81, 144, 81, 144, 81};
void gpio_config(void);
void timer_config(void);
void dma_config(void);
/*!
\brief configure the GPIO ports
\param[in] none
\param[out] none
\retval none
*/
void gpio_config(void)
{
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_AF);
/*configure PA0(TIMER1 CH0) as alternate function*/
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0);
}
/*!
\brief configure the DMA peripheral
\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 DMA0 channel4 */
dma_deinit(DMA0, DMA_CH4);
/* DMA channel4 initialize */
dma_init_struct.periph_addr = (uint32_t)TIMER1_CH0CV;
dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_init_struct.memory_addr = (uint32_t)buffer;
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_16BIT;
dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL;
dma_init_struct.number = 10;
dma_init_struct.priority = DMA_PRIORITY_HIGH;
dma_init(DMA0, DMA_CH4, &dma_init_struct);
dma_circulation_enable(DMA0, DMA_CH4);
/* enable DMA channel5 */
dma_channel_enable(DMA0, DMA_CH4);
}
/*!
\brief configure the TIMER peripheral
\param[in] none
\param[out] none
\retval none
*/
void timer_config(void)
{
timer_oc_parameter_struct timer_ocintpara;
timer_parameter_struct timer_initpara;
rcu_periph_clock_enable(RCU_TIMER1);
timer_deinit(TIMER1);
/* TIMER1 configuration */
timer_initpara.prescaler = 1 - 1;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 225 - 1;
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter = 0;
timer_init(TIMER1, &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(TIMER1, TIMER_CH_0, &timer_ocintpara);
timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_0, 0);
timer_channel_output_mode_config(TIMER1, TIMER_CH_0, TIMER_OC_MODE_PWM0);
timer_channel_output_shadow_config(TIMER1, TIMER_CH_0, TIMER_OC_SHADOW_DISABLE);
/* TIMER1 primary output enable */
timer_primary_output_config(TIMER1, ENABLE);
/* channel DMA request source selection */
timer_channel_dma_request_source_select(TIMER1, TIMER_DMAREQUEST_CHANNELEVENT);
/* configure the TIMER DMA transfer */
timer_dma_transfer_config(TIMER1, TIMER_DMACFG_DMATA_CH0CV, TIMER_DMACFG_DMATC_1TRANSFER);
/* TIMER1 update DMA request enable */
timer_dma_enable(TIMER1, TIMER_DMA_CH0D);
/* auto-reload preload enable */
timer_auto_reload_shadow_enable(TIMER1);
/* TIMER1 counter enable */
timer_enable(TIMER1);
}
/*!
\brief main function
\param[in] none
\param[out] none
\retval none
*/
int main(void)
{
gpio_config();
dma_config();
timer_config();
while (1)
;
}
在配置中需要注意的是传给DMA0的数组元素要是32位的,并且使 dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_32BIT;,最后将timer_channel_dma_request_source_select设置为TIMER_DMAREQUEST_CHANNELEVENT,将timer_dma_enable设置为TIMER_DMA_CH0D,以将DMA0_CH4绑定位TIMER1_CH0的输出,就可以输出设置的波形了。
在我的例子里,芯片工作在180Mhz,TIMER1设置为1分频,所以TIMER1的时钟是也是180Mhz,而WS2812需要的是800khz的频率,所以将计数周期设置为225即可满足180M/225=800K,然后根据WS2812的需求,高电平占空设置为225*(800/1250)=144,低电平占空设置为225*(450/1250)=81即可得到驱动WS2812所需要bit。
|