• 一、GPIO操作


    1.1 硬件原理图

         

       

      

      四个引脚接到LED上,跟别是GPF4,GPF5,GPF6和GPF7,前三个引脚分别控制三个LED,GPF7此引脚作为DM9000网卡的中断。

      发光二极管的正极接3.3V电源,负极接在MCU上,当MCU的对应的引脚给一个低电平的时候,电路导通,发光二极管发光。

      芯片手册,GPIO配置,如下图,控制LED的属于GPF管脚:

      

      GPF的寄存器如下图:

      

    • GPFCON:GPF管脚的控制寄存器
    • GPFDAT:GPF管脚的数据寄存器
    • GPFUP:GPF上拉使能的寄存器

      

      GPF4-GPF6对应GPFCON寄存器的13—8位。 

      

    1.2 LED 操作

    1.2.1 点亮一个  led 灯

    (1)汇编编写

      led_on.S

     1 @******************************************************************************
     2 @ File:led_on.S
     3 @ 功能:LED点灯程序,点亮LED1
     4 @******************************************************************************       
     5             
     6 .text
     7 .global _start
     8 _start:     
     9             LDR     R0,=0x56000050      @ R0设为GPFCON寄存器。此寄存器
    10                                         @ 用于选择端口B各引脚的功能:
    11                                         @ 是输出、是输入、还是其他
    12             MOV     R1,#0x00000100        
    13             STR     R1,[R0]             @ 设置GPF4为输出口, 位[8:7]=0b01
    14             LDR     R0,=0x56000054      @ R0设为GPBDAT寄存器。此寄存器
    15                                         @ 用于读/写端口B各引脚的数据
    16             MOV     R1,#0x00000000      @ 此值改为0x00000010,
    17                                         @ 可让LED1熄灭
    18             STR     R1,[R0]             @ GPF4输出0,LED1点亮
    19 MAIN_LOOP:
    20             B       MAIN_LOOP

      Makefile

    1 led_on.bin : led_on.S
    2     arm-linux-gcc -g -c -o led_on.o led_on.S
    3     arm-linux-ld -Ttext 0x0000000 -g led_on.o -o led_on_elf
    4     arm-linux-objcopy -O binary -S led_on_elf led_on.bin
    5 clean:
    6     rm -f   led_on.bin led_on_elf *.o

      make 执行编译,生成 led_on.bin。烧录到开发板

    (2)用C语言编写

      一个程序编译的时候会经过下面几个步骤:预处理、编译、汇编和链接。

      编译就是将源程序编译成 .S

      汇编就是将.S 编译成 .o

      链接就是将多个 .o 链接成一个可执行程序

    • 启动文件:
      • 需要做硬件初始化
        • 关看门狗
        • 初始化时钟
        • 初始化 SDRAM,若是 SRAM(内置) 不需要初始化,若是 SDRAM(外挂的),则首先要初始化 SDRAM
      • 设置栈,即将 栈指针 sp 指向某块内存,
      • 设置 main 函数的返回地址
      • 调用 main 函数
      • 清理工作

      启动程序 crt0.S

     1 @******************************************************************************
     2 @ File:crt0.S
     3 @ 功能:通过它转入C程序
     4 @******************************************************************************       
     5 
     6 .text
     7 .global _start
     8 _start:
     9     ldr     r0, =0x53000000     @ WATCHDOG寄存器地址
    10     mov     r1, #0x0                     
    11     str     r1, [r0]            @ 写入0,禁止WATCHDOG,否则CPU会不断重启
    12 
    13     ldr     sp, =1024*4         @ 设置堆栈,注意:不能大于4k, 因为现在可用的内存只有4K
    14                                 @ nand flash中的代码在复位后会移到内部ram中,此ram只有4K
    15     bl      main                @ 调用C程序中的main函数,bl 指令会调用 main 函数,并将返回地址保存在 lr 寄存器中
    16 
    17 
    18 halt_loop:                      @ main 函数执行完之后,会返回到这里做清理工作,我们这里写的是进入死循环
    19     b       halt_loop

      led_on.c

    1 #define GPFCON      (*(volatile unsigned long *)0x56000050)
    2 #define GPFDAT      (*(volatile unsigned long *)0x56000054)
    3 
    4 int main()
    5 {
    6     GPFCON = 0x00000100;    // 设置GPF4为输出口, 位[8:7]=0b01
    7     GPFDAT = 0x00000000;    // GPF4输出0,LED1点亮
    8 }

      Makefile

    1 led_on.bin : crt0.S  led_on.c
    2     arm-linux-gcc -g -c -o crt0.o crt0.S
    3     arm-linux-gcc -g -c -o led_on.o led_on.c
    4     arm-linux-ld -Ttext 0x0000000 -g crt0.o led_on.o -o led_on_elf
    5     arm-linux-objcopy -O binary -S led_on_elf led_on.bin
    6     arm-linux-objdump -D -m arm  led_on_elf > led_on.dis
    7 clean:
    8     rm -f led_on.dis led_on.bin led_on_elf *.o

    1.2.2 点亮三个LED

      除了 led_on.c 不一样之外,其余的和上面的 C语言编写的程序一样

      led_on.c

     1 #define GPFCON      (*(volatile unsigned long *)0x56000050)
     2 #define GPFDAT      (*(volatile unsigned long *)0x56000054)
     3 
     4 #define GPF4_out    (1<<(4*2))
     5 #define GPF5_out    (1<<(5*2))
     6 #define GPF6_out    (1<<(6*2))
     7 
     8 void delay_ms(unsigned int val);
     9 
    10 int main()
    11 {
    12     int i = 0;
    13     GPFCON = GPF4_out|GPF5_out|GPF6_out;        // 将LED1,2,4对应的GPF4/5/6三个引脚设为输出
    14 
    15     while(1)
    16     {
    17         delay_ms(500);
    18         GPFDAT = (~(i<<4));     // 根据i的值,点亮LED1,2,4
    19         if(++i == 8)
    20             i = 0;
    21     }
    22 
    23     return 0;
    24 }
    25 
    26 /* 对于12M 晶振来说的 */
    27 void delay_ms(unsigned int val)
    28 {
    29     unsigned int i;
    30 
    31     while(val > 0)
    32     {
    33         for(i = 0; i < 187; ++i)
    34             asm("nop");
    35 
    36         val--; 
    37     }
    38 }

    1.2.3 用按键控制LED

      按键的原理图如下所示:

          

      

      

      EINT0 和 EINT2 分别在 GPF0 和 GPF2 引脚上, EINT11 在 GPG3 引脚上

      按键引脚需要去读,按键按下形成回路,所以按键的引脚设置为输入,当按键按下的时候,由于按键接地,则按键的引脚处为低电平0,弹起后被拉高为1

     1 #define GPFCON      (*(volatile unsigned long *)0x56000050)
     2 #define GPFDAT      (*(volatile unsigned long *)0x56000054)
     3 
     4 #define GPGCON      (*(volatile unsigned long *)0x56000060)
     5 #define GPGDAT      (*(volatile unsigned long *)0x56000064)
     6 
     7 /*
     8  * LED1,LED2,LED4对应GPF4、GPF5、GPF6
     9  */
    10 #define    GPF4_out    (1<<(4*2))
    11 #define    GPF5_out    (1<<(5*2))
    12 #define    GPF6_out    (1<<(6*2))
    13 
    14 #define    GPF4_msk    (3<<(4*2))
    15 #define    GPF5_msk    (3<<(5*2))
    16 #define    GPF6_msk    (3<<(6*2))
    17 
    18 /*
    19  * S2,S3,S4对应GPF0、GPF2、GPG3
    20  */
    21 #define GPF0_in     (0<<(0*2))
    22 #define GPF2_in     (0<<(2*2))
    23 #define GPG3_in     (0<<(3*2))
    24 
    25 #define GPF0_msk    (3<<(0*2))
    26 #define GPF2_msk    (3<<(2*2))
    27 #define GPG3_msk    (3<<(3*2))
    28 
    29 int main()
    30 {
    31         unsigned long dwDat;
    32         // LED1,LED2,LED4对应的3根引脚设为输出
    33         GPFCON &= ~(GPF4_msk | GPF5_msk | GPF6_msk);
    34         GPFCON |= GPF4_out | GPF5_out | GPF6_out;
    35         
    36         // S2,S3对应的2根引脚设为输入
    37         GPFCON &= ~(GPF0_msk | GPF2_msk);
    38         GPFCON |= GPF0_in | GPF2_in;
    39 
    40         // S4对应的引脚设为输入
    41         GPGCON &= ~GPG3_msk;
    42         GPGCON |= GPG3_in;
    43 
    44         while(1){
    45             //若Kn为0(表示按下),则令LEDn为0(表示点亮)
    46             dwDat = GPFDAT;             // 读取GPF管脚电平状态
    47         
    48             if (dwDat & (1<<0))        // S2没有按下
    49                 GPFDAT |= (1<<4);       // LED1熄灭
    50             else    
    51                 GPFDAT &= ~(1<<4);      // LED1点亮
    52                 
    53             if (dwDat & (1<<2))         // S3没有按下
    54                 GPFDAT |= (1<<5);       // LED2熄灭
    55             else    
    56                 GPFDAT &= ~(1<<5);      // LED2点亮
    57     
    58             dwDat = GPGDAT;             // 读取GPG管脚电平状态
    59             
    60             if (dwDat & (1<<3))         // S4没有按下
    61                 GPFDAT |= (1<<6);       // LED3熄灭
    62             else    
    63                 GPFDAT &= ~(1<<6);      // LED3点亮
    64     }
    65 
    66     return 0;
    67 }

      

      

      

      

  • 相关阅读:
    c# vs2010 excel 上传oracle数据
    Viola-Jones人脸检測
    apache commons-configuration包读取配置文件
    linux 读取文件
    linux 统计某个文件的行数
    linux 判空处理
    linux 查看某个目录下文件的数量
    nginx 配置文件正确性测试
    使用postman上传excel文件测试导入excel
    java 反射获取字段为List类型中的泛型类型
  • 原文地址:https://www.cnblogs.com/kele-dad/p/6877236.html
Copyright © 2020-2023  润新知