388 lines
10 KiB
C
388 lines
10 KiB
C
/***************************************************************
|
||
*Copyright (C), 2017, Shanghai Eastsoft Microelectronics Co., Ltd
|
||
*文件名: lib_scu.c
|
||
*作 者: Liut
|
||
*版 本: V1.00
|
||
*日 期: 2017/07/14
|
||
*描 述: 系统控制模块库函数
|
||
*备 注: 适用于 ES8P508x芯片
|
||
本软件仅供学习和演示使用,对用户直接引用代码所带来的风险或后果不承担任何法律责任。
|
||
***************************************************************/
|
||
#include "lib_scu.h"
|
||
|
||
/***************************************************************
|
||
函数名:SCU_OpenXTAL
|
||
描 述: 开启外部时钟
|
||
输入值:无
|
||
输出值:无
|
||
返回值:系统时钟源
|
||
***************************************************************/
|
||
void SCU_OpenXTAL(void)
|
||
{
|
||
SCU_RegUnLock();
|
||
SCU->SCLKEN1.XTAL_EN = 1;
|
||
SCU->SCLKEN0.XTAL_LP = 0;
|
||
while(SCU->SCLKEN1.XTAL_RDY == 0); //等待外部时钟稳定
|
||
SCU_RegLock() ;
|
||
}
|
||
|
||
/***************************************************************
|
||
函数名:SCU_NMISelect
|
||
描 述:设置NMI不可屏蔽中断
|
||
输入值:不可屏蔽中断
|
||
输出值:无
|
||
返回值:无
|
||
***************************************************************/
|
||
void SCU_NMISelect(SCU_TYPE_NMICS NMI_Type)
|
||
{
|
||
SCU_RegUnLock();
|
||
SCU->NMICON.NMICS = NMI_Type;
|
||
SCU_RegLock() ;
|
||
}
|
||
|
||
/***************************************************************
|
||
函数名:SCU_GetPWRCFlagStatus
|
||
描 述:获取PWRC复位状态寄存器标志位状态
|
||
输入值:PWRC寄存器标志位
|
||
输出值:无
|
||
返回值:RESET/SET
|
||
***************************************************************/
|
||
FlagStatus SCU_GetPWRCFlagStatus(SCU_TYPE_PWRC PWRC_Flag)
|
||
{
|
||
FlagStatus bitstatus = RESET;
|
||
if((SCU->PWRC.Word & (uint32_t)PWRC_Flag) != (uint32_t)RESET)
|
||
bitstatus = SET;
|
||
else
|
||
bitstatus = RESET;
|
||
|
||
return bitstatus;
|
||
}
|
||
|
||
/***************************************************************
|
||
函数名:SCU_ClearPWRCFlagBit
|
||
描 述:清除PWRC复位状态寄存器标志位
|
||
输入值:PWRC寄存器标志位
|
||
输出值:无
|
||
返回值:无
|
||
***************************************************************/
|
||
void SCU_ClearPWRCFlagBit(SCU_TYPE_PWRC PWRC_Flag)
|
||
{
|
||
SCU_RegUnLock() ;
|
||
SCU->PWRC.Word &= ~((uint32_t)PWRC_Flag);
|
||
SCU_RegLock() ;
|
||
}
|
||
|
||
/***************************************************************
|
||
函数名:SCU_GetLVDFlagStatus
|
||
描 述:获取LVDD寄存器标志位状态
|
||
输入值:LVD寄存器标志位
|
||
输出值:无
|
||
返回值:RESET/SET
|
||
***************************************************************/
|
||
FlagStatus SCU_GetLVDFlagStatus(SCU_TYPE_LVD0CON LVD_Flag)
|
||
{
|
||
FlagStatus bitstatus = RESET;
|
||
|
||
if((SCU->LVDCON.Word & (uint32_t)LVD_Flag) != (uint32_t)RESET)
|
||
bitstatus = SET;
|
||
else
|
||
bitstatus = RESET;
|
||
|
||
return bitstatus;
|
||
}
|
||
|
||
/***************************************************************
|
||
函数名:SCU_SysClkSelect
|
||
描 述:选择系统时钟
|
||
输入值:时钟源
|
||
输出值:无
|
||
返回值:无
|
||
***************************************************************/
|
||
void SCU_SysClkSelect(SCU_TYPE_SYSCLK Sysclk)
|
||
{
|
||
SCU_RegUnLock() ;
|
||
SCU->SCLKEN0.CLK_SEL = Sysclk;
|
||
SCU_RegLock() ;
|
||
}
|
||
|
||
/***************************************************************
|
||
函数名:SCU_GetSysClk
|
||
描 述:获取系统时钟源
|
||
输入值:无
|
||
输出值:无
|
||
返回值:系统时钟源
|
||
***************************************************************/
|
||
SCU_TYPE_SYSCLK SCU_GetSysClk(void)
|
||
{
|
||
return (SCU_TYPE_SYSCLK)(SCU->SCLKEN0.CLK_SEL);
|
||
}
|
||
|
||
/***************************************************************
|
||
函数名:SCU_HRCReadyFlag
|
||
描 述:获取HRC稳定标志位
|
||
输入值:无
|
||
输出值:无
|
||
返回值:RESET(不稳定)/SET(稳定)
|
||
***************************************************************/
|
||
FlagStatus SCU_HRCReadyFlag(void)
|
||
{
|
||
FlagStatus bitstatus = RESET;
|
||
|
||
if((SCU->SCLKEN1.HRC_RDY) != (uint32_t)RESET)
|
||
bitstatus = SET;
|
||
else
|
||
bitstatus = RESET;
|
||
|
||
return bitstatus;
|
||
}
|
||
|
||
/***************************************************************
|
||
函数名:SCU_XTALReadyFlag
|
||
描 述:获取XTAL稳定标志位
|
||
输入值:无
|
||
输出值:无
|
||
返回值:RESET(不稳定)/SET(稳定)
|
||
***************************************************************/
|
||
FlagStatus SCU_XTALReadyFlag(void)
|
||
{
|
||
FlagStatus bitstatus = RESET;
|
||
|
||
if((SCU->SCLKEN1.XTAL_RDY) != (uint32_t)RESET)
|
||
bitstatus = SET;
|
||
else
|
||
bitstatus = RESET;
|
||
|
||
return bitstatus;
|
||
}
|
||
|
||
/***************************************************************
|
||
函数名:SCU_LOSCReadyFlag
|
||
描 述:获取LOSC稳定标志位
|
||
输入值:无
|
||
输出值:无
|
||
返回值:RESET(不稳定)/SET(稳定)
|
||
***************************************************************/
|
||
FlagStatus SCU_PLLReadyFlag(void)
|
||
{
|
||
FlagStatus bitstatus = RESET;
|
||
|
||
if((SCU->SCLKEN1.PLL_RDY) != (uint32_t)RESET)
|
||
bitstatus = SET;
|
||
else
|
||
bitstatus = RESET;
|
||
|
||
return bitstatus;
|
||
}
|
||
|
||
/***************************************************************
|
||
函数名:SystemClockConfig
|
||
描 述:系统时钟配置:内部时钟,20MHZ,打开所有外设时钟
|
||
输入值:无
|
||
输出值:无
|
||
返回值:无
|
||
***************************************************************/
|
||
void SystemClockConfig(void)
|
||
{
|
||
uint32_t Prot_Temp;
|
||
|
||
Prot_Temp = SCU->PROT.PROT;
|
||
|
||
if(Prot_Temp != 0) //写保护了
|
||
SCU_RegUnLock(); //解锁
|
||
|
||
SCU_HRC_Enable(); //使能内部20MHZ
|
||
while(SCU_HRCReadyFlag() != SET); //等待时钟开启
|
||
SCU_SysClkSelect(SCU_SysClk_HRC); //选择内部20MHZ为系统时钟
|
||
|
||
SCU_SysClk_Div1(); //系统时钟后分频1:1
|
||
|
||
SystemCoreClock = 20000000;
|
||
|
||
if(Prot_Temp != 0) //写保护了
|
||
SCU_RegLock(); //打开写保护
|
||
}
|
||
|
||
/***************************************************************
|
||
函数名:DeviceClockAllEnable
|
||
描 述:打开所有外设时钟
|
||
输入值:无
|
||
输出值:无
|
||
返回值:无
|
||
***************************************************************/
|
||
void DeviceClockAllEnable(void)
|
||
{
|
||
uint32_t Prot_Temp;
|
||
|
||
Prot_Temp = SCU->PROT.PROT;
|
||
if(Prot_Temp != 0) //写保护了
|
||
SCU_RegUnLock(); //解锁
|
||
|
||
SCU->PCLKEN0.Word = 0xFFFFFFFF;
|
||
SCU->PCLKEN1.Word = 0xFFFFFFFF; //打开所有外设时钟
|
||
|
||
if(Prot_Temp != 0) //写保护了
|
||
SCU_RegLock(); //打开写保护
|
||
}
|
||
|
||
/***************************************************************
|
||
函数名:DeviceClockAllDisable
|
||
描 述:关闭所有外设时钟
|
||
输入值:无
|
||
输出值:无
|
||
返回值:无
|
||
***************************************************************/
|
||
void DeviceClockAllDisable(void)
|
||
{
|
||
uint32_t Prot_Temp;
|
||
|
||
Prot_Temp = SCU->PROT.PROT;
|
||
if(Prot_Temp != 0) //写保护了
|
||
SCU_RegUnLock(); //解锁
|
||
|
||
SCU->PCLKEN0.Word = 0x00000000; //关闭所有外设时钟,scu无法关闭
|
||
SCU->PCLKEN1.Word = 0x00000000;
|
||
|
||
if(Prot_Temp != 0) //写保护了
|
||
SCU_RegLock(); //打开写保护
|
||
}
|
||
|
||
/***************************************************************
|
||
函数名:SystemClockConfig
|
||
描 述:系统时钟选择
|
||
输入值:CLKx 系统时钟源选择
|
||
输出值:无
|
||
返回值:无
|
||
***************************************************************/
|
||
void SystemClockSelect(SCU_TYPE_SYSCLK SYSCLKx , SCU_TYPE_CLK_SEL CLK_SEL)
|
||
{
|
||
SCU_RegUnLock(); //解锁
|
||
|
||
switch(SYSCLKx)
|
||
{
|
||
case 0:
|
||
SCU_HRC_Enable();
|
||
while(SCU_HRCReadyFlag() != SET);
|
||
break;
|
||
case 1:
|
||
SCU_XTAL_Enable();
|
||
while(SCU_XTALReadyFlag() != SET);
|
||
break;
|
||
case 2:
|
||
SCU_PLL_Enable();
|
||
while(SCU_PLLReadyFlag() != SET);
|
||
break;
|
||
default:break;
|
||
}
|
||
|
||
SCU->SCLKEN0.SYSCLK_DIV = 0;
|
||
SCU->SCLKEN0.CLK_SEL = CLK_SEL;
|
||
|
||
SCU_RegLock();
|
||
}
|
||
|
||
|
||
/***************************************************************
|
||
函数名:PLLClock_Config
|
||
描 述:PLL时钟配置,并设置PLL时钟为系统时钟
|
||
输入值:pll_en:是否开启PLL,pll_origin:pll时钟源选择,pll_out:pll输出频率选择,sys_pll:系统时钟是否使用PLL时钟
|
||
输出值:无
|
||
返回值:无
|
||
***************************************************************/
|
||
void PLLClock_Config(TYPE_FUNCEN pll_en , SCU_PLL_Origin pll_origin ,SCU_PLL_Out pll_out,TYPE_FUNCEN sys_pll)
|
||
{
|
||
SCU_RegUnLock();
|
||
|
||
if(pll_en == DISABLE) //如果PLL配置为禁止,则直接禁止PLL,并返回
|
||
{
|
||
SCU->SCLKEN0.PLL_MUX = 0;
|
||
SCU->SCLKEN1.PLL_BYLOCK = 0;
|
||
SCU->SCLKEN0.CLKFLT_BY = 0x00;
|
||
SCU->SCLKEN1.PLL_EN = 0;
|
||
return;
|
||
}
|
||
|
||
if((pll_origin == SCU_PLL_HRC)) //如果使用内部高速时钟,需开启内部高速时钟
|
||
{
|
||
if(SCU->SCLKEN1.HRC_RDY == 0)
|
||
{
|
||
SCU->SCLKEN1.HRC_EN = 1;
|
||
while(SCU->SCLKEN1.HRC_RDY == 0); //等待HRC开启
|
||
}
|
||
}
|
||
|
||
if((pll_origin == SCU_PLL_XTAL_32K)
|
||
|| (pll_origin == SCU_PLL_XTAL_4M)
|
||
||(pll_origin == SCU_PLL_XTAL_8M)
|
||
|| (pll_origin == SCU_PLL_XTAL_16M)
|
||
|| (pll_origin == SCU_PLL_XTAL_20M)) //如果使用外部时钟,需开启外部时钟
|
||
{
|
||
if(SCU->SCLKEN1.XTAL_RDY == 0)
|
||
{
|
||
SCU->SCLKEN1.XTAL_EN = 1;
|
||
SCU->SCLKEN0.XTAL_LP = 0;
|
||
while(SCU->SCLKEN1.XTAL_RDY == 0); //等待XTAL开启
|
||
}
|
||
}
|
||
|
||
switch(pll_origin)
|
||
{
|
||
case SCU_PLL_HRC:
|
||
SCU->SCLKEN1.PLL_REF_SEL = 0x00;
|
||
break;
|
||
case SCU_PLL_LRC:
|
||
SCU->SCLKEN1.PLL_REF_SEL = 0x02;
|
||
break;
|
||
case SCU_PLL_XTAL_32K:
|
||
SCU->SCLKEN1.PLL_REF_SEL = 0x03;
|
||
break;
|
||
case SCU_PLL_XTAL_4M:
|
||
SCU->SCLKEN1.PLL_REF_SEL = 0x04;
|
||
break;
|
||
case SCU_PLL_XTAL_8M:
|
||
SCU->SCLKEN1.PLL_REF_SEL = 0x05;
|
||
break;
|
||
case SCU_PLL_XTAL_16M:
|
||
SCU->SCLKEN1.PLL_REF_SEL = 0x06;
|
||
break;
|
||
case SCU_PLL_XTAL_20M:
|
||
SCU->SCLKEN1.PLL_REF_SEL = 0x07;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
SCU->SCLKEN1.PLL_48M_SEL = pll_out; //配置PLL输出为32或48Mhz
|
||
|
||
SCU->SCLKEN1.PLL_EN = 1;
|
||
while(SCU->SCLKEN1.PLL_RDY == 0);
|
||
|
||
|
||
if(sys_pll == ENABLE)
|
||
{
|
||
|
||
if(pll_out == SCU_PLL_32M)
|
||
{
|
||
SCU->SCLKEN0.CLKFLT_BY = 0;
|
||
}
|
||
else
|
||
{
|
||
SCU->SCLKEN0.CLKFLT_BY = 0x55; //48M 时钟滤波旁路
|
||
}
|
||
SCU->SCLKEN1.PLL_BYLOCK = 1;
|
||
SCU->SCLKEN0.PLL_MUX = 1;
|
||
}
|
||
else
|
||
{
|
||
SCU->SCLKEN0.PLL_MUX = 0;
|
||
SCU->SCLKEN1.PLL_BYLOCK = 0;
|
||
SCU->SCLKEN0.CLKFLT_BY = 0x00;
|
||
}
|
||
|
||
SCU_RegLock();
|
||
}
|
||
|
||
/*************************END OF FILE**********************/
|
||
|
||
|
||
|