Topic:S5PC100的pwm的背光控制(作者:Baiduluckyboy)
//------------------------------------------------------------------------------------------------------------------------------
// Topic:S5PC100的pwm的背光控制(作者:Baiduluckyboy)
// 作者:Baiduluckyboy(wangyuluyulu@126.com)
// 论坛账号:Baiduluckyboy (经常在CSDN出没)
// 版权:解放军电子工程学院Baiduluckyboy(wangyuluyulu@126.com)
// 平台:wince6.0.0 S5PC100 BSP
// 发布日期:2010-09-08
// 最后修改:
// 注意事项:未经作者同意,商业网站不能转载,并且不得在转载的时候擅自修改、删除文章的任何部分
//------------------------------------------------------------------------------------------------------------------------------
/****************************************Copyright (c)**************************************************
**--------------File Info-------------------------------------------------------------------------------
** File Name: pwm.c
** Last modified Date: 2010-7-09
** Last Version: V1.0
** Description: S5PC100 PWM 驱动
** This driver uses PWM with Timer0 or Timer1, the ouput is TOUT0 or TOUT1
**------------------------------------------------------------------------------------------------------
** Created By: muscle boy
** Created date: 2010-7-09
** Version: V1.0
** Descriptions: The original version
**
**------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
** Version:
** Description:
**
********************************************************************************************************/
#include <windows.h>
#include <ceddk.h>
#include <s5pc100.h>
#include <backlight_pdd.h>
#define PRIVATE static
#define PUBLIC
#define IOCTL_PWM_SET_PRESCALER 1
#define IOCTL_PWM_SET_DIVIDER 2
#define IOCTL_PWM_START 3
#define IOCTL_PWM_GET_FREQUENCY 4
///LED
#define SMDKC100_LED2 GPH14_Output
#define SMDKC100_LED3 GPH15_Output
#define SMDKC100_LED4 GPH16_Output
#define SMDKC100_LED5 GPH17_Output
/* GPIO,PWM 寄存器对应的虚拟地址 */
PRIVATE volatile S5PC100_GPIO_REG * v_GPIOregs;
PRIVATE volatile S5PC100_PWM_REG * v_PWMregs;
PRIVATE DWORD g_OpenCount = 0;
void PWM_SetPrescaler(BYTE t_num, BYTE value);
BOOL PWM_SetDivider(BYTE t_num, BYTE value);
/muscle boy
/*******************************************************************************************
函数名称: PWM_ConfigPin
描 述: 初始化 GPB0 为 TOUT0 功能
输入参数: DWORD t_num: 定时器编号: 0 或 1
输出参数: 无
返 回: 无
********************************************************************************************/
PRIVATE void PWM_ConfigPin(DWORD t_num)//ok
{
if (t_num == 0)
{
// TOUT0口设置
Set_PinData(v_GPIOregs, GPD00_TOUT_0,1);
Set_PinFunction(v_GPIOregs,GPD00_TOUT_0);
}
else if (t_num == 1)
{
// TOUT1口设置
Set_PinData(v_GPIOregs, GPD01_TOUT_1,1);
Set_PinFunction(v_GPIOregs,GPD01_TOUT_1);
}
}
/*******************************************************************************************
函数名称: PWM_ConfigPWMDefault
描 述: 恢复 PWM0 和 PWM1 的硬件为默认值
输入参数: DWORD t_num: 定时器编号: 0 或 1
输出参数: 无
返 回: 无
********************************************************************************************/
PRIVATE void PWM_ConfigPWMDefault(DWORD t_num)//OK
{
if (t_num == 0)
{
// TOUT0口设置
v_GPIOregs->GPDCON &= ~(0x03 << 0); // rGPBCON[1:0] = 00b,设置GPD0 为输入GPIO
v_GPIOregs->GPDPUD &= ~(0x1 << 0); // 上拉
v_PWMregs->TCFG0 &= ~0xFF; // Timer0 预分频恢复为0
v_PWMregs->TCFG1 &= ~0x0F; // MUX0
v_PWMregs->TCON &= ~0x1F; // Timer0 TCON
v_PWMregs->TCNTB0 = 0; // 定时值(PWM周期)
v_PWMregs->TCMPB0 = 0; // 设置PWM占空比
}
if (t_num == 1)
{
// TOUT1口设置
v_GPIOregs->GPBCON &= ~(0x03 << 2); // rGPBCON[1:0] = 00b,设置GPB1 为输入GPIO
v_GPIOregs->GPDPUD &= ~(0x1 << 1); // 上拉
v_PWMregs->TCFG0 &= ~0xFF; // Timer1 预分频恢复为0
v_PWMregs->TCFG1 &= ~(0x0F << 4); // MUX1
v_PWMregs->TCON &= ~(0xF << 8); // Timer1 TCON
v_PWMregs->TCNTB1 = 0; // 定时值(PWM周期)
v_PWMregs->TCMPB1 = 0; // 设置PWM占空比
}
}
/*******************************************************************************************
函数名称: PWM_InitializeAddresses
描 述: 取得相关寄存器的虚拟地址
输入参数: 无
输出参数: 无
返 回: > 0 分配到的虚拟地址; FALSE: 失败
********************************************************************************************/
BOOL PWM_InitializeAddresses(void)//OK
{
BOOL bRet = TRUE;
PHYSICAL_ADDRESS ioPhysicalBase = {0,0};
ioPhysicalBase.LowPart = S5PC100_BASE_REG_PA_GPIO;
v_GPIOregs = (volatile S5PC100_GPIO_REG *)MmMapIoSpace(ioPhysicalBase, sizeof(S5PC100_GPIO_REG), FALSE);
if (v_GPIOregs == NULL)
{
// RETAILMSG(1, (TEXT("[BKL_PDD] v_pGPIORegs MmMapIoSpace() Failed /n/r")));
return FALSE;
}
ioPhysicalBase.LowPart = S5PC100_BASE_REG_PA_PWM;
v_PWMregs = (volatile S5PC100_PWM_REG *)MmMapIoSpace(ioPhysicalBase, sizeof(S5PC100_PWM_REG), FALSE);
if (v_PWMregs == NULL)
{
// RETAILMSG(1, (TEXT("[BKL_PDD] v_pPWMRegs MmMapIoSpace() Failed /n/r")));
return FALSE;
}
if (v_GPIOregs)
{
v_GPIOregs->GPDPUD = v_GPIOregs->GPDPUD&(~(3<<0)); //GPD0 Pull-up/down disabled
}
return TRUE;
}
/*******************************************************************************************
函数名称: PWM_SetPrescaler
描 述: 设置定时器 0 和 1 的预分频值
输入参数: BYTE t_num: 定时器编号: 0 或 1
BYTE value: 预分频值, 值从 0 ~ 255
输出参数: 无
返 回: 无
********************************************************************************************/
void PWM_SetPrescaler(BYTE t_num, BYTE value)//OK PWM_SetPrescaler(0, PWM0_1_PRESCALER)
{
if ((t_num == 0) || (t_num == 1))
{
v_PWMregs->TCFG0 &= ~0xFF;
v_PWMregs->TCFG0 |= (value<<0); // 设置定时器 0,1 的预分频值
}
}
/*******************************************************************************************
函数名称: PWM_SetDivider
描 述: 设置定时器 0 和 1 的分频器分频值
输入参数: BYTE t_num: 定时器编号: 0 或 1
BYTE value: 分频值: 2,4,8,16
输出参数: 无
返 回: TRUE: 成功; FALSE: 失败
********************************************************************************************/
BOOL PWM_SetDivider(BYTE t_num, BYTE value)//OK PWM_SetDivider(0, 2)
{
BYTE tmp;
if ((t_num > 1) || (value > 16))
return FALSE;
for (tmp = 0; tmp < 4; tmp++)
{
if ((2 << tmp) == value)
break;
}
if (tmp > 4)
return FALSE; // value 取值只能为 2,4,8,16
if (t_num == 0)
{
v_PWMregs->TCFG1 &= ~0x0F;
v_PWMregs->TCFG1 |= tmp;
}
else
{
v_PWMregs->TCFG1 &= ~(0x0F << 4);
v_PWMregs->TCFG1 |= (tmp << 4);
}
return TRUE;
}
/*******************************************************************************************
函数名称: PWM_StartPWM
描 述: 设置定时器 0 或 1 的周期和占空比, 并启动 pwm
输入参数: DWORD t_num: 定时器编号: 0 或 1
DWORD cycle: 取值为 0 ~ 65535
DWORD duty : 取值为 0 ~ 63535
输出参数: 无
返 回: TRUE: 成功; FALSE: 失败
注 意: 占空比为 duty / cycle
********************************************************************************************/
BOOL PWM_StartPWM(DWORD t_num, DWORD cycle, DWORD duty)//OK PWM_StartPWM(0, 100, 50)
{
DWORD tmp;
if ((cycle > 65535)||(duty > 65535))
{
return FALSE;
}
if ((duty > cycle)||(t_num > 1))
{
return FALSE;
}
if (t_num == 0)
{
PWM_ConfigPin(0);
PWM_SetPrescaler(0, PWM0_1_PRESCALER);
PWM_SetDivider(0, 2);
v_PWMregs->TCNTB0 = cycle & 0xFFFF; // 定时值(PWM周期)
v_PWMregs->TCMPB0 = duty & 0xFFFF; // 设置PWM占空比
v_PWMregs->TCON &= ~0x1f;//TCON[8:11]清零(包括停止定时器)
v_PWMregs->TCON |= 0xF;//启用手动更新,立刻把TCNTB寄存器数值载入TCNT
v_PWMregs->TCON &=~0x2;//启用手动更新,立刻把TCNTB寄存器数值载入TCNT
}
else
{
PWM_ConfigPin(1);
v_PWMregs->TCNTB1 = cycle & 0xFFFF; // 定时值(PWM周期)
v_PWMregs->TCMPB1 = duty & 0xFFFF; // 设置PWM占空比
v_PWMregs->TCON &= ~0xf;//TCON[8:11]清零(包括停止定时器)
v_PWMregs->TCON |= 0xF;//启用手动更新,立刻把TCNTB寄存器数值载入TCNT
v_PWMregs->TCON &=~0x2;//启用手动更新,立刻把TCNTB寄存器数值载入TCNT
}
return TRUE;
}
/*******************************************************************************************
函数名称: PWM_Init
描 述: 驱动程序初始化函数
输入参数: DWORD dwContext: 设备管理器传递给本驱动的参数, 通常为流接口驱动在注册表内的位置
输出参数: 无
返 回: 驱动程序句柄
*******************************************************************************************/
PUBLIC DWORD BKL_Init(DWORD dwContext)
{
PWM_InitializeAddresses();
// RETAILMSG(1, (TEXT("::: PWM_Init Sucessfully. /r/n")));
PWM_StartPWM(0, 5000, 2500);
//Set_PinFunction(v_GPIOregs,SMDKC100_LED2); //LED OUTPUT
return (DWORD)1;
}
/*******************************************************************************************
函数名称: DllEntry
描 述: 驱动程序动态库入口
输入参数:
输出参数:
返 回:
*******************************************************************************************/
PUBLIC BOOL WINAPI
DllEntry(HANDLE hInstDll, DWORD dwReason, LPVOID lpvReserved)
{
switch ( dwReason )
{
case DLL_PROCESS_ATTACH:
RETAILMSG(0, (TEXT("PWM: DLL_PROCESS_ATTACH/r/n")));
DisableThreadLibraryCalls((HMODULE) hInstDll);
break;
case DLL_PROCESS_DETACH:
RETAILMSG(1, (TEXT("PWM: DLL_PROCESS_DETACH/r/n")));
break;
}
return (TRUE);
}
/*******************************************************************************************
函数名称: PWM_Close
描 述: 驱动程序关闭函数
输入参数: DWORD Handle: 驱动程序引用事例句柄
输出参数: 无
返 回: FALSE: 失败 TRUE: 成功
*******************************************************************************************/
BOOL BKL_Close(DWORD Handle)
{
if (g_OpenCount > 0)
{
PWM_ConfigPWMDefault(0);
PWM_ConfigPWMDefault(1);
}
g_OpenCount = 0;
return TRUE;
}
/*******************************************************************************************
函数名称: PWM_Deinit
描 述: 驱动程序卸载函数
输入参数: DWORD dwContext: 驱动程序句柄
输出参数: 无
返 回: FALSE: 失败 TRUE: 成功
*******************************************************************************************/
BOOL BKL_Deinit(DWORD dwContext)
{
PWM_ConfigPWMDefault(0); /* 恢复 PWM 相关硬件为默认值 */
PWM_ConfigPWMDefault(1);
// 释放申请的虚拟空间
if (v_GPIOregs)
VirtualFree((PVOID) v_GPIOregs, 0, MEM_RELEASE);
if (v_PWMregs)
VirtualFree((PVOID) v_PWMregs, 0, MEM_RELEASE);
return TRUE;
}// PWM_Deinit
/*******************************************************************************************
函数名称: PWM_Open
描 述: 打开驱动程序
输入参数: DWORD dwData : 设备驱动程序句柄
DWORD dwAccess : 访问请求代码,是读和写的组合
DWORD dwShareMode: 共享模式
输出参数:
返 回: 驱动程序引用事例句柄
*******************************************************************************************/
DWORD BKL_Open(DWORD dwData, DWORD dwAccess, DWORD dwShareMode)
{
if (g_OpenCount > 0)
return 0;
PWM_ConfigPWMDefault(0); /* 恢复 PWM 相关硬件为默认值 */
PWM_ConfigPWMDefault(1);
g_OpenCount++;
return g_OpenCount;
}
/*******************************************************************************************
函数名称: PWM_IOControl
描 述: 驱动程序 I/O 请求
输入参数:
输出参数:
返 回: TRUE: 成功 FALSE: 失败
*******************************************************************************************/
BOOL
BKL_IOControl(
DWORD Handle,
DWORD dwIoControlCode,
PBYTE pInBuf,
DWORD nInBufSize,
PBYTE pOutBuf,
DWORD nOutBufSize,
PDWORD pBytesReturned
)
{
BOOL bErr = FALSE;
switch (dwIoControlCode)
{
case IOCTL_PWM_SET_PRESCALER: /* 设置预分频值 */
PWM_StartPWM(0, 5000, 2500);
bErr = TRUE;
Set_PinData(v_GPIOregs, SMDKC100_LED2, 1);//LED DENG
RETAILMSG(1, (TEXT("PWM: IOCTL_PWM_SET_PRESCALER/r/n")));
break;
case IOCTL_PWM_SET_DIVIDER:
break;
case IOCTL_PWM_START:
PWM_StartPWM(0, 5000, 2000);
bErr = TRUE;
Set_PinData(v_GPIOregs, SMDKC100_LED2, 0);//LED DENG
RETAILMSG(1, (TEXT("PWM: IOCTL_PWM_START/r/n")));
break;
case IOCTL_PWM_GET_FREQUENCY:
break;
default:
break;
}
return bErr;
}
// PWM_IOControl
/*******************************************************************************************
函数名称: PWM_Read
描 述: 从 IIC 从机读取数据
输入参数: DWORD Handle : 驱动程序引用事例句柄
LPVOID pBuffer : 接收缓冲区
DWORD dwNumBytes: 要读的字节数
输出参数: 无
返 回: 实际读到字节数
*******************************************************************************************/
DWORD BKL_Read(DWORD Handle, LPVOID pBuffer, DWORD dwNumBytes)
{
return 0;
}
/*******************************************************************************************
函数名称: PWM_Write
描 述: 向 IIC 从机发送数据
输入参数:
输出参数:
返 回: 成功发送的字节数
*******************************************************************************************/
DWORD BKL_Write(DWORD Handle, LPCVOID pBuffer, DWORD dwNumBytes)
{
return 0;
}
/*******************************************************************************************
函数名称: PWM_Seek
描 述: 对设备的数据指针进行操作,本驱动不支持该函数
输入参数:
输出参数:
返 回:
*******************************************************************************************/
DWORD BKL_Seek(DWORD Handle, long lDistance, DWORD dwMoveMethod)
{
return 0;
}
/*******************************************************************************************
函数名称: pwm_PowerUp
描 述: 电源上电驱动处理函数
输入参数:
输出参数:
返 回: 无
*******************************************************************************************/
void BKL_PowerUp(void)
{
return;
}
/*******************************************************************************************
函数名称: pwm_PowerDown
描 述: 电源下电驱动处理函数
输入参数:
输出参数:
返 回: 无
*******************************************************************************************/
void BKL_PowerDown(void)
{
return;
}
以上是我的pwm控制的驱动程序,经过自己测试已经通过,主要是通过在按键中断里面根据按键按下的长短来产生不同的PWM占空比,进行背光的控制。
如有不妥之处,请各位同仁指正,愿我们共同交流,共同进步。请给我留言。。。。