1. 简介
使用定时器1 在PB3引脚上输出频率100K的PWM波,然后使用ADC0 的通道1采集输入的电压型号来改变定时器1PWM的占空比。
2. 时钟分析
- Cortex-M4 时钟最高200M
- APB2总线 时钟最高100M
- APB1总线 时钟最高50M
ADC时钟由APB2时钟经2、4、6、8分频或由AHB时钟经5、6、10、20分频获得,它们是通过
设置ADC\\\\\_SYNCCTL寄存器的ADCCK位来选择。
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了
/*! \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.下载验证