ARM技术论坛
直播中

马祥

7年用户 774经验值
私信 关注
[经验]

使用ADC来改变定时器1PWM的占空比

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=

原作者:我只是个野指针

更多回帖

发帖
×
20
完善资料,
赚取积分