📄 hw_pwm.c
字号:
/*********************************************************************************
* Copyright (C),2004-2005, Fuzhou Rockchip Co.,Ltd.
* All Rights Reserved
* V1.00
* FileName : Hw_pwm.c
* Author : lzy
* Description:
* History :
* <author> <time> <version> <desc>
* lzy 07/23/29 1.0 ORG
$Log: Hw_pwm.c,v $
Revision 1.4 2008/07/21 03:31:55 Administrator
PWM 频率切换 BUG!
Revision 1.3 2008/06/19 04:43:33 Administrator
代码整理!
Revision 1.2 2008/05/29 12:34:38 HXY
PWM_Stop中恢复关闭PWM clock的动作,以便背光灭时关闭PWM clock
Revision 1.1.1.1 2008/05/07 04:15:08 Administrator
no message
Revision 1.1.1.1 2008/03/06 13:29:07 Lingzhaojun
no message
Revision 1.8 2007/11/16 09:46:39 Lingzhaojun
提交linzhenyuan驱动修改
Revision 1.7 2007/11/10 04:29:33 Huangxinyu
调试修改
Revision 1.6 2007/11/02 03:55:15 Xiexiuxin
更改 PWM_PowerOnInit
Revision 1.5 2007/10/23 08:26:12 Huangxinyu
调试后修改bug
Revision 1.4 2007/10/15 09:18:49 Huangxinyu
根据RK27提交修改driver
Revision 1.3 2007/10/08 02:38:46 Lingzhaojun
添加版本自动注释脚本
*log : HJ 07/10/19
修改PWM_PowerOnInit,增加Scu_ClockEnable()
去除变量pwmfreq
修改PWM_SetFreq()接口
*********************************************************************************/
#include "include.h"
#include "hw_include.h"
#include "hw_pwm.h"
#include "hw_pll.h"
void PWM_SetFreq(PWM_CH_t pwm_ch, UINT32 nHz);
void PWM_SetRate(PWM_CH_t pwm_ch, UINT32 rate);
static pPWMReg_t pPWMReg[4] =
{
(pPWMReg_t)APB0_PWM_BASE,
(pPWMReg_t)(APB0_PWM_BASE + 0x10),
(pPWMReg_t)(APB0_PWM_BASE + 0x20),
(pPWMReg_t)(APB0_PWM_BASE + 0x30)
};
static UINT32 PwmFreq[PWM_MAX_CH] = {NULL, NULL, NULL, };
static UINT32 PwmRate[PWM_MAX_CH] = {NULL,NULL,NULL,};
#define PWM_DIV PWM_DIV2 // PWM_DIV32
/**************************************************************************
* 函数描述: 初始化PWM, freq (1~~1024)
* 入口参数: pwm_ch: PWM 通道号
* nHz: 默认PWM 频率(Hz),
* rate: 默认占空比( 高电平时间/ 总时间) 0 -100
* 出口参数: 无
* 返回值: 无
***************************************************************************/
BOOL PWM_Init(PWM_CH_t pwm_ch, UINT32 nHz, UINT32 rate)
{
UINT32 divh;
if ((nHz == 0) || (pwm_ch >= PWM_MAX_CH) || (rate > 100))
return FALSE;
Scu_ClockEnable(PWM_CLOCK);
PwmFreq[pwm_ch] = nHz;
PwmRate[pwm_ch] = rate;
pPWMReg[pwm_ch]->PWM_CTRL = PWM_DIV | PWM_RESET;
divh = (1000 * Pll_get_apb_freq()) / nHz;
divh = divh >> (1 + (PWM_DIV >> 9));
pPWMReg[pwm_ch]->PWM_LRC = (0 == divh) ? 1 : divh;
PWM_SetRate(pwm_ch, rate);
pPWMReg[pwm_ch]->PWM_CNTL = 0x0;
pPWMReg[pwm_ch]->PWM_CTRL = PWM_DIV | PWM_ENABLE | PWM_TimeEN;
return TRUE;
}
/**************************************************************************
* 函数描述: 停止PWM 输出
* 入口参数: pwm_ch: PWM 通道号
* 出口参数: 无
* 返回值: 无
***************************************************************************/
void PWM_Stop(PWM_CH_t pwm_ch)
{
pPWMReg[pwm_ch]->PWM_CTRL &= ~(PWM_ENABLE | PWM_TimeEN);
#if (RK2710 != CHIPTYPE)
Scu_ClockDisable(PWM_CLOCK);
#endif
}
/**************************************************************************
* 函数描述: 停止PWM 输出
* 入口参数: pwm_ch: PWM 通道号
* 出口参数: 无
* 返回值: 无
***************************************************************************/
void PWM_DeInit(PWM_CH_t pwm_ch)
{
pPWMReg[pwm_ch]->PWM_CTRL &= ~(PWM_ENABLE | PWM_TimeEN);
PwmRate[pwm_ch] = 0;
PwmFreq[pwm_ch] = 0;
Scu_ClockDisable(PWM_CLOCK);
}
/**************************************************************************
* 函数描述: 调整PWM 占空比
* 入口参数: pwm_ch: PWM 通道号
* rate: 默认占空比(0~~100 高电平时间/ 总时间)
* 出口参数: 无
* 返回值: 无
***************************************************************************/
void PWM_SetRate(PWM_CH_t pwm_ch, UINT32 rate)
{
UINT32 divh, divtotal;
Scu_ClockEnable(PWM_CLOCK);
PwmRate[pwm_ch] = rate;
divtotal = ReadReg32(&pPWMReg[pwm_ch]->PWM_LRC);
//divtotal = pPWMReg[pwm_ch]->PWM_LRC;
divh = divtotal * rate / 100;
pPWMReg[pwm_ch]->PWM_HRC = divh ? divh : 1;
pPWMReg[pwm_ch]->PWM_CTRL |= PWM_ENABLE | PWM_TimeEN;
}
/**************************************************************************
* 函数描述: 根据APB 频率调整PWM 参数
* 入口参数: APBfreq: APB 频率(Hz)
* 出口参数: 无
* 返回值: 无
***************************************************************************/
void PWM_UpdateApbFreq(PWM_CH_t pwm_ch, UINT32 nKHz)
{
UINT32 divl, divh, divtotal, pwmfreq, tmp;
DECLARE_CUP_SR;
Scu_ClockEnable(PWM_CLOCK);
//divl = pPWMReg[pwm_ch]->PWM_LRC;
//divh = pPWMReg[pwm_ch]->PWM_HRC;
pwmfreq = PwmFreq[pwm_ch];
if (pwmfreq)
{
// add to avoid other code interrupt the setting to change PWM frequence. lzy 4.14
ENTER_CRITICAL();
tmp = (1000 * nKHz) / pwmfreq;
tmp = tmp >> (1 + (PWM_DIV >> 9));
divtotal = (0 == tmp) ? 1 : tmp;
tmp = divtotal*PwmRate[pwm_ch]/100;
pPWMReg[pwm_ch]->PWM_CNTL = 0x0;
pPWMReg[pwm_ch]->PWM_LRC = divtotal;
pPWMReg[pwm_ch]->PWM_HRC = tmp;
EXIT_CRITICAL();
}
}
/**************************************************************************
* 函数描述: 根据APB 频率调整所有PWM 通道的频率参数
* 入口参数: APBfreq: APB 频率(KHz)
* 出口参数: 无
* 返回值: 无
***************************************************************************/
void PWM_UpdateAllApbFreq(UINT32 nKHz)
{
UINT16 cnt = PWM_MAX_CH;
while (cnt)
{
PWM_UpdateApbFreq(cnt - 1, nKHz);
cnt--;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -