嵌入式课设阻容测量仪
通过IDAC对所接器件充放电流,用ADC采集被测器件上电压,读取AD值。
·如果接电阻,无论大小,AD值会是4294967286 ;如果不接或者接电容,AD最大会是74164,根据数值可自动判断器件类型。
·对电容充电,采集电容电压,判断AD值,如果大于一定数值,认为电容值偏小,下一步将充电时间减半;如果小于一定数值,认为电容值偏大,下一步将充电时间在现在时间上加1/2;直至不满足上述两种情况,则认为电容值刚好合适。注意电容需放电。
对电阻充电,采集电阻电压,判断AD值,如果大于一定数值,认为电阻值偏大,下一步将充电时间减半;如果小于一定数值,认为电阻值偏小,下一步将充电时间在现在时间上加1/2;直至不满足上述两种情况,则认为电阻值刚好合适。
这个是查阅资料发现在实际测试中的一个规律。我原本的打算是:先恒流源输出电流一段时间,然后停止电流输出,过一小段时间,测试器件上的电压,如果是电阻,其电压应该为0,因为它上面没有电流流过,如果是电容,电压应该不为0,因为电容放电需要时间。
·计算电阻值,输出器件类型及AD值转换后的电容/电阻值。
由:
可得电容值。
t2-t1=0.8-0.2=0.6;1.024是ADC的参考电压;65535是16位ADC的总量程
由十六进制转化为十进制公式可得电流值,进而求出电阻值。
#include
#include “STDIO.H”
#include “STDLIB.H”
#define CHARGETIME 1000
#define IDLE 0
#define CAP_CHECKING 1
#define RES_CHECKING 2
#define CAP_TEST 3
#define RES_TEST 4
uint16 InterruptCnt =0 ;
uint16 currentrang = IDAC_RANGE_32uA;
uint32 g_output[2],lastdata,outdata;
float capvalue;
uint8 g_state = IDLE;
uint8 test_flag = 0;
char Buffer[8];
uint16 chargetime = CHARGETIME>>1 ;
uint16 chargecurrent = 0xF0;
float current,resvalue ;
uint8 range_flag = 0;
/*******************************************************************************
Define Interrupt service routine and allocate an vector to the Interrupt
*******************************************************************************/
CY_ISR(InterruptHandler)
{
/ Read Status register in order to clear the sticky Terminal Count (TC) bit
/* Increment the Counter to indicate the keep track of the number of
}
void discharge(void)
{
AMux_Connect(0); //电容放电
InterruptCnt = 0; //计时清零
while(InterruptCnt<500); //放电延时,+100确保放电彻底
AMux_Disconnect(0); //停止放电
}
/*******************************************************************************
******************************************************************************/
int main()
{
/ Enable the global interrupt */
CyGlobalIntEnable;
/* Enable the Interrupt component connected to Timer interrupt */
TimerISR_StartEx(InterruptHandler);
/* Start the components */
AMux_Start();
// AMux_Connect(0);
AMux_Disconnect(0);
Opamp_Start();
ADC_DelSig_1_Start();
/* Display TMR-16 on LCD */
LCD_Start();
IDAC_Start();
IDAC_Sleep();
LCD_ClearDisplay();
Timer_1_Start();
discharge();//电容放电
while(1)
{
switch(g_state)
{
case IDLE :
IDAC_Wakeup(); //开始充电
IDAC_SetValue(chargecurrent); //设置充电电流
InterruptCnt = 0; //计时清零
while(InterruptCnt < chargetime);//充电延时
IDAC_Sleep(); //充电结束
ADC_DelSig_1_StartConvert();//开启ADC,采集被测器件上电压
while(!ADC_DelSig_1_IsEndConversion(ADC_DelSig_1_RETURN_STATUS));//等到ADC转换完毕
g_output[0] = ADC_DelSig_1_GetResult32();//读取AD值
if(g_output[0] < 100000) //如果接的电阻,无论大小,AD值会是4294967286 ,如果不接或者接电容,AD最大会是74164,所以可以根据这两个值来判断器件类型
{
discharge(); //电容放电
g_state = CAP_CHECKING;
}
else g_state = RES_CHECKING;
break;
case CAP_CHECKING :
IDAC_Wakeup(); //开始充电
IDAC_SetValue(chargecurrent); //设置新的充电电流
InterruptCnt = 0; //计时清零
while(InterruptCnt < chargetime);//充电延时
IDAC_Sleep(); //充电结束
ADC_DelSig_1_StartConvert();//开启ADC,采集被测器件上电压
while(!ADC_DelSig_1_IsEndConversion(ADC_DelSig_1_RETURN_STATUS));
//等到ADC转换完毕
g_output[0] = ADC_DelSig_1_GetResult32();//读取AD值
// LCD_Position(0u, 0u);
// LCD_PrintU32Number(g_output[0]);
//后续加均值滤波
discharge(); //电容放电
if(g_output[0] > 65000)
//判断AD值,如果大于65000,认为电容值偏小,下一步将充电时间减半
{
if(chargetime<16)
//如果充电时间小于100,下一步将电流值减小一半
{
chargecurrent = chargecurrent>>1;
//充电电流减半
if(chargecurrent == 0)
{
chargecurrent = 0x01;
chargetime = chargetime>>1;
}
}
else chargetime = chargetime>>1;//充电时间减半
}
else if(g_output[0] < 45000)
//判断AD值,如果小于45000,认为电容值偏大,下一步将充电时间在现在时间上加1/2
{
chargetime += chargetime>>1;//充电时间增加一半
}
else
//如果不满足上述两种情况,则认为电容值刚好合适,下一步进入容值计算
{
g_state = CAP_TEST;//进入下一个状态
current = (float)(chargecurrent31.875)/255;//计算电流的实际值,用于后续电容计算
}
break;
case CAP_TEST :
IDAC_Wakeup();
InterruptCnt = 0;
while(InterruptCnt < chargetime0.2);//充电一小段时间
IDAC_Sleep(); //充电结束
ADC_DelSig_1_StartConvert();
while(!ADC_DelSig_1_IsEndConversion(ADC_DelSig_1_RETURN_STATUS));
g_output[0] = ADC_DelSig_1_GetResult32();
AMux_Connect(0); //放电
InterruptCnt = 0;
while(InterruptCnt<500);//放电延时
AMux_Disconnect(0);
IDAC_Wakeup();
InterruptCnt = 0;
while(InterruptCnt < chargetime*0.8);//充电一大段时间
IDAC_Sleep(); //充电结束
ADC_DelSig_1_StartConvert();
while(!ADC_DelSig_1_IsEndConversion(ADC_DelSig_1_RETURN_STATUS));
g_output[1] = ADC_DelSig_1_GetResult32(); capvalue=(float)(current*65535*chargetime*0.6/((g_output[1]- g_output[0]) *1.024*1000));
LCD_Position(0u, 0u);
LCD_PrintString("CAP");
sprintf(Buffer,"%2.3fuF",capvalue);//输出电容值
LCD_Position(1u, 0u);
LCD_PrintString(&Buffer);
AMux_Connect(0); //放电
InterruptCnt = 0;
while(InterruptCnt<500);//放电延时
AMux_Disconnect(0);
if(g_output[0] == 74164)
//如果ADC值等于74164,认为被测器件移除,所有状态恢复初始值
{
chargetime = CHARGETIME>>1 ;
chargecurrent = 0xF0;
IDAC_SetValue(chargecurrent);
g_state = IDLE;
}
break;
case RES_CHECKING :
IDAC_Wakeup(); //开始充电
IDAC_SetValue(chargecurrent); //设置充电电流
ADC_DelSig_1_StartConvert();
//开启ADC,采集被测器件上电压
while(!ADC_DelSig_1_IsEndConversion(ADC_DelSig_1_RETURN_STATUS));//等到ADC转换完毕
g_output[0] = ADC_DelSig_1_GetResult32();//读取AD值
if( g_output[0] > 65000) // 电阻偏大,减小电流
{
chargecurrent = chargecurrent>>1;
if(chargecurrent < 0x01 && currentrang == IDAC_RANGE_255uA)
{
IDAC_SetRange(IDAC_RANGE_32uA);
chargecurrent = 0xFF;
currentrang = IDAC_RANGE_32uA;
}
if(chargecurrent < 0x01 && currentrang == IDAC_RANGE_2mA)
{
IDAC_SetRange(IDAC_RANGE_255uA);
chargecurrent = 0xFF;
currentrang = IDAC_RANGE_255uA;
}
}
else if( g_output[0] < 5000)//电阻偏小,增大电流
{
chargecurrent +=chargecurrent>>1;
if(chargecurrent>0XFF&¤trang==IDAC_RANGE_32uA)
{
IDAC_SetRange(IDAC_RANGE_255uA);
chargecurrent = 0x20;
currentrang = IDAC_RANGE_255uA;
}
if(chargecurrent>0XFF&¤trang==IDAC_RANGE_255uA)
{
IDAC_SetRange(IDAC_RANGE_2mA);
chargecurrent = 0x20;
currentrang = IDAC_RANGE_2mA;
}
}
else
{
if(currentrang == IDAC_RANGE_32uA)
{
current = (float)(chargecurrent*31.875)/255;
}
else if (currentrang == IDAC_RANGE_255uA)
{
current = (float)(chargecurrent*255)/255;
}
else
{
current = (float)(chargecurrent*2040)/255;
} resvalue=(double)( g_output[0]*1.024*1000000/(current*65535));
LCD_Position(0u, 0u);
LCD_PrintString("RES");
sprintf(Buffer,"%2.3fR",resvalue);
LCD_Position(1u, 0u);
LCD_PrintString(&Buffer);
g_state = RES_CHECKING;
}
break;
}
}
}
/* END OF FILE */