linux 心跳灯_嵌入式linux——点亮led灯(二)

本文介绍了如何在Linux环境下,使用汇编和C语言编程来点亮不同LED灯,包括设置栈、传递参数以及实现按键控制LED亮灭的程序。涉及寄存器配置、栈的使用以及条件判断操作。
摘要由CSDN通过智能技术生成

刚才在jz2440板子上写了一个点亮中间led的程序,前前后后十几分钟才好。最终代码

本节内容:

1. 汇编点灯

2. C点灯

3. 参数选择点灯

4. 按键点灯

1. 汇编点灯

.text

.global_start

_start:/*在这个程序中,完成点亮中间的led灯D11

* GPF5 从原理图得知,低电平点亮

* GPFCON 0x56000050

* GPFDAT 0x56000054*/ldr r0,=0x56000050ldr r1,=0x400str r1, [r0]

mov r0, #0ldr r1,=0x56000054str r0, [r1]

halt:

b halt

makefile如下

all:

arm-linux-gcc -c -o led_on.o led_on.S

arm-linux-ld -Ttext 0 led_on.o -o led_on.elf

arm-linux-objcopy -O binary -S led_on.elf led_on.bin

arm-linux-objdump -D led_on.elf >led_on.dis

clean:

rm*.bin *.o *.elf

这个点灯程序还是比较简单的,在原理图上找到led连接的io口,在看一下高低电平点亮。

然后,往配置寄存器地址里面写配置io口的配置输出。往数据寄存器地址写入输出高低电平,即可。

在makefile文件中,用arm-linux-gcc编译器:.s -> .o -> .elf -> .bin 就有了bin文件可以烧到板子上看一下现象。

2. C点灯

刚才又写了两个程序。第一个,是用c程序点灯,汇编和c文件代码如下

.text

.global_start

_start:

ldr sp,=4096

/*调用c函数点灯*/bl main

halt:

b halt

intmain()

{

unsignedint *pGPFCON = (unsigned int *)0x56000050;

unsignedint *pGPFDAT = (unsigned int *)0x56000054;*pGPFCON = 0x400;*pGPFDAT = 0;return 0;

}

点灯的功能在c文件中实现,但是调用c函数之前,需要设置栈,因为1)c程序的变量保存在栈中;2)调用c函数之前,要保存当前状态,保存在栈中。所以要设置好栈,就是sp寄存器。本代码只适应于nand启动,不适合nor启动,后面会补上,片内SRAM有4k,用作栈。

汇编中直接用bl xxx,就可以直接调用c文件中的函数 xxx 函数,c文件中实现点灯。

3. 参数选择点灯

第二个是在汇编文件中调用c函数时,传入参数,选择点亮那个led灯。

.text

.global_start

_start:

ldr sp,=4096 /*nand启动*/mov r0, #1bl main

halt:

b halt

int main(intlednum)

{

unsignedint *pGPFCON = (unsigned int *)0x56000050;

unsignedint *pGPFDAT = (unsigned int *)0x56000054;if (lednum == 1)

{*pGPFCON = 0x100;*pGPFDAT = 0;return 0;

}if (lednum == 2)

{*pGPFCON = 0x400;*pGPFDAT = 0;return 0;

}if (lednum == 3)

{*pGPFCON = 0x1000;*pGPFDAT = 0;return 0;

}

}

在汇编文件中调用c函数,用r0,r1,r2寄存器传入第一个、第二个、第三个参数,在c文件中正常接收即可,return位置可以在最后,但是这么写的话,可以少判断两条语句(如果第一条就返回)。

4. 按键点灯,刚才写了按键的点灯程序。功能:一个按键,一个led。按键按下,灯就亮,松开就灭。一共有三段程序,如下:

int main(intlednum)

{

unsignedint *pGPFCON = (unsigned int *)0x56000050;

unsignedint *pGPFDAT = (unsigned int *)0x56000054;

unsignedint *pGPGCON = (unsigned int *)0x56000060;

unsignedint *pGPGDAT = (unsigned int *)0x56000064;//GPF4 ouput,先清位,再置为

*pGPFCON &= ~(3<<8) ;*pGPFCON |= (1<<8) ;//GPF0 is input

*pGPFCON &= ~(3<<0);*pGPGDAT &= ~(3<<6);*pGPFDAT = 0XFF;while ( 1)

{//第一段代码:实现按下两 ,松开灭/*if ( *pGPFDAT & ((1<<0)) )

*pGPFDAT |= (1<<4); // 没按下 灭

else

*pGPFDAT &= ~(1<<4); // 按下 on*/

//第二段代码:上电亮,按键无反应, (~(1<<0)) 不是0,所以不能用来判断//按键1,是GPF0,上面初始是FF,1111 1111,(1<<0) 是 0000 0001 取反是 1111 1110 与操作后,无论是否有按键按下,肯定是非0,真,执行当作按键按下,灯亮/*if ( *pGPFDAT & (~(1<<0)) )

*pGPFDAT &= ~(1<<4); // 按下亮

else

*pGPFDAT |= (1<<4); // 没按下灭*/

//第三段代码:实现按下亮,松开灭

if ( !(*pGPFDAT & (1<<0)) )*pGPFDAT &= ~(1<<4); //按下亮

else

*pGPFDAT |= (1<<4); //没按下灭

}return 0;

}

一共有三段代码,一三可以是实现功能,到那时第二段不可以,想了好半天,才发现问题,写在了注释了,以后,判断某位置的话,用第一种比较好,三有些麻烦。

之后还要写一个,按一下亮,再按一下灭的程序

总结:

1. 调用C函数之前要设置栈

2. 汇编调用C函数用r0,r1等寄存器传送参数。

3. 判断寄存器某位0或1的方法。rxx & (yy << zz)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值