嵌入式课设阻容测量仪

嵌入式课设阻容测量仪

原理

通过IDAC对所接器件充放电流,用ADC采集被测器件上电压,读取AD值。
·如果接电阻,无论大小,AD值会是4294967286 ;如果不接或者接电容,AD最大会是74164,根据数值可自动判断器件类型。
·对电容充电,采集电容电压,判断AD值,如果大于一定数值,认为电容值偏小,下一步将充电时间减半;如果小于一定数值,认为电容值偏大,下一步将充电时间在现在时间上加1/2;直至不满足上述两种情况,则认为电容值刚好合适。注意电容需放电。
对电阻充电,采集电阻电压,判断AD值,如果大于一定数值,认为电阻值偏大,下一步将充电时间减半;如果小于一定数值,认为电阻值偏小,下一步将充电时间在现在时间上加1/2;直至不满足上述两种情况,则认为电阻值刚好合适。
这个是查阅资料发现在实际测试中的一个规律。我原本的打算是:先恒流源输出电流一段时间,然后停止电流输出,过一小段时间,测试器件上的电压,如果是电阻,其电压应该为0,因为它上面没有电流流过,如果是电容,电压应该不为0,因为电容放电需要时间。
·计算电阻值,输出器件类型及AD值转换后的电容/电阻值。
由:
嵌入式课设阻容测量仪_第1张图片
可得电容值。
t2-t1=0.8-0.2=0.6;1.024是ADC的参考电压;65535是16位ADC的总量程
由十六进制转化为十进制公式可得电流值,进而求出电阻值。
嵌入式课设阻容测量仪_第2张图片
#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

    • in the status register. Note that the function is not called, but rather
    • the status is read directly.
      */
      Timer_1_STATUS;

    /* Increment the Counter to indicate the keep track of the number of

    • interrupts received */
      InterruptCnt++;

}
void discharge(void)
{
AMux_Connect(0); //电容放电
InterruptCnt = 0; //计时清零
while(InterruptCnt<500); //放电延时,+100确保放电彻底
AMux_Disconnect(0); //停止放电
}

/*******************************************************************************

  • Function Name: main

  • Summary:
  • Main function performs following functions:
  • 1: Enables the clock
  • 2: Start the Timer
  • 3: Initializes the LCD
  • 4: Print Period, capture, counter value on LCD
  • Parameters:
  • None.
  • Return:
  • None.

******************************************************************************/
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 < chargetime
0.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 */

你可能感兴趣的:(嵌入式)