我只是个野指针 · 2022年12月04日 · 江苏

【GD32F427开发板试用】 ADC改变定时器1 PWM占空比

1. 简介

使用定时器1 在PB3引脚上输出频率100K的PWM波,然后使用ADC0 的通道1采集输入的电压型号来改变定时器1PWM的占空比。

2. 时钟分析

 title=

  • Cortex-M4                 时钟最高200M
  • APB2总线                 时钟最高100M
  • APB1总线                 时钟最高50M

ADC时钟由APB2时钟经2、4、6、8分频或由AHB时钟经5、6、10、20分频获得,它们是通过
设置ADC\\\\\_SYNCCTL寄存器的ADCCK位来选择。
                                title=
      ADC时钟最高40MHz
      TIMER时钟由AHB时钟分频获得,它的频率可以等于CK\\\\\_APBx、CK\\\\\_APBx的两倍或CK\\\\\_APBx的四倍。
      所以定时器时钟最高200M

3.串口重定向

//printf配置 初始化USART0 GPIOA15(Tx) GPIOA10(Rx)
void printf\\_config(void)
{
/* enable GPIO clock */
rcu\\_periph\\_clock\\_enable(RCU\\_GPIOA);

/* enable USART clock */
rcu\\_periph\\_clock\\_enable(RCU\\_USART0);

/* configure the USART0 TX pin and USART0 RX pin */
gpio\\_af\\_set(GPIOA, GPIO\\_AF\\_7, GPIO\\_PIN\\_15);
gpio\\_af\\_set(GPIOA, GPIO\\_AF\\_7, GPIO\\_PIN\\_10);

/* configure USART0 TX as alternate function push-pull */
gpio\\_mode\\_set(GPIOA, GPIO\\_MODE\\_AF, GPIO\\_PUPD\\_PULLUP, GPIO\\_PIN\\_15);
gpio\\_output\\_options\\_set(GPIOA, GPIO\\_OTYPE\\_PP, GPIO\\_OSPEED\\_50MHZ, GPIO\\_PIN\\_15);

/* configure USART0 RX as alternate function push-pull */
gpio\\_mode\\_set(GPIOA, GPIO\\_MODE\\_AF, GPIO\\_PUPD\\_PULLUP, GPIO\\_PIN\\_10);
gpio\\_output\\_options\\_set(GPIOA, GPIO\\_OTYPE\\_PP, GPIO\\_OSPEED\\_50MHZ, GPIO\\_PIN\\_10);

/* USART configure */
usart\\_deinit(USART0);
usart\\_baudrate\\_set(USART0, 115200U);
usart\\_receive\\_config(USART0, USART\\_RECEIVE\\_ENABLE);
usart\\_transmit\\_config(USART0, USART\\_TRANSMIT\\_ENABLE);
usart\\_enable(USART0);
}

/* 将C库的printf函数重定目标为USART */
int fputc(int ch, FILE *f)
{
usart\_data\_transmit(USART0, (uint8\_t)ch);
while(RESET == usart\_flag\_get(USART0, USART\_FLAG\_TBE));
return ch;
}

4.初始化定时器 配置PWM

设置PWM频率为100K,即设置周期计数2000
注意 计数器的分频值 = PSC+1 分频值不能设置为1 否则时钟频率则为100M了
 title=
/*!
\brief      configure the TIMER peripheral
\param[in]  none
\param[out] none
\retval     none
*/
void timer_pwm_config(void)
{

timer_oc_parameter_struct timer_ocintpara;
timer_parameter_struct timer_initpara;

/*将PB3 (TIMER1 CH1)配置为备用功能*/
rcu_periph_clock_enable(RCU_GPIOB);

gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_3);

gpio_af_set(GPIOB, GPIO_AF_1, GPIO_PIN_3);

rcu_periph_clock_enable(RCU_TIMER1);
rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);

timer_deinit(TIMER1);

/* TIMER1 configuration */
timer_initpara.prescaler         = 0;
timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection  = TIMER_COUNTER_UP;
timer_initpara.period            = 1999;
timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter = 0;
timer_init(TIMER1,&timer_initpara);

/* CH1 configuration in PWM mode */
timer_ocintpara.ocpolarity  = TIMER_OC_POLARITY_HIGH;
timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
timer_ocintpara.ocnpolarity  = TIMER_OCN_POLARITY_HIGH;
timer_ocintpara.outputnstate = TIMER_CCXN_DISABLE;
timer_ocintpara.ocidlestate  = TIMER_OC_IDLE_STATE_LOW;
timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;

timer_channel_output_config(TIMER1,TIMER_CH_1,&timer_ocintpara);

/* PWM模式1下的CH1配置 */
timer_channel_output_pulse_value_config(TIMER1,TIMER_CH_1,249);
timer_channel_output_mode_config(TIMER1,TIMER_CH_1,TIMER_OC_MODE_PWM0);
timer_channel_output_shadow_config(TIMER1,TIMER_CH_1,TIMER_OC_SHADOW_DISABLE);

/* auto-reload preload enable */
timer_auto_reload_shadow_enable(TIMER1);
/* auto-reload preload enable */
timer_enable(TIMER1);
}

5. 配置ADC

void adc_config(void)
{
/* enable GPIOA clock */
rcu_periph_clock_enable(RCU_GPIOA);
/* enable ADC clock */
rcu_periph_clock_enable(RCU_ADC0);
/* config ADC clock */
adc_clock_config(ADC_ADCCK_PCLK2_DIV8);

/* config the GPIO as analog mode */
gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_1);

adc_deinit();
adc_sync_mode_config(ADC_SYNC_MODE_INDEPENDENT);
adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, DISABLE);
adc_special_function_config(ADC0, ADC_SCAN_MODE, DISABLE);                                 //启用或禁用ADC特殊转换模式功能:禁用
adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);                                      //ADC数据对其:   右
adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, 1U);                                  //ADC外部触发分频:1

adc_external_trigger_source_config(ADC0, ADC_REGULAR_CHANNEL, ADC_EXTTRIG_REGULAR_T0_CH0); //配置ADC外部触发源:TIMER0 CH0事件
adc_external_trigger_config(ADC0, ADC_REGULAR_CHANNEL, EXTERNAL_TRIGGER_DISABLE);          //禁用外部触发器

adc_enable(ADC0);                         //启用ADC接口
delay_1ms(1U);
adc_calibration_enable(ADC0);             //ADC校准
}

6.主函数

int main(void)
{
unsigned int adc_voltage_value = 0;
unsigned int duty_cycle_value  = 0;
/* configure systick */
systick_config();
printf_config();

timer_pwm_config();
adc_config();

while(1) {

adc_voltage_value = adc_channel_sample(ADC_CHANNEL_1);
duty_cycle_value = adc_voltage_value*2000 /4095;
timer_channel_output_pulse_value_config(TIMER1,TIMER_CH_1,duty_cycle_value);
printf("adc_channel_sample = %d \r\n",adc_voltage_value);
printf("duty_cycle_value   = %d \r\n",duty_cycle_value);
delay_1ms(100);

}
}

7.下载验证

 title=
 title=

 title=

 title=

推荐阅读
关注数
10693
内容数
187
中国高性能通用微控制器领域的领跑者兆易创新GD系列芯片技术专栏。
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息