=============第三个实验============用c语言轮流点亮3个LED===================
1.crt0.S
.text
.global _start
_start:
ldr r0, =0x53000000 @ WATCHDOG寄存器地址
mov r1, #0x0
str r1, [r0] @ 写入0,禁止WATCHDOG,否则CPU会不断重启
ldr sp, =1024*4@ 设置堆栈,注意:不能大于4k, 因为现在可用的内存只有4K
@ nand flash中的代码在复位后会移到内部ram中,此ram只有4K
bl main @ 调用C程序中的main函数
halt_loop:
b halt_loop
2.leds.c
#define GPFCON (*(volatile unsigned long *)0x56000050)
#define GPFDAT (*(volatile unsigned long *)0x56000054)
#define GPF4_out (1<<(4*2))
#define GPF5_out (1<<(5*2))
#define GPF6_out (1<<(6*2))
void wait(volatile unsigned long dly)
{
for(; dly > 0; dly--);
}
int main(void)
{
unsigned long i = 0;
GPFCON = GPF4_out|GPF5_out|GPF6_out;// 将LED1,2,4对应的GPF4/5/6三个引脚设为输出
while(1){
wait(30000);
GPFDAT = (~(i<<4)); // 根据i的值,点亮LED1,2,4
if(++i == 8)
i = 0;
}
return 0;
}
3.leds.lds
SECTIONS {
. = 0x00;
.text : { *(.text) }
.rodata ALIGN(4) : {*(.rodata)}
.data ALIGN(4) : { *(.data) }
.bss ALIGN(4) : { *(.bss) *(COMMON) }
}
4.Makefile
CFLAGS := -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -ffreestanding
leds.bin : crt0.S leds.c
arm-linux-gcc $(CFLAGS) -c -o crt0.o crt0.S
arm-linux-gcc $(CFLAGS) -c -o leds.o leds.c
arm-linux-ld -Ttext 0x0000000 crt0.o leds.o -o leds_elf
# arm-linux-ld -Tleds.lds crt0.o leds.o -o leds_elf
arm-linux-objcopy -O binary -S leds_elf leds.bin
arm-linux-objdump -D -m arm leds_elf > leds.dis
clean:
rm -f leds.dis leds.bin leds_elf *.o
=============第四个实验============按键控制LED=============================
用按键控制LED
1.看原理图
2.
1)配置按键的引脚为输入,LED的引脚为输出
2)读按键的引脚,根据值来设置LED的引脚
按位操作
1.清零 a的bit3清零
位与 a = a & ~(1 << 3)
2.置1 a的bit3 = 1
位或 a = a | (1 << 3)
1.crt0.S
.text
.global _start
_start:
ldr r0, =0x53000000 @ WATCHDOG寄存器地址
mov r1, #0x0
str r1, [r0] @ 写入0,禁止WATCHDOG,否则CPU会不断重启
ldr sp, =1024*4 @ 设置堆栈,注意:不能大于4k, 因为现在可用的内存只有4K
@ nand flash中的代码在复位后会移到内部ram中,此ram只有4K
bl main @ 调用C程序中的main函数
halt_loop:
b halt_loop
2.key_led.c
#define GPFCON (*(volatile unsigned long *)0x56000050)
#define GPFDAT (*(volatile unsigned long *)0x56000054)
#define GPGCON (*(volatile unsigned long *)0x56000060)
#define GPGDAT (*(volatile unsigned long *)0x56000064)
/*
* LED1,LED2,LED4对应GPF4、GPF5、GPF6
*/
#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))
/*
* S2,S3,S4对应GPF0、GPF2、GPG3
*/
#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;
// LED1,LED2,LED4对应的3根引脚设为输出
GPFCON &= ~(GPF4_msk | GPF5_msk | GPF6_msk);
GPFCON |= GPF4_out | GPF5_out | GPF6_out;
// S2,S3对应的2根引脚设为输入
GPFCON &= ~(GPF0_msk | GPF2_msk);
GPFCON |= GPF0_in | GPF2_in;
// S4对应的引脚设为输入
GPGCON &= ~GPG3_msk;
GPGCON |= GPG3_in;
while(1){
//若Kn为0(表示按下),则令LEDn为0(表示点亮)
dwDat = GPFDAT; // 读取GPF管脚电平状态
if (dwDat & (1<<0)) // S2没有按下
GPFDAT |= (1<<4); // LED1熄灭
else
GPFDAT &= ~(1<<4); // LED1点亮
if (dwDat & (1<<2)) // S3没有按下
GPFDAT |= (1<<5); // LED2熄灭
else
GPFDAT &= ~(1<<5); // LED2点亮
dwDat = GPGDAT; // 读取GPG管脚电平状态
if (dwDat & (1<<3)) // S4没有按下
GPFDAT |= (1<<6); // LED3熄灭
else
GPFDAT &= ~(1<<6); // LED3点亮
}
return 0;
}
3.Makefile
key_led.bin : crt0.S key_led.c
arm-linux-gcc -g -c -o crt0.o crt0.S
arm-linux-gcc -g -c -o key_led.o key_led.c
arm-linux-ld -Ttext 0x0000000 -g crt0.o key_led.o -o key_led_elf
arm-linux-objcopy -O binary -S key_led_elf key_led.bin
arm-linux-objdump -D -m arm key_led_elf > key_led.dis
clean:
rm -f key_led.dis key_led.bin key_led_elf *.o