6410 gpio

来源:互联网 发布:mac的appstore打不开 编辑:程序博客网 时间:2024/04/27 10:08

2 下面来看看tiny6410关于LED的原理图如图(1)所示:

 

                                                                   图1    LED原理图

3 LED实例,代码如下所示:(代码摘自\光盘4\实验代码\3-3-1\src\main.c)

 main.c

[cpp] view plaincopy
  1. /********************************************************** 
  2. *实验要求:   用Tiny6410上的4个LED资源实现跑马灯程序。 
  3. *功能描述:   Tiny6410用下面4个引脚连接了LED发光二极管,分别是 
  4. *             GPK4--LED1 
  5. *             GPK5--LED2 
  6. *             GPK6--LED3 
  7. *             GPK7--LED4 
  8. *             本程序将控制这四个管脚的输出电平,实现跑马灯的效果  
  9. *日    期:   2011-3-10 
  10. *作    者:   国嵌 
  11. **********************************************************/  
  12. #include "def.h"  
  13. #include "gpio.h"  
  14.   
  15. #define LED1_ON   ~(1<<4)  
  16. #define LED2_ON   ~(1<<5)  
  17. #define LED3_ON   ~(1<<6)  
  18. #define LED4_ON   ~(1<<7)  
  19.   
  20. #define LED1_OFF   (1<<4)  
  21. #define LED2_OFF   (1<<5)  
  22. #define LED3_OFF   (1<<6)  
  23. #define LED4_OFF   (1<<7)  
  24. #define LEDALL_OFF (0xf<<4)  
  25.   
  26. //GPIO  
  27. #define GPIO_BASE               (0x7F008000)  
  28. //oGPIO_REGS类型在 gpio.h 中定义  
  29. #define GPIO       (( volatile oGPIO_REGS *)GPIO_BASE)  
  30.   
  31. //函数声明  
  32. void delay(int times);  
  33. void LedPortInit(void);  
  34. void LedRun(void);  
  35.   
  36. /* 
  37.  * 程序入口 
  38.  * */  
  39. int main(void)  
  40. {     
  41.     LedPortInit();  
  42.     LedRun();  
  43. }  
  44.   
  45. /* 
  46.  * 延时函数 
  47.  * */  
  48. void delay(int times)  
  49. {  
  50.     int i;  
  51.     for(;times>0;times--)  
  52.       for(i=0;i<3000;i++);  
  53. }  
  54.   
  55. /* 
  56.  *   初始化连接LED灯的管脚资源 
  57.  * @ 通过将GPIO_BASE强制转化为(volatile oGPIO_REGS*)型的指针可以很方便 
  58.  * 的访问各个GPIO寄存器的值,这种方法比通过使用寄存器地址的宏定义访问 
  59.  * 寄存器单元更加规范和科学。 
  60.  * */    
  61. void LedPortInit(void)  
  62. {  
  63.     u32 uConValue;  
  64.     uConValue = GPIO->rGPIOKCON0;  
  65.     uConValue &= ~(0xffff<<16);  
  66.     uConValue |= 0x1111<<16;  
  67.     GPIO->rGPIOKCON0 = uConValue;              
  68. }  
  69.   
  70. /* 
  71.  *   跑马灯的实现函数 
  72.  * @ 通过控制连接LED的管脚的输出电平点亮和熄灭各个LED。 
  73.  * @ 逐个循环点亮各个LED。在每点亮一个后保持一定时间再熄灭它,接着 
  74.  * 点亮下一个LED,这样就形成了一个跑马灯的效果。 
  75.  * @ 这是一个需要改善的跑马灯程序,想想怎么优化这段代码。 
  76.  * */  
  77. void LedRun(void)  
  78. {  
  79.     GPIO->rGPIOKDAT |= LEDALL_OFF;  
  80.     while(1)  
  81.     {  
  82.         GPIO->rGPIOKDAT &= LED1_ON;     
  83.         delay(1000);  
  84.         GPIO->rGPIOKDAT |= LEDALL_OFF;  
  85.   
  86.         GPIO->rGPIOKDAT &= LED2_ON;  
  87.         delay(1000);  
  88.         GPIO->rGPIOKDAT |= LEDALL_OFF;  
  89.   
  90.         GPIO->rGPIOKDAT &= LED3_ON;  
  91.         delay(1000);  
  92.         GPIO->rGPIOKDAT |= LEDALL_OFF;  
  93.   
  94.         GPIO->rGPIOKDAT &= LED4_ON;  
  95.         delay(1000);  
  96.         GPIO->rGPIOKDAT |= LEDALL_OFF;  
  97.     }  
  98. }  

4 程序代码分析:

    首先来看一下宏定义部分:#define GPIO_BASE (0x7F008000)  ,此处定义了GPIO所有相关寄存器的初始地址,由芯片手册S3C6410X.pdf,第308页可以得到此地址。以下为手册截图。由下图2可以看出,GPIO相关寄存器的初始地址即为GPACON的地址0x7F008000。

                                                          图2 GPIO的内存映射地址

    了解#define GPIO     (( volatile oGPIO_REGS *)GPIO_BASE)之前我们先来看看oGPIO_REGS的定义(代码摘自\光盘4\实验代码\3-3-1\src\peripheral\gpio.h)

gpio.h

[cpp] view plaincopy
  1. #ifndef __GPIO_H__  
  2. #define __GPIO_H__  
  3.   
  4. #ifdef __cplusplus  
  5. extern "C" {  
  6. #endif  
  7.   
  8. #include "def.h"  
  9.   
  10. typedef struct tag_GPIO_REGS  
  11. {  
  12.     u32 rGPIOACON;          //0x7F008000  
  13.     u32 rGPIOADAT;  
  14.     u32 rGPIOAPUD;  
  15.     u32 rGPIOACONSLP;  
  16.     u32 rGPIOAPUDSLP;  
  17.     u32 reserved1[3];  
  18.       
  19.     u32 rGPIOBCON;          //0x7F008020  
  20.     u32 rGPIOBDAT;  
  21.     u32 rGPIOBPUD;  
  22.     u32 rGPIOBCONSLP;  
  23.     u32 rGPIOBPUDSLP;     
  24.     u32 reserved2[3];  
  25.           
  26.     u32 rGPIOCCON;          //0x7F008040  
  27.     u32 rGPIOCDAT;  
  28.     u32 rGPIOCPUD;  
  29.     u32 rGPIOCCONSLP;  
  30.     u32 rGPIOCPUDSLP;     
  31.     u32 reserved3[3];  
  32.           
  33.     u32 rGPIODCON;          //0x7F008060  
  34.     u32 rGPIODDAT;  
  35.     u32 rGPIODPUD;  
  36.     u32 rGPIODCONSLP;  
  37.     u32 rGPIODPUDSLP;     
  38.     u32 reserved4[3];  
  39.           
  40.     u32 rGPIOECON;          //0x7F008080  
  41.     u32 rGPIOEDAT;  
  42.     u32 rGPIOEPUD;  
  43.     u32 rGPIOECONSLP;  
  44.     u32 rGPIOEPUDSLP;     
  45.     u32 reserved5[3];  
  46.           
  47.     u32 rGPIOFCON;          //0x7F0080A0  
  48.     u32 rGPIOFDAT;  
  49.     u32 rGPIOFPUD;  
  50.     u32 rGPIOFCONSLP;  
  51.     u32 rGPIOFPUDSLP;     
  52.     u32 reserved6[3];  
  53.           
  54.     u32 rGPIOGCON;          //0x7F0080C0  
  55.     u32 rGPIOGDAT;  
  56.     u32 rGPIOGPUD;  
  57.     u32 rGPIOGCONSLP;  
  58.     u32 rGPIOGPUDSLP;     
  59.     u32 reserved7[3];  
  60.       
  61.     u32 rGPIOHCON0;         //0x7F0080E0  
  62.     u32 rGPIOHCON1;  
  63.     u32 rGPIOHDAT;  
  64.     u32 rGPIOHPUD;  
  65.     u32 rGPIOHCONSLP;  
  66.     u32 rGPIOHPUDSLP;     
  67.     u32 reserved8[2];  
  68.   
  69.     u32 rGPIOICON;          //0x7F008100  
  70.     u32 rGPIOIDAT;  
  71.     u32 rGPIOIPUD;  
  72.     u32 rGPIOICONSLP;  
  73.     u32 rGPIOIPUDSLP;     
  74.     u32 reserved9[3];  
  75.   
  76.     u32 rGPIOJCON;          //0x7F008120  
  77.     u32 rGPIOJDAT;  
  78.     u32 rGPIOJPUD;  
  79.     u32 rGPIOJCONSLP;  
  80.     u32 rGPIOJPUDSLP;     
  81.     u32 reserved10[3];  
  82.       
  83.     u32 rGPIOOCON;          //0x7F008140  
  84.     u32 rGPIOODAT;  
  85.     u32 rGPIOOPUD;  
  86.     u32 rGPIOOCONSLP;  
  87.     u32 rGPIOOPUDSLP;     
  88.     u32 reserved11[3];    
  89.   
  90.     u32 rGPIOPCON;          //0x7F008160  
  91.     u32 rGPIOPDAT;  
  92.     u32 rGPIOPPUD;  
  93.     u32 rGPIOPCONSLP;  
  94.     u32 rGPIOPPUDSLP;     
  95.     u32 reserved12[3];  
  96.   
  97.     u32 rGPIOQCON;          //0x7F008180  
  98.     u32 rGPIOQDAT;  
  99.     u32 rGPIOQPUD;  
  100.     u32 rGPIOQCONSLP;  
  101.     u32 rGPIOQPUDSLP;     
  102.     u32 reserved13[3];    
  103.   
  104.     u32 rSPCON;             //0x7F0081A0  
  105.     u32 reserved14[3];  
  106.     u32 rMEM0CONSTOP;       //0x7F0081B0  
  107.     u32 rMEM1CONSTOP;       //0x7F0081B4  
  108.     u32 reserved15[2];  
  109.     u32 rMEM0CONSLP0;       //0x7F0081C0  
  110.     u32 rMEM0CONSLP1;       //0x7F0081C4  
  111.     u32 rMEM1CONSLP;        //0x7F0081C8  
  112.     u32 reserved;  
  113.     u32 rMEM0DRVCON;        //0x7F0081D0  
  114.     u32 rMEM1DRVCON;        //0x7F0081D4  
  115.     u32 reserved16[10];  
  116.   
  117.     u32 rEINT12CON;         //0x7f008200  
  118.     u32 rEINT34CON;         //0x7f008204  
  119.     u32 rEINT56CON;         //0x7f008208  
  120.     u32 rEINT78CON;         //0x7f00820C  
  121.     u32 rEINT9CON;          //0x7f008210  
  122.     u32 reserved17[3];  
  123.   
  124.     u32 rEINT12FLTCON;      //0x7f008220  
  125.     u32 rEINT34FLTCON;      //0x7f008224  
  126.     u32 rEINT56FLTCON;      //0x7f008228  
  127.     u32 rEINT78FLTCON;      //0x7f00822C  
  128.     u32 rEINT9FLTCON;       //0x7f008230  
  129.     u32 reserved18[3];  
  130.   
  131.     u32 rEINT12MASK;        //0x7f008240  
  132.     u32 rEINT34MASK;        //0x7f008244  
  133.     u32 rEINT56MASK;        //0x7f008248  
  134.     u32 rEINT78MASK;        //0x7f00824C  
  135.     u32 rEINT9MASK;         //0x7f008250  
  136.     u32 reserved19[3];    
  137.   
  138.     u32 rEINT12PEND;        //0x7f008260  
  139.     u32 rEINT34PEND;        //0x7f008264  
  140.     u32 rEINT56PEND;        //0x7f008268  
  141.     u32 rEINT78PEND;        //0x7f00826C  
  142.     u32 rEINT9PEND;         //0x7f008270  
  143.     u32 reserved20[3];            
  144.   
  145.     u32 rPRIORITY;          //0x7f008280  
  146.     u32 rSERVICE;           //0x7f008284  
  147.     u32 rSERVICEPEND;       //0x7f008288  
  148.     u32 reserved21;  
  149.   
  150.     u32 reserved22[348];  
  151.       
  152.     u32 rGPIOKCON0;         //0x7f008800  
  153.     u32 rGPIOKCON1;         //0x7f008804  
  154.     u32 rGPIOKDAT;          //0x7f008808  
  155.     u32 rGPIOKPUD;          //0x7f00880c  
  156.   
  157.     u32 rGPIOLCON0;         //0x7f008810  
  158.     u32 rGPIOLCON1;         //0x7f008814  
  159.     u32 rGPIOLDAT;          //0x7f008818  
  160.     u32 rGPIOLPUD;          //0x7f00881c  
  161.   
  162.     u32 rGPIOMCON;          //0x7f008820  
  163.     u32 rGPIOMDAT;          //0x7f008824  
  164.     u32 rGPIOMPUD;          //0x7f008828      
  165.     u32 reserved23;  
  166.   
  167.     u32 rGPIONCON;          //0x7f008830  
  168.     u32 rGPIONDAT;          //0x7f008834  
  169.     u32 rGPIONPUD;          //0x7f008838      
  170.     u32 reserved24;  
  171.   
  172.     u32 reserved25[16];  
  173.   
  174.     u32 rSPCONSLP;          //0x7f008880  
  175.   
  176.     u32 reserved26[31];       
  177.   
  178.     u32 rEINT0CON0;         //0x7f008900  
  179.     u32 rEINT0CON1;         //0x7f008904  
  180.     u32 reserved27[2];  
  181.   
  182.     u32 rEINT0FLTCON0;      //0x7f008910  
  183.     u32 rEINT0FLTCON1;      //0x7f008914  
  184.     u32 rEINT0FLTCON2;      //0x7f008918  
  185.     u32 rEINT0FLTCON3;      //0x7f00891c  
  186.     u32 rEINT0MASK;         //0x7f008920  
  187.     u32 rEINT0PEND;         //0x7f008924  
  188.     u32 reserved28[2];  
  189.     u32 rSLPEN;             //0x7f008930  
  190.   
  191. }   
  192. oGPIO_REGS;  
  193.   
  194. #ifdef __cplusplus  
  195. }  
  196. #endif  
  197.   
  198. #endif //__GPIO_H__  


 

    由此可以看出oGPIO_REGS为一结构体,(( volatile oGPIO_REGS *)GPIO_BASE)为指向此结构体的指针,该指针即GPIO指向的初始地址为GPIO_BASE(0x7F008000),通过使用此指针,可以遍历到从GPIO_BASE地址(0x7F008000)开始到0x7F008930地址处的所有寄存器。注意:上面结构体中所有元素,类型都是u32类型的,刚好四个字节,同时,由图2可知,如GPACON和GPADAT等寄存器地址都相差4,对于这段连续地址,如若中间没有对应某个寄存器,则用某些u32类型的数组填充,如u32 reserved1[3]等等。

下面开始看main.c中的main函数,main函数主要完成两个步骤,(1)LED初始化(LedPortInit()),(2)点亮LED(LedRun()).   

LED初始化:

GPK总共有16个引脚,而每个引脚需要GPIO控制寄存器(GP*CON)使用4位来控制IO管脚的功能,即4*16=64位来控制所有GPK组的16个引脚。所以需要GPK使用了两个控制寄存器,GPKCON0和GPKCON1,从图1所示,我们使用的是GPK4,GPK5,GPK6,GPK7来控制LED灯的点亮与熄灭,所以此处我们只需使用GPKCON0来将GPK4,GPK5,GPK6,GPK7设置成输出功能。如图3所示,GPKCON寄存器配置如下:

                                                                         图3 GPKCON寄存器配置图

配置代码如下:

1 .       u32 uConValue;

2 .       uConValue = GPIO->rGPIOKCON0;

3 .       uConValue &= ~(0xffff<<16);      0000 0000 0000 0000 1111 1111 1111 1111

4 .       uConValue |= 0x1111<<16;

5 .       GPIO->rGPIOKCON0 = uConValue;

    首先我们要知道,在控制某个管脚的时候,我们不能去改变其它不使用管脚的状态,第二行获得GPKCON此时的状态将其赋给uConValue,第三行用于将GPKCON的高16位清零,低16位不变;第四行用于将GPKCON的高16为变为0001 0001 0001 0001(即GPK4,GPK5,GPK6,GPK7管脚都设置为输出模式),低16为仍然不变。最后将此值赋回到GPKCON寄存器当中。至此,完成整个LED的初始化工作。

点亮LED:注意GPKDAT为16位寄存器,虽然由gpio.h中看到rGPIOKDAT为32位,只是相当于我们忽略了其中的高16位,因为数据是从低地址往高地址处依次存放的。

GPIO->rGPIOKDAT |= LEDALL_OFF;    //4个灯全灭

         while(1)
         {
                 GPIO->rGPIOKDAT &= LED1_ON;         //GPK4管脚的灯亮
                 delay(1000);
                 GPIO->rGPIOKDAT |= LEDALL_OFF;   //GPK4管脚的灯灭

                 GPIO->rGPIOKDAT &= LED2_ON;      //GPK5管脚的灯亮
                 delay(1000);
                 GPIO->rGPIOKDAT |= LEDALL_OFF;  //GPK4管脚的灯灭

                 GPIO->rGPIOKDAT &= LED3_ON;     //GPK6管脚的灯亮
                 delay(1000);
                 GPIO->rGPIOKDAT |= LEDALL_OFF;  //GPK4管脚的灯灭

                 GPIO->rGPIOKDAT &= LED4_ON;   //GPK7管脚的灯亮
                 delay(1000);
                 GPIO->rGPIOKDAT |= LEDALL_OFF;  //GPK4管脚的灯灭
  }

 

首先通过如下宏定义来表明LED的亮与灭。

#define LED1_ON   ~(1<<4)           执行步骤:1<<4  -> ~(1<<4) ,对应步骤为:0000 0000 0000 0001->0000 0000 0001 0000->1111 1111 1110 1111
#define LED2_ON   ~(1<<5)          
#define LED3_ON   ~(1<<6)
#define LED4_ON   ~(1<<7)

#define LED1_OFF   (1<<4)         执行步骤:1<<4         对应步骤为:0000 0000 0000 0001->0000 0000 0001 0000
#define LED2_OFF   (1<<5)
#define LED3_OFF   (1<<6)
#define LED4_OFF   (1<<7)
#define LEDALL_OFF (0xf<<4)     执行步骤:0xf<<4, 对应步骤为:0000 0000 0000 1111->0000 0000 1111 0000

 

下面完成整个程序的运行步骤:

1 打开rvds

 

  新建一个空的arm可执行镜像LED:

在E:\tiny6410下自动多出一个LED目录

目录下自动创建了如下一些文件及文件夹:

 

将src目录和6410_scatter.txt拖入LED目录下:

将src下的代码直接拖入rvds:

得到如下添加代码后的工程,并打开main函数。

开始配置工程:

1 在汇编过程中选择处理器型号ARM1176JZF-S

2 在编译中选择处理器型号ARM1176JZF-S

3 在链接过程中选择scattered,文件选择scattered.txt

保存后,编译程序,出现如下错误:

解决方法:在配置框中的汇编的预处理中做如下设置:

然后点击Add,将VIC_MODE预处理值设为1:

保存后重新编译,编译通过,在Debug目录下会多出一个LED.axf文件,此文件为要运行在开发板的文件。

现在开始通过JLINK来调试开发板。首先链接开发板与jlink线。

将开发板上的S2拨到Nand Flash启动那一侧,开启开发板电源,在超级终端上快速按下回车键,让U-Boot停留在功能选单上,不要让它进入Linux系统,如下图所示:

 

 在XP里,点击开始菜单,选择程序->SEGGER->J-Link ARM V4.10i->J-Link GDB Server,启动画面如下所示:

上图表明jlink已经正确链接上了。

然后需要配置AXD Debugge,让它使用J-Link来调试,通过以下方法启动AXD Debugger

启动AXD Debugger后,在AXD Debugger主界面上打开主菜单的Options -> Configure Target,在弹出的Choose Target对话框中,点击Add, 将会弹出文件选择对话框,在文件打开对话框中,定位到J-Link的安装目录(默认是E:\Program Files\SEGGER\JLinkARM_V410i),在目录中选择JLinkRDI.dll打开即可,如下图所示:

可能AXD会提示找不到JLinkARM.DLL,如下图所示:

解决方法是:先不理会这个对话框,打开我的电脑,再次定位到J-Link的安装目录(默认是E:\Program Files\SEGGER\JLinkARM_V410i),将其中的JLinkARM.DLL文件拷贝到RVDS的安装目录下的Bin目录下(默认是C:\Program Files\ARM\ADSv1_2\Bin),再在上面的对话框上点击“确定”即可。

下面通过File->Load  image,载入LED.axf文件,进行调试。


原创粉丝点击