Tiny6410之按键裸机驱动

操作步骤:

第一步:查看开发板电路原理图
  找到LED 和按键的管脚所对应的寄存器
  LED:(见Tiny6410之LED裸机驱动)
    nLED_1 - GPK4
    nLED_2 - GPK5
    nLED_3 - GPK6
    nLED_4 - GPK7


  Buttons:
    K1   GPN0
    K2   GPN1
    K3   GPN2
    K4   GPN3
  由原理图可知LED对应的寄存器为GPK寄存器,buttons 对应的寄存器为GPL,由二极管的特性可知当LED_n为低电平时LED灯亮
第二步:查看数据手册找到GPK寄存器和 GPL寄存器的地址及每位表示的意义

  LED:(见Tiny6410之LED裸机驱动)
    Register     Address
  GPKCON0   0x7F008800
  GPKCON1   0x7F008804
  GPKDAT     0x7F008808
  GPKPUD     0x7F00880C

  BUTTONS:


  GPNCON    0x7F008830
  GPNDAT     0x7F008834
  GPLPUD     0x7F008838

  通过数据手册知道GPK寄存器有两个控制寄存器(GPKCON0和GPKCON1)和一个数据寄存器(GPKPDAT)
  [GPK0 GPK1 GPK2 GPK3 GPK4 GPK5 GPK6 GPK7] 在GPKCON0中每4位表示一个GBKn(0<=n<=7)
  [GPK8 GPK9 GPK10 GPK11 GPK12 GPK13 GPK14 GPK15] 在GPKCON1中每4位表示一个GBKn(8<=n<=15)

  通过数据手册知道GPL寄存器有两个控制寄存器(GPLCON0和GPLCON1)和一个数据寄存器(GPLDAT)
  [GPN0-GPN15] 在GPLCON0中每2位表示一个GBNn(0<=n<=15)
第三步:设置寄存器的值
  由第一步可知LED主要用到的管脚为GPK4、GPK5、GPK6、GPK7;Buttons主要用到的管脚是GPL8、GPL9、GPL10、GPL11;
由第二步可知GPK[4-7]有GPKCON0 控制、GPL[8-11]由GPLCON1控制
  1)LED将管脚设置为输出、Buttons将管脚设置为输入
      LED作为显示是属于输出由数据手册可知(0000 = Input 0001 = Output)故只要讲GPKn对应的4位设置为0001即表示输出
Buttons作为按键是属于输如由数据手册可知(00 = Input 01 = Output)故只要讲GPNn对应的4位设置为00即表示输入
  2)LED将管脚的值设为低电平LED灯亮
     Buttons将管脚的值设置为高电平即表示按下
  LED的数据寄存器为GPKDAT,由数据手册关于GPKDAT的介绍就可知GPKDAT第n位的值即表示GPKn(0<=n<=15)的电平状态(一般都是0表示低电平,1表示高电平)
第四步:编写代码
  1)关看门狗
      通过数据手册找到看门狗的控制寄存器地址


      Register    Address
      WTCON     0x7E004000
  2)设置控制寄存器(GPKCON0)的值
  3)设置数据寄存器(GPKDAT)的值
第五步:编写Makefile

 1 led.bin: start.o main.o
 2     arm-linux-ld -Ttext 0x50000000 -o led.elf $^
 3     arm-linux-objcopy -O binary led.elf led.bin
 4     arm-linux-objdump -D led.elf > led_elf.dis
 5 %.o : %.S
 6     arm-linux-gcc -o $@ $< -c
 7 %.o : %.c
 8     arm-linux-gcc -o $@ $< -c
 9 clean:
10     rm *.o *.elf *.bin *.dis -rf
Makefile Code

第六步:将代码在虚拟机上编译生成.bin 文件

第七步:将.bin文件烧写到开发板运行

第八步:实验现象,一个按键控制一个灯的灭

代码实现:

 1 //start.S
 2 .global _start
 3 _start:
 4  //关看门狗
 5    ldr r0, =0x7E004000
 6    mov r1, #0
 7    str r1, [r0]
 8    
 9 // 设置堆栈
10    ldr sp,=0xC002000   //SRAM 的映射地址是0X0C000000
11    
12    //调用点灯函数
13    bl main
14 halt:
15     b halt
16 /////////////////////////////
17 //Tiny6410Addr.h
18 #ifndef _Tiny6410Addr_H
19 #define _Tiny6410Addr_H
20 //GPK 
21 #define GPIO_BASE (0x7F008800)
22 #define rGPKCON0 (*(volatile unsigned long *)(GPIO_BASE+0x00))
23 #define rGPKDAT  (*(volatile unsigned long *)(GPIO_BASE+0x08))
24 
25 //GPN
26 #define rGPNCON   (*(volatile unsigned long *)(GPIO_BASE+0x30))
27 #define rGPNDAT   (*(volatile unsigned long *)(GPIO_BASE+0x34))
28 
29 #endif
30 
31 //////////////////////////
32 //button.c
33 #include "Tiny6410Addr.h"
34 #define GPK4_OUT  (1<<4*4)
35 #define GPK5_OUT  (1<<4*5)
36 #define GPK6_OUT  (1<<4*6)
37 #define GPK7_OUT  (1<<4*7)
38 //延时函数
39 void delay()
40 {
41    volatile int i = 0x10000;
42    while (i--);
43 }
44 
45 int main()
46 {
47     unsigned int data = 0xF0;
48     //将GPK4-7设置为输出
49     rGPKCON0 = GPK4_OUT | GPK5_OUT |GPK6_OUT |GPK7_OUT;
50     // 配置GPN为输入功能
51     rGPNCON = 0;
52     while (1)
53     {
54         //K1按下
55         if (rGPNDAT & (1<<0))
56         GPKDAT &= ~(1<<4);
57         else
58             GPKDAT |=data;
59         //K2按下
60         if (rGPNDAT & (1<<1))
61         GPKDAT &= ~(1<<5);
62         else
63             GPKDAT |=data;
64         //K3按下
65         if (rGPNDAT & (1<<2))
66         GPKDAT &= ~(1<<6);
67         else
68             GPKDAT |=data;
69         //K4按下
70         if (rGPNDAT & (1<<3))
71         GPKDAT &= ~(1<<7);
72         else
73             GPKDAT |=data;
74     }
75     
76      
77 }
C Code
海阔凭鱼跃,天高任鸟飞。
原文地址:https://www.cnblogs.com/chenshikun/p/5814446.html