前提
测电容的方法还是接触19年电赛国赛的F题遇到的,有两种测电容的芯片,一个是官方的FDC2214芯片,一个是NE555芯片。因为FDC2214比较贵,所以我们最终采用的NE555定时器来测量电容的值。利用NE555芯片来搭建振荡电路,测量产生的脉冲的宽度,来得到电容的值。
555定时器是一种数字电路和模拟电路相结合的中规模集成电路,其应用极为广泛,通过其外部不同的连接,就可以构成单稳态触发器和多谐振荡器。
单稳态的意思是:在触发信号未加之前,触发器处于稳定状态,经触发信号触发后,触发器翻转,产生一个新的状态,但新的状态只能暂时保持(暂稳状态),经过一定的时间(由电路参数决定)后自动翻转到原来稳定的状态。所以只有一个稳定的状态,也就是单稳态的名字的由来。
多谐振荡器:无稳态触发器没有稳定的状态,同时需要外加触发脉冲,就能输出一定频率的矩形脉冲(自激振荡),因为矩形波含有丰富的谐波,故也称为多谐振荡器。
这里我们采用的方案为多谐振荡器,也是最主要介绍的内容。
多谐电路的搭建
如上图1所示是有NE555定时器搭建的多谐振荡器。R1,R2和C是外接的元件。
通过接通UCC后,它经过R1和R2对电容C充电,电压uc上升。当0<uc<1/3UCC,触发器置1,uo输出高电平。1/3UCC <uc<2/3UCC时,触发器状态保持不变,uo输出仍为高电平。当uc上升高于2/3VCC时,触发器置0,uo输出低电平。这时NE555芯片内部的放电管T导通,电容C通过R2和T 放电,uc下降。当uc下降略低于1/3VCC时,触发器置1,uo输出高电平,VCC对电容C充电。如此重复上述过程,uo为连续的矩形波,上述过程如下图所示。
第一个暂稳状态的脉冲宽度为tp1,即电容的充电时间
第二个暂稳状态的脉冲宽度为tp2,即电容的放电时间
故uo引脚(芯片的第三引脚)输出的脉冲周期为
其频率为
由555定时器组成的振荡器,最高工作频率可达300kHz。
图3和图4是在Multisim仿真下两极板接入0.01μF和0.05μF的电容,所得到的周期分别为4.19ms和20.739ms。
电容检测程序设计
通过上述的几条公式,我们可以知道,只需要检测NE555芯片第3引脚输出的脉冲周期或者脉冲的高电平的宽度就可以了,再通过相应的公式转化就可以得到所测的电容值,也就是振荡电路中的那个C的值。
利用STM32F103ZE采集NE555芯片产生的脉冲(这里我们是根据19年国赛的题目,因为要对比出较小范围内的不同电容值的差异性,所以我们是在200ms中得出555芯片产生的脉冲个数,间接就可以得到脉冲的周期了,即200/n)。将stm32的PA0接NE555芯片的第三引脚,将TIM2_CH1_ETR 为外部脉冲计数,利用定时器3进行200ms的定时,每隔200ms后进入一次中断函数,对所测量的脉冲个数进行统计。R1和R2为我们接的都是200k的阻值。NE555芯片第5引脚接的电容为0.01uF的电容。
其定时器代码下所示:
time.c
#include "timer.h" #include "led.h" #include "usart.h" void TIM3_Int_Init(u16 arr,u16 psc) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能 TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 计数到5000为500ms TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 10Khz的计数频率 TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位 TIM_ITConfig( //使能或者失能指定的TIM中断 TIM3, //TIM2 TIM_IT_Update | //TIM 中断源 TIM_IT_Trigger, //TIM 触发中断源 ENABLE //使能 ); NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能 NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器 TIM_Cmd(TIM3, ENABLE); //使能TIMx外设 } u16 Freq=0; void TIM3_IRQHandler(void) //TIM3中断 { if(TIM_GetITStatus(TIM3,TIM_IT_Update)!= RESET) //检查TIM3更新中断发生与否 { TIM_ClearITPendingBit(TIM3,TIM_IT_Update); //清除TIMx更新中断标志 Freq=TIM_GetCounter(TIM2); //读取200ms内计数器计的CNT值 这个值就是我们所测量的脉冲个数 TIM_SetCounter(TIM2,0); k=1; } } void TIM2_Cap_Init(void) //配置 TIM2_CH1_ETR 为外部脉冲计数 { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能TIM2时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //PA0 清除之前设置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 输入 GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_ResetBits(GPIOA,GPIO_Pin_0); //PA0 下拉 //初始化定时器2 TIM2 TIM_TimeBaseStructure.TIM_Period =0xFFFF; //设定计数器自动重装值 TIM_TimeBaseStructure.TIM_Prescaler =0; //预分频器 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式 TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位 TIM_ITRxExternalClockConfig(TIM2,TIM_TS_ETRF); //配置外部触发,否则不会计数 TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0); TIM_SetCounter(TIM2, 0); TIM_Cmd(TIM2,ENABLE ); //使能定时器2 }
time.h
#ifndef __TIMER_H #define __TIMER_H #include "sys.h" void TIM3_Int_Init(u16 arr,u16 psc); void TIM2_Cap_Init(void); #endif
全部的工程文件已经上传,也可以利用我这个工程文件来进行更改,同样也上传了51的代码。如果有正在作19年国赛的F题纸张计数的内容的同学,就可以直接拿去用了。
51程序代码:
链接:https://pan.baidu.com/s/1H0pPJYT27rEYgkx7PDC0QQ
提取码:1111
STM32程序代码:
链接:https://pan.baidu.com/s/1ib8-fDtNo4d202_lM16XVg
提取码:1111
可能会有一些错误,欢迎大家批评指正!