基于GD32F350的数字式电容表设计方案
2024-11-15 来源:elecfans
GD32F350开发板使用了兆易最新推出的ARM Cortex-M4的32位通用微控制器GD32F350RB,这款芯片自带2路比较器,非常适合用来制作一款低成本的数字式电容表。
设计方案:
图1是由比较器构成的RC自激振荡电路,R1、R2为比较器正端提供1/2偏压,R3是正反馈电阻,待测电容Cx与RT、CT决定了振荡器的输出频率,基本不受供电电压影响。比较器负输入端与输出端的波形见图2。当RT和CT固定不变时,比较器输出端PT1输出的方波频率与待测电容Cx的容量成反比。
图1
图2
利用GD32F350RB片内自带的轨对轨比较器CMP0,只要外加少量阻容元件,就能构成图1的RC自激振荡电路。然后配置GD32F350的TIMER1每1秒中断1次,读取脉冲个数并计算就能得到待测电容Cx的值。这款低成本的数字电容表的测量范围(具有2位小数的3个自动切换的量程):
1.00pf- 1999.99pf
2.00nf- 999.99nf
1.00uf- 10.00uf
方案实施:
A、硬件资源:
参阅GD32F350手册可知,GD32F350内置的通用比较器可连接的资源非常丰富,用户可以很灵活方便组成各种不同应用功能。本方案(见图3)使用图中红框的连接引脚实现图1自激振荡器功能。比较器的输出直接触发GD32F350内部的EXTI进行计数。
图3
同时,为开发板配置了一片OLED显示屏用来显示测试结果,相关原理图见图4。使用洞洞板焊接了所需的外扩电路。
图4
B、软件资源:
软件流程很简单,见图5.
图5
C、中断资源:
1、ADC_CMP_IRQn
2、CMP0输出中断EXTI21
3、TIMER1_IRQn
D、开发环境:
1、使用MDK5;
2、下载GigaDevice.GD32F30x0_DFP.1.0.0.pack为MDK5添加驱动补丁。
3、 下载GD官方GD32F3x0_Firmware_Library_V1.0.0.rar固件库,直接利用GD32F3x0_Firmware_Library_V1.0.0Template文件夹的演示工程修改添加代码。
在gd_eval_led_init()函数中配置了LED4来监测1秒中断的工作状况,在官方gd32f3x0_eval.h定义的LED有误,请参考https://bbs.eeworld.com.cn/thread-869871-1-1.html进行修改。
E、主要代码
图4
B、软件资源:
软件流程很简单,见图5.
图5
C、中断资源:
1、ADC_CMP_IRQn
2、CMP0输出中断EXTI21
3、TIMER1_IRQn
D、开发环境:
1、使用MDK5;
2、下载GigaDevice.GD32F30x0_DFP.1.0.0.pack为MDK5添加驱动补丁。
3、 下载GD官方GD32F3x0_Firmware_Library_V1.0.0.rar固件库,直接利用GD32F3x0_Firmware_Library_V1.0.0Template文件夹的演示工程修改添加代码。
在gd_eval_led_init()函数中配置了LED4来监测1秒中断的工作状况,在官方gd32f3x0_eval.h定义的LED有误,请参考https://bbs.eeworld.com.cn/thread-869871-1-1.html进行修改。
E、主要代码
main()
#include 'gd32f3x0.h'
#include
#include 'gd32f3x0_eval.h'
#include 'oled.h'
static void rcu_config(void);
static void gpio_config(void);
static void nvic_configuration(void);
static void cmp_config(void);
static void timer1_configuration(void);
static void To_Buf(void);
__IO uint32_t CAP_Value,CMP_Count=0x00;__IO uint32_t CAP;
uint8_t Number_buf[12],CAP_OK=0;
int main(void)
{
SystemInit();
rcu_config();
gpio_config();
gd_eval_led_init(LED4);
OLED_Init();
OLED_Clear();
cmp_config();
timer1_configuration();
nvic_configuration();
LCD_Print(8,0,'基于GD32F350的',TYPE16X16,TYPE8X16);
LCD_Print(24,16,'数字电容表',TYPE16X16,TYPE8X16);
CAP_OK=0x00;
while(1)
{
while(CAP_OK==0x00);
To_Buf();
LCD_Print(16,40,Number_buf,TYPE16X16,TYPE8X16);
CAP_OK=0x00;
CMP_Count=0;
}
}
cmp_config()
static void cmp_config(void)
{
cmp_mode_init(CMP0,CMP_VERYLOWSPEED , CMP_PA5, CMP_HYSTERESIS_HIGH);
cmp_output_init(CMP0,CMP_OUTPUT_NONE,CMP_OUTPUT_POLARITY_NOINVERTED);//CMP_OUTPUT_TIMER2IC0
cmp_enable(CMP0);
}
gpio_config()
static void gpio_config(void)
{
gpio_output_options_set(GPIOA,GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_1|GPIO_PIN_5);
gpio_mode_set(GPIOA,GPIO_MODE_ANALOG, GPIO_PUPD_PULLUP, GPIO_PIN_1|GPIO_PIN_5);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_6);
gpio_mode_set(GPIOA,GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_6);
gpio_af_set(GPIOA,GPIO_AF_7, GPIO_PIN_6);
gpio_output_options_set(GPIOB,GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_12|GPIO_PIN_14|GPIO_PIN_15);
gpio_mode_set(GPIOB,GPIO_MODE_OUTPUT,GPIO_PUPD_PULLUP,GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_12|GPIO_PIN_14|GPIO_PIN_15);
}
nvic_configuration()
static void nvic_configuration(void)
{
nvic_priority_group_set(NVIC_PRIGROUP_PRE1_SUB3);
nvic_irq_enable(TIMER1_IRQn,1, 1);
nvic_irq_enable(ADC_CMP_IRQn,0, 1);
exti_init(EXTI_21,EXTI_INTERRUPT,EXTI_TRIG_RISING);
exti_interrupt_enable(EXTI_21);
}
timer1_configuration()
void timer1_configuration(void)
{timer_oc_parameter_struct timer_ocintpara;
timer_parameter_structtimer_initpara;
timer_deinit(TIMER1);
timer_initpara.prescaler=5399;
timer_initpara.alignedmode=TIMER_COUNTER_EDGE;
timer_initpara.counterdirection=TIMER_COUNTER_UP;
timer_initpara.period=1480;
timer_initpara.clockdivision=TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter= 0;
timer_init(TIMER1,&timer_initpara);
timer_ocintpara.ocpolarity=TIMER_OC_POLARITY_HIGH;
timer_ocintpara.outputstate= TIMER_CCX_ENABLE;
timer_channel_output_config(TIMER1,TIMER_CH_0,&timer_ocintpara);
timer_channel_output_pulse_value_config(TIMER1,TIMER_CH_0,740);
timer_channel_output_mode_config(TIMER1,TIMER_CH_0,TIMER_OC_MODE_TIMING);
timer_channel_output_shadow_config(TIMER1,TIMER_CH_0,TIMER_OC_SHADOW_DISABLE);
timer_interrupt_enable(TIMER1,TIMER_INT_CH0);
timer_interrupt_flag_clear(TIMER1,TIMER_INT_CH0);
timer_enable(TIMER1);
}
ADC_CMP_IRQHandler()
void ADC_CMP_IRQHandler(void)
{
CMP_Count++;
EXTI_PD|=0X200000;
}
TIMER1_IRQHandler()
void TIMER1_IRQHandler(void)
{
if(SET== timer_interrupt_flag_get(TIMER1, TIMER_INT_CH0))
{
timer_interrupt_flag_clear(TIMER1,TIMER_INT_CH0);
CAP_Value=CMP_Count;
gd_eval_led_toggle(LED4);
CAP_OK=0x01;
}
}
OLED驱动代码网上彼彼皆是,就不再重复贴出了。