现在在学习ARM,用的是TE6410,昨天已经点亮LED了,今天继续想用按键来控制和点亮led,参照书上的程序修改了一下,开始不行,按键没有反应。
后来仔细对照电路图,发现TE6410的led图与大多数的不一样,
1、就是多了一个三极管,那么相应的0就是熄灭,1就是点亮。
2、另外一个就是它的led分别由GPM0-3控制,而GPM口是4位的,与其他口不一样。
于是修改程序,最后终于能按键控制led灯得点亮和熄灭,程序如下:
1 #define GPMCON (*(volatile unsigned long *)0x7F008820) //GPMCOM地址
2 #define GPMDAT (*(volatile unsigned long *)0x7F008824) //GPMDAT地址
3
4 #define GPNCON (*(volatile unsigned long *)0x7F008830)
5 #define GPNDAT (*(volatile unsigned long *)0x7F008834)
6
7 //#define GPNCON (*(volatile unsigned long *)0x56000060)
8 //#define GPNDAT (*(volatile unsigned long *)0x56000064)
9
10 /*
11 * LED1-4对应GPM0、GPM1、GPM2、GPM3
12 */
13 #define GPM0_out (1<<(0*4)) //这里是*4,因为端口是4位的
14 #define GPM1_out (1<<(1*4))
15 #define GPM2_out (1<<(2*4))
16 #define GPM3_out (1<<(3*4))
17
18 /*
19 * K1-K4对应GPN1、GPN2、GPN3、GPN4
20 */
21 #define GPN1_in ~(3<<(1*2)) //3对应0b11,那么移位取反后为0b00
22 #define GPN2_in ~(3<<(2*2))
23 #define GPN3_in ~(3<<(3*2))
24 #define GPN4_in ~(3<<(4*2))
25
26 int main()
27 {
28 unsigned long dwDat;
29 // LED1-LED4对应的4根引脚设为输出
//此为按位或,那么就是每个口的状态都能够保持先前的设置不改变
30 GPMCON = GPM0_out | GPM1_out | GPM2_out | GPM3_out ;
31
32 // K1-K4对应的4根引脚设为输入
//此为按位与,由于先前每位都取反为0,这样就保证GPNCON要控制下的端口都为0
33 GPNCON = GPN1_in & GPN2_in & GPN3_in & GPN4_in;
34
35 // K3-K4对应的2根引脚设为输入
36 // GPNCON = GPN3_IN & GPN4_IN ;
37
38 while(1){
39 //若Kn为0(表示按下),则令LEDn为0(表示点亮)
40 dwDat = GPNDAT; // 读取GPN管脚电平状态
41
42 if (dwDat & (1<<1)) // K1没有按下
43 GPMDAT |= (1<<0); // LED1
44 else
50 GPMDAT &= ~(1<<1); // LED2点亮
51
52 // dwDat = GPNDAT; // 读取GPN管脚电平状态
53
54 if (dwDat & (1<<3)) // K3没有按下
55 GPMDAT |= (1<<2); // LED3熄灭
56 else
57 GPMDAT &= ~(1<<2); // LED3点亮
58
59 if (dwDat & (1<<4)) // K4没有按下
60 GPMDAT |= (1<<3); // LED4熄灭
61 else
62 GPMDAT &= ~(1<<3); // LED4点亮
63 }
64
65 return 0;
66 }
完成之后make,生成key_led.bin文件,之后就是通过DNW下载程序到开发板运行。(具体步骤见我前面的文章)
通过这个例子,使我对S3C6410有了更加进一步的了解,特别是对于GPIO口,怎么去操作不同的口,因为有的口得位数是不一样的。
同样,韦老师的例子也给了我很大的启发。通过位的左右移动,即可用简单的汇编来达到效果,比用C中的语句控制简洁明了多了。
所以我后来又修改了一下程序,是其中两个led俺家熄灭,两个led按键点亮,具体程序如下:
1 #define GPMCON (*(volatile unsigned long *)0x7F008820) //GPMCOM地址
2 #define GPMDAT (*(volatile unsigned long *)0x7F008824) //GPMDAT地址
3
4 #define GPNCON (*(volatile unsigned long *)0x7F008830)
5 #define GPNDAT (*(volatile unsigned long *)0x7F008834)
6
7 //#define GPNCON (*(volatile unsigned long *)0x56000060)
8 //#define GPNDAT (*(volatile unsigned long *)0x56000064)
9
10 /*
11 * LED1-4对应GPM0、GPM1、GPM2、GPM3
12 */
13 #define GPM0_out (1<<(0*4)) //这里是*4,因为端口是4位的
14 #define GPM1_out (1<<(1*4))
15 #define GPM2_out (1<<(2*4))
16 #define GPM3_out (1<<(3*4))
17
18 /*
19 * K1-K4对应GPN1、GPN2、GPN3、GPN4
20 */
21 #define GPN1_in ~(3<<(1*2)) //3对应0b11,那么移位取反后为0b00
22 #define GPN2_in ~(3<<(2*2))
23 #define GPN3_in ~(3<<(3*2))
24 #define GPN4_in ~(3<<(4*2))
25
26 int main()
27 {
28 unsigned long dwDat;
29 // LED1-LED4对应的4根引脚设为输出
//此为按位或,那么就是每个口的状态都能够保持先前的设置不改变
30 GPMCON = GPM0_out | GPM1_out | GPM2_out | GPM3_out ;
31
32 // K1-K4对应的4根引脚设为输入
//此为按位与,由于先前每位都取反为0,这样就保证GPNCON要控制下的端口都为0
33 GPNCON = GPN1_in & GPN2_in & GPN3_in & GPN4_in;
34
35 // K3-K4对应的2根引脚设为输入
36 // GPNCON = GPN3_IN & GPN4_IN ;
37
38 while(1){
39 //若Kn为0(表示按下),则令LEDn为0(表示点亮)
40 dwDat = GPNDAT; // 读取GPN管脚电平状态
41
42 if (dwDat & (1<<1)) // K1没有按下
43 GPMDAT &=~ (1<<0); // LED1熄灭
44 else
45 GPMDAT |= (1<<0); // LED1点亮
46
47 if (dwDat & (1<<2)) // K2没有按下
48 GPMDAT &=~ (1<<1); // LED2熄灭
49 else
50 GPMDAT |= (1<<1); // LED2点亮
51
52 // dwDat = GPNDAT; // 读取GPN管脚电平状态
53
54 if (dwDat & (1<<3)) // K3没有按下
55 GPMDAT |= (1<<2); // LED3点亮
56 else
57 GPMDAT &= ~(1<<2); // LED3熄灭
58
59 if (dwDat & (1<<4)) // K4没有按下
60 GPMDAT |= (1<<3); // LED4点亮
61 else
62 GPMDAT &= ~(1<<3); // LED4熄灭
63 }
64
65 return 0;
66 }