GPIO实验(二)

=============第三个实验============用c语言轮流点亮3个LED===================

1.crt0.S
.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

 

2.leds.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;
}

 

3.leds.lds

SECTIONS {
    . = 0x00;
      .text          :   { *(.text) }
    .rodata ALIGN(4) : {*(.rodata)}
      .data ALIGN(4) : { *(.data) }
      .bss ALIGN(4)  : { *(.bss)  *(COMMON) }
}

4.Makefile

CFLAGS     := -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -ffreestanding
leds.bin : crt0.S  leds.c
    arm-linux-gcc $(CFLAGS) -c -o crt0.o crt0.S
    arm-linux-gcc $(CFLAGS) -c -o leds.o leds.c
    arm-linux-ld -Ttext 0x0000000 crt0.o leds.o -o leds_elf
#    arm-linux-ld -Tleds.lds  crt0.o leds.o -o leds_elf
    arm-linux-objcopy -O binary -S leds_elf leds.bin
    arm-linux-objdump -D -m arm  leds_elf > leds.dis
clean:
    rm -f   leds.dis leds.bin leds_elf *.o

=============第四个实验============按键控制LED=============================

用按键控制LED
1.看原理图
2.
  1)配置按键的引脚为输入,LED的引脚为输出
  2)读按键的引脚,根据值来设置LED的引脚

按位操作
1.清零 a的bit3清零
  位与  a = a & ~(1 << 3)
2.置1 a的bit3 = 1
  位或 a = a | (1 << 3)

1.crt0.S
.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

2.key_led.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;
}

3.Makefile

key_led.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 0x0000000 -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

原文地址:https://www.cnblogs.com/liulipeng/p/3401250.html