本帖最后由 mcsgy 于 2011-9-14 00:40 编辑
/******************************************************************************
工程名称:GPIO控制流水灯
作者: mcsgy
日期: 2011年9月11日
更新日期:2011年9月12日,2011年9月13日(加入中断控制)
参考: Cube的《助学入门实验2 GPIO实验》
******************************************************************************/
#include "NUC1xx.h"
void DrvSYS_Delay(uint32_t us) //系统延时程序
{
SysTick->LOAD = (us * (SystemCoreClock / 10000)) / 100;
SysTick->VAL = (0x00);
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk;
/* Waiting for down-count to zero */
while((SysTick->CTRL & (1 << 16)) == 0);
}
/*****************************时钟初始化程序********************************/
void M0_Clock_Init(void)
{
volatile uint32_t delayCnt;
SYSCLK->PWRCON.XTL12M_EN=1; //使能外部12M时钟
for(delayCnt=0;delayCnt<10000;delayCnt++); //等待外部12M时钟就绪
SYSCLK->PLLCON.PLL_SRC=0; //PLL时钟配置
SYSCLK->PLLCON.IN_DV=1;
SYSCLK->PLLCON.FB_DV=46;
SYSCLK->PLLCON.OUT_DV=3;
SYSCLK->PLLCON.PD=0;
SYSCLK->PLLCON.OE=0;
// DrvSYS_Delay(5000);
SYSCLK->CLKSEL0.HCLK_S=2; //选择PLL输出做为系统时钟48M
for(delayCnt=0;delayCnt<10000;delayCnt++); //等待PLL稳定这里不能用DrvSYS_Delay()来延时,
//因为此时系统时钟还未稳定,否则会出错,比如类似于0x5000_0100没有读写权限的错误。
SystemCoreClockUpdate(); //系统时钟更新完毕之后,便可用DrvSYS_Delay(us)函数
DrvSYS_Delay(5000); //
}
/*******************************IO口初始化子程序*********************************/
void IO_Init(void)
{
GPIOA->PMD.PMD2=1; //将GPIOA2,3,4,5设置为推挽输出
GPIOA->PMD.PMD3=1;
GPIOA->PMD.PMD4=1;
GPIOA->PMD.PMD5=1;
GPIOB->PMD.PMD10=1; //将GPIOB10设置为推挽输出
GPIOB->DOUT&=~(0x00000400); //GPIOB10输出低,蜂鸣器不响
}
/***************************中断初始化程序*******************************/
void SYSINT_Init(void)
{
GPIOB->PMD.PMD14=0; //将GPIOB14,15设置为输入
GPIOB->PMD.PMD15=0;
GPIOB->IMD&=0x3FFF; //设置为边沿触发方式
GPIOB->DBEN|=(BIT14+BIT15); //去抖使能
GPIOB->IEN=0;
GPIOB->IEN|=(BIT14+BIT15); //使能为下降沿触发方式
NVIC->ISER[0]|=(BIT2+BIT3);
}
/*****************************主程序main函数***********************************/
int main (void)
{
UNLOCKREG(); //解锁寄存器
M0_Clock_Init(); //初始化时钟
IO_Init(); //初始化LED灯IO
SYSINT_Init(); //初始化外部Key1,Key2中断
{
unsigned char i=8;
while(i--)
{
GPIOA->DOUT&=~BIT2; //依次点亮LED1,LED2,LED3,LED4并一直循环
DrvSYS_Delay(100000); //廷时100毫秒
GPIOA->DOUT|=BIT2;
GPIOA->DOUT&=~BIT3;
DrvSYS_Delay(100000);
GPIOA->DOUT|=BIT3;
GPIOA->DOUT&=~BIT4;
DrvSYS_Delay(100000);
GPIOA->DOUT|=BIT4;
GPIOA->DOUT&=~BIT5;
DrvSYS_Delay(100000);
GPIOA->DOUT|=BIT5;
}
}
while(1)
{
// if(!((GPIOB->PIN) & BIT14)) //按键点亮LED1
// {
// GPIOA->DOUT&=~BIT2;
// }
// else
// {
// GPIOA->DOUT|=BIT2;
// }
// if(!((GPIOB->PIN) & BIT15)) //按键点亮LED2
// {
// GPIOA->DOUT&=~BIT3;
// }
// else
// {
// GPIOA->DOUT|=BIT3;
// }
}
}
/***************************INT0中断服务程序******************************/
void EINT0_IRQHandler(void)
{
GPIOB->IEN|=(~BIT14); //关闭中断
DrvSYS_Delay(10000); //延时去抖
if(!((GPIOB->PIN) & BIT14)) //判断按键是否按下
{
GPIOA->DOUT^=(BIT2+BIT4); //IO口与1异或取反
}
GPIOB->ISRC|=BIT14; //清中断标志
GPIOB->IEN|=BIT14; //开启中断
}
/***************************INT1中断服务程序******************************/
void EINT1_IRQHandler(void)
{
GPIOB->IEN|=(~BIT15);
DrvSYS_Delay(10000);
if(!((GPIOB->PIN) & BIT15))
{
GPIOA->DOUT^=(BIT2+BIT3+BIT4+BIT5);
}
GPIOB->ISRC|=BIT15;
GPIOB->IEN|=BIT15;
}
|