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

 背光驱动程序设计

 

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

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

    首先设置prescaler value:

    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:

    static void BAK_SetTCNTB( DWORD v_Tcntb) { if(v_Tcntb<=0xffff) { v_pPWMRegs->TCNTB1 = v_Tcntb; } }

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

static void BAK_SetTCMPB( DWORD v_Tcmpb) { if(v_Tcmpb<=0xffff) { v_pPWMRegs->TCMPB1 = v_Tcmpb; } }

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

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个级别):

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的代码如下:

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:获取背光亮度级别的接口。

部分接口的具体调用见下一篇,背光调节的应用程序设计。

你可能感兴趣的:(基于S3C2450 + WINCE的背光驱动及背光亮度调节应用程序移植详解之驱动篇[原创])