Chinaunix首页 | 论坛 | 博客
  • 博客访问: 235881
  • 博文数量: 48
  • 博客积分: 2500
  • 博客等级: 少校
  • 技术积分: 480
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-24 11:02
文章分类

全部博文(48)

文章存档

2010年(33)

2009年(14)

2008年(1)

我的朋友

分类: 嵌入式

2010-09-10 15:56:52

1、首先需要一个包含GPIO引脚地址的文件micro2440_GPX.h
/*
 * mini2440开发板的GPIO操作宏定义头文件
 * author: jimmy
 * website: http://www.visky.cublog.cn
 */
#define GPIOBASE 0x56000000
#define GPXCON_ADDR(x) (*(volatile unsigned long *)(GPIOBASE + x))
#define GPXDAT_ADDR(x) (*(volatile unsigned long *)(GPIOBASE + x + 4))
#define GPXUP_ADDR(x) (*(volatile unsigned long *)(GPIOBASE + x + 8))

#define GPA 0x0
#define GPB 0x10
#define GPC 0x20
#define GPD 0x30
#define GPE 0x40
#define GPF 0x50
#define GPG 0x60
#define GPH 0x70
#define GPJ 0xd0

/*GPX的属性配置寄存器 X代表不同的类型*/
#define GPACON GPXCON_ADDR(GPA) 
#define GPBCON GPXCON_ADDR(GPB)
#define GPCCON GPXCON_ADDR(GPC)
#define GPDCON GPXCON_ADDR(GPD)
#define GPECON GPXCON_ADDR(GPE)
#define GPFCON GPXCON_ADDR(GPF)
#define GPGCON GPXCON_ADDR(GPG)
#define GPHCON GPXCON_ADDR(GPH)
#define GPJCON GPXCON_ADDR(GPJ)


/*GPX的数据寄存器*/
#define GPADAT GPXDAT_ADDR(GPA) 
#define GPBDAT GPXDAT_ADDR(GPB)
#define GPCDAT GPXDAT_ADDR(GPC)
#define GPDDAT GPXDAT_ADDR(GPD)
#define GPEDAT GPXDAT_ADDR(GPE)
#define GPFDAT GPXDAT_ADDR(GPF)
#define GPGDAT GPXDAT_ADDR(GPG)
#define GPHDAT GPXDAT_ADDR(GPH)
#define GPJDAT GPXDAT_ADDR(GPJ)

#define GPBUP GPXUP_ADDR(GPB)
#define GPCUP GPXUP_ADDR(GPC)
#define GPDUP GPXUP_ADDR(GPD)
#define GPEUP GPXUP_ADDR(GPE)
#define GPFUP GPXUP_ADDR(GPF)
#define GPGUP GPXUP_ADDR(GPG)
#define GPHUP GPXUP_ADDR(GPH)
#define GPJUP GPXUP_ADDR(GPJ)


#define GPAXOUT(x) (GPACON & (GPXMASK & (0x0 << x))) /*GPA比较特殊*/
/******************************************************************************
 设置GPIO控制端口GPXCON的x位为输出,GPXCON必须为GPBCON~GPJCON,
 x必须<=16
把对应bit变为01即设置为输出
 ******************************************************************************/
#define GPXXOUT(GPXCON,x) (GPXCON |=  (0x1 << (2 * x)))

/******************************************************************************
  设置GPIO控制端口GPXCON的x位为输入,GPXCON必须为GPBCON~GPJCON,
  x必须<=16
把对应bit变为00即设置为输出
 ******************************************************************************/
#define GPXXIN(GPXCON,x) (GPXCON &= ((GPXCON & ~(0x3 << (2 * x)))))

/********************************************************************************
 设置GPIO端口GPXDAT的x位为高电平,GPXCON必须为GPBCON~GPJCON,
 x视不同的BANK拥有的I/O口的个数而定
 ********************************************************************************/
#define GPXXSET(GPXDAT, x) GPXDAT = GPXDAT | (1 << x)

/********************************************************************************
 设置GPIO端口GPXDAT的x位为低电平,GPXCON必须为GPBCON~GPJCON,
 x视不同的BANK拥有的I/O口的个数而定
 ********************************************************************************/
#define GPXXCLR(GPXDAT, x) GPXDAT = GPXDAT & ~(1 << x)

/*******************************************************************************
 拉高GPXUP端口的x位,GPXCON必须为GPBCON~GPJCON,
 x视不同的BANK拥有的I/O口的个数而定
 *******************************************************************************/
#define GPXUPSET(GPXUP, x) GPXUP = GPXUP | (1 << x)

/*******************************************************************************
 拉低GPXUP端口的x位,GPXCON必须为GPBCON~GPJCON,
 x视不同的BANK拥有的I/O口的个数而定
 *******************************************************************************/
#define GPXUPCLR(GPXUP, x) GPXUP = GPXUP & ~(1 << x)

2、建立启动文件crt0.S
@******************************************************************************
@ File: crt0.S
@ 功能:通过它转入C程序
@******************************************************************************      

.text
.global _start
_start:
            ldr     r0, =0x53000000     @ WATCHDOG @WATCHDOG寄存器地址
            mov     r1, #0x0                    
            str     r1, [r0]            @ 写入0,禁止WATCHDOG,否则CPU会不断重启
           
            ldr     sp, =1024*4         @ 设置堆栈,注意不能大于4KB,因为现在可用的内存只有4KB
                                        @ nand flash中的代码在复位后会移到内部ram(只有4KB)
            bl      main                @ 调用C程序中的main函数
halt_loop:
            b       halt_loop           @ 死循环

3、创建主程序文件key_led.c
#include "micro2440_GPX.h"

/**
 * nfs 0x32000000 192.168.0.13:/work/nfs_root/key_led.bin
 * nand erase 0x0 0x10000            -----64K
 * nand erase write.jffs2 0x32000000 0x0 $(filesize)
 * 务必设置跳线从nand flash启动
 * 按键按下时为低电平
 * 00表示输入,01表示输出
 */

int main()
{
    unsigned long dwData;

    /* 设置4个LED灯处于输出状态 */
    GPXXOUT(GPBCON, 5);        /* GPB5 led1 */
    GPXXOUT(GPBCON, 6);        /* GPB6 led2 */
    GPXXOUT(GPBCON, 7);        /* GPB7 led3 */
    GPXXOUT(GPBCON, 8);        /* GPB8 led4 */

    /* 设置六个按键处于输入状态 */
    GPXXIN(GPGCON, 0);        /* GPG0 key1 */
    GPXXIN(GPGCON, 3);        /* GPG3 key2 */
    GPXXIN(GPGCON, 5);        /* GPG5 key3 */
    GPXXIN(GPGCON, 6);        /* GPG6 key4 */
    GPXXIN(GPGCON, 7);        /* GPG7 key5 */
    GPXXIN(GPGCON, 11);        /* GPG11 key6 */

    while(1) {
    dwData = GPGDAT;

     /* GPG11的状态 */
        if(dwData & (1<<11)) 
             GPBDAT |= (1<<5);        /* 设置GPB5的值为1 */
        else
             GPBDAT &= ~(1<<5);        /* 设置GPB5的值为0, led1点亮 */

        /* GPG7的状态 */
        if(dwData & (1<<7)) 
             GPBDAT |= (1<<6);        /* 设置GPB6的值为1 */
        else
             GPBDAT &= ~(1<<6);        /* 设置GPB6的值为0, led2点亮 */

        /* GPG6的状态 */
        if(dwData & (1<<6)) 
             GPBDAT |= (1<<7);        /* 设置GPB7的值为1 */
        else
             GPBDAT &= ~(1<<7);        /* 设置GPB7的值为0, led3点亮 */

        /* GPG5的状态 */
        if(dwData & (1<<5))
             GPBDAT |= (1<<8);        /* 设置GPB8的值为1 */
        else
             GPBDAT &= ~(1<<8);        /* 设置GPB8的值为0, led4点亮 */

        /* GPG3的状态 */
        if(dwData & (1<<3))
             GPBDAT |= (1<<5)|(1<<6);        /* 设置GPB5/6的值为1 */
        else
             GPBDAT &= ~((1<<5) | (1<<6) );    /*设置GPB5/6的值为0, led1, led2点亮 */

        /* GPG0的状态 */
        if(dwData & (1<<0))
             GPBDAT |= (1<<8)|(1<<7);        /* 设置GPB7/8的值为1 */
        else
             GPBDAT &= ~((1<<7) |(1<<8));    /* 设置GPB7/8的值为0, led3, led4点亮 */   
    }

    return 0;
}

4、创建Makefile
led_on_c.bin : crt0.S  key_led.c
    arm-linux-gcc -g -c -o crt0.o crt0.S
    arm-linux-gcc -g -c -o key_led.o key_led.c
    arm-linux-ld -Ttext 0x00000000 -g  crt0.o key_led.o -o key_led_elf
    arm-linux-objcopy -O binary -S key_led_elf key_led.bin
    arm-linux-objdump -D -m arm  key_led_elf > key_led.dis
clean:
    rm -f key_led.dis key_led.bin key_led_elf *.o
第2、3行分别编译crt0.S、key_led.c
第4行将编译的结果链接起来
第5行把链接得到的ELF格式可执行文件key_led_elf转换成key_led.bin
第6行将结果转换为汇编代码以供查看

5、总结:程序本身不难,但需要参考所对应开发板的手册来查看各个GPIO的地址以及输入输出设置为低电平还是高电平,参考嵌入式Linux应用开发完全手册和micro2440开发板相关手册
阅读(1580) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~