基于GD32F3RCT6芯片通过PWM与DMA结合硬件控制呼吸灯 用C语言写一份代码
时间: 2023-05-23 11:07:23 浏览: 136
这里是ChitGPT,以下是基于GD32F3RCT6芯片通过PWM与DMA结合硬件控制呼吸灯的C语言代码:
```c
#include "gd32f3x0.h"
#define PWM_FREQ_HZ 10000 // 设定PWM输出频率为10kHz
#define PWM_PERIOD (SystemCoreClock / PWM_FREQ_HZ)
#define LED_GPIO_PORT GPIOD
#define LED_GPIO_PIN GPIO_PIN_2
#define PWM_TIMER TIMER0
#define PWM_TIMER_CHANNEL TIMER_CH_2
uint16_t pwm_duty = 0; // 设定占空比为50%
void pwm_init()
{
// 打开PWM时钟
rcu_periph_clock_enable(RCU_TIMER0);
// 配置PWM定时器
timer_auto_reload_value_config(PWM_TIMER, PWM_PERIOD - 1);
timer_deadtime_config(PWM_TIMER, 0, 0);
timer_output_idle_state_config(PWM_TIMER, TIMER_OC_MODE_PWM1, TIMER_OC_STATE_DISABLE, TIMER_OC_NSTATE_DISABLE);
timer_output_shadow_config(PWM_TIMER, TIMER_OC_MODE_PWM1, TIMER_OC_SHADOW_ENABLE);
timer_primary_output_config(PWM_TIMER, TIMER_OC_MODE_PWM1, TIMER_OC_POLARITY_HIGH);
// 配置PWM通道
timer_channel_output_pulse_value_config(PWM_TIMER, PWM_TIMER_CHANNEL, 0);
timer_channel_output_mode_config(PWM_TIMER, PWM_TIMER_CHANNEL, TIMER_OC_MODE_PWM1);
timer_channel_output_shadow_enable(PWM_TIMER, PWM_TIMER_CHANNEL);
// 启动PWM定时器
timer_enable(PWM_TIMER);
}
void dma_init()
{
// 打开DMA时钟
rcu_periph_clock_enable(RCU_DMA);
// 配置DMA通道
dma_deinit(DMA_CH3);
dma_single_data_parameter_struct dma_init_struct;
dma_init_struct.periph_addr = (uint32_t)&TIMER0_CCR2(PWM_TIMER);
dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_init_struct.memory0_addr = (uint32_t)&pwm_duty;
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_init_struct.direction = DMA_MEMORY_TO_PERIPH;
dma_init_struct.number = 1;
dma_init_struct.periph_data_width = DMA_PERIPH_DATA_SIZE_HALFWORD;
dma_init_struct.memory_data_width = DMA_MEMORY_DATA_SIZE_HALFWORD;
dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
dma_init(DMA_CH3, dma_init_struct);
// 启动DMA传输
dma_channel_enable(DMA_CH3);
}
void gpio_init()
{
// 打开 GPIO 时钟
rcu_periph_clock_enable(RCU_GPIOD);
gpio_init_struct gpio_init_struct;
gpio_init_struct.mode = GPIO_MODE_AF;
gpio_init_struct.speed = GPIO_OSPEED_50MHZ;
gpio_init_struct.pull = GPIO_NOPULL;
gpio_init_struct.pin = LED_GPIO_PIN;
gpio_init_struct.af = GPIO_AF_1; // PWM映射到AF1
gpio_init(LED_GPIO_PORT, &gpio_init_struct);
}
int main(void)
{
pwm_init();
dma_init();
gpio_init();
while(1)
{
for(int i=0; i<100; i++)
{
pwm_duty = (uint16_t)(PWM_PERIOD * i / 100); // 呼吸灯前半周期,占空比线性增加
while(dma_flag_get(DMA_CH3, DMA_FLAG_FTF)==RESET); // 等待DMA传输完成
dma_flag_clear(DMA_CH3, DMA_FLAG_FTF);
}
for(int i=99; i>=0; i--)
{
pwm_duty = (uint16_t)(PWM_PERIOD * i / 100); // 呼吸灯后半周期,占空比线性减少
while(dma_flag_get(DMA_CH3, DMA_FLAG_FTF)==RESET); // 等待DMA传输完成
dma_flag_clear(DMA_CH3, DMA_FLAG_FTF);
}
}
return 0;
}
```
在以上代码中,我们首先定义了呼吸灯使用的PWM频率和占空比变量。然后,在`pwm_init()`函数中对PWM输出定时器进行了配置,使用了PWM1输出模式,并且开启了影子传输功能。在`dma_init()`函数中对DMA进行了初始化,并将PWM输出定时器CCR加入DMA传输队列中。最后,在`gpio_init()`函数中对呼吸灯使用的GPIO进行了初始化。在主函数中,我们使用一个for循环和if判断,实现呼吸灯流动的效果。
以上代码仅为参考,具体实现方式可能因硬件配置和应用场景而异,请根据实际需求进行调整。
阅读全文