www.pudn.com > PRMCharger_V0.04.rar > adc.c, change:2008-03-09,size:10939b


/****************************************Copyright (c)************************************************** 
**                              智 能 充 电 器 开 发 小 组 
**                                     OurAVR 论坛 
**                                   QQ 群: 26052247  
** 
**                               http://www.ouravr.com/bbs 
** 
**--------------文件信息-------------------------------------------------------------------------------- 
**文   件   名: ADC.c 
**创   建   人: Trinove 
**最后修改日期: 2008年01月13日 
**描        述: AD转换的底层函数  FOR AVR MCU / Mega16 
**               
**--------------历史版本信息---------------------------------------------------------------------------- 
** 创建人: Trinove 
** 版  本: v0.03 
** 日 期: 2008年01月13日 
** 描 述: 原始版本 
** 
**--------------当前版本修订------------------------------------------------------------------------------ 
** 修改人: martin7wind 枫仔 
** 日 期: 2008年03月01日 
** 描 述: For 智能充电器 
** 
**--------------当前版本修订------------------------------------------------------------------------------ 
** 修改人: 吕海安 
** 日 期: 2008年03月02日 
** 描 述: 修改格式,归档 
**------------------------------------------------------------------------------------------------------ 
********************************************************************************************************/ 
#include "config.h" 
#include "ADC.h"   
// ADCSR 
#define    ADEN     7 
#define    ADSC     6 
#define    ADATE    5   
#define    ADFR     5 
#define    ADIF     4 
#define    ADIE     3 
#define    ADPS2    2 
#define    ADPS1    1 
#define    ADPS0    0 
// 模拟量处理相关的全局变量的定义(仅在模块内被调用) 
 
/********************************************************************************************************* 
** 函数名称: s_analog_init 
** 功能描述: ADC 初始化,查询模式,预分频128,转换时间104us,右对齐 
** 输入参数: 无 
** 输出参数: 无 
********************************************************************************************************/ 
void s_analog_init(void) 
{ 
    // adc转换初始化 
    ADCSRA = 0x00;  // 禁止 AD 转换 
    ADMUX = 0x00; 
    SFIOR |= 0x00; 
    ACSR = 0x80;    // 禁止模拟比较器 
    ADCSRA = 0xE7; 
    //ADCSRA |= BIT(ADSC); 
} 
/********************************************************************************************************* 
** 函数名称: s_analog 
** 功能描述: 模拟量采集函数,用以一次采集某个关键模拟量 
** 输入参数: 无 
** 输出参数: INT16U result: ADC data 
********************************************************************************************************/ 
INT16U s_analog(void) 
{ 
    INT32U value = 0;  // 声明为long,否则在后续计算中会溢出 
    INT16U result = 0; 
    Disable();  
    ADCSRA |= BIT(ADSC); // ADSR 置位,ADC开始 
    while(!(ADCSRA & BIT(ADIF))) // ADSR被清0代表转换完成 
    { 
        // 计算实际电压 
        value = ADCL; // 首先读低位 
        value |= (INT16S)ADCH << 8; // 然后读高位      
        result = (value * VREF_VOL) >> 10; // 10 Bit ADC 计算出采样到的电压值 
        Enable(); 
        break; 
    } 
    return result; 
} 
/********************************************************************************************************* 
** 函数名称: vol_to_bat_vol 
** 功能描述: ADC 测量电压向电池实际模拟量转化函数 
** 输入参数: INT16U vol: 电压采样电路上面 AD 采样出的值 
** 输出参数: INT16U result:  
********************************************************************************************************/ 
INT16U vol_to_bat_vol(INT16U vol) 
{    
    INT16U temp = 0; 
    INT32U temp1 = 0; 
    temp1 = (vol * ((INT8U)(VOL_AMP * 10))) / 10; 
    temp = (INT16U) temp1; 
    return temp;  
} 
/********************************************************************************************************* 
** 函数名称: vol_to_bat_cur 
** 功能描述: 放电的时候,电压是负值 
**           采样电阻0.1欧.  
**           放电电流2A  
**           充电电流2A  
**           放大倍数为1+100/8.2=13.2  
**           放大后电压为0.1*2*13.2=+/-2.64  
**           放大器后偏置电压VREF=3.75  
**           最后的电压为1.11~6.39V 
**           最后的电压为(1.11~6.39V) / 2 = 0.555 V ~ 3.195 V   
**     
**           ( Vcur * 13.2 + 3.75 ) / 2 = Vadc 
**       =>   6.6 * Vcur = Vadc - 0x01FF / 2 
**       =>   CUR_AMP * Vcur = Vadc - 0xFF 
** 
** 输入参数: INT16U vol: 电流采样电路上面 AD 采样出的值 
** 输出参数: INT16S temp: 实际电流 mA 
********************************************************************************************************/ 
INT16S vol_to_bat_cur(INT16U vol) 
{ 
    INT32S temp; 
    temp = vol - (VREF_VOL / 2); 
    temp = (INT16S)(temp * 100 / (INT8U)(CUR_AMP * 10)); 
    return temp; 
} 
/********************************************************************************************************* 
** 函数名称: vol_to_temp 
** 功能描述:  
** 输入参数: INT16U vol: 
** 输出参数: INT16U vol: 
********************************************************************************************************/ 
INT16U vol_to_temp(INT16U vol) 
{ 
    return vol; 
} 
 
/********************************************************************************************************* 
** 函数名称: filter_adc 
** 功能描述: 多通道数值滤波处理,用全局变量做为缓冲区 
**           均值法滤波 
** 输入参数: INT8U channel: 
** 输出参数: 0 
********************************************************************************************************/ 
INT8U filter_adc(INT8U channel) 
{ 
    INT32U temp1 = 0; 
    INT16U result = 0; 
    ADMUX = (ADMUX & 0xF8) | channel;   // 选择对应的通道   
    delay_us(300); 
    s_analog();  // 舍去第一次值     
    result = s_analog(); 
    
    //将测量数据存入全局数据表 
    switch(channel) 
    { 
        case BAT_0_VOL_CH: 
            temp1 = (((INT16U)Bat0_Vol_H) << 8) + Bat0_Vol_L;  
            temp1 = temp1 * 0.75 + vol_to_bat_vol(result) * 0.25;    
            Bat0_Vol_H = (INT8U)(temp1 >> 8); 
            Bat0_Vol_L = (INT8U) (temp1 & 0xff);                
            break; 
        case BAT_0_CUR_CH:     
            if((result > (VREF_VOL / 2 - 100)) && (result < (VREF_VOL / 2 + 100))) 
            { 
                result = VREF_VOL / 2; 
            }        
            temp1 = ((INT16U)Bat0_Cur_H << 8) + Bat0_Cur_L;  
            temp1 = temp1 * 0.75 + vol_to_bat_cur(result) * 0.25;    
            Bat0_Cur_H = (INT8U)(temp1 >> 8); 
            Bat0_Cur_L = (INT8U) (temp1 & 0xff);           
          break; 
        case BAT_0_TEMP_CH:                 
            temp1 = ((INT16U)Bat0_Temp_H << 8) + Bat0_Temp_L;  
            temp1 = temp1 * 0.75 + vol_to_temp(result) * 0.25;    
            Bat0_Temp_H = (INT8U)(temp1 >> 8); 
            Bat0_Temp_L = (INT8U) (temp1 & 0xff);  
            break; 
        case BAT_1_VOL_CH: 
            temp1 = (((INT16U)Bat1_Vol_H) << 8) + Bat1_Vol_L;  
            temp1 = temp1 * 0.75 + vol_to_bat_vol(result) * 0.25;    
            Bat1_Vol_H = (INT8U)(temp1 >> 8); 
            Bat1_Vol_L = (INT8U) (temp1 & 0xff);           
            break; 
        case BAT_1_CUR_CH:   
            if((result > (VREF_VOL / 2 - 100)) && (result < (VREF_VOL / 2 + 100))) 
            { 
                result = VREF_VOL / 2; 
            }   
            temp1 = ((INT16U)Bat1_Cur_H << 8) + Bat1_Cur_L;  
            temp1 = temp1 * 0.75 + vol_to_bat_cur(result) * 0.25;    
            Bat1_Cur_H = (INT8U)(temp1 >> 8); 
            Bat1_Cur_L = (INT8U) (temp1 & 0xff);    
            break; 
        case BAT_1_TEMP_CH:          
            temp1 = ((INT16U)Bat1_Temp_H << 8) + Bat1_Temp_L;  
            temp1 = temp1 * 0.75 + vol_to_temp(result) * 0.25;    
            Bat1_Temp_H = (INT8U)(temp1 >> 8); 
            Bat1_Temp_L = (INT8U) (temp1 & 0xff);  
            break; 
        default: 
            break;     // 异常处理为空 
    } 
    return 0; 
} 
/********************************************************************************************************* 
** 函数名称: ReadBatterySTAT 
** 功能描述: 察看电池状态 
** 输入参数: INT8U channel: 第几路电池 
** 输出参数: 0 
********************************************************************************************************/ 
void ReadBatterySTAT(INT8U channel) 
{    
    INT8U Key = NO_KEY; 
    INT8U i;  
    if(channel == BATTERY0) 
    { 
        lcd_locate(0,0);  
        lcd_print_stringF("BAT0:       mV  ");      	      
        lcd_locate(0,1); 
        lcd_print_stringF("            mA  ");       
    } 
    else if (channel == BATTERY1) 
    { 
        lcd_locate(0,0);  
        lcd_print_stringF("BAT1:       mV  ");     	      
        lcd_locate(0,1); 
        lcd_print_stringF("            mA  ");		 
    } 
    else if (channel == BATTERY_BOTH) 
    { 
        lcd_cls();  // 清屏  
        lcd_locate(5,0); 
        lcd_print_stringF("mV");  
         lcd_locate(14,0); 
        lcd_print_stringF("mV");   
        lcd_locate(5,1); 
        lcd_print_stringF("mA");  
         lcd_locate(14,1); 
        lcd_print_stringF("mA");     				 
    }       
    while (Key != BT_CANCEL) 
    { 
        LED1 = 1; 
        LED2 = !LED2; 
        for(i=0; i<7; i++) 
        { 
            filter_adc(i);   
        } 
        if(channel == BATTERY0) 
        { 
            lcd_locate(7,0);   
            lcd_print_number((((INT16U)Bat0_Vol_H << 8) + Bat0_Vol_L),4,0);         	      
            lcd_locate(7,1); 
            lcd_print_number((((INT16U)Bat0_Cur_H << 8) + Bat0_Cur_L),4,0);        
        } 
        else if (channel == BATTERY1) 
        { 
            lcd_locate(7,0); 
            lcd_print_number((((INT16U)Bat1_Vol_H << 8) + Bat1_Vol_L),4,0);      	      
            lcd_locate(7,1);                             
            lcd_print_number((((INT16U)Bat1_Cur_H << 8) + Bat1_Cur_L),4,0); 		 
        } 
        else if (channel == BATTERY_BOTH) 
        { 
            lcd_locate(0,0);   
            lcd_print_number((((INT16U)Bat0_Vol_H << 8) + Bat0_Vol_L),4,0);         	      
            lcd_locate(0,1); 
            lcd_print_number((((INT16U)Bat0_Cur_H << 8) + Bat0_Cur_L),4,0);        
            lcd_locate(9,0);  
            lcd_print_number((((INT16U)Bat1_Vol_H << 8) + Bat1_Vol_L),4,0);      	      
            lcd_locate(9,1);                              
            lcd_print_number((((INT16U)Bat1_Cur_H << 8) + Bat1_Cur_L),4,0); 				 
        }   
        Key = read_keycode(); 
    } 
} 
/**************************************************************************************×***************** 
**                                 END OF FILE 
********************************************************************************************************/

送体验金的网站