您的位置:首页 > 其它

基于S3C2450 + WINCE的背光驱动及背光亮度调节应用程序移植详解之驱动篇

2014-02-26 21:13 316 查看
 背光驱动程序设计

 

1. 这里硬件接口使用S3C2450的GPB1,即定时器1.

    定时器的输入频率 = PCLK /{prescaler value + 1} / {divider value}。

    首先设置prescaler value:

   

[cpp] view
plaincopy

static void BAK_SetPrescaleAndMux( DWORD v_Prescale, DWORD v_Mux )  

{  

    // Set prescale.  

    if(v_Prescale<=255)  

    {  

        v_pPWMRegs->TCFG0 = v_pPWMRegs->TCFG0 & (~0xff) | v_Prescale;  

    }  

    // Set divider value.Timer1 is used  

    switch(v_Mux)  

    {  

    case 1:// 1/2  

        v_pPWMRegs->TCFG1 = v_pPWMRegs->TCFG1 & (~0xF0) | (0x0<<4);  

        break;  

    case 2:// 1/4  

        v_pPWMRegs->TCFG1 = v_pPWMRegs->TCFG1 & (~0xF0) | (0x1<<4);  

        break;  

    case 3:// 1/8  

        v_pPWMRegs->TCFG1 = v_pPWMRegs->TCFG1 & (~0xF0) | (0x2<<4);  

        break;  

    case 4:// 1/16  

        v_pPWMRegs->TCFG1 = v_pPWMRegs->TCFG1 & (~0xF0) | (0x3<<4);  

        break;  

    case 5:  

    default:// External TCLK0  

        v_pPWMRegs->TCFG1 = v_pPWMRegs->TCFG1 & (~0xF0) | (0x4<<4);  

        break;  

    }  

}  

    然后设置divider value:

   

[cpp] view
plaincopy

static  void BAK_SetTCNTB( DWORD v_Tcntb)  

{  

    if(v_Tcntb<=0xffff)  

    {  

        v_pPWMRegs->TCNTB1 = v_Tcntb;  

    }  

}  

2.    接着设置TOUT1的定时器PWM脉宽:

[cpp] view
plaincopy

static void BAK_SetTCMPB( DWORD v_Tcmpb)  

{  

    if(v_Tcmpb<=0xffff)  

    {  

        v_pPWMRegs->TCMPB1 = v_Tcmpb;  

    }  

}  

 3.   设置完这些就可以开启TOUT1了。代码如下:

[cpp] view
plaincopy

static void BAK_StartPwmTimer( void )  

{  

    // Set GPB1 to TOUT1.  

    v_pIOPregs->GPBCON &= ~(0x03<<2);  

    v_pIOPregs->GPBCON |= (0x02<<2);  

    // Stop pwm timer 1, first.  

    v_pPWMRegs->TCON &= ~(0xF<<8);  

    v_pPWMRegs->TCON |= (0x6<<8);  // 这里0x2<<8也OK吧!!!!!  

    // Start it again.    

    v_pPWMRegs->TCON &= ~(0xF<<8);  

    v_pPWMRegs->TCON |= (0x9<<8);  

}  

 4.   背光亮度调节代码如下(将亮度设置为10个级别):

[cpp] view
plaincopy

static void BAK_AdjuctBacklightLevel(DWORD v_Level)  

{  

    if((v_Level>=BAK_LEVEL_MIN)&&(v_Level<=BAK_LEVEL_MAX))// v_Level=[1:10]  

    {  

        l_dwBackLightLevel = v_Level;  

        BAK_SetTCMPB((l_dwTcntb * la_dwLevel[v_Level-1])/100);  

    }  

}  

5.以上事情都做完了后,就可以编写通用的流接口程序了。由于程序比较简单,这里

仅贴上XXX_IOControl的代码如下:

[cpp] view
plaincopy

BOOL BAK_IOControl(  

        DWORD hOpenContext,  

        DWORD dwCode,  

        PBYTE pBufIn,  

        DWORD dwLenIn,  

        PBYTE pBufOut,  

        DWORD dwLenOut,  

        PDWORD pdwActualOut   

        )  

{  

    DWORD dwErr = ERROR_INVALID_PARAMETER;  

    BOOL bRc;  

      

    RETAILMSG(lqm_bakdbg, (TEXT("[lqm:BKL] IOCTL code  = %d/r/n"), dwCode));  

    switch (dwCode)   

    {  

    case IOCTL_POWER_CAPABILITIES:  // determines device-specific capabilities  

        RETAILMSG(DBGBAK, (TEXT("[lqm:BKL] IOCTL_POWER_CAPABILITIES/r/n")));  

        if (pBufOut && dwLenOut >= sizeof (POWER_CAPABILITIES) && pdwActualOut)   

        {  

            __try   

            {  

                PPOWER_CAPABILITIES PowerCaps = (PPOWER_CAPABILITIES)pBufOut;  

                // Right now supports D0 (permanently on) and D4(off) only.  

                memset(PowerCaps, 0, sizeof(*PowerCaps));  

                PowerCaps->DeviceDx = 0x12; //support D0, D1,  D4  

                *pdwActualOut = sizeof(*PowerCaps);  

                bRc = TRUE;  

                dwErr = ERROR_SUCCESS;  

            }  

            __except(EXCEPTION_EXECUTE_HANDLER)   

            {  

                RETAILMSG(DBGBAK1, (TEXT("<BKL> exception in ioctl/r/n")));  

            }  

        }  

        else  

            bRc = FALSE;  

        break;  

  

    case IOCTL_POWER_QUERY: // determines whether changing power state is feasible  

        RETAILMSG(DBGBAK, (TEXT("<BKL> Received IOCTL_POWER_QUERY/r/n")));  

        if (pBufOut && dwLenOut >= sizeof(CEDEVICE_POWER_STATE))   

        {  

            // Return a good status on any valid query, since we are always ready to  

            // change power states (if asked for state we don't support, we move to next highest, eg D3->D4).  

            __try   

            {  

                CEDEVICE_POWER_STATE ReqDx = *(PCEDEVICE_POWER_STATE)pBufOut;  

  

                if (VALID_DX(ReqDx))   

                {  

                    // This is a valid Dx state so return a good status.  

                    bRc = TRUE;  

                    dwErr = ERROR_SUCCESS;  

                }  

                else  

                {  

                    bRc = FALSE;  

                }  

                RETAILMSG(DBGBAK, (TEXT("<BKL> IOCTL_POWER_QUERY %s/r/n"), dwErr == ERROR_SUCCESS ? (TEXT("succeeded")) : (TEXT("failed")) ));  

            }  

            __except(EXCEPTION_EXECUTE_HANDLER)   

            {  

                RETAILMSG(DBGBAK1, (TEXT("<BKL> Exception in ioctl/r/n")));  

            }  

        }  

        else          

            bRc = FALSE;  

        break;  

  

    case IOCTL_POWER_SET: // requests a change from one device power state to another  

         RETAILMSG(lqm_bakdbg, (TEXT("[lqm:BKL] Received IOCTL_POWER_SET/r/n")));  

        if (pBufOut && dwLenOut >= sizeof(CEDEVICE_POWER_STATE))   

        {  

            __try   

            {  

                CEDEVICE_POWER_STATE ReqDx = *(PCEDEVICE_POWER_STATE)pBufOut;  

  

                if (VALID_DX(ReqDx))   

                {  

                    RETAILMSG(lqm_bakdbg,(TEXT("[lqm:BKL] Received IOCTL_POWER_SET=%d/r/n"), ReqDx));  

                    if( ReqDx == (CEDEVICE_POWER_STATE)D2 || ReqDx == (CEDEVICE_POWER_STATE)D3)  

                    bklStatus = (CEDEVICE_POWER_STATE)D4;  

                    else  

                    bklStatus = ReqDx;  

  

                    //SetEvent(g_evtBacklight);  

                    // 调整亮度值后调用函数执行调整  

                    BAK_hw_setBL();  

                    *(PCEDEVICE_POWER_STATE) pBufOut = bklStatus;  

                    *pdwActualOut = sizeof(CEDEVICE_POWER_STATE);  

                    bRc = TRUE;  

                    dwErr = ERROR_SUCCESS;  

                    RETAILMSG(lqm_bakdbg, (TEXT("[lqm:BKL] IOCTL_POWER_SET to D%d /r/n"), ReqDx));  

                }  

                else   

                {  

                    bRc = FALSE;  

                    RETAILMSG(DBGBAK1, (TEXT("<BKL> Invalid state request D%d/r/n"), ReqDx));  

                }  

            }  

            __except(EXCEPTION_EXECUTE_HANDLER)   

            {  

                RETAILMSG(DBGBAK1, (TEXT("<BKL> Exception in ioctl/r/n")));  

            }  

        }  

        else      

        {     

            bRc = FALSE;  

        }  

        break;  

      

    case IOCTL_POWER_GET: // gets the current device power state  

        RETAILMSG(DBGBAK, (TEXT("<BKL> Received IOCTL_POWER_GET/r/n/n")));      

        if (pBufOut != NULL && dwLenOut >= sizeof(CEDEVICE_POWER_STATE))   

        {  

            __try   

            {  

                *(PCEDEVICE_POWER_STATE)pBufOut = getBacklightStatus();  

  

                bRc = TRUE;  

                dwErr = ERROR_SUCCESS;  

  

                RETAILMSG(DBGBAK, (TEXT("<BKL> IOCTL_POWER_GET: passing back %u/r/n"), getBacklightStatus()));  

            }  

            __except(EXCEPTION_EXECUTE_HANDLER)   

            {  

                RETAILMSG(DBGBAK1, (TEXT("<BKL> Exception in ioctl/r/n")));  

            }  

        }  

        else          

            bRc = FALSE;  

        break;  

    // 背光亮度调节  

    case IOCTL_BACKLIGHT_ADJUST:          

         if (pBufOut != NULL && (dwLenOut>=sizeof(DWORD)))  

         {  

            DWORD dwBackLight = *((DWORD*)pBufOut);  

            if((BAK_LEVEL_MAX <dwBackLight) || (BAK_LEVEL_MIN > dwBackLight ))  

            {  

                *(DWORD*)pBufOut = ERROR_INVALID_PARAMETER;  

                *pdwActualOut = sizeof(DWORD);  

  

                bRc = FALSE;  

            }  

            else  

            {  

                BAK_AdjuctBacklightLevel(*(DWORD*)pBufOut);  

                // Adjust backlight level.  

                *(DWORD*)pBufOut = ERROR_SUCCESS;  

                *pdwActualOut = sizeof(DWORD);  

                bRc = TRUE;  

            }  

         }  

         else  

         {  

            bRc = FALSE;  

         }  

        break;  

    case IOCTL_BACKLIGHT_GETLEVEL:                

         if (pBufOut != NULL && (dwLenOut>=sizeof(DWORD)))  

         {  

            // Return the current backlight level.  

            *(DWORD*)pBufOut = l_dwBackLightLevel;  

            *pdwActualOut = sizeof(DWORD);  

            bRc = TRUE;  

         }  

         else  

         {  

            bRc = FALSE;  

         }  

        break;    

     }  

    return(bRc);  

}  

 

可以看到有如下几个case:

IOCTL_POWER_CAPABILITIES;

IOCTL_POWER_QUERY;

IOCTL_POWER_SET;

IOCTL_POWER_GET;

IOCTL_BACKLIGHT_ADJUST;

IOCTL_BACKLIGHT_GETLEVEL;

其中

IOCTL_POWER_CAPABILITIES:代表电源管理器请求设备驱动返回设备支持的电源状态及相关特征;

IOCTL_POWER_SET:请求驱动更新设备的电源状态;
IOCTL_POWER_QUERY:电源管理器询问设备是否准备好进行状态切换;
IOCTL_POWER_GET:请求驱动返回当前设备的电源状态;

IOCTL_BACKLIGHT_ADJUST:调节背光亮度的接口;

IOCTL_BACKLIGHT_GETLEVEL:获取背光亮度级别的接口。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: