⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 power.c

📁 非常好的电源管理和按键处理
💻 C
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************
*
*  $Log: D:\VM700\software\power.c $
*
*  1     03-11-17 19:51  Wang Guanping
*  Begin to edit the source code.
*****************************************************************************/


#define GLOBALS_POWER
#include "include.h"

static int8u Power_Timer;
static bool EI_PowerOff_Request;
static void EnterPowerOff(void);
extern void PwmAdjust(int8u index);
extern void DisplayAvInStr(void);
extern void MCU_IO_Init(void);
extern void Enable_TimerB(void);
static bool CheckPowerOn(MESSAGE_ID nMsg);

extern int8u Video_Format_mem;

/*

需要响应和处理的事件如下:
1.面板和遥控器上的POWER按键开关
2.ACC熄灭后关机,开启后开机
3.防盗检测到后关机
4.电压低电后关机
5.非防盗和低电的情况下,检测到外部唤醒信号后开机
6.上电时通知外围设备
7.断电时通知外围设备
8.上电时要通知LCD回位
9.断电时要通知LCD回位,并且只有在回位后MCU才能降频运行
10.低电检测分为两个部分:
   一个是正常的A/D转换,每隔50毫秒采样一次,数值精确,速度慢
   一个是电压异常中断,当电压发生异常波动,高于上限值或者低于下限值时产生中断,速度快,只能表示电压异常

*/


extern void Osd_Init_Start(void);   //jief add
extern void CCFL_Power(bool bPower);
//TFT IC initialization: RB5,TFT_4094
//MTV018,UPD16431的初始化在各自的驱动程序里
//将下列参数写入到外围设备之中
//nAspect
//nRB5
extern void TFT_Device_Init(void)
{
    LoadT100TestPara(ParaDataNtscCvbs,TOTAL);
    if(Video_Format_mem==CVBS_PAL)
        Load_PAL_to_T100();
    else if(Video_Format_mem==CVBS_SECAM)
        Load_SECAM_to_T100();

    #if ADD_PALM
        else if(Video_Format_mem==CVBS_PALM)
        Load_PALM_to_T100();
    #endif

    else
        Load_NTSC_to_T100();
    SetWatchDog;
  #if POWER_ON_LOGO==0
    //070313;OSDInit();
  #else
    T100I2CWriteByte(TW100,0x18,0x3f);//Switch Analog Source Mux to YUV
    //T100I2CWriteByte(TW100+4,0x00,0x01);//Switch Analog Source Mux to CVBS
    T100I2CWriteByte(TW100,0xC2,0x12);//0213.avoid ghost shape;
  #endif

    //T100I2CWriteByte(TW100+4,0x07,0x24);              //Set Auto Blue Screen On
    //ShowAllFonts();

    gobal_user_para.brightness=nBright;
    gobal_user_para.contrast=nContrast;
    gobal_user_para.color=nColor;
    gobal_user_para.tint=nTint;
    if(DimmerFuncSet==0) nAutoDimmer_Flag=0;
    gobal_user_para.setup_dimmer.option=nAutoDimmer_Flag;
    gobal_user_para.setup_dimmer.dimmer=nDimmer;
    gobal_user_para.lcd_mode=nAspect;
    gobal_user_para.mirror=nMirror;
    gobal_user_para.source=nSource;
    gobal_user_para.volume=nVolume;
    gobal_user_para.language=nLanguage;
    gobal_user_para.blue=nBlueScreen;

/*    if(nBlueScreen)
        T100I2CWriteByte(TW100+4,0x07,0x24);//full blue screen;
    else
        T100I2CWriteByte(TW100+4,0x07,0x04);
    */
    //SetAutoBlueScreen();

    //??? if not to do as below,display will be abnormal at start.
    /*{
        if(nAspect==NORMAL)
            PostMessage(ScreenMsgQueue,MSG_LCD_SCALE,FULL);
        PostMessage(ScreenMsgQueue,MSG_LCD_SCALE,(int16u)nAspect);
    }*/

    Delay_ms(5);
    RB5_Init();
    return;
}

/*
时序要求:
B+打开后,延时200MS打开TFT,再延时50MS打开CCFL,之后才能设置ABRT
异常关机时,快速对B+放电后,再关闭其它设备。放电持续时间为200MS,以免耗电。关机后延时2S再回收显示屏。
按键关机时,对B+正常关机而不是放电。
按键关机后,只有按键或者WAKEUP才能开机
*/


//系统设备电源M5V控制
//SWITCH_ON信号用来安全的打开/关闭电源
//SWITCH_OFF信号用来快速的放电、关闭电源,该信号本身消耗电流很大,因此不能长久的置为有效,
//在放电完毕后应该设置SWITCH_ON,将SWITCH_OFF复位,
//当SWITCH_OFF=1时,SWITCH_ON信号可以不起作用
//   SWITCH_OFF,SWITCH_ON
//       0        0        = NORMAL POWER OFF
//       0        1        = NORMAL POWER ON
//       1        0        = QUICKLY POWER DOWN
//       1        1        = QUICKLY POWER DOWN, DO NOT USE THIS STATE


static void M5V_SW(bool bPower)     //该模块控制所有电源
{
    if(bPower==false)
        Clr_SWITCH_ON
    else
        Set_SWITCH_ON
    return;
}

extern void CCFL_Power(bool bPower)
{
    if(bPower==false)
    {
        Clr_CCFL_EN;
        return;
    }
    Clr_CCFL_EN;
    Delay_ms(10);
    Set_CCFL_EN;
    Delay_ms(10);
    Clr_CCFL_EN;
    Delay_ms(10);
    Set_CCFL_EN;
    return;
}

//电池电压检测(A/D)
//根据电压的绝对值来判断是否应该开机
//static int8u nSampleBattery;

//机器电源打开时,开关电源充电,有可能将B+拉低,因此在等待电源稳定的时间内
//(INITIAL_STEP1)不要响应B+异常中断。
//同时需要在主循环里面监视B+异常的持续时间,若时间过长,要马上关机

//ACC,B+都是沿触发中断,外部的尖脉冲有可能错误触发中断,
//因此需要消抖处理

//检测,电压异常
//当ACC,B+公用一个中断源时,先发生的中断会屏蔽后来的中断,
//因此后发生的信号只能依靠扫描的方式进行检测
/*extern void Battery_Abnormal_Detect(void)
{
    if(nPowerState==INITIAL_STEP1)return;

    //沿信号要复位采样计数器
    nSampleBattery=N_SAMPLE_VOLTAGE;
    if(F_PowerStatus_Val()==0)return;//已经检测完,不再检测
    for(Sample=0;;)
    {
        //循环体执行时间:12 instruction cycle
        //正常情况下,B_DET_H=L, B_DET_L=H
        if(_B_H_DET_Val==0&&_B_L_DET_Val)   //先进中断,再检测I/O
        {
            return;
        }
        Sample--;
        if(Sample==0)break;
    }
    //现在检测到电压异常,检测完成,要求关机。到底是高电压异常,还是低电压异常,不判断。
    EmergencyPowerDown();
    return;
}*/

//060929.带ZENER DIODE;
//#define V0    0x98      //最低开机电压;
//#define V1    0xcc      //最高开机电压;
//#define V2    0xc4      //最低关机电压;

//061008.带ZENER DIODE;
//#define V0    0x98        //最低开机电压;
//#define V1    0xcc+8      //最高开机电压;
//#define V2    0xc4+4      //最低关机电压;

//061009.ONLY DIVIDE VOLTAGE BY TWO RESISTORS:100K/20K=5:1
#if 0
#define V0    ((255/5*8+3)/6-1)         //最低关机电压;9V
#define V1    ((255/5*8+3)/6+12)       //最低开机电压;9.5V
#define V2    ((255/5*16+3)/6)      //最高开机电压;16V
#define V3    ((255/5*16+3)/6+8)      //最低关机电压;17V    0xff/5V*17V/6
#endif
//#define V0    ( Div((255/5*8+3),6)-1  )     //最低关机电压;9V
//#define V1    ( Div((255/5*8+3),6)+12 )     //最低开机电压;9.5V
//#define V2    ( Div((255/5*16+3),6)   )     //最高开机电压;16V
//#define V3    ( Div((255/5*16+3),6)+8 )    //最低关机电压;17V    0xff/5V*17V/6
#define V0    0x48         //最低关机电压;9V
#define V1    0x4C       //最低开机电压;9.5V
#define V2    0x84      //最高开机电压;16V
#define V3    0x8C      //最低关机电压;17V    0xff/5V*17V/6

extern void Battery_Abnormal_Detect(void)
{
    int8u i;
    int8u HighV=0;
    //if(nPowerState<SYSTEM_RUN)return;
    for(i=0;i<4;i++)
    {
        HighV+=(ADC_8b(10)>>2);
    }
#if VOLTAGE_DETECT==0
    HighV=V1+5;//debug;
#endif
        if(HighV>=V1&&HighV<=V2)//061011.
        {
            F_PowerStatus_Set();
            if(nPowerState==POWER_OFF&&PowerOffSource==BATTERY_POWER_OFF)//&&BatteryFailTimer==0)
                Send_Power_On();
        }
        if(HighV>=V3||HighV<=V0)  //061011.
        {
            F_PowerStatus_Clr();
            if(nPowerState!=POWER_OFF)
            {
                EnterPowerOff();//060819.
                Send_Power_Off();
                PowerOffSource=BATTERY_POWER_OFF;
                nPowerState=POWER_OFF;
            }
        }
}

static void CheckPowerOff(MESSAGE_ID nMsg)
{
    if(EI_PowerOff_Request)
    {
        EI_PowerOff_Request=false;
        nMsg=MSG_POWER_OFF;

    }
    if(nMsg==MSG_POWER_OFF)
    {
        Power_Timer=0;
        //阻止除POWER之外的其它按键
        Clr_Machine_Power();
        Disable_TimerA();
        ClrBit(Video_Flag,F_SysMenu);
        MCU_IO_Refresh();
        EnterPowerOff();
        nPowerState=POWER_OFF;//debug;
    }
}

//电池电压异常中断
//只有在异常时才会中断,中断的唯一目的是快速关机,并马上保存eeprom
//异常有两个来源:ACC失效,B+异常。
//在这里判断关机信号的来源,进行关机的处理。
//由于是双向触发,只有在可能导致关机的事件发生时,
//才需要中断响应和处理,开机的事件可以通过扫描来识别
void ISR_EI1()
{
    return;//debug;0212;

/*  MCCSR=0B00000010;//  Fcpu=Fosc2
    //nPC无用,在这里用作临时变量
    nPC=nPF^PFDR;
    //记忆EI1中断端口的值,以便在中断发生后判断中断来源
    nPF&=0b11111000;
    nPF|=(PFDR&0b00000111);

    if(ValBit(nPC,_ACC_DET))
    {
        nPC=0;
        ACC_Off_Detect();
        return;
    }
    nPC=0;
    Battery_Abnormal_Detect();
*/
}
#if D_ADD_ACC_DETECT

static void ACC_Off_Detect(void)
{
    //沿信号要复位采样计数器
    nSampleACC=N_SAMPLE_ACC;
    if(ValBit(Det_Flag,F_ACC_Det)==0)return;
    for(Sample=0;;)
    {
        //循环体执行时间:12 instruction cycle
        if(ACC_OFF_DET_Val==0)
        {
            return;
        }
        Sample--;
        if(Sample==0)break;
    }
    ClrBit(Det_Flag,F_ACC_Det);
    nCloseACCTimer=MAX_IGNITION_TIME;
    Send_Power_Off();
    CheckPowerOff(MSG_POWER_OFF);
    return;
}


static void ACC_Detect()
{
    bool port;

    port = ACC_OFF_DET_Val;  //采样

    //if(gobal_user_para.source==1)return;//AV2时不进行ACC检测控制
    if(nSampleACC)nSampleACC--;
    if(nSampleACC==0)
    {
        //多次采样确认
        if(port)
            ACC_Off_Detect();//管脚变为invalid
        else
        {
            if (ValBit(Setting_Flag,F_On_Off)
                 &&Machine_Power()==0&&F_PowerStatus_Val())
               {
                  Send_Power_On();
               }
            SetBit(Det_Flag,F_ACC_Det);
        }
    }

    if(ValBit(Det_Flag,F_ACC_Det))
    {
        nSampleACC=N_SAMPLE_ACC;
        if(port)
            ACC_Off_Detect();//管脚变为invalid
        return;
    }
    if(port)
    {
        //端口电平与标志位一致 :=invalid
        nSampleACC = N_SAMPLE_ACC;
        return;
    }

}

#endif


extern bool T100aIsInReset(void)
{
    if(!Main_Power())return false;

    if(nPowerState<=INITIAL_STEP2)
        return true;
    return false;
}

//系统全速运行
static void SystemPowerUp()
{
    MCCSR=0B00000010;//  Fcpu=Fosc2
    CCFL_Power(false);
    M5V_SW(true);

    Enable_TimerA();
    return;
}


static bool CheckPowerOn(MESSAGE_ID nMsg)
{
    EI_PowerOff_Request=false;

    if(/*060918.PowerOffSource!=KEY_POWER_OFF||*/nMsg==MSG_POWER_ON)
    {
        MCCSR=0B00000010;//  Fcpu=Fosc2
        nPowerState=SWITCH_ON_DELAY;
        //nPowerState=RESET_POWER_UP;     //070113.
        Power_Timer=0;
        return true;
    }

    return false;
}

static void EnterPowerOff(void)
{
    //zyq.the following sentence is moved to below in order to avoid flashing before screen close.
    Disable_TimerA();
    I2C_Disable();
    ADC_Disable;
    Power_Timer=0;
    MCU_IO_Refresh();
    ClearMessage(PwrMsgQueue);
    ClearMessage(OsdMsgQueue);
    nPowerState=POWER_OFF;
    //070108.SetBit(Sys_Flag,F_SystemWait);
    //BatteryFailTimer=200;
    return;
}

//本函数的入口只有两个消息和标志位g_Flag.F_MachineState
//其它所有底层中断和检测函数,都必须通过这个途径来和本函数进行交互
//需要处理的对象如下:
//SWITCH_ON,SWITCH_OFF
//ACC,LOCK,_POSITION_SW
//B+ FAILURE,B+ VOLTAGE AD CONVERTER
//TFT,CCFL,ABRT,TV_PCON,BEEP
//Fcpu
//MUTE1,MUTE2
extern void PowerManage()
{
    MESSAGE nMsg;

    Battery_Abnormal_Detect();    //060819.
#if D_ADD_ACC_DETECT
    ACC_Detect();
#endif
    if(nPowerState<INITIAL_STEP4)
    {
        Adject_Volume(0);
        Mute_Audio_Set;
    }
    nMsg=*GetMessage(PwrMsgQueue);
    //Time slot is 12ms
    Power_Timer++;
    //061107.ClrBit(Sys_Flag,F_SystemWait);

    switch(nPowerState)
    {
        case RESET_POWER_UP:
            //Mute_Audio_Set;
            if(Power_Timer>=42)
            {
                MCCSR=0B00000010;//  Fcpu=Fosc2
                PowerOffSource=POWER_ON;
                nPowerState=SWITCH_ON_DELAY;
                Power_Timer=0;
                CheckPowerOff(nMsg.ID);
                CCFL_Power(false);
            }
            break;

        case SWITCH_ON_DELAY:

            //Mute_Audio_Set;
            //ClrBit(Setting_Flag,F_Audio_Mute);//060920.
            #if 0
            if(ValBit(Det_Flag,F_ACC_Det)==0)
            {
                Send_Power_Off();
                CheckPowerOff(MSG_POWER_OFF);//power off!
                break;
            }
            #endif

          #if ResetJudge==ResetJudgeNew
            CCFL_Power(false);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -