【嵌入式Linux+ARM】GPIO操作
1.GPIO介绍
GPIO(general purpose i/o ports)意思为通用输入/输出端口,通俗的说就是一些引脚。
我们可以通过它们输出高低电平 或 读入引脚的状态。
s3c2440中有130个I/O端口,分为A~J共9组,GPA、GPB、..... GPJ
2.GPIO寄存器
既然要操作GPIO,必须对相应的寄存器进行操作,2440中gpio寄存器有:
GPxCON——选择引脚功能(输入、输出、保留等)
GPxDAT——用来读写引脚
GPcUP ——某一位是1时,相应的引脚无内部上拉电阻;为0时,有内部上拉电阻
3.原理图
LED:
按键:
4.实验代码:
>>使用汇编语言实现点灯:
led_on.S
.text .global _start _start: LDR R0, =0x56000050 //GPFCON寄存器地址 MOV R1, #0x00001500 //见技术手册相应的配置,一般01为输出引脚 STR R1, [R0] //设置为输出 LDR R0, =0x56000054 //GPFDAT寄存器 MOV R1, #0x00000000 STR R1, [R0] //往GPFDAT寄存器写值 MAIN_LOOP: B MAIN_LOOP //循环等待Makefile:
led_on.bin:led_on.S arm-linux-gcc -g -c led_on.S -o led_on.o arm-linux-ld -Ttext 0x00000000 -g led_on.o -o led_on_elf //-Ttext表示设置连接地址 arm-linux-objcopy -O binary -S led_on_elf led_on.bin //把elf文件转换为.bin文件 clean: rm -rf *.bin *.o *elf
>>使用C语言实现点灯
使用c语言来写,需要一个启动文件,可以用来关闭看门口,设置堆栈等。
crt0.S
.text .global _begin _begin: LDR R0, =0x53000000 //看门狗寄存器地址 MOV R1, #0x00000000 //写0禁止看门狗 STR R1, [R0] LDR SP, =1024*4 //设置堆栈,注意不能大于4K,因为现在可用的SRAM空间只有4K BL main //调用main函数,最后注意,汇编语言大小写无所谓的 _LOOP: B _LOOP
led_on_c.c
#define GPFCON *(volatile unsigned long *)0x56000050 #define GPFDAT *(volatile unsigned long *)0x56000054 int main() { GPFCON=0x00001500;//简单的配置为输出 GPFDAT=0x00000000;//简单的输出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 //把elf文件转换为反汇编文件 clean: rm -f led_on_c.dis led_on_c.bin led_on_c_elf *.o
>>使用按键+c语言实现点灯
看上面的原理图,原理就是把按键的引脚配置为输入引脚,以读取引脚的状态;
但按键被按下时,引脚读到的是低电平;当按键松开时,读取到高电平;
crt0.S同上;
key_led.c
/* GPF4 GPF5 GPF6 --led GPF0 GPF2 GPG3 --key */ #define GPFCON (*(volatile unsigned long *)0x56000050) #define GPFDAT (*(volatile unsigned long *)0x56000054) #define GPGCON (*(volatile unsigned long *)0x56000060) #define GPGDAT (*(volatile unsigned long *)0x56000064) #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)) #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; //1 output pin GPFCON &= ~(GPF4_msk | GPF5_msk | GPF6_msk); GPFCON |= (GPF4_out | GPF5_out | GPF6_out); //input pin GPFCON &= ~(GPF0_msk | GPF2_msk); GPFCON |= (GPF0_in | GPF2_in); GPGCON &= ~GPG3_msk; GPGCON |= GPG3_in; while(1) { dwDat = GPFDAT; if(dwDat & (1<<0)) GPFDAT |= (1<<4); else GPFDAT &= ~(1<<4);//light if(dwDat & (1<<2)) GPFDAT |= (1<<5); else GPFDAT &= ~(1<<5); dwDat = GPGDAT; if(dwDat & (1<<3)) GPFDAT |= (1<<6); else GPFDAT &= ~(1<<6); } return 0; }
Makefile相应的修改即可;
上面的程序编译都会得到bin文件,我们把它烧录进nand flash中即可,烧录可以使用工具,也可以通过固化在nor flash中的Uboot来烧录,方法很多,烧录后,上电,2440CPU会自动把nand flash前4k的内容,拷贝到2440片内4k的SRAM中运行,这块内存俗称stepping stone区。
注:原创文章,转载请注明出处:http://blog.csdn.net/scottly1/article/details/38960309
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。