HC32F46x底层操作(时钟,IO等初始化)
//相关APIbool SYS_SystemClockInit(SYS_CRYSTAL_SOURCE CrystalSelect, bool PLLEnable, u16 MainClockFreq);//HC32F46X系统主时钟初始化
void SYS_DeviceClockEnable(SYS_DEV_CLOCK DevCloce,bool Enable); //外设时钟使能或关闭控制
void SYS_GPIOx_SetAF(GPIO_TypeDef *GPIOx, u8 io_num, u8 Func); //GPIO复用功能设置(特殊功能一旦选中,无需初始化设置IO)
void SYS_GPIOx_OneInit(GPIO_TypeDef *GPIOx, u8 io_num, SYS_GPIO_MODE mode, SYS_GPIO_DRV GPIO_DRV_x);//初始化一个IO
SYS_CLOCK_SOURCE SYS_GetSystemClockSource(void); //获取系统主时钟来源
u32 SYS_GetPLLClockSpeed(SYS_PLL_TYPE PLLn); //获取PLL时钟频率
u32 SYS_GetHCLKSpeed(void); //获取系统主时钟HCLK速度
u32 SYS_GetClockSpeed(SYS_CLOCK_TYPE ClockSelect); //获取时钟速度
#define SYS_GetPCLK1Speed() SYS_GetClockSpeed(SYS_CLOCK_PCLK1) //获取PCLK1时钟速度
void SYS_GPIO_SetINER(u8 GPIO_Group, bool isEnable); //设置GPIO输入MOS开关
void SYS_GPIO_IntConfig(GPIO_TypeDef *GPIOx, u8 io_num, bool isEnable);//GPIO外部中断配置函数
void SYS_EXTI_SetEdge(EXTI_TYPE EXIT_n, EIRQ_EDGE_TYPE Edge); //设置中断线(事件线)触发边沿
void SYS_EXTI_SetFilter(EXTI_TYPE EXIT_n, EIRQ_FILTER_TYPE Filter); //设置中断线(事件线)滤波
void SYS_EXTI_ClearInt(EXTI_TYPE EXIT_n); //清除外部中断状态
u16 SYS_EXTI_GetInt(void); //获取外部中断状态
void SYS_NVIC_SetVectorTable(u32 NVIC_VectTab, u32 ROM_BaseAddr); //设置向量表地址
void SYS_SoftReset(void); //系统软复位
void SYS_SetJtagMode(SYS_JTAG_MODE mode); //设置JTAG模式
void SYS_EnableIrq(void); //开总中断
void SYS_DisableIrq(void); //关闭总中断
void SystemInit(void); //系统底层初始化-在汇编中调用
void Delay_US(u32 time); //软件us延时
void Delay_MS(u32 time); //软件ms延时
void SYS_DelayMS(u32 ms); //系统毫秒延时
void IWDG_Feed(void); //独立看门狗喂狗(刷新计数值)
bool IWDG_GetEnableStatus(void); //获取独立看门狗开关状态
void MSR_MSP(u32 addr); //设置栈顶地址
//c文件
/*************************************************************************************************************
* 文件名 : hc32f46x_system.h
* 功能 : HC32F46X芯片相关系统操作
* 作者 : cp1300@139.com
* 创建时间 : 2021-06-13
* 最后修改时间 : 2021-06-13
* 详细 : 2021-07-27:修复了由于EFM未解锁配置导致flash延时设置错误,无法使用更高频率运行问题;
2021-07-29:如果是app程序,会自动在初始化函数中调用SYS_NVIC_SetVectorTable()//设置向量表地址
2021-08-08:增加jata模式设置SYS_SetJtagMode();并上电初始化设置为SWD模式
*************************************************************************************************************/
#include "hc32f46x_system.h"
#include "hc32f46x.h"
#include "typedef.h"
#include "stdio.h"
#include "hc32f46x_irq.h"
#include "dma.h"
#define XTAL_CLOCK 8 //外部高速时钟频率 8MHZ
#define HRC_CLOCK_16 16 //内部高速时钟16/20MHz
#define HRC_CLOCK_20 20 //内部高速时钟16/20MHz
#define MRC_CLOCK 8 //内部中速时钟8MHz-系统启动后的默认时钟
static const SYS_XTALSTB_TYPE scg_XTALSTB = SYS_XTALSTB_131; //XTAL时钟稳定周期 ;一个周期0.2442毫秒
volatile u64 g_OS_RunTime = 0; //操作系统运行时间-单位ms
static u32 SYS_GetClockDiv(SYS_CLOCK_TYPE ClockSelect); //获取时钟相对于主时钟的分频值
static void SYS_SetFlashWaitCycle(u8 SysClock); //普通读模式(SLPMRD=0),flash等待周期设置
static void SYS_SetGPIOWaitCycle(u8 SysClock); //设置GPIO读取等待周期
static bool SYS_SetMPLL_P(bool isUseHRC, u16 ClockFreq); //设置MPLL的P通道时钟(用于设置主时钟)
static void SYS_CONFIG_SetLock(bool isLock); //系统时钟电源控制等寄存器上锁与解锁
/*************************************************************************************************************************
* 函数 : bool SYS_SystemClockInit(SYS_CRYSTAL_SOURCE CrystalSelect, bool PLLEnable, u16 MainClockFreq)
* 功能 : HC32F46X系统主时钟初始化
* 参数 : CrystalSelect:时钟晶振源选择;PLLEnable:是否使能PLL,MainClockFreq:系统主时钟频率(PLL开启才有效),15-200MHZ
* 返回 : 是否设置成功
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-06-14
* 最后修改时间 : 2021-06-14
* 说明 : 一定要设置好flash的延时,否则会导致系统无法运行
只有选择SYS_CLOCK_XTAL SYS_CLOCK_HRC 才能使能PLL,只有使能了PLL MainClockFreq参数才有效
会初始化g_mStopWatchClass
2021-07-27:修复了由于EFM未解锁配置导致flash延时设置错误,无法使用更高频率运行问题;
*************************************************************************************************************************/
bool SYS_SystemClockInit(SYS_CRYSTAL_SOURCE CrystalSelect, bool PLLEnable, u16 MainClockFreq)
{
u32 temp;
u32 DelayCount;
bool isStatus = FALSE;
switch(CrystalSelect)
{
case SYS_CRYSTAL_XTAL : //外部高速时钟4-24MHz
{
//去除寄存器写保护
SYS_CONFIG_SetLock(FALSE); //系统时钟电源控制等寄存器上锁与解锁;
//第一步:检查当前是否使用的外部高速时钟,如果是的,请切换到内部时钟
CMU_XTALSTDCR = 0; //CMU XTAL振荡故障控制寄存器复位
//第二步:关闭外部时钟
CMU_XTALCR = 0x01; //XTALSTP位写1,关闭XTAL振荡器,才可以开始后续的设置
DelayCount = 0xFFFFF;
while(CMU_OSCSTBSR & BIT3) //等待XTALSTBF=0,就是XTAL停止了
{
DelayCount --;
if(DelayCount == 0) goto end_loop; //等待超时了
}
//第三步:开始设置XTAL时钟
if(XTAL_CLOCK >= 20) temp = 0;
else if(XTAL_CLOCK >= 16) temp = 1;
else if(XTAL_CLOCK >= 8) temp = 2;
else temp = 3;
temp |= BIT7; //使能高速驱动
CMU_XTALCFGR = temp; //设置到XTAL配置寄存器
CMU_XTALSTBCR = scg_XTALSTB & 0xF; //设置稳定时间 稳定计数器的一个计数周期=LRC周期 /8 ;一个周期0.2442毫秒
//第四步:启动XTAL并等待稳定
CMU_XTALCR = 0; //启动XTAL振荡器
DelayCount = 0xFFFFFF;
while((CMU_OSCSTBSR & BIT3) == 0) //等待XTALSTBF=0,就是XTAL停止了
{
DelayCount --;
if(DelayCount == 0) goto end_loop; //等待超时了
}
//稳定后,如果不使能PLL,直接设置为主时钟
if(PLLEnable == FALSE)
{
CMU_CKSWR = SYS_CLOCK_XTAL; //切换时钟源
CMU_SCFGR = 0; //时钟分频全部为1
isStatus = TRUE;
}
else
{
isStatus = SYS_SetMPLL_P(FALSE, MainClockFreq); //设置MPLL的P通道时钟(用于设置主时钟)
}
}break;
case SYS_CRYSTAL_XTAL32 : //外部低速时钟32.768Khz
case SYS_CRYSTAL_HRC : //内部高速时钟16/20MHz
case SYS_CRYSTAL_MRC : //内部中速时钟8MHz-系统启动后的默认时钟
case SYS_CRYSTAL_LRC : //内部低速时钟32.768Khz
default:goto end_loop;
}
end_loop:
#if(SYS_STOP_WATCH_EN)
g_mStopWatchClass.Init(); //时间测量计时器初始化,必须在系统时钟初始化后进行一次初始化
#endif //SYS_STOP_WATCH_EN
SYS_CONFIG_SetLock(TRUE); //系统时钟电源控制等寄存器上锁与解锁
return isStatus;
}
/*************************************************************************************************************************
* 函数 : static bool SYS_SetMPLL_P(bool isUseHRC, u16 ClockFreq)
* 功能 : 设置MPLL的P通道时钟(用于设置主时钟)
* 参数 : isUseHRC:是否使用内部HRC时钟作为时钟源,否则使用外部时钟;ClockFreq:需要输出的时钟频率
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-06-14
* 最后修改时间 : 2021-06-14
* 说明 : 必须先初始化时钟输入,并等待时钟稳定后才能初始化PLL
不会检查是否使用PLL作为主时钟,设置前必须切换到其它时钟,比如默认的内部中速时钟
不会设置时钟寄存器写保护
*************************************************************************************************************************/
static bool SYS_SetMPLL_P(bool isUseHRC, u16 ClockFreq)
{
u32 DelayCount;
u32 TempReg = 0;
u32 M; //VCO输入分频
u32 P; //VCO输出分频,只能从2-16分频
u32 N; //VCO倍频
u32 PLLCFGR; //记录CMU_PLLCFGR的值
CMU_PLLCR = 1; //PLL停止
DelayCount = 0xFFFFF;
while(CMU_OSCSTBSR & BIT5) //等待MPLLSTBF=0,就是MPLL停止
{
DelayCount --;
if(DelayCount == 0) return FALSE; //等待超时了
}
PLLCFGR = CMU_PLLCFGR; //记录CMU_PLLCFGR的值
//清除 PLLCFGR M,P,N,PLLSRC的值
PLLCFGR &= ~(((u32)0xF<<28) | (0x1FF<<8) | BIT7 | 0x1F);
if(isUseHRC) //使用内部高速时钟,频率为16MHz
{
M = HRC_CLOCK_16;
TempReg |= BIT7; //1:选择内部高速振荡器作为 MPLL/UPLL的输入时钟
}
else //使用外部高速时钟
{
M = XTAL_CLOCK;
}
M -= 1;
TempReg |= M & 0x1F; //VCO输入分频,确保输入频率为1MHz,便于后面倍频
//根据要输出的时钟范围,设置倍频系数N以及分频系数P N:240-480,P:2-16也就是输出范围为:15~200
if(ClockFreq < 15) ClockFreq = 15; //最小频率限制
if(ClockFreq > 200) ClockFreq = 200; //最大频率限制
if(ClockFreq <= 30) //15-30
{
P = PLL_DIV_16; //16分频输出
N = 16 * ClockFreq; //计算VCO频率
}
else if(ClockFreq <= 60) //30-60
{
P = PLL_DIV_8; //8分频输出
N = 8 * ClockFreq; //计算VCO频率
}
else if(ClockFreq <= 120) //60-120
{
P = PLL_DIV_4; //4分频输出
N = 4 * ClockFreq; //计算VCO频率
}
else if(ClockFreq <= 200) //120-200
{
P = PLL_DIV_2; //2分频输出
N = 2 * ClockFreq; //计算VCO频率
}
TempReg |= P << 28; //系统时钟用MPLL分频
N -= 1;
TempReg |= N << 8; //MPLL倍频系数
TempReg |= PLLCFGR;
CMU_PLLCFGR = TempReg;
//启动MPLL并等待稳定
CMU_PLLCR = 0; //启动MPLL
DelayCount = 0xFFFFFF;
while((CMU_OSCSTBSR & BIT5) == 0) //等待MPLLSTBF=1,就是MPLL稳定
{
DelayCount --;
if(DelayCount == 0) return FALSE; //等待超时了
}
//等待MPLL稳定后,设置各个时钟分频,优先使用最高时钟,确保不超出最大时钟范围
TempReg = 0;
//先设置HCLK时钟,最大200MHz,设置为0,系统时钟1分频
if(ClockFreq > 100) TempReg |= 1<<20; //大于100M后ExMC时钟2分频
if(ClockFreq > 100) TempReg |= 1<<16; //大于100M后PCLK4时钟2分频
//PCLK 3最大50MHz
if(ClockFreq > 100) TempReg |= 2 << 12; //大于100MHz后4分频
else if(ClockFreq > 50) TempReg |= 1 << 12; //大于50MHz后2分频
//PCLK 2最大60MHz
if(ClockFreq > 120) TempReg |= 2 << 8; //大于120MHz后4分频
else if(ClockFreq > 60) TempReg |= 1 << 12; //大于60MHz后2分频
if(ClockFreq > 100) TempReg |= 1<<4; //大于100M后PCLK 1时钟2分频
if(ClockFreq > 100) TempReg |= 1<<0; //大于100M后PCLK 0时钟2分频
CMU_SCFGR = TempReg; //时钟分频寄存器设置
//开始设置flash等待周期
SYS_SetFlashWaitCycle(ClockFreq); //普通读模式(SLPMRD=0),flash等待周期设置
//设置GPIO读取等待周期
SYS_SetGPIOWaitCycle(ClockFreq); //设置GPIO读取等待周期
//稳定后,更换时钟源
CMU_CKSWR = SYS_CLOCK_MPLL; //切换时钟源
nop;nop;nop;nop;
if(CMU_CKSWR == SYS_CLOCK_MPLL) return TRUE;
return FALSE;
}
/*************************************************************************************************************************
* 函数 : static void SYS_SetFlashWaitCycle(u8 SysClock)
* 功能 : 普通读模式(SLPMRD=0),flash等待周期设置
* 参数 : SysClock:系统主时钟,单位MHZ
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-06-14
* 最后修改时间 : 2021-06-14
* 说明 : 要求电源电压必须在2.7~3.6V之间,建议为3.3V
2021-07-27:修复了由于EFM未解锁导致配置未成功问题;
*************************************************************************************************************************/
static void SYS_SetFlashWaitCycle(u8 SysClock)
{
u32 temp = EFM->FRMC;
temp &=~(0xF<<4); //清除设置
if(SysClock <= 33) temp|=0<<4; //0等待
if(SysClock <= 66) temp|=1<<4; //1等待
if(SysClock <= 99) temp|=2<<4; //2等待
if(SysClock <= 132) temp|=3<<4; //3等待
if(SysClock <= 168) temp|=4<<4; //4等待
if(SysClock <= 200) temp|=5<<4; //5等待
else temp|=15<<4; //15等待
SYS_EFM_CONFIG_Unlock(); //EFM寄存器解锁
while(EFM->FRMC != temp) //设置并判断是否配置成功
{
EFM->FRMC = temp; //设置等待周期
nop;nop;nop;nop;nop;
}
SYS_EFM_CONFIG_Lock(); //EFM寄存器配置上锁
}
/*************************************************************************************************************************
* 函数 : void SYS_EnableFlashCache(bool isEnable)
* 功能 : 是否使能flash cache
* 参数 : isEnable:TRUE:使能;FALSE:失能
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-06-25
* 最后修改时间 : 2021-06-25
* 说明 : 2021-07-27:修复了由于EFM未解锁导致配置未成功问题;
*************************************************************************************************************************/
void SYS_EnableFlashCache(bool isEnable)
{
u32 temp = EFM->FRMC;
if(isEnable) temp |= BIT16;
else temp &= ~BIT16;
SYS_EFM_CONFIG_Unlock(); //EFM寄存器解锁
EFM->FRMC = temp|BIT24; //设置CACHE,并复位CACHE
nop;nop;nop;nop;
EFM->FRMC &= ~BIT24; //取消复位(不确定是否会自动取消,此处进行手动取消复位)
SYS_EFM_CONFIG_Lock(); //EFM寄存器配置上锁
}
/*************************************************************************************************************************
* 函数 : void SYS_EnableFlashLVM(bool isEnable)
* 功能 : 是否使能flash 超低速模式
* 参数 : isEnable:TRUE:使能;FALSE:失能
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-06-25
* 最后修改时间 : 2021-06-25
* 说明 : 用于节能
2021-07-27:修复了由于EFM未解锁导致配置未成功问题;
*************************************************************************************************************************/
void SYS_EnableFlashLVM(bool isEnable)
{
u32 temp = EFM->FRMC;
if(isEnable) temp |= BIT8;
else temp &= ~BIT8;
SYS_EFM_CONFIG_Unlock(); //EFM寄存器解锁
EFM->FRMC = temp; //设置
SYS_EFM_CONFIG_Lock(); //EFM寄存器配置上锁
}
/*************************************************************************************************************************
* 函数 : void SYS_EnableFlashSLPMD(bool isEnable)
* 功能 : 是否使能flash 超低功耗读取模式
* 参数 : isEnable:TRUE:使能;FALSE:失能
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-07-27
* 最后修改时间 : 2021-07-27
* 说明 : 用于低功耗
*************************************************************************************************************************/
void SYS_EnableFlashSLPMD(bool isEnable)
{
u32 temp = EFM->FRMC;
if(isEnable) temp |= BIT0;
else temp &= ~BIT0;
SYS_EFM_CONFIG_Unlock(); //EFM寄存器解锁
EFM->FRMC = temp; //设置
SYS_EFM_CONFIG_Lock(); //EFM寄存器配置上锁
}
/*************************************************************************************************************************
* 函数 : static void SYS_SetGPIOWaitCycle(u8 SysClock)
* 功能 : 设置GPIO读取等待周期
* 参数 : SysClock:系统主时钟,单位MHZ
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-06-14
* 最后修改时间 : 2021-06-14
* 说明 : 用于GPIO读取插入等待周期
*************************************************************************************************************************/
static void SYS_SetGPIOWaitCycle(u8 SysClock)
{
u32 temp = GPIO_CCR;
temp &=~(0x3<<14); //清除设置
if(SysClock < 42) temp|=0<<14; //0等待
if(SysClock < 84) temp|=1<<14; //1等待
if(SysClock < 126) temp|=2<<14; //2等待
else temp|=3<<14; //3等待
if(GPIO_WPR & BIT0) //允许写入GPIO配置寄存器
{
GPIO_CCR = temp; //设置等待周期
}
else
{
GPIO_WPR = 0xA501; //GPIO配置 写许可
GPIO_CCR = temp; //设置等待周期
GPIO_WPR = 0xA500; //GPIO配置 写许可禁用
}
}
/*************************************************************************************************************************
* 函数 : void SYS_DeviceClockEnable(SYS_DEV_CLOCK DevCloce,bool Enable)
* 功能 : 外设时钟使能或关闭控制
* 参数 : DevCloce:外设选择;Enable:TRUE使能;FALSE失能
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-06-19
* 最后修改时间 : 2021-06-19
* 说明
*************************************************************************************************************************/
void SYS_DeviceClockEnable(SYS_DEV_CLOCK DevCloce,bool Enable)
{
u8 n = DevCloce >> 8;
u8 bit = DevCloce&0xff;
const __IO uint32_t * const pPWR_FCG[] = {&PWR_FCG0, &PWR_FCG1, &PWR_FCG2, &PWR_FCG3};
if(bit > 31) return; //防止超出范围
if(n >= sizeof(pPWR_FCG)/4) return ; //防止索引超出范围
//设置对应时钟
SYS_CONFIG_SetLock(FALSE); //系统时钟电源控制等寄存器上锁与解锁
if(Enable == TRUE) *((__IO uint32_t *)pPWR_FCG) &= ~(1<<bit); //使能写0
else *((__IO uint32_t *)pPWR_FCG) |= (1<<bit); //关闭写1
SYS_CONFIG_SetLock(TRUE); //系统时钟电源控制等寄存器上锁与解锁
}
/*************************************************************************************************************************
* 函数 : void SYS_GPIOx_SetAF(GPIO_TypeDef *GPIOx, u8 io_num, u8 Func)
* 功能 : GPIO复用功能设置(特殊功能一旦选中,无需初始化设置IO)
* 参数 : GPIOx:GPIO对象;io_num:io索引,从0开始, Func:复用功能设置,0-63
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-06-19
* 最后修改时间 : 2021-06-19
* 说明 : 用于设置GPIO特殊功能,特殊功能一旦选中,无需初始化设置IO
默认全部不开启附功能
*************************************************************************************************************************/
void SYS_GPIOx_SetAF(GPIO_TypeDef *GPIOx, u8 io_num, u8 Func)
{
u8 GPIO_Group;
if(io_num > 15) return;
switch((u32)GPIOx)
{
case (u32)GPIOA: GPIO_Group = 0;break;
case (u32)GPIOB: GPIO_Group = 1;break;
case (u32)GPIOC: GPIO_Group = 2;break;
case (u32)GPIOD: GPIO_Group = 3;break;
case (u32)GPIOE: GPIO_Group = 4;break;
case (u32)GPIOH: GPIO_Group = 5;break;
default:return;
}
SYS_GPIO_CONFIG_Unlock(); //IO配置解锁
GPIO_FSR_Px(GPIO_Group, io_num) = Func & 0x3F;
SYS_GPIO_CONFIG_Lock(); //IO配置上锁
}
/*************************************************************************************************************************
* 函数 : void SYS_GPIOx_OneInit(GPIO_TypeDef *GPIOx, u8 io_num, SYS_GPIO_MODE mode, SYS_GPIO_DRV GPIO_DRV_x)
* 功能 : 初始化一个IO
* 参数 : GPIOx:GPIO对象;io_num:io索引,从0开始;mode:GPIO_DRV_x:IO驱动能力
* 返回 : 无
* 依赖 : 底层与OS
* 作者 : cp1300@139.com
* 时间 : 2021-06-19
* 最后修改时间 : 2021-06-19
* 说明 : 用于初始化一个IO
mode模式:
OUT_PP = 0, //推挽输出
OUT_OD = 1, //开漏输出
IN_FLOATING = 2, //浮空输入
IN_IPU = 3, //上拉输入
IN_AIN = 4, //模拟输入
GPIO_DRV_x驱动能力:
GPIO_DRV_0 = 0, //低驱动能力
GPIO_DRV_1 = 1, //中驱动能力
GPIO_DRV_2 = 2, //高驱动能力
初始化IO的时候,会将IO的复用模式设置为GPIO
*************************************************************************************************************************/
void SYS_GPIOx_OneInit(GPIO_TypeDef *GPIOx, u8 io_num, SYS_GPIO_MODE mode, SYS_GPIO_DRV GPIO_DRV_x)
{
u8 GPIO_Group;
u16 temp;
if(io_num > 15) return;
switch((u32)GPIOx)
{
case (u32)GPIOA: GPIO_Group = 0;break;
case (u32)GPIOB: GPIO_Group = 1;break;
case (u32)GPIOC: GPIO_Group = 2;break;
case (u32)GPIOD: GPIO_Group = 3;break;
case (u32)GPIOE: GPIO_Group = 4;break;
case (u32)GPIOH: GPIO_Group = 5;break;
default:return;
}
SYS_GPIO_CONFIG_Unlock(); //IO配置解锁
GPIO_CR_Px(GPIO_Group, io_num) |= BIT15 | BIT14; //关闭数字输出开启锁存,请在输出锁存有效时(LTE=1)进行端口功能切换,以避免切换期间端口上输出期待之外毛刺。
temp = GPIO_CR_Px(GPIO_Group, io_num);
temp &= ~BIT14; //输出锁存无效
temp &= ~0x3FF; //清除配置
switch(GPIO_DRV_x) //驱动能力
{
case GPIO_DRV_0 : break; //低驱动能力
case GPIO_DRV_1 : temp |= BIT4; //中驱动能力
case GPIO_DRV_2 : temp |= BIT5; //高驱动能力
default:break;
}
switch(mode)
{
case OUT_PP :temp|=BIT1;break; //推挽输出
case OUT_OD :temp|=BIT2|BIT1;break; //开漏输出
case IN_FLOATING :break; //浮空输入
case IN_IPU :temp|=BIT6;break; //上拉输入
case IN_AIN :break; //模拟输入
default:break;
}
//如果是模拟输入,则不用开启数字功能,否则就要开启
if(mode != IN_AIN)
{
temp &= ~BIT15; //数字功能使能
}
GPIO_FSR_Px(GPIO_Group, io_num) = 0; //复用功能设置为默认的IO模式
GPIO_CR_Px(GPIO_Group, io_num) = temp; //重新配置
SYS_GPIO_CONFIG_Lock(); //IO配置上锁
}
/*************************************************************************************************************************
* 函数 : SYS_CLOCK_SOURCE SYS_GetSystemClockSource(void)
* 功能 : 获取系统主时钟来源
* 参数 : 无
* 返回 : 时钟来源,见SYS_CLOCK_SOURCE
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-06-14
* 最后修改时间 : 2021-06-14
* 说明 :
*************************************************************************************************************************/
SYS_CLOCK_SOURCE SYS_GetSystemClockSource(void)
{
return (SYS_CLOCK_SOURCE)(CMU_CKSWR & 0x7);
}
/*************************************************************************************************************************
* 函数 : u32 SYS_GetPLLClockSpeed(SYS_PLL_TYPE PLLn)
* 功能 : 获取PLL时钟频率
* 参数 : PLLn:PLL输出通达选择,见 SYS_PLL_TYPE
* 返回 : 时钟频率,单位Hz
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-06-14
* 最后修改时间 : 2021-06-14
* 说明 : 无效或者PLL未就绪,返回0
*************************************************************************************************************************/
u32 SYS_GetPLLClockSpeed(SYS_PLL_TYPE PLLn)
{
u32 M; //VCO输入分频
u32 P; //VCO输出P分频
u32 Q; //VCO输出Q分频
u32 R; //VCO输出R分频
u32 N; //VCO倍频
u32 temp;
switch(PLLn)
{
case SYS_MPLL_P : //MPLL P通道输出,用于系统主时钟
{
if((CMU_OSCSTBSR & BIT5) == 0) return 0; //MPLL未稳定就绪
P = (CMU_PLLCFGR >> 28) & 0x0F;
N = (CMU_PLLCFGR >> 8) & 0x1FF;
M =(CMU_PLLCFGR >> 0) & 0xF;
P += 1;
M += 1;
N += 1;
temp = (CMU_PLLCFGR & BIT7) ? HRC_CLOCK_16 : XTAL_CLOCK;
temp /= M;
temp *= N;
temp /= P;
temp *= 1000000;
return temp;
}
case SYS_MPLL_Q : //MPLL Q通道输出
{
if((CMU_OSCSTBSR & BIT5) == 0) return 0; //MPLL未稳定就绪
Q = (CMU_PLLCFGR >> 24) & 0x0F;
N = (CMU_PLLCFGR >> 8) & 0x1FF;
M =(CMU_PLLCFGR >> 0) & 0xF;
Q += 1;
M += 1;
N += 1;
temp /= M;
temp *= N;
temp /= Q;
temp *= 1000000;
return temp;
}
case SYS_MPLL_R : //MPLL R通道输出
{
if((CMU_OSCSTBSR & BIT5) == 0) return 0; //MPLL未稳定就绪
R = (CMU_PLLCFGR >> 20) & 0x0F;
N = (CMU_PLLCFGR >> 8) & 0x1FF;
M =(CMU_PLLCFGR >> 0) & 0xF;
R += 1;
M += 1;
N += 1;
temp /= M;
temp *= N;
temp /= R;
temp *= 1000000;
return temp;
}
case SYS_UPLL_P : //UPLL P通道输出
{
if((CMU_OSCSTBSR & BIT6) == 0) return 0; //UPLL未稳定就绪
}
case SYS_UPLL_Q : //UPLL Q通道输出
{
if((CMU_OSCSTBSR & BIT6) == 0) return 0; //UPLL未稳定就绪
}
case SYS_UPLL_R : //UPLL R通道输出
{
if((CMU_OSCSTBSR & BIT6) == 0) return 0; //UPLL未稳定就绪
}
default: return 0;
}
}
/*************************************************************************************************************************
* 函数 : u32 SYS_GetClockDiv(SYS_CLOCK_TYPE ClockSelect)
* 功能 : 获取时钟相对于主时钟的分频值
* 参数 : ClockSelect:时钟选择
* 返回 : 分频值
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-06-11
* 最后修改时间 : 2021-06-11
* 说明 :
*************************************************************************************************************************/
static u32 SYS_GetClockDiv(SYS_CLOCK_TYPE ClockSelect)
{
u8 n = 0;
const u8 DivBuff[] = {1,2,4,8,16,32,64, 1};
switch(ClockSelect)
{
case SYS_CLOCK_HCLK : n = (CMU_SCFGR>>24)&0x07; break; //HCLK
case SYS_CLOCK_EXCLK : n = (CMU_SCFGR>>20)&0x07; break; //EXCK
case SYS_CLOCK_PCLK4 : n = (CMU_SCFGR>>16)&0x07; break; //PCLK4
case SYS_CLOCK_PCLK3 : n = (CMU_SCFGR>>12)&0x07; break; //PCLK3
case SYS_CLOCK_PCLK2 : n = (CMU_SCFGR>>8)&0x07; break; //PCLK2
case SYS_CLOCK_PCLK1 : n = (CMU_SCFGR>>4)&0x07; break; //PCLK1
case SYS_CLOCK_PCLK0 : n = (CMU_SCFGR>>0)&0x07; break; //PCLK0
default:break;
}
return DivBuff;
}
/*************************************************************************************************************************
* 函数 : u32 SYS_GetHCLKSpeed(void)
* 功能 : 获取系统主时钟HCLK速度
* 参数 : ClockSelect:时钟选择
* 返回 : 分频值
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-06-14
* 最后修改时间 : 2021-06-14
* 说明 :
*************************************************************************************************************************/
u32 SYS_GetHCLKSpeed(void)
{
SYS_CLOCK_SOURCE ClockSource;
ClockSource = SYS_GetSystemClockSource(); //获取系统主时钟来源
switch(ClockSource)
{
case SYS_CLOCK_HRC : return HRC_CLOCK_16 * 1000000; //内部高速时钟16/20MHz
case SYS_CLOCK_MRC : return MRC_CLOCK * 1000000; //内部中速时钟8MHz-系统启动后的默认时钟
case SYS_CLOCK_LRC : return 32768; //内部低速时钟32.768Khz
case SYS_CLOCK_XTAL : return XTAL_CLOCK * 1000000; //外部高速时钟4-24MHz
case SYS_CLOCK_XTAL32 : return 32768; //外部低速时钟32.768Khz
case SYS_CLOCK_MPLL : return SYS_GetPLLClockSpeed(SYS_MPLL_P);//MPLL_P
default : return 0;
}
}
/*************************************************************************************************************************
* 函数 : u32 SYS_GetClockSpeed(SYS_CLOCK_TYPE ClockSelect)
* 功能 : 获取时钟速度
* 参数 : ClockSelect:时钟选择
* 返回 : 分频值
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-06-14
* 最后修改时间 : 2021-06-14
* 说明 : 所有时钟必须都是从HCLK进行分频,暂不支持来自别的时钟源
*************************************************************************************************************************/
u32 SYS_GetClockSpeed(SYS_CLOCK_TYPE ClockSelect)
{
u32 temp;
temp = SYS_GetHCLKSpeed(); //获取系统主时钟速度
temp /= SYS_GetClockDiv(ClockSelect); //通过分频计算时钟速度
return temp;
}
/*************************************************************************************************************************
* 函数 : void SYS_GPIO_SetINER(u8 GPIO_Group, bool isEnable)
* 功能 : 设置GPIO输入MOS开关
* 参数 : GPIO_Group:IO组,定义如下:
#define SYS_PINAER_PA (1<<0) //控制 PA0~PA15 输入MOS开关
#define SYS_PINAER_PB (1<<1) //控制 PB0~PB15 输入MOS开关
#define SYS_PINAER_PC (1<<2) //控制 PC0~PC15 输入MOS开关
#define SYS_PINAER_PD (1<<3) //控制 PD0~PD15 输入MOS开关
#define SYS_PINAER_PE (1<<4) //控制 PE0~PE15 输入MOS开关
#define SYS_PINAER_PH (1<<5) //控制 PH0~PH2 输入MOS开关
isEnable:TRUE:使能MOS常开,FALSE:关闭常开
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-06-19
* 最后修改时间 : 2021-06-19
* 说明 : 各I/O都具有通用输入 GPI功能,且在数字功能禁止位 PCRxy.DDIS为 0时, GPI功能始终有效, 与功能选择寄存器中 PFSRxy的 FSEL设定值无关 。通过访问端口输
入数据寄存器 PIDRx可以获取当前端口的状态。也可以通过端口控制寄存器 PCRxy的 PIN位查询相应的单 I/O端口状态, PIDRx.PIN寄存器位与 PCRxy.PIN位等价。默认情况下,为了降低功耗,
I/O的输入 MOS是被关闭的。只有在读取 PIDRx PCRxy寄存器时,才会被打开。根据需要,也可以通过设置寄存器 PINAER.PINAEx为 1,让
I/O的输入 MOS一直处于打开状态。
也就是如果需要高速读取的时候,可以一直开着,平时没有必要开
*************************************************************************************************************************/
void SYS_GPIO_SetINER(u8 GPIO_Group, bool isEnable)
{
SYS_GPIO_CONFIG_Unlock(); //IO配置解锁
if(isEnable) //使能
{
GPIO_INAER |= GPIO_Group & 0x3F;
}
else
{
GPIO_INAER &= ~(GPIO_Group & 0x3F);
}
SYS_GPIO_CONFIG_Lock(); //IO配置上锁
}
/*************************************************************************************************************************
* 函数 : void SYS_GPIO_IntConfig(GPIO_TypeDef *GPIOx, u8 io_num, bool isEnable)
* 功能 : GPIO外部中断配置函数
* 参数 : GPIOx:IO组;io_num:对应的IO 编号0-15;isEnable:是否使能中断
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-06-20
* 最后修改时间 : 2021-06-20
* 说明 :
*************************************************************************************************************************/
void SYS_GPIO_IntConfig(GPIO_TypeDef *GPIOx, u8 io_num, bool isEnable)
{
u8 GPIO_Group;
if(io_num > 15) return;
switch((u32)GPIOx)
{
case (u32)GPIOA: GPIO_Group = 0;break;
case (u32)GPIOB: GPIO_Group = 1;break;
case (u32)GPIOC: GPIO_Group = 2;break;
case (u32)GPIOD: GPIO_Group = 3;break;
case (u32)GPIOE: GPIO_Group = 4;break;
case (u32)GPIOH: GPIO_Group = 5;break;
default:return;
}
SYS_GPIO_CONFIG_Unlock(); //IO配置解锁
if(isEnable) //使能
{
GPIO_CR_Px(GPIO_Group, io_num) |= BIT12; //使能外部中断
}
else
{
GPIO_CR_Px(GPIO_Group, io_num) &= ~BIT12; //关闭外部中断
}
SYS_GPIO_CONFIG_Lock(); //IO配置上锁
}
/*************************************************************************************************************************
* 函数 : void SYS_EXTI_SetEdge(EXTI_TYPE EXIT_n, EIRQ_EDGE_TYPE Edge)
* 功能 : 设置中断线(事件线)触发边沿
* 参数 : Exti_n:中断线,见EXTI_TYPE;Edge:触发边沿,见EIRQ_EDGE_TYPE
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-06-19
* 最后修改时间 : 2021-06-19
* 说明 :
*************************************************************************************************************************/
void SYS_EXTI_SetEdge(EXTI_TYPE EXIT_n, EIRQ_EDGE_TYPE Edge)
{
u32 temp;
if(EXIT_n > 15) return;
temp = INTC->EIRQCR;
temp &= ~0x03; //清除最低2位
temp |= Edge & 0x03;
INTC->EIRQCR = temp; //设置触发边沿
}
/*************************************************************************************************************************
* 函数 : void SYS_EXTI_SetFilter(EXTI_TYPE EXIT_n, EIRQ_FILTER_TYPE Filter)
* 功能 : 设置中断线(事件线)滤波
* 参数 : Exti_n:中断线,见EXTI_TYPE;Filter:滤波,见EIRQ_FILTER_TYPE
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-06-19
* 最后修改时间 : 2021-06-19
* 说明 :
*************************************************************************************************************************/
void SYS_EXTI_SetFilter(EXTI_TYPE EXIT_n, EIRQ_FILTER_TYPE Filter)
{
u32 temp;
if(EXIT_n > 15) return;
temp = INTC->EIRQCR;
temp &= ~(BIT7|(0x03<<4)); //清除滤波选项
if(Filter < IRQ_FILTER_DISABLE) //需要开启滤波
{
temp |= BIT7 | (Filter<<4); //开启并设置滤波
}
INTC->EIRQCR = temp; //设置滤波
}
/*************************************************************************************************************************
* 函数 : void SYS_EXTI_ClearInt(EXTI_TYPE EXIT_n)
* 功能 : 清除外部中断状态
* 参数 : Exti_n:中断线,见EXTI_TYPE
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-06-19
* 最后修改时间 : 2021-06-19
* 说明 : 向EXTI_PR寄存器对应位写1清除,外部中断退出的时候进行清除
*************************************************************************************************************************/
void SYS_EXTI_ClearInt(EXTI_TYPE EXIT_n)
{
INTC->EICFR |= 1<<EXIT_n; //清除挂起的中断状态
}
/*************************************************************************************************************************
* 函数 : u16 SYS_EXTI_GetInt(void)
* 功能 : 获取外部中断状态
* 参数 : 无
* 返回 : 每一个bit代表一个中断状态
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-06-19
* 最后修改时间 : 2021-06-19
* 说明 : 对应位为1代表中断有效
*************************************************************************************************************************/
u16 SYS_EXTI_GetInt(void)
{
return INTC->EIFR;
}
/*************************************************************************************************************************
* 函数 : static void SYS_CONFIG_SetLock(bool isLock)
* 功能 : 系统时钟电源控制等寄存器上锁与解锁
* 参数 : isLock:TRUE:上锁;FALSE:解锁;
* 返回 :
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-07-22
* 最后修改时间 : 2021-07-22
* 说明 : PWR_FPRC. FPRCB0:
CMU_XTALCFGR,CMU_XTALSTBCR,CMU_XTALCR,CMU_XTALSTDCR, CMU_XTALSTDSR,CMU_HRCTRM,CMU_HRCCR,CMU_MRCTRM,
CMU_MRCCR,CMU_PLLCFGR,CMU_PLLCR,CMU_UPLLCFGR, CMU_UPLLCR,CMU_OSCSTBSR,CMU_CKSWR,CMU_SCFGR, CMU_UFSCKCFGR,
CMU_TPIUCKCFGR,CMU_MCO1CFGR,CMU_MCO2CFGR, CMU_XTAL32CR,CMU_XTALC32CFGR,CMU_XTAL32NFR, CMU_LRCCR,CMU_LRCTRM
PWR_XTAL32CS
PWR_FPRC. FPRCB1:
PWR_PWRC0 PWR_PWRC1 PWR_PWRC2 PWR_PWRC3 PWR_PDWKE0
PWR_PDWKE1 PWR_PDWKE2 PWR_PDWKES PWR_PDWKF0 PWR_PDWKF1
PWR_PWCMR CMU_PERICKSEL, CMU_I2SCKSEL,
PWR_MDSWCR PWR_STPMCR PWR_RAMPC0 PWR_RAMOPM RMU_RSTF0
PWR_FPRC. FPRCB3:
PWR_PVDCR0 PWR_PVDCR1 PWR_PVDFCR PWR_PVDLCR PWR_PVDICR PWR_PVDDSR
PWR_FCG0PRC.B0:
PWR_FCG0
*************************************************************************************************************************/
static void SYS_CONFIG_SetLock(bool isLock)
{
if(isLock)
{
PWR_FCG0PC = 0xA5A50000;
PWR_FPRC = 0xA500;
}
else
{
PWR_FCG0PC = 0xA5A50001;
PWR_FPRC = 0xA50B;
}
}
/*************************************************************************************************************************
* 函数 : void SYS_PWR_SetLock(bool isLock)
* 功能 : 对CMU寄存器进行加锁保护
* 参数 : isLock:TRUE:上锁;FALSE:解锁;
* 返回 :
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-07-22
* 最后修改时间 : 2021-07-22
* 说明 : CMU_XTALCFGR,CMU_XTALSTBCR,CMU_XTALCR,CMU_XTALSTDCR, CMU_XTALSTDSR,CMU_HRCTRM,CMU_HRCCR,CMU_MRCTRM,
CMU_MRCCR,CMU_PLLCFGR,CMU_PLLCR,CMU_UPLLCFGR, CMU_UPLLCR,CMU_OSCSTBSR,CMU_CKSWR,CMU_SCFGR, CMU_UFSCKCFGR,
CMU_TPIUCKCFGR,CMU_MCO1CFGR,CMU_MCO2CFGR, CMU_XTAL32CR,CMU_XTALC32CFGR,CMU_XTAL32NFR, CMU_LRCCR,CMU_LRCTRM
PWR_XTAL32CS
*************************************************************************************************************************/
void SYS_CMU_SetLock(bool isLock)
{
//PWR_FPRC. FPRCB0
}
/*************************************************************************************************************************
* 函数 : void IWDG_Feed(void)
* 功能 : 独立看门狗喂狗(刷新计数值)
* 参数 : 无
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-07-27
* 最后修改时间 : 2021-07-27
* 说明 :
*************************************************************************************************************************/
void IWDG_Feed(void)
{
SWDT->RR = 0x0123;
SWDT->RR = 0x3210;
}
/*************************************************************************************************************************
* 函数 : bool IWDG_GetEnableStatus(void)
* 功能 : 获取独立看门狗开关状态
* 参数 : 无
* 返回 : TRUE:开启了看门狗;FALSE:看门狗没有开启
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-07-27
* 最后修改时间 : 2021-07-27
* 说明 :
*************************************************************************************************************************/
bool IWDG_GetEnableStatus(void)
{
u32 ICG0 = ICG->DATA;
u32 SWDTCLK = 10*1000;
u32 temp1 = 0,temp2 = 0;
if((ICG0 & BIT0) == 0) //使能了SWDT
{
uart_printf("SWDT看门狗开启 ");
if((ICG0 & BIT1) == 0)
{
uart_printf("溢出中断 ");
}
else
{
uart_printf("溢出复位 ");
}
switch((ICG0>>4) & 0xF)
{
case 0: temp1 = 1;break; //1分频
case 4: temp1 = 16;break; //16分频
case 5: temp1 = 32;break; //32分频
case 6: temp1 = 64;break; //64分频
case 7: temp1 = 128;break; //128分频
case 8: temp1 = 256;break; //256分频
case 11: temp1 = 2048;break; //2048分频
default:DEBUG("无效的SWDT分频值:0x%X\r\n", ((ICG0>>4) & 0xF));
}
if(temp1 != 0)
{
SWDTCLK /= temp1;
uart_printf("%d分频 ", temp1);
}
switch((ICG0>>2) & 0x3)
{
case 0: temp2 = 256;break; //256周期
case 1: temp2 = 4096;break; //4096周期
case 2: temp2 = 16384;break; //16384周期
case 3: temp2 = 65536;break; //65536周期
}
uart_printf("周期%d ", temp2);
temp2 /= SWDTCLK;
uart_printf("溢出时间%d秒\r\n", temp2);
return TRUE;
}
else
{
uart_printf("SWDT看门狗关闭\r\n");
return FALSE;
}
}
/*************************************************************************************************************************
* 函数 : void SYS_NVIC_SetVectorTable(u32 NVIC_VectTab, u32 ROM_BaseAddr)
* 功能 : 设置向量表地址
* 参数 : NVIC_VectTab:基址;ROM_BaseAddr:ROM基址
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2018-01-13
* 最后修改时间 : 2021-07-29
* 说明 : 用于跳转启动应用后进行设置
*************************************************************************************************************************/
void SYS_NVIC_SetVectorTable(u32 NVIC_VectTab, u32 ROM_BaseAddr)
{
SCB->VTOR = NVIC_VectTab|(ROM_BaseAddr); //设置NVIC的向量表偏移寄存器
}
/*************************************************************************************************************************
* 函数 : void SYS_SetJtagMode(SYS_JTAG_MODE mode)
* 功能 : 设置JTAG模式
* 参数 : mode:JTAG_MODE、SWD_MODE、DISABLE_JTAG
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-08-08
* 最后修改时间 : 2021-08-08
* 说明 :
*************************************************************************************************************************/
void SYS_SetJtagMode(SYS_JTAG_MODE mode)
{
switch(mode)
{
case JTAG_MODE: //全功能JTAG模式
{
SYS_GPIO_CONFIG_Unlock(); //IO配置解锁
GPIO_SPCR = 0x1F; //使能全部IO
SYS_GPIO_CONFIG_Lock(); //IO配置上锁
}break;
case SWD_MODE: //只使能SWD模式
{
SYS_GPIO_CONFIG_Unlock(); //IO配置解锁
GPIO_SPCR = 0x03; //使能SWDIO SWCLK
SYS_GPIO_CONFIG_Lock(); //IO配置上锁
}break;
case DISABLE_JTAG: //全部关闭
{
SYS_GPIO_CONFIG_Unlock(); //IO配置解锁
GPIO_SPCR = 0x00; //全部关闭
SYS_GPIO_CONFIG_Lock(); //IO配置上锁
}break;
default:break;
}
}
//软件us延时
void Delay_US(u32 time)
{
#if(SYS_STOP_WATCH_EN)
u64 EndTimeUs = time + g_mStopWatchClass.GetCounter();
while(EndTimeUs > g_mStopWatchClass.GetCounter()); //等待时间到达
#else
u32 i;
while(time --)//软件延时未计算
{
for(i = 0;i < 5;i ++)
nop;
}
#endif //SYS_STOP_WATCH_EN
}
//软件ms延时
void Delay_MS(u32 time)
{
#if(SYS_STOP_WATCH_EN)
u64 EndTimeUs = time;
u64 cnt;
EndTimeUs *= 1000;
EndTimeUs += g_mStopWatchClass.GetCounter();
do
{
cnt = g_mStopWatchClass.GetCounter();
}
while(EndTimeUs > cnt); //等待时间到达
#else
u32 i;
while(time --) //软件延时未计算
{
for(i = 0;i < 5998;i ++)
{
nop;
}
}
#endif //SYS_STOP_WATCH_EN
}
/*************************************************************************************************************************
* 函数 : void SYS_DelayMS(u32 ms)
* 功能 : 系统毫秒延时
* 参数 : 无
* 返回 : 无
* 依赖 : 底层宏定义,或者OS
* 作者 : cp1300@139.com
* 时间 : 2018-03-10
* 最后修改时间 : 2018-03-10
* 说明 : 如果没有使用操作系统将使用Delay_MS()延时,如果启用了操作系统,并且操作系统运行了,则使用OSTimeDlyHMSM延时
*************************************************************************************************************************/
void SYS_DelayMS(u32 ms)
{
#ifdef _UCOS_II_ //使能了操作系统
#if(OS_VERSION>30000) //使用的ucos_iii
static OS_ERR err;
if(OSRunning==OS_STATE_OS_STOPPED) //操作系统还没有初始化
{
Delay_MS(ms);
return; //操作系统还没有初始化并启动,延时无效
}
OSTimeDlyHMSM((ms/1000)/3600, ((ms/1000)%3600)/60, (ms/1000)%60, ms%1000, OS_OPT_TIME_HMSM_STRICT, &err);
#else
if(OSRunning==OS_FALSE) //操作系统还没有初始化
{
Delay_MS(ms);
return; //操作系统还没有初始化并启动,延时无效
}
OSTimeDlyHMSM((ms/1000)/3600, ((ms/1000)%3600)/60, (ms/1000)%60, ms%1000);
#endif //OS_VERSION
#else //没有使能操作系统
Delay_MS(ms);
#endif //UCOS_II_EN
}
#if(UCOS_II_EN) //使能了操作系统
#include "ucos_ii.h"
/*************************************************************************************************************************
* 函数 : void Sleep(u32 ms)
* 功能 : 线程挂起延时
* 参数 : ms:延时时间
* 返回 : 无
* 依赖 : OS
* 作者 : cp1300@139.com
* 时间 : 2020-08-21
* 最后修改时间 : 2020-08-21
* 说明 : 必须使用了操作系统,并且操作系统启动了,不能在中断中调用
*************************************************************************************************************************/
void Sleep(u32 ms)
{
SYS_DelayMS(ms);
}
//系统时钟中断服务函数
void SysTick_Handler(void)
{
CPU_SR_ALLOC();
OS_ENTER_CRITICAL(); /* Tell uC/OS-II that we are starting an ISR*/
OSIntEnter(); //进入中断
g_OS_RunTime ++; //操作系统运行时间增加 2018-02-08
OS_EXIT_CRITICAL();
OSTimeTick(); /* Call uC/OS-II's OSTimeTick() */
OSIntExit(); /* Tell uC/OS-II that we are leaving the ISR*/
}
/*************************************************************************************************************************
* 函数 : void SYS_OS_TickInit(void)
* 功能 : 系统OS滴答时钟初始化
* 参数 : 无
* 返回 : 无
* 依赖 : 底层与OS
* 作者 : cp1300@139.com
* 时间 : 2021-06-26
* 最后修改时间 : 2021-06-26
* 说明 :
*************************************************************************************************************************/
void SYS_OS_TickInit(void)
{
u32 SYS_CLK = SYS_GetHCLKSpeed();
SysTick->CTRL = 0; //关闭定时器,配置复位
SysTick->CTRL |= 1<<2; //使用内核时钟,也就是HCLK作为时钟源,这个与别的单片机不一样
SysTick->VAL = 0; //计数器清零
SysTick->CTRL|=1<<1; //开启SYSTICK中断
SysTick->LOAD=SYS_CLK / OS_TICKS_PER_SEC; //产生1ms中断
SysTick->CTRL|=1<<0; //开启SYSTICK
}
//获取操作系统运行时间(单位ms)
u64 SYS_GetOSRunTime(void)
{
return g_OS_RunTime;
}
#endif //UCOS_II_EN
/*************************************************************************************************************************
* 函数 : void SystemInit(void)
* 功能 : 系统底层初始化-在汇编中调用
* 参数 : 无
* 返回 : 无
* 依赖 : 底层与OS
* 作者 : cp1300@139.com
* 时间 : 2021-06-23
* 最后修改时间 : 2021-06-23
* 说明 :
*************************************************************************************************************************/
void SystemInit(void)
{
IWDG_Feed(); //系统启动后立即进行一次喂狗
SYS_SetJtagMode(SWD_MODE); //设置为SWD模式,释放不需要的IO
SYS_DeviceClockEnable(DEV_SRAMRET, TRUE); //使能Ret_RAM时钟
#if(SYS_THIS_IS_APP)
SYS_NVIC_SetVectorTable(SYS_NVIC_VectTab_FLASH, _ROM_START_ADDR_); //设置向量表地址
#endif
SYS_EnableFlashLVM(FALSE); //关闭flash 超低速模式
SYS_EnableFlashSLPMD(FALSE); //关闭flash 超低功耗读取模式
SYS_EnableFlashCache(TRUE); //使能flash cache
SYS_DeviceClockEnable(DEV_AOS, TRUE); //使能软件触发,需要依赖AOS
INTC_Init(); //中断控制器初始化(在系统初始化中调用,请勿重复调用)
DMA_Init(); //DMA初始化
}
//THUMB指令不支持汇编内联
//采用如下方法实现执行汇编指令WFI
void WFI_SET(void)
{
__ASM volatile("wfi");
}
//关闭系统总中断(但是不包括fault和NMI中断)
void SYS_DisableIrq(void)
{
__ASM volatile("cpsid i");
}
//开启系统总中断
void SYS_EnableIrq(void)
{
__ASM volatile("cpsie i");
}
//设置栈顶地址
//addr:栈顶地址
#if(__GNUC__)
void MSR_MSP(u32 addr)
{
__ASM volatile ("MSR msp, %0" : : "r" (addr) : );
}
#else
void MSR_MSP(u32 addr)
{
"MSR MSP, r0";//set Main Stack value
"BX r14";
}
#endif //__GNUC__
//进入待机模式
void SYS_Standby(void)
{
// SCB->SCR|=1<<2; //使能SLEEPDEEP位 (SYS->CTRL)
// RCC->APB1ENR|=1<<28;//使能电源时钟
// PWR->CSR|=1<<8; //设置WKUP用于唤醒
// PWR->CR|=1<<2; //清除Wake-up 标志
// PWR->CR|=1<<1; //PDDS置位
WFI_SET(); //执行WFI指令,进入待机模式
}
//系统软复位
void SYS_SoftReset(void)
{
SCB->AIRCR =0X05FA0000|(u32)0x04;
}
#if(SYS_WDG_EN_) //使能看门狗
//允许SWDT在低功耗模式下允许,并且刷新范围0-100, SWDTCLK/32 SWDTCLK=10KHZ也就是最终频率:312.5Hz
//溢出周期4096,也就是最终溢出时间13.1072秒;溢出后复位,复位后SWDT自动启动
#define SYS_ICG0 (0xFFFF0000ul | BIT15 | BIT14| BIT13 | (5<<4) | (1<<2) | BIT1)
#else
#define SYS_ICG0 0xFFFFFFFFul
#endif //SYS_WDG_EN_
#if(_ROM_START_ADDR_<0X300) //ROM地址必须在配置地址之前才有效
#if(__GNUC__)
const uint32_t u32ICG[] __attribute__((section(".ARM.__at_0x400"))) =
#elif defined (__CC_ARM)
const uint32_t u32ICG[] __attribute__((at(0x400))) =
#elif defined (__ICCARM__)
__root const uint32_t u32ICG[] @ 0x400 =
#else
#error "unsupported compiler!!"
#endif
{
//SWDTCLK 10KHz
/* ICG 0~ 3 */
SYS_ICG0,
0xFFFFFFFFul,
0xFFFFFFFFul,
0xFFFFFFFFul,
/* ICG 4~ 7 */
0xFFFFFFFFul,
0xFFFFFFFFul,
0xFFFFFFFFul,
0xFFFFFFFFul,
};
#endif //_ROM_START_ADDR_
//
//加入以下代码,支持printf函数,而不需要选择use MicroLIB
#if PRINTF_EN_ && (!__ICCARM__)
//标准库需要的支持函数
#if(__GNUC__)
struct FILE
#else
#pragma import(__use_no_semihosting)
struct __FILE
#endif //__GNUC__
{
int handle;
/* Whatever you require here. If the only file you are using is */
/* standard output using printf() for debugging, no file handling */
/* is required. */
};
/* FILE is typedef’ d in stdio.h. */
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
{
x = x;
}
//__use_no_semihosting was requested, but _ttywrch was
void _ttywrch(int ch)
{
ch = ch;
}
#endif
//
//PRINTF_EN
#if (PRINTF_EN_)
#include "uart.h"
bool isPrintfOut = TRUE; //printf输出使能
UART_CH_Type PrintfCh = UART_PRINTF_CH; //printf通道设置
int fputc(int ch,FILE *f)
{
if(isPrintfOut == TRUE) //使能输出
{
UARTx_SendByte(PrintfCh, (u8)ch);
}
return ch;
}
#endif
//头文件
/*************************************************************************************************************
* 文件名: hc32f46x_system.c
* 功能: HC32F46X芯片相关系统操作
* 作者: cp1300@139.com
* 创建时间: 2021-06-13
* 最后修改时间:2021-06-13
* 详细:
*************************************************************************************************************/
#ifndef _HC32F46X_SYSTEM_H_
#define _HC32F46X_SYSTEM_H_
#include "typedef.h"
#include "hc32f46x.h"
#include "hc32f46x_const.h"
#include "hc32f46x_map.h"
#include "core_cm4.h"
#include "hc32f46x_irq.h"
#define UCOS_II_EN 1 //使能操作系统-兼容一些代码中的宏定义
#define PRINTF_EN_ 1 //printf输出重定义 ,0:关闭,1:串口
#define UART_PRINTF_CH UART_CH1 //uart printf串口选择
#define SYS_OS_TICK_TIME_CH TIMER_CH4 //滴答时钟所使用的定时器选择
#define SYS_DELAY_TIME_CH TIMER_CH3 //硬件延时所需的定时器选择-用于硬件延时以及时间测量用
#define SYS_STOP_WATCH_EN 1 //是否使能系统时间测量工具-用于精确的us,ms延时,已经时间测量
#define SYS_MALLOC_EN_ 0 //使能SYSMalloc()
#define SYS_RTC_EN_ 0 //使能全局RTC g_timer
#define SYS_CMD_EN_ 1 //使能系统命令行
#define SYS_CMD_COUNT 20 //定义系统命令行最大命令数量
#define SYS_WDG_EN_ 1 //是否使能 SWDG相当于独立看门狗,溢出时间大概13秒(具体设置见代码ICG0设置位置)
#define SYS_THIS_IS_APP 1 //标记当前是否是APP程序
//请检查sct文件中的ROM地址与大小是否与此处设置一致,如果不一致请修改!
#if(SYS_THIS_IS_APP) //app程序,从64KB位置开始执行
#define _ROM_START_ADDR_ 0x00010000 //ROM起始地址
#define _ROM_SIZE_ (416*1024) //ROM大小
#else //IAP程序,从头开始执行
#define _APP_START_ADDR_ 0x00010000 //APP程序入口地址
#define _ROM_START_ADDR_ 0x00000000 //ROM起始地址
#define _ROM_SIZE_ (64*1024) //ROM大小
#endif //SYS_THIS_IS_APP
//中断等级
#define SYS_INT_HIGHEST_PRO 1 //系统预留最高优先级中断
#define SYS_INT_DELAY_TIME_PRO 0 //阻塞延时中断优先级-使用FIQ中断
#define SYS_INT_OS_TICK_PRO 3 //系统滴答时钟中断优先级
#define SYS_INT_UART_RX_PRO 4 //UART串口中断优先级
#define SYS_INT_RTC_PRO 5 //RTC中断优先级
#define SYS_INT_TIMA5_PRO 10 //StopWatch使用的TIMA5定时器溢出中断优先级
//全局中断线选择,后续的中断请不要占用
#define SYS_IRQ_UART1_RX_NUM Int020_IRQn //串口1接收中断
#define SYS_IRQ_UART2_RX_NUM Int021_IRQn //串口2接收中断
#define SYS_IRQ_UART3_RX_NUM Int022_IRQn //串口3接收中断
#define SYS_IRQ_UART4_RX_NUM Int023_IRQn //串口4接收中断
#define SYS_IRQ_TIMA5_OVR_NUM Int024_IRQn //StopWatch使用的TIMA5定时器溢出中断
//相关API
bool SYS_SystemClockInit(SYS_CRYSTAL_SOURCE CrystalSelect, bool PLLEnable, u16 MainClockFreq);//HC32F46X系统主时钟初始化
void SYS_DeviceClockEnable(SYS_DEV_CLOCK DevCloce,bool Enable); //外设时钟使能或关闭控制
void SYS_GPIOx_SetAF(GPIO_TypeDef *GPIOx, u8 io_num, u8 Func); //GPIO复用功能设置(特殊功能一旦选中,无需初始化设置IO)
void SYS_GPIOx_OneInit(GPIO_TypeDef *GPIOx, u8 io_num, SYS_GPIO_MODE mode, SYS_GPIO_DRV GPIO_DRV_x);//初始化一个IO
SYS_CLOCK_SOURCE SYS_GetSystemClockSource(void); //获取系统主时钟来源
u32 SYS_GetPLLClockSpeed(SYS_PLL_TYPE PLLn); //获取PLL时钟频率
u32 SYS_GetHCLKSpeed(void); //获取系统主时钟HCLK速度
u32 SYS_GetClockSpeed(SYS_CLOCK_TYPE ClockSelect); //获取时钟速度
#define SYS_GetPCLK1Speed() SYS_GetClockSpeed(SYS_CLOCK_PCLK1) //获取PCLK1时钟速度
void SYS_GPIO_SetINER(u8 GPIO_Group, bool isEnable); //设置GPIO输入MOS开关
void SYS_GPIO_IntConfig(GPIO_TypeDef *GPIOx, u8 io_num, bool isEnable);//GPIO外部中断配置函数
void SYS_EXTI_SetEdge(EXTI_TYPE EXIT_n, EIRQ_EDGE_TYPE Edge); //设置中断线(事件线)触发边沿
void SYS_EXTI_SetFilter(EXTI_TYPE EXIT_n, EIRQ_FILTER_TYPE Filter); //设置中断线(事件线)滤波
void SYS_EXTI_ClearInt(EXTI_TYPE EXIT_n); //清除外部中断状态
u16 SYS_EXTI_GetInt(void); //获取外部中断状态
void SYS_NVIC_SetVectorTable(u32 NVIC_VectTab, u32 ROM_BaseAddr); //设置向量表地址
void SYS_SoftReset(void); //系统软复位
void SYS_SetJtagMode(SYS_JTAG_MODE mode); //设置JTAG模式
void SYS_EnableIrq(void); //开总中断
void SYS_DisableIrq(void); //关闭总中断
void SystemInit(void); //系统底层初始化-在汇编中调用
void Delay_US(u32 time); //软件us延时
void Delay_MS(u32 time); //软件ms延时
void SYS_DelayMS(u32 ms); //系统毫秒延时
void IWDG_Feed(void); //独立看门狗喂狗(刷新计数值)
bool IWDG_GetEnableStatus(void); //获取独立看门狗开关状态
void MSR_MSP(u32 addr); //设置栈顶地址
//高速IO操作
__inline void SYS_GPIO_Negate(GPIO_TypeDef *GPIOx, u16 io_bit) {GPIOx->OTR = io_bit;} //IO翻转取反-高速
__inline void SYS_GPIO_Out1(GPIO_TypeDef *GPIOx, u16 io_bit) {GPIOx->OSR = io_bit;} //IO输出高电平-高速
__inline void SYS_GPIO_Out0(GPIO_TypeDef *GPIOx, u16 io_bit) {GPIOx->ORR = io_bit;} //IO输出低电平-高速
#define nop __asm("nop")
#if(SYS_STOP_WATCH_EN)
#include "StopWatch.h"
#endif //SYS_STOP_WATCH_EN
#if(SYS_MALLOC_EN_) //使能用户内存分配
#include "SYSMalloc.h"
#endif //SYS_MALLOC_EN_
#if(SYS_RTC_EN_) //使能RTC
#include "RTC.h"
#endif //SYS_RTC_EN_
#if(UCOS_II_EN)
#define _UCOS_II_ //是否使能UCOS_II操作系统-兼容我以前的代码中的OS定义
#include "ucos_ii.h"
void SYS_OS_TickInit(void); //系统OS滴答时钟初始化
void Sleep(u32 ms);//线程挂起延时
u64 SYS_GetOSRunTime(void); //获取操作系统运行时间(单位ms)
//OS临界区管理,会关闭任务调度
#if(OS_VERSION>30000) //使用的ucos_iii
#define OS_UCOS_III 1 //当前使用的是ucos iii
#define OS_TICKS_PER_SEC OS_CFG_TICK_RATE_HZ //兼容ucos-ii的滴答时钟1秒钟定义
#define OS_CRITICAL_SR_VAL CPU_SRcpu_sr //记录CPU中断状态的临时变量
#define OS_EnterCriticalSection() OS_CRITICAL_ENTER() //进入临界区
#define OS_LeaveCriticalSection() OS_CRITICAL_EXIT() //退出临界区
#else //使用的ucos_ii
#define OS_CRITICAL_SR_VAL OS_CPU_SRcpu_sr //记录CPU中断状态的临时变量
#define OS_EnterCriticalSection() OS_ENTER_CRITICAL() //进入临界区
#define OS_LeaveCriticalSection() OS_EXIT_CRITICAL() //退出临界区
#endif
#endif //UCOS_II_EN
//printf输出定义
#if (PRINTF_EN_) //使能到串口
#include "uart.h"
#include "stdio.h"
extern bool isPrintfOut;
extern UART_CH_Type PrintfCh; //printf通道设置
#define get_uart_printf_status() (isPrintfOut)
#define uart_printf_enable() (isPrintfOut=TRUE) //开启串口打印
#define uart_printf_disable() (isPrintfOut=FALSE) //关闭串口打印
#define uart_printf(format,...) (printf(format, ##__VA_ARGS__)) //串口打印
#define DEBUG(format,...) (printf("<DebugFile: "__FILE__", Line: %d> "format, __LINE__, ##__VA_ARGS__)) //DEBUG输出
#define info_printf(format,...) (printf("<info>:"format, ##__VA_ARGS__)) //系统打印信息
#definePRINTF_SetUartCh(ch) (PrintfCh=ch) //重定向printf输出通道
#endif
//IO口操作,只对单一的IO口!
//确保n的值小于16!
#define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n)//输出
#define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n)//输入
#define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n)//输出
#define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n)//输入
#define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n)//输出
#define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n)//输入
#define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n)//输出
#define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n)//输入
#define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n)//输出
#define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n)//输入
#define PHout(n) BIT_ADDR(GPIOH_ODR_Addr,n)//输出
#define PHin(n) BIT_ADDR(GPIOH_IDR_Addr,n)//输入
//中断向量表基址
#define SYS_NVIC_VectTab_RAM ((u32)0x20000000)
#define SYS_NVIC_VectTab_FLASH ((u32)0x00000000)
#endif //_HC32F46X_SYSTEM_H_
需要的数据类型定义
/*************************************************************************************************************
* 文件名 :hc32f46x_const.h
* 功能 :hc32f46x寄存器常量定义
* 作者 :cp1300@139.com
* 创建时间 :2021-06-13
* 最后修改时间:2021-06-13
* 详细:
*************************************************************************************************************/
#ifndef _HC32F46X_CONST_
#define _HC32F46X_CONST_
#include "typedef.h"
//晶振选择,只有HRC与XTAL能作为PLL时钟源
typedef enum
{
SYS_CRYSTAL_HRC = 0, //内部高速时钟16/20MHz
SYS_CRYSTAL_MRC = 1, //内部中速时钟8MHz-系统启动后的默认时钟
SYS_CRYSTAL_LRC = 2, //内部低速时钟32.768Khz
SYS_CRYSTAL_XTAL = 3, //外部高速时钟4-24MHz
SYS_CRYSTAL_XTAL32 = 4, //外部低速时钟32.768Khz
}SYS_CRYSTAL_SOURCE;
//系统主时钟来源
typedef enum
{
SYS_CLOCK_HRC = 0, //内部高速时钟16/20MHz
SYS_CLOCK_MRC = 1, //内部中速时钟8MHz-系统启动后的默认时钟
SYS_CLOCK_LRC = 2, //内部低速时钟32.768Khz
SYS_CLOCK_XTAL = 3, //外部高速时钟4-24MHz
SYS_CLOCK_XTAL32 = 4, //外部低速时钟32.768Khz
SYS_CLOCK_MPLL = 5, //MPLL
}SYS_CLOCK_SOURCE;
//时钟类型定义
typedef enum
{
SYS_CLOCK_HCLK = 0, //HCLK
SYS_CLOCK_EXCLK = 1, //EXCK
SYS_CLOCK_PCLK4 = 2, //PCLK4
SYS_CLOCK_PCLK3 = 3, //PCLK3
SYS_CLOCK_PCLK2 = 4, //PCLK2
SYS_CLOCK_PCLK1 = 5, //PCLK1
SYS_CLOCK_PCLK0 = 6, //PCLK0
}SYS_CLOCK_TYPE;
//外部高速时钟XTAL稳定时间选择
//稳定计数器的一个计数周期=LRC周期 /8
typedef enum
{
SYS_XTALSTB_35 = 1, //稳定计数器35个周期
SYS_XTALSTB_67 = 2, //稳定计数器67个周期
SYS_XTALSTB_131 = 3, //稳定计数器131个周期
SYS_XTALSTB_259 = 4, //稳定计数器259个周期
SYS_XTALSTB_547 = 5, //稳定计数器547个周期
SYS_XTALSTB_1059 = 6, //稳定计数器1059个周期
SYS_XTALSTB_2147 = 7, //稳定计数器2147个周期
SYS_XTALSTB_4291 = 8, //稳定计数器4291个周期
SYS_XTALSTB_8163 = 9, //稳定计数器8163个周期
}SYS_XTALSTB_TYPE;
//PLL分频系数定义
#define PLL_DIV_2 1 //PLL 2分频
#define PLL_DIV_3 2 //PLL 3分频
#define PLL_DIV_4 3 //PLL 4分频
#define PLL_DIV_5 4 //PLL 5分频
#define PLL_DIV_6 5 //PLL 6分频
#define PLL_DIV_7 6 //PLL 7分频
#define PLL_DIV_8 7 //PLL 8分频
#define PLL_DIV_9 8 //PLL 9分频
#define PLL_DIV_10 9 //PLL 10分频
#define PLL_DIV_11 10 //PLL 11分频
#define PLL_DIV_12 11 //PLL 12分频
#define PLL_DIV_13 12 //PLL 13分频
#define PLL_DIV_14 13 //PLL 14分频
#define PLL_DIV_15 14 //PLL 15分频
#define PLL_DIV_16 15 //PLL 16分频
//PLL时钟定义
typedef enum
{
SYS_MPLL_P = 0, //MPLL P通道输出,用于系统主时钟
SYS_MPLL_Q = 1, //MPLL Q通道输出
SYS_MPLL_R = 2, //MPLL R通道输出
SYS_UPLL_P = 3, //UPLL P通道输出
SYS_UPLL_Q = 4, //UPLL Q通道输出
SYS_UPLL_R = 5, //UPLL R通道输出
}SYS_PLL_TYPE;
//外设时钟开关定义-注意,写1是关闭,写0是开启
//高8位定义寄存器,低8位定义偏移bit
typedef enum
{
DEV_KEYSCAN = 0x0000+31, //PWR_FCG0
DEV_DCU4 = 0x0000+27, //PWR_FCG0
DEV_DCU3 = 0x0000+26, //PWR_FCG0
DEV_DCU2 = 0x0000+25, //PWR_FCG0
DEV_DCU1 = 0x0000+24, //PWR_FCG0
DEV_CRC = 0x0000+23, //PWR_FCG0
DEV_TRNG = 0x0000+22, //PWR_FCG0
DEV_HASH = 0x0000+21, //PWR_FCG0
DEV_AES = 0x0000+20, //PWR_FCG0
DEV_AOS = 0x0000+17, //PWR_FCG0
DEV_FCM = 0x0000+16, //PWR_FCG0
DEV_DMA2 = 0x0000+15, //PWR_FCG0
DEV_DMA1 = 0x0000+14, //PWR_FCG0
DEV_SRAMRET = 0x0000+10, //PWR_FCG0
DEV_SRAM3 = 0x0000+8, //PWR_FCG0
DEV_SRAM1_2 = 0x0000+4, //PWR_FCG0
DEV_SRAMH = 0x0000+0, //PWR_FCG0
DEV_USART4 = 0x0100+27, //PWR_FCG1
DEV_USART3 = 0x0100+26, //PWR_FCG1
DEV_USART2 = 0x0100+25, //PWR_FCG1
DEV_USART1 = 0x0100+24, //PWR_FCG1
DEV_SPI4 = 0x0100+19, //PWR_FCG1
DEV_SPI3 = 0x0100+18, //PWR_FCG1
DEV_SPI2 = 0x0100+17, //PWR_FCG1
DEV_SPI1 = 0x0100+16, //PWR_FCG1
DEV_I2S4 = 0x0100+15, //PWR_FCG1
DEV_I2S3 = 0x0100+14, //PWR_FCG1
DEV_I2S2 = 0x0100+13, //PWR_FCG1
DEV_I2S1 = 0x0100+12, //PWR_FCG1
DEV_SDIOC2 = 0x0100+11, //PWR_FCG1
DEV_SDIOC1 = 0x0100+10, //PWR_FCG1
DEV_USBFS = 0x0100+8, //PWR_FCG1
DEV_IIC3 = 0x0100+6, //PWR_FCG1
DEV_IIC2 = 0x0100+5, //PWR_FCG1
DEV_IIC1 = 0x0100+4, //PWR_FCG1
DEV_QSPI = 0x0100+3, //PWR_FCG1
DEV_CAN = 0x0100+0, //PWR_FCG1
DEV_TIMER6_3 = 0x0200+18, //PWR_FCG2
DEV_TIMER6_2 = 0x0200+17, //PWR_FCG2
DEV_TIMER6_1 = 0x0200+16, //PWR_FCG2
DEV_EMB = 0x0200+15, //PWR_FCG2
DEV_TIMER4_3 = 0x0200+10, //PWR_FCG2
DEV_TIMER4_2 = 0x0200+9, //PWR_FCG2
DEV_TIMER4_1 = 0x0200+8, //PWR_FCG2
DEV_TIMERA_6 = 0x0200+7, //PWR_FCG2
DEV_TIMERA_5 = 0x0200+6, //PWR_FCG2
DEV_TIMERA_4 = 0x0200+5, //PWR_FCG2
DEV_TIMERA_3 = 0x0200+4, //PWR_FCG2
DEV_TIMERA_2 = 0x0200+3, //PWR_FCG2
DEV_TIMERA_1 = 0x0200+2, //PWR_FCG2
DEV_TIMER0_2 = 0x0200+1, //PWR_FCG2
DEV_TIMER0_1 = 0x0200+0, //PWR_FCG2
DEV_OTS = 0x0300+12, //PWR_FCG3
DEV_CMP = 0x0300+8, //PWR_FCG3
DEV_ADC2 = 0x0300+1, //PWR_FCG3
DEV_ADC1 = 0x0300+0, //PWR_FCG3
}SYS_DEV_CLOCK;
//GPIO模式定义
typedef enum
{
OUT_PP = 0, //推挽输出
OUT_OD = 1, //开漏输出
IN_FLOATING = 2, //浮空输入
IN_IPU = 3, //上拉输入
IN_AIN = 4, //模拟输入
}SYS_GPIO_MODE;
//IO驱动模式选择
typedef enum
{
GPIO_DRV_0 = 0, //低驱动能力
GPIO_DRV_1 = 1, //中驱动能力
GPIO_DRV_2 = 2, //高驱动能力
}SYS_GPIO_DRV;
typedef enum
{
JTAG_MODE = 0, //使能全功能JTAG模式
SWD_MODE = 1, //使能SWD模式
DISABLE_JTAG = 2, //关闭模式
}SYS_JTAG_MODE;
//GPIO输入MOS常开设置,IO组定义,可以|
#define SYS_PINAER_PA (1<<0) //控制 PA0~PA15 输入MOS开关
#define SYS_PINAER_PB (1<<1) //控制 PB0~PB15 输入MOS开关
#define SYS_PINAER_PC (1<<2) //控制 PC0~PC15 输入MOS开关
#define SYS_PINAER_PD (1<<3) //控制 PD0~PD15 输入MOS开关
#define SYS_PINAER_PE (1<<4) //控制 PE0~PE15 输入MOS开关
#define SYS_PINAER_PH (1<<5) //控制 PH0~PH2 输入MOS开关
//外部中断触发设置
typedef enum
{
EXTI_NULL_EDGE = 0, //关闭触发
EXTI_POS_EDGE = 1, //上升沿
EXTI_NEG_EDGE = 2, //下升沿
EXTI_BOTH_EDGE = 3, //双边沿
}EXTI_EDGE_TYPE;
//中断与事件线触发电平设置
typedef enum
{
EIRQ_NEG_EDGE = 0, //下升沿
EIRQ_POS_EDGE = 1, //上升沿
EIRQ_BOTH_EDGE = 2, //双边沿
EIRQ_LOW_LEVEL = 3, //低电平
}EIRQ_EDGE_TYPE;
//中断控制器的数字滤波设置
typedef enum
{
IRQ_FILTER_PCLK3 = 0, //滤波器采样时钟=PCLK3
IRQ_FILTER_PCLK3_8 = 1, //滤波器采样时钟=PCLK3/8
IRQ_FILTER_PCLK3_32 = 2, //滤波器采样时钟=PCLK3/32
IRQ_FILTER_PCLK3_64 = 3, //滤波器采样时钟=PCLK3/64
IRQ_FILTER_DISABLE = 4, //滤波器关闭
}EIRQ_FILTER_TYPE;
//中断源选择
typedef enum
{
SYS_INT_SWI_IRQ0 = 0u,
SYS_INT_SWI_IRQ1 = 1u,
SYS_INT_SWI_IRQ2 = 2u,
SYS_INT_SWI_IRQ3 = 3u,
SYS_INT_SWI_IRQ4 = 4u,
SYS_INT_SWI_IRQ5 = 5u,
SYS_INT_SWI_IRQ6 = 6u,
SYS_INT_SWI_IRQ7 = 7u,
SYS_INT_SWI_IRQ8 = 8u,
SYS_INT_SWI_IRQ9 = 9u,
SYS_INT_SWI_IRQ10 = 10u,
SYS_INT_SWI_IRQ11 = 11u,
SYS_INT_SWI_IRQ12 = 12u,
SYS_INT_SWI_IRQ13 = 13u,
SYS_INT_SWI_IRQ14 = 14u,
SYS_INT_SWI_IRQ15 = 15u,
SYS_INT_SWI_IRQ16 = 16u,
SYS_INT_SWI_IRQ17 = 17u,
SYS_INT_SWI_IRQ18 = 18u,
SYS_INT_SWI_IRQ19 = 19u,
SYS_INT_SWI_IRQ20 = 20u,
SYS_INT_SWI_IRQ21 = 21u,
SYS_INT_SWI_IRQ22 = 22u,
SYS_INT_SWI_IRQ23 = 23u,
SYS_INT_SWI_IRQ24 = 24u,
SYS_INT_SWI_IRQ25 = 25u,
SYS_INT_SWI_IRQ26 = 26u,
SYS_INT_SWI_IRQ27 = 27u,
SYS_INT_SWI_IRQ28 = 28u,
SYS_INT_SWI_IRQ29 = 29u,
SYS_INT_SWI_IRQ30 = 30u,
SYS_INT_SWI_IRQ31 = 31u,
// External Interrupt.
SYS_INT_EXTI_EIRQ0 = 0u,
SYS_INT_EXTI_EIRQ1 = 1u,
SYS_INT_EXTI_EIRQ2 = 2u,
SYS_INT_EXTI_EIRQ3 = 3u,
SYS_INT_EXTI_EIRQ4 = 4u,
SYS_INT_EXTI_EIRQ5 = 5u,
SYS_INT_EXTI_EIRQ6 = 6u,
SYS_INT_EXTI_EIRQ7 = 7u,
SYS_INT_EXTI_EIRQ8 = 8u,
SYS_INT_EXTI_EIRQ9 = 9u,
SYS_INT_EXTI_EIRQ10 = 10u,
SYS_INT_EXTI_EIRQ11 = 11u,
SYS_INT_EXTI_EIRQ12 = 12u,
SYS_INT_EXTI_EIRQ13 = 13u,
SYS_INT_EXTI_EIRQ14 = 14u,
SYS_INT_EXTI_EIRQ15 = 15u,
// DMAC
SYS_INT_DMA1_TC0 = 32u,
SYS_INT_DMA1_TC1 = 33u,
SYS_INT_DMA1_TC2 = 34u,
SYS_INT_DMA1_TC3 = 35u,
SYS_INT_DMA2_TC0 = 36u,
SYS_INT_DMA2_TC1 = 37u,
SYS_INT_DMA2_TC2 = 38u,
SYS_INT_DMA2_TC3 = 39u,
SYS_INT_DMA1_BTC0 = 40u,
SYS_INT_DMA1_BTC1 = 41u,
SYS_INT_DMA1_BTC2 = 42u,
SYS_INT_DMA1_BTC3 = 43u,
SYS_INT_DMA2_BTC0 = 44u,
SYS_INT_DMA2_BTC1 = 45u,
SYS_INT_DMA2_BTC2 = 46u,
SYS_INT_DMA2_BTC3 = 47u,
SYS_INT_DMA1_ERR = 48u,
SYS_INT_DMA2_ERR = 49u,
// EFM
SYS_INT_EFM_PEERR = 50u,
SYS_INT_EFM_COLERR = 51u,
SYS_INT_EFM_OPTEND = 52u,
// QSPI
SYS_INT_QSPI_INTR = 54u,
// DCU
SYS_INT_DCU1 = 55u,
SYS_INT_DCU2 = 56u,
SYS_INT_DCU3 = 57u,
SYS_INT_DCU4 = 58u,
// TIMER 0
SYS_INT_TMR01_GCMA = 64u,
SYS_INT_TMR01_GCMB = 65u,
SYS_INT_TMR02_GCMA = 66u,
SYS_INT_TMR02_GCMB = 67u,
// RTC
SYS_INT_RTC_ALM = 81u,
SYS_INT_RTC_PRD = 82u,
// XTAL32 stop
SYS_INT_XTAL32_STOP = 84u,
// XTAL stop
SYS_INT_XTAL_STOP = 85u,
// wake-up timer
SYS_INT_WKTM_PRD = 86u,
// SWDT
SYS_INT_SWDT_REFUDF = 87u,
// TIMER 6
SYS_INT_TMR61_GCMA = 96u,
SYS_INT_TMR61_GCMB = 97u,
SYS_INT_TMR61_GCMC = 98u,
SYS_INT_TMR61_GCMD = 99u,
SYS_INT_TMR61_GCME = 100u,
SYS_INT_TMR61_GCMF = 101u,
SYS_INT_TMR61_GOVF = 102u,
SYS_INT_TMR61_GUDF = 103u,
SYS_INT_TMR61_GDTE = 104u,
SYS_INT_TMR61_SCMA = 107u,
SYS_INT_TMR61_SCMB = 108u,
SYS_INT_TMR62_GCMA = 112u,
SYS_INT_TMR62_GCMB = 113u,
SYS_INT_TMR62_GCMC = 114u,
SYS_INT_TMR62_GCMD = 115u,
SYS_INT_TMR62_GCME = 116u,
SYS_INT_TMR62_GCMF = 117u,
SYS_INT_TMR62_GOVF = 118u,
SYS_INT_TMR62_GUDF = 119u,
SYS_INT_TMR62_GDTE = 120u,
SYS_INT_TMR62_SCMA = 123u,
SYS_INT_TMR62_SCMB = 124u,
SYS_INT_TMR63_GCMA = 128u,
SYS_INT_TMR63_GCMB = 129u,
SYS_INT_TMR63_GCMC = 130u,
SYS_INT_TMR63_GCMD = 131u,
SYS_INT_TMR63_GCME = 132u,
SYS_INT_TMR63_GCMF = 133u,
SYS_INT_TMR63_GOVF = 134u,
SYS_INT_TMR63_GUDF = 135u,
SYS_INT_TMR63_GDTE = 136u,
SYS_INT_TMR63_SCMA = 139u,
SYS_INT_TMR63_SCMB = 140u,
// TIMER A
SYS_INT_TMRA1_OVF = 256u,
SYS_INT_TMRA1_UDF = 257u,
SYS_INT_TMRA1_CMP = 258u,
SYS_INT_TMRA2_OVF = 259u,
SYS_INT_TMRA2_UDF = 260u,
SYS_INT_TMRA2_CMP = 261u,
SYS_INT_TMRA3_OVF = 262u,
SYS_INT_TMRA3_UDF = 263u,
SYS_INT_TMRA3_CMP = 264u,
SYS_INT_TMRA4_OVF = 265u,
SYS_INT_TMRA4_UDF = 266u,
SYS_INT_TMRA4_CMP = 267u,
SYS_INT_TMRA5_OVF = 268u,
SYS_INT_TMRA5_UDF = 269u,
SYS_INT_TMRA5_CMP = 270u,
SYS_INT_TMRA6_OVF = 272u,
SYS_INT_TMRA6_UDF = 273u,
SYS_INT_TMRA6_CMP = 274u,
// USB FS
SYS_INT_USBFS_GLB = 275u,
// USRAT
SYS_INT_USART1_EI = 278u,
SYS_INT_USART1_RI = 279u,
SYS_INT_USART1_TI = 280u,
SYS_INT_USART1_TCI = 281u,
SYS_INT_USART1_RTO = 282u,
SYS_INT_USART1_WUPI = 432u,
SYS_INT_USART2_EI = 283u,
SYS_INT_USART2_RI = 284u,
SYS_INT_USART2_TI = 285u,
SYS_INT_USART2_TCI = 286u,
SYS_INT_USART2_RTO = 287u,
SYS_INT_USART3_EI = 288u,
SYS_INT_USART3_RI = 289u,
SYS_INT_USART3_TI = 290u,
SYS_INT_USART3_TCI = 291u,
SYS_INT_USART3_RTO = 292u,
SYS_INT_USART4_EI = 293u,
SYS_INT_USART4_RI = 294u,
SYS_INT_USART4_TI = 295u,
SYS_INT_USART4_TCI = 296u,
SYS_INT_USART4_RTO = 297u,
// SPI
SYS_INT_SPI1_SRRI = 299u,
SYS_INT_SPI1_SRTI = 300u,
SYS_INT_SPI1_SPII = 301u,
SYS_INT_SPI1_SPEI = 302u,
SYS_INT_SPI2_SRRI = 304u,
SYS_INT_SPI2_SRTI = 305u,
SYS_INT_SPI2_SPII = 306u,
SYS_INT_SPI2_SPEI = 307u,
SYS_INT_SPI3_SRRI = 309u,
SYS_INT_SPI3_SRTI = 310u,
SYS_INT_SPI3_SPII = 311u,
SYS_INT_SPI3_SPEI = 312u,
SYS_INT_SPI4_SRRI = 314u,
SYS_INT_SPI4_SRTI = 315u,
SYS_INT_SPI4_SPII = 316u,
SYS_INT_SPI4_SPEI = 317u,
//软件触发
SYS_INT_AOS_STRG = 319u,
// TIMER 4
SYS_INT_TMR41_GCMUH = 320u,
SYS_INT_TMR41_GCMUL = 321u,
SYS_INT_TMR41_GCMVH = 322u,
SYS_INT_TMR41_GCMVL = 323u,
SYS_INT_TMR41_GCMWH = 324u,
SYS_INT_TMR41_GCMWL = 325u,
SYS_INT_TMR41_GOVF = 326u,
SYS_INT_TMR41_GUDF = 327u,
SYS_INT_TMR41_RLOU = 328u,
SYS_INT_TMR41_RLOV = 329u,
SYS_INT_TMR41_RLOW = 330u,
SYS_INT_TMR42_GCMUH = 336u,
SYS_INT_TMR42_GCMUL = 337u,
SYS_INT_TMR42_GCMVH = 338u,
SYS_INT_TMR42_GCMVL = 339u,
SYS_INT_TMR42_GCMWH = 340u,
SYS_INT_TMR42_GCMWL = 341u,
SYS_INT_TMR42_GOVF = 342u,
SYS_INT_TMR42_GUDF = 343u,
SYS_INT_TMR42_RLOU = 344u,
SYS_INT_TMR42_RLOV = 345u,
SYS_INT_TMR42_RLOW = 346u,
SYS_INT_TMR43_GCMUH = 352u,
SYS_INT_TMR43_GCMUL = 353u,
SYS_INT_TMR43_GCMVH = 354u,
SYS_INT_TMR43_GCMVL = 355u,
SYS_INT_TMR43_GCMWH = 356u,
SYS_INT_TMR43_GCMWL = 357u,
SYS_INT_TMR43_GOVF = 358u,
SYS_INT_TMR43_GUDF = 359u,
SYS_INT_TMR43_RLOU = 360u,
SYS_INT_TMR43_RLOV = 361u,
SYS_INT_TMR43_RLOW = 362u,
// EMB
SYS_INT_EMB_GR0 = 390u,
SYS_INT_EMB_GR1 = 391u,
SYS_INT_EMB_GR2 = 392u,
SYS_INT_EMB_GR3 = 393u,
// EVENT PORT
SYS_INT_EVENT_PORT1 = 394u,
SYS_INT_EVENT_PORT2 = 395u,
SYS_INT_EVENT_PORT3 = 396u,
SYS_INT_EVENT_PORT4 = 397u,
// I2S
SYS_INT_I2S1_TXIRQOUT = 400u,
SYS_INT_I2S1_RXIRQOUT = 401u,
SYS_INT_I2S1_ERRIRQOUT = 402u,
SYS_INT_I2S2_TXIRQOUT = 403u,
SYS_INT_I2S2_RXIRQOUT = 404u,
SYS_INT_I2S2_ERRIRQOUT = 405u,
SYS_INT_I2S3_TXIRQOUT = 406u,
SYS_INT_I2S3_RXIRQOUT = 407u,
SYS_INT_I2S3_ERRIRQOUT = 408u,
SYS_INT_I2S4_TXIRQOUT = 409u,
SYS_INT_I2S4_RXIRQOUT = 410u,
SYS_INT_I2S4_ERRIRQOUT = 411u,
// COMPARATOR
SYS_INT_ACMP1 = 416u,
SYS_INT_ACMP2 = 417u,
SYS_INT_ACMP3 = 418u,
// I2C
SYS_INT_I2C1_RXI = 420u,
SYS_INT_I2C1_TXI = 421u,
SYS_INT_I2C1_TEI = 422u,
SYS_INT_I2C1_EE1 = 423u,
SYS_INT_I2C2_RXI = 424u,
SYS_INT_I2C2_TXI = 425u,
SYS_INT_I2C2_TEI = 426u,
SYS_INT_I2C2_EE1 = 427u,
SYS_INT_I2C3_RXI = 428u,
SYS_INT_I2C3_TXI = 429u,
SYS_INT_I2C3_TEI = 430u,
SYS_INT_I2C3_EE1 = 431u,
// PVD
SYS_INT_PVD_PVD1 = 433u,
SYS_INT_PVD_PVD2 = 434u,
// Temp. sensor
SYS_INT_OTS = 435u,
// FCM
SYS_INT_FCMFERRI = 436u,
SYS_INT_FCMMENDI = 437u,
SYS_INT_FCMCOVFI = 438u,
// WDT
SYS_INT_WDT_REFUDF = 439u,
// ADC
SYS_INT_ADC1_EOCA = 448u,
SYS_INT_ADC1_EOCB = 449u,
SYS_INT_ADC1_CHCMP = 450u,
SYS_INT_ADC1_SEQCMP = 451u,
SYS_INT_ADC2_EOCA = 452u,
SYS_INT_ADC2_EOCB = 453u,
SYS_INT_ADC2_CHCMP = 454u,
SYS_INT_ADC2_SEQCMP = 455u,
// TRNG
SYS_INT_TRNG_END = 456u,
// SDIOC
SYS_INT_SDIOC1_SD = 482u,
SYS_INT_SDIOC2_SD = 485u,
// CAN
SYS_INT_CAN_INT = 486u,
SYS_INT_MAX = 511u,
}INT_SOURCE_TYPE;
//EXTI线定义
typedef enum
{
EXTI_0 = 0, //EXTI0
EXTI_1 = 1, //EXTI1
EXTI_2 = 2, //EXTI2
EXTI_3 = 3, //EXTI3
EXTI_4 = 4, //EXTI4
EXTI_5 = 5, //EXTI5
EXTI_6 = 6, //EXTI6
EXTI_7 = 7, //EXTI7
EXTI_8 = 8, //EXTI8
EXTI_9 = 9, //EXTI9
EXTI_10 = 10, //EXTI10
EXTI_11 = 11, //EXTI11
EXTI_12 = 12, //EXTI12
EXTI_13 = 13, //EXTI13
EXTI_14 = 14, //EXTI14
EXTI_15 = 15, //EXTI15
}EXTI_TYPE;
//位带操作,实现51类似的GPIO控制功能
//具体实现思想,参考<<CM3权威指南>>第五章(87页~92页).M4同M3类似,只是寄存器地址变了.
//IO口操作宏定义
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
#define MEM_ADDR(addr)*((volatile unsigned long*)(addr))
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
//IO口地址映射
#define GPIOA_ODR_Addr (GPIOA_BASE+4)
#define GPIOB_ODR_Addr (GPIOB_BASE+4)
#define GPIOC_ODR_Addr (GPIOC_BASE+4)
#define GPIOD_ODR_Addr (GPIOD_BASE+4)
#define GPIOE_ODR_Addr (GPIOE_BASE+4)
#define GPIOH_ODR_Addr (GPIOH_BASE+4)
#define GPIOA_IDR_Addr (GPIOA_BASE+0)
#define GPIOB_IDR_Addr (GPIOB_BASE+0)
#define GPIOC_IDR_Addr (GPIOC_BASE+0)
#define GPIOD_IDR_Addr (GPIOD_BASE+0)
#define GPIOE_IDR_Addr (GPIOE_BASE+0)
#define GPIOH_IDR_Addr (GPIOH_BASE+0)
#endif //_HC32F46X_CONST_
兄弟,
有个<>的小图标,是用来插入代码用的,
效果很好,可以试试
页:
[1]