02.ARM-mini2440-GPIO操作-led_on_c

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012075395/article/details/78814399

ARM-mini2440-GPIO操作-led_on_c
主要看芯片手册

这里mini2440的GPB5为例,LED灯的亮灭。

LED灯IO引脚
LED灯IO引脚

S3C2440芯片配置引脚
Port B(GPB): 11-input/out port
GPB总共有11个IO。

配置引脚由寄存器来控制。
分为控制寄存器(GPBCON)和数据寄存器(GPBDAT)
这里写图片描述

这里写图片描述

所以设置:GPBCON [11:10] = 01

这里写图片描述

当端口被配置为输入端口时,相应的位是引脚状态。当端口被配置为输出端口时,引脚状态与相应的位相同。当端口被配置为函数PIN时,将读取未定义的值。
所以设置:GPBDAT [5] = 00

这里暂时没有用到
GPBUP
0:连接到相应端口引脚的起止功能已启用。
1:拉起功能被禁用。

使用C语言编写程序
1。main函数并不特别,一样要被别人调用,执行完成也要返回。
2。启动文件,
硬件初始化
①关闭看门狗,(一定要的)√
②初始化时钟,(暂时可以不要)×
③初始化sdram,(暂时可以不要)×
软件初始化:
①设置栈,sp->内存,
②设置返回地址
③调用main
④清理工作

启动文件如下,

@******************************************************************************
@ File:crt0.S
@ 功能:通过它转入C程序
@******************************************************************************       

.text
.global _start
_start:
            ldr     r0, =0x53000000     @ WATCHDOG寄存器地址
            mov     r1, #0x0                     
            str     r1, [r0]            @ 写入0,禁止WATCHDOG,否则CPU会不断重启

            ldr     sp, =1024*4         @ 设置堆栈,注意:不能大于4k, 因为现在可用的内存只有4K
                                        @ nand flash中的代码在复位后会移到内部ram中,此ram只有4K
            bl      main                @ 调用C程序中的main函数
halt_loop:
            b       halt_loop

main函数C文件

#define GPBCON      (*(volatile unsigned long *)0x56000010)
#define GPBDAT      (*(volatile unsigned long *)0x56000014)

int main()
{
    GPBCON = 0x00000400;    // 设置GPB5为输出口, 位[11:10]=0b01
    GPBDAT = 0x00000000;    // GPB4输出0,LED点亮

    return 0;
}

Makefile文件

led_on_c.bin : crt0.S  led_on_c.c
    arm-linux-gcc -g -c -o crt0.o crt0.S
    arm-linux-gcc -g -c -o led_on_c.o led_on_c.c
    arm-linux-ld -Ttext 0x0000000 -g  crt0.o led_on_c.o -o led_on_c_elf
    arm-linux-objcopy -O binary -S led_on_c_elf led_on_c.bin
    arm-linux-objdump -D -m arm  led_on_c_elf > led_on_c.dis
clean:
    rm -f led_on_c.dis led_on_c.bin led_on_c_elf *.o

①crt0.s汇编不编译,预处理-汇编-编译,得到.o文件
②led_on_c.c汇编不编译,预处理-汇编-编译,得到.o文件
③将2个文件链接到一起,“-Ttext 0x0000000”代表意思是代码段从0开始,得到led_on_c_elf
④转换成2进制文件
⑤led_on_c_elf反馈编译一下,“-D”所有的段都反馈编译。“arm”代表arm架构

下面作为参考,流水灯的c文件

#define GPFCON      (*(volatile unsigned long *)0x56000050)
#define GPFDAT      (*(volatile unsigned long *)0x56000054)

#define GPF4_out    (1<<(4*2))
#define GPF5_out    (1<<(5*2))
#define GPF6_out    (1<<(6*2))

void  wait(volatile unsigned long dly)
{
    for(; dly > 0; dly--);
}

int main(void)
{
    unsigned long i = 0;

    GPFCON = GPF4_out|GPF5_out|GPF6_out;        // 将LED1,2,4对应的GPF4/5/6三个引脚设为输出

    while(1){
        wait(30000);
        GPFDAT = (~(i<<4));        // 根据i的值,点亮LED1,2,4
        if(++i == 8)
            i = 0;
    }

    return 0;
}

下面作为参考,按键控制灯的c文件

#define GPFCON      (*(volatile unsigned long *)0x56000050)
#define GPFDAT      (*(volatile unsigned long *)0x56000054)

#define GPGCON      (*(volatile unsigned long *)0x56000060)
#define GPGDAT      (*(volatile unsigned long *)0x56000064)

/*
 * LED1,LED2,LED4对应GPF4、GPF5、GPF6
 */
#define GPF4_out    (1<<(4*2))
#define GPF5_out    (1<<(5*2))
#define GPF6_out    (1<<(6*2))

#define GPF4_msk    (3<<(4*2))
#define GPF5_msk    (3<<(5*2))
#define GPF6_msk    (3<<(6*2))

/*
 * S2,S3,S4对应GPF0、GPF2、GPG3
 */
#define GPF0_in     (0<<(0*2))
#define GPF2_in     (0<<(2*2))
#define GPG3_in     (0<<(3*2))

#define GPF0_msk    (3<<(0*2))
#define GPF2_msk    (3<<(2*2))
#define GPG3_msk    (3<<(3*2))

int main()
{
        unsigned long dwDat;
        // LED1,LED2,LED4对应的3根引脚设为输出
        GPFCON &= ~(GPF4_msk | GPF5_msk | GPF6_msk);
        GPFCON |= GPF4_out | GPF5_out | GPF6_out;

        // S2,S3对应的2根引脚设为输入
        GPFCON &= ~(GPF0_msk | GPF2_msk);
        GPFCON |= GPF0_in | GPF2_in;

        // S4对应的引脚设为输入
        GPGCON &= ~GPG3_msk;
        GPGCON |= GPG3_in;

        while(1){
            //若Kn为0(表示按下),则令LEDn为0(表示点亮)
            dwDat = GPFDAT;             // 读取GPF管脚电平状态

            if (dwDat & (1<<0))        // S2没有按下
                GPFDAT |= (1<<4);       // LED1熄灭
            else    
                GPFDAT &= ~(1<<4);      // LED1点亮

            if (dwDat & (1<<2))         // S3没有按下
                GPFDAT |= (1<<5);       // LED2熄灭
            else    
                GPFDAT &= ~(1<<5);      // LED2点亮

            dwDat = GPGDAT;             // 读取GPG管脚电平状态

            if (dwDat & (1<<3))         // S4没有按下
                GPFDAT |= (1<<6);       // LED3熄灭
            else    
                GPFDAT &= ~(1<<6);      // LED3点亮
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/u012075395/article/details/78814399