2440裸机学习之——LED灯的控制

 s3c2440有130个I/O口,GPA,GPB...GPJ通过设置寄存器来确定其功能。
   GPxCON寄存器:
   选择引脚的功能,GPBCON-GPJCON每两位控制一根引脚: 00表示输入,01表示输出,10表示特殊功能,11保留不用。
   GPACON特殊,每一位控制一根引脚,共23根,某位为0时,为输出引脚,当某位1时,相应引脚为地址线或用于地址控制, 此时GPADTA无用。
     一般的,GPACON设为全1,以便访问外部存储器件。
   GPxDAT寄存器:
   当引脚为输入时,读其对应位可知电平状态是高还是低。
   当引脚为输出时, 写寄存器对应位则引脚输出高电平或低电平。
   GPxUP寄存器:
   某位为1时,相应引脚无内部上拉电阻,为0时,相应引脚使用内部上拉电阻 。
   这里只讨论GPIO口的使用,其余的做成子函数,直接调用,可暂时不深究。

 

#include "def.h"
#include "option.h"
#include "2440addr.h"
#include "2440lib.h"
#include "2440slib.h"

/* 延迟函数*/
void delay(U32 count)
{
U32 i,j;
for(i=count;i>0;i--)
{
   for(j=0;j<10000;j++);
}
}


int Main(int argc,char **argv) //main函数
{

U8 key;
U32 mpll_val=0;
  
mpll_val = (92<<12)|(1<<4)|(1);

ChangeMPllValue((mpll_val>>12)&0xff, (mpll_val>>4)&0x3f, mpll_val&3);   //设置主时钟频率405MHZ
ChangeClockDivider(key, 12);      //设置时钟驱动频率的函数  
   
     MMU_DisableICache();    //对内存管理单元MMU的设置
     MMU_DisableDCache();

//呵呵,第一次 看到Arm是不是很晕,先不管他以上是我照搬过来的。  

//以下是GPB配制寄存器和数据寄存器


     rGPBCON=0x155555;   
//控制GPBCON全部为01,即输出

   
     
     while(1)
     {
   /*rGPBDAT = (0x0e<<5);    //00001110左移5位,LED1亮
      delay(120);
      rGPBDAT = (0x0d<<5);    //00001101左移5位,LED2亮
      delay(120);
      rGPBDAT = (0x0b<<5);    //00001011左移5位,LED3亮
      delay(120);
      rGPBDAT = (0x07<<5);    //00000111左移5位,LED4亮
      delay(120);
*/
     //从LED1到LED4依次亮
     rGPBDAT=(0x0e<<5);
     delay(120);
     rGPBDAT<<=1;
     delay(120);
     rGPBDAT<<=1;
     delay(120);
     rGPBDAT<<=1;
     //从LED4到LED1依次亮
     rGPBDAT=0x0e0;
     delay(120);
     rGPBDAT>>=1;
     delay(120);
     rGPBDAT>>=1;
     delay(120);
     rGPBDAT>>=1;
     delay(120);
     //两边灯往中间亮
     rGPBDAT=0x0c0;
     delay(120);
     rGPBDAT=0x120;
     delay(120);
     //全亮全灭两次
     rGPBDAT=0x0;
     delay(60);
     rGPBDAT=0x1e0;
     delay(60);
     rGPBDAT=0x0;
     delay(60);
     rGPBDAT=0x1e0;
     delay(60);
     //蜂鸣器响
     rGPBDAT=0x0f;
     delay(120);
     }
}

以上是我编写的例子,以下是摘自互联网

 

===========性感的分隔线============

KEY+LED测试

/*
LED IO控制,数据,上拉寄存器
*/
#define GPBCON (*(volatile unsigned *)0x56000010)
#define GPBDAT (*(volatile unsigned *)0x56000014)
#define GPBUP (*(volatile unsigned *)0x56000018)

/*
KEY IO控制,数据,上拉寄存器
*/
#define GPGCON (*(volatile unsigned *)0x56000060)
#define GPGDAT (*(volatile unsigned *)0x56000064)
#define GPGUP (*(volatile unsigned *)0x56000068)

寄存器地址,可参考2440的datasheet

/*
LED1-4对应的GPB5,GPB6,GPB7,GPB8


*/
#define GPB5_out (1<<(5*2))     //LED1
#define GPB6_out (1<<(6*2))     //LED2
#define GPB7_out (1<<(7*2))     //LED3
#define GPB8_out (1<<(8*2))     //LED4

LED,将十进制1左移多少位,对着datasheet从高位向底位自己手写一次,就明白了,刚开始我也不明白为什么用这样方式。

/*
K1-K6对应GPG0,GPG3,GPG5,GPG6,GPG7,GPG11
*/
#define GPG11_in ~(3<<(11*2))   //key6
#define GPG7_in ~(3<<(7*2))    //key5
#define GPG6_in ~(3<<(6*2))    //key4
#define GPG5_in ~(3<<(5*2))    //key3
#define GPG3_in ~(3<<(3*2))    //key2
#define GPG0_in ~(3<<(0*2))    //key1
int main()
{
/*用作读取KEY状态值*/
unsigned long dwDat=0;
/*LED1~LED4对应的4根引脚设为输出*/
GPBCON=GPB5_out | GPB6_out | GPB7_out | GPB8_out; //将输出的引脚在配置寄存器中设为01
/*KEY1-KEY6对应的6根引脚设为输入*/
GPGCON=GPG11_in & GPG7_in & GPG6_in & GPG5_in & GPG3_in & GPG0_in;//讲输入的引脚在配置寄存器中设为00
/*关闭KEY和LED的引脚上拉*/
GPBUP=0xFFFFFFFF;
GPGUP=0xFFFFFFFF;



while(1)
{
   GPBDAT=0xFFFFFFFF;
   dwDat=GPGDAT;                  //读取KEY引脚状态
   if(dwDat & (1<<11))            //key6是否按下 按下时,电压拉入地,为低电平,状态0
   {
    GPBDAT |=(1<<5);            //熄灭LED1
   }else{
    GPBDAT &=~(1<<5);           //点亮LED1
   }
  
   if(dwDat & (1<<7))             //判断KEY5是否按下
   {
    GPBDAT |=(1<<6);            //熄灭LED2
   }else{
    GPBDAT &=~(1<<6);           //点亮LED2
   }
  
   if(dwDat & (1<<6))            //key4
   {
    GPBDAT |=(1<<7);
   }else{
    GPBDAT &=~(1<<7);
   }
  
   if(dwDat & (1<<5))             //key3
   {
    GPBDAT |=(1<<8);
   }else{
    GPBDAT &=~(1<<8);
   }
  
   if(dwDat & (1<<3))              //key2
   {
    GPBDAT |=(1<<5) | (1<<6);
   }else{
    GPBDAT &=~((1<<5) | (1<<6));
   }
  
   if(dwDat & (1<<0))                  //key1
   {
    GPBDAT |=(1<<7) | (1<<8);
   }else{
    GPBDAT &= ~((1<<7) | (1<<8));
   }
   
}
return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
看门狗(Watchdog)是一种硬件定时器,用于监视系统是否正常运行。如果系统正常运行,那么看门狗会在设定的时间间隔内被定期喂狗;如果系统出现异常,看门狗就会在时间间隔到达后触发中断或复位操作,以恢复系统的正常运行。 在Mini2440上,看门狗的控制寄存器位于WTDAT、WTCON和WTCNT中。其中,WTDAT用于设置看门狗的计数器初始值,WTCON用于配置看门狗的工作模式和计数器时钟源,WTCNT则是看门狗的计数器。 下面是一个简单的示例代码,用于启动看门狗并设置其定时时间为5秒钟: ```c #include "s3c2440_soc.h" void delay(int count) { while(count--); } int main() { /* 设置看门狗定时时间为5秒钟 */ WTCON = (0x1 << 5) | (0x3 << 3) | (0x1 << 0); /* 启动看门狗 */ WTCNT = 0x10000; while(1) { /* 喂狗 */ WTCNT = 0x10000; delay(100000); /* 业务处理 */ // ... } return 0; } ``` 在上述代码中,我们首先设置了看门狗的定时时间为5秒钟。然后在主循环中,我们每隔一段时间就喂狗一次,以保证看门狗不会触发中断或复位操作。同时,我们还可以在喂狗的时间间隔内进行业务处理。 需要注意的是,在实际应用中,我们通常不会像上述代码一样简单地启动一个看门狗并喂狗。实际上,我们需要在系统正常运行时定期喂狗,以确保看门狗不会触发中断或复位操作;同时,我们还需要在系统出现异常时及时处理异常并复位系统,以防止系统陷入死循环或其他错误状态。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值