GD32H7系列是兆易创新推出的新一代高性能MCU,基于ARM cortex-M7内核,主频高达600M。在使用该产品的时候,我们发现有几个引脚:PA0_C,PA1_C,PC2_C,PC3_C不太一样,这些引脚和PA0,PA1,PC2,PC3有什么区别和联系呢,下面我们来测试一下。
先看看用户手册GPIO章节关于ADC模拟配置的描述,文中说PA0_C,PA1_C,PC2_C,PC3_C是直接连到ADC的模拟输入端,Pxy_C和Pxy之间是通过模拟开关直接相连,开关的默认状态取决于SYSCFG_PMCFG寄存器中PxySWON位的复位值,那复位值究竟是0还是1呢。
根据手册上对于PxySWON位的描述,0是关闭模拟开关,1是打开模拟开关(引脚断开),因为开发板上有PC2_C引脚,不妨以PC2和PC2_C来测试较为方便。
先进行程序设计,参考GD样例程序ADC0_TIMER_trigger_inserted_channel,这个样例程序和我们要测试的功能比较接近,稍加改动即可。两个通道ADC2_IN12(PC2), ADC2_IN0(PC2_C),ADC注入组长度改为2,timer1比较事件触发ADC转换,ADC中断服务程序中读取转换结果。
1.时钟配置
void rcu_config(void)
{
/* enable GPIOC clock */
rcu_periph_clock_enable(RCU_GPIOC);
/* enable ADC clock */
rcu_periph_clock_enable(RCU_ADC2);
/* enable trigsel clock */
rcu_periph_clock_enable(RCU_TRIGSEL);
/* enable timer1 clock */
rcu_periph_clock_enable(RCU_TIMER1);
rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);
}
2. GPIO 初始化,只配置PC2即可,PC2_C不需要进行模式配置。
void gpio_config(void)
{
gpio_mode_set(GPIOC, GPIO_MODE_ANALOG, GPIO_PUPD_NONE,GPIO_PIN_2);
}
3. 定时器配置为5KHz,占空比为40%的PWM波,上升沿触发ADC转换
void timer_config(void)
{
timer_oc_parameter_struct timer_ocintpara;
timer_parameter_struct timer_initpara;
/* TIMER1 configuration */
timer_initpara.prescaler = 59999;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = 9999;
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter = 0;
timer_init(TIMER1, &timer_initpara);
/* CH0 configuration in PWM mode1 */
timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
timer_channel_output_config(TIMER1, TIMER_CH_1, &timer_ocintpara);
timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1, 3999);
timer_channel_output_mode_config(TIMER1, TIMER_CH_1, TIMER_OC_MODE_PWM1);
timer_channel_output_shadow_config(TIMER1, TIMER_CH_1, TIMER_OC_SHADOW_DISABLE);
}
4. ADC2配置
void adc_config(void)
{
/* reset ADC */
adc_deinit(ADC2);
/* ADC clock config */
adc_clock_config(ADC2, ADC_CLK_SYNC_HCLK_DIV6);
/* ADC contineous function enable */
adc_special_function_config(ADC2, ADC_CONTINUOUS_MODE, DISABLE);
/* ADC scan mode enable */
adc_special_function_config(ADC2, ADC_SCAN_MODE, ENABLE);
/* ADC resolution config */
adc_resolution_config(ADC2, ADC_RESOLUTION_12B);
/* ADC data alignment config */
adc_data_alignment_config(ADC2, ADC_DATAALIGN_RIGHT);
/* ADC channel length config */
adc_channel_length_config(ADC2, ADC_INSERTED_CHANNEL, 2);
adc_inserted_channel_config(ADC2, 0, ADC_CHANNEL_0, 240);
adc_inserted_channel_config(ADC2, 1, ADC_CHANNEL_12, 240);
/* ADC trigger config */
adc_external_trigger_config(ADC2, ADC_INSERTED_CHANNEL, EXTERNAL_TRIGGER_RISING);
/* clear the ADC flag */
adc_interrupt_flag_clear(ADC2, ADC_INT_FLAG_EOC);
adc_interrupt_flag_clear(ADC2, ADC_INT_FLAG_EOIC);
/* enable ADC interrupt */
adc_interrupt_enable(ADC2, ADC_INT_EOIC);
/* enable ADC interface */
adc_enable(ADC2);
/* wait for ADC stability */
delay_1ms(1);
/* ADC calibration mode config */
adc_calibration_mode_config(ADC2, ADC_CALIBRATION_OFFSET_MISMATCH);
/* ADC calibration number config */
adc_calibration_number(ADC2, ADC_CALIBRATION_NUM1);
/* ADC calibration and reset calibration */
adc_calibration_enable(ADC2);
}
5. ADC2触发源选择
void trigsel_config(void)
{
trigsel_init(TRIGSEL_OUTPUT_ADC2_INSTRG, TRIGSEL_INPUT_TIMER1_CH1);
}
6. ADC2中断优先级初始化
void nvic_config(void)
{
nvic_priority_group_set(NVIC_PRIGROUP_PRE1_SUB3);
nvic_irq_enable(ADC2_IRQn, 1, 1);
}
7. ADC2中断服务程序
void ADC2_IRQHandler(void)
{
/* clear the ADC flag */
adc_interrupt_flag_clear(ADC2, ADC_INT_FLAG_EOIC);
/* read ADC inserted group data register */
inserted_data[0] = adc_inserted_data_read(ADC2, ADC_INSERTED_CHANNEL_0);
inserted_data[1] = adc_inserted_data_read(ADC2, ADC_INSERTED_CHANNEL_1);
}
8. 串口输出ADC转换结果
while(1) {
delay_1ms(3000);
printf("\r\n ADC2 inserted channel 0 data = %d \r\n", inserted_data[0]);
printf("\r\n ADC2 inserted channel 1 data = %d \r\n", inserted_data[1]);
printf("\r\n ***********************************\r\n");
}
编译下载完程序后,先用万用表测量PC2和PC2_C两个引脚电压,PC2接近3.28V,PC2_C为1.82V左右,调节开发板上的电位器VR1,PC2_C的电压会跟着变化,PC2电压不变,说明在复位状态下PC2和PC2_C是处于断开状态。
串口显示如下:
在GPIO初始化中加入函数syscfg_analog_switch_disable(),也就是置PxySWON位为0。
void gpio_config(void)
{
gpio_mode_set(GPIOC, GPIO_MODE_ANALOG, GPIO_PUPD_NONE,GPIO_PIN_2);
syscfg_analog_switch_disable(SYSCFG_PC2_ANALOG_SWITCH);
}
void syscfg_analog_switch_disable(uint32_t gpio_answ)
{
SYSCFG_PMCFG &= (uint32_t)(~gpio_answ);
}
编译下载运行,再用万用表测量PC2和PC2_C两个引脚电压,两个引脚电压比较接近,PC2为1.92V,PC2_C为1.86V,说明模拟开关处于关闭状态。
串口输出显示:
综上所述,复位状态下,PxySWON位为1,模拟开关处于断开状态,和手册上讲的复位值为0,有点出入。