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.下载验证