03 ARM11 时钟、led、串口、蜂鸣器、按键

led.bin:start.o uart.o key_led.o
        arm-linux-ld -Ttext 0 -o led.elf start.o uart.o key_led.o
        arm-linux-objcopy -O binary led.elf led.bin
        arm-linux-objdump -D led.elf>led.dis
        cp *.bin /tftpboot/ -r
start.o:start.S
        arm-linux-gcc -c start.S -o start.o
uart.o:uart.c
        arm-linux-gcc -c uart.c -o uart.o
key_led.o:key_led.c
        arm-linux-gcc -c key_led.c -o key_led.o
clean:
        rm -rf *.o *.elf *.dis *.bin /tftpboot/led.bin

Makefile :添加key_led.o , uart.o

@
@ 功能:运行后,进入串口功能,按'q'退出进入key_led功能,按key1,key2,key3,key4点
@       亮相应的led灯,按key5全部点亮,按key6进入led循环点亮,并使蜂鸣器响起。
@ 时间:2012-12-01
@

.globl _start
_start:

@外设地址范围
#define busaddr 0x70000000
#define wtcon 0x7e004000

@led灯使用的寄存器地址
#define gpmcon 0x7f008820
#define gpmdat 0x7f008824

@时钟使用的寄存器地址
#define apll_lock 0x7e00f000
#define others 0x7e00f900
#define clk_div0 0x7e00f020
#define apll_con 0x7e00f00c
#define mpll_con 0x7e00f010
#define clk_src 0x7e00f01c

@串口使用的寄存器地址
#define gpacon 0x7f008000
#define ulcon0 0x7f005000
#define ucon0 0x7f005004
#define ufcon0 0x7f005008
#define umcon0 0x7f00500c
#define ubrdiv0 0x7f005028
#define udivslot0 0x7f00502c
#define ufstat0 0x7f005018
#define utxh0 0x7f005020
#define urxh0 0x7f005024

@蜂鸣器使用的寄存器
#define gpfcon 0x7f0080a0
#define gpfdat 0x7f0080a4

@告诉CPU外设地址范围
	ldr r0, =busaddr
	orr r0, r0, #0x13
	mcr p15, 0, r0, c15, c2, 4

@关闭看门狗
	ldr r0, =wtcon
	mov r1, #0
	str r1, [r0]
@调用时钟初始化代码,调用led点灯代码
	bl clock_init
	bl uart_init
	ldr sp, =8*1024
	bl uart
	bl key_led
	bl pwm_buzzer
	bl led_loop

	b .

@蜂鸣器
pwm_buzzer:
	ldr r0, =gpfcon
	ldr r1, =(1<<30)
	str r1, [r0]

	ldr r0, =gpfdat
	ldr r1, =(1<<15)
	str r1, [r0]

	mov pc, lr

@led循环点灯程序
led_loop:
@设置引脚为输出模式
	ldr r0, =gpmcon
	ldr r1, =0x1111
	str r1, [r0]

@设置输出引脚循环输出低电平
	ldr r0, =gpmdat
led_loop1:
	mov r1, #0xe
	str r1, [r0]
	bl delay
	mov r1, #0xd
	str r1, [r0]
	bl delay
	mov r1, #0xb
	str r1, [r0]
	bl delay
	mov r1, #0x7
	str r1, [r0]
	bl delay
	b led_loop1

@延时
delay:
	ldr r2, =100000
delay_sub:
	sub r2, r2, #1
	cmp r2, #0
	bne delay_sub
	moveq pc, lr


@时钟初始化为532MHz
clock_init:

@设置lock_time,有默认值,不设置也可以
	ldr r0, =apll_lock
	ldr r1, =0xffff
	str r1, [r0]
	str r1, [r0,#4]
	str r1, [r0,#8]

@开启异步模式
	ldr r0, =others
	ldr r1, [r0]
	bic r1, r1, #0xc0
	str r1, [r0]

@等待异步模式启动动完成
clock_loop1:
	ldr r1, [r0]
	and r1, #0xf00
	cmp r1, #0
	bne clock_loop1

@设置分频系数
	ldr r0, =clk_div0
	ldr r1, =((0)|(0<<4)|(1<<8)|(1<<9)|(3<<12))
	str r1, [r0]

@设定apll时钟频率
	ldr r0, =apll_con
	ldr r1, =((1)|(3<<8)|(266<<16)|(1<<31))
	str r1, [r0]

@设定mpll时钟频率
	ldr r0, =mpll_con
	ldr r1, =((1)|(3<<8)|(266<<16)|(1<<31))
	str r1, [r0]

@切换到apll和mpll时钟工作
	ldr r0, =clk_src
	mov r1, #0x3
	str r1, [r0]

@初始化完毕,返回
	mov pc, lr

@串口的初始化
uart_init:
@将GPA0、GPA1、GPA2、GPA3设为对应功能引脚RXD[0],TXD[0],CTSn[0],RTSn[0]
	ldr r0, =gpacon
	ldr r1, =0x22
	str r1, [r0]

@数据位,停止位,校验位,模式的设置
	ldr r0, =ulcon0
	mov r1, #0x3
	str r1, [r0]

@时钟的选择,发送接收的使能
	ldr r0, =ucon0
	mov r1, #0x5
	str r1, [r0]

@FIFO启用
	ldr r0, =ufcon0
	ldr r1, =0x01
	str r1, [r0]

@流量控制,默认配置,可以省略
	ldr r0, =umcon0
	mov r1, #0
	str r1, [r0]

@波特率整数部分设置
	ldr r0, =ubrdiv0
	mov r1, #34
	str r1, [r0]

@波特率小数部分设置
	ldr r0, =udivslot0
	ldr r1, =0xdfdd
	str r1, [r0]

	mov pc, lr

 

start.S : 整合时钟、led、按键、串口、蜂鸣器功能。

#define ufstat0 (*(volatile unsigned long *)0x7f005018)
#define urxh0 (*(volatile unsigned char *)0x7f005024)
#define utxh0 (*(volatile unsigned char *)0x7f005020)

char getchar_uart(void)
{
	while ((ufstat0 & 0x7f) == 0)
		;
	return urxh0;
}

void putchar_uart(char c)
{
	while (ufstat0 & (1<<14))
		;
	utxh0 = c;
}

int uart(void)
{
	char p;
	while(1){
		p = getchar_uart();
		if (p == 'q')
			return 0;
		putchar_uart(p);
	}

	return 0;
}

 

uart.c :start.S文件中调用的串口使能函数代码。

 

#define gpncon (*(volatile unsigned long *)0x7f008830)

#define gpndat (*(volatile unsigned long *)0x7f008834)

#define gpmcon (*(volatile unsigned long *)0x7f008820)

#define gpmdat (*(volatile unsigned long *)0x7f008824)



int key_led(void)

{

	gpncon &= ~(0xfff);

	gpmcon &= ~(0xffff);

	gpmcon |= 0x1111;

	while(1){

		if(gpndat & (1<<0))

			gpmdat |= (1<<0);

		else

			gpmdat &= ~(1<<0);

		if(gpndat & (1<<1))

			gpmdat |= (1<<1);

		else

			gpmdat &= ~(1<<1);

		if(gpndat & (1<<2))

			gpmdat |= (1<<2);

		else

			gpmdat &= ~(1<<2);

		if(gpndat & (1<<3))

			gpmdat |= (1<<3);

		else

			gpmdat &= ~(1<<3);

		if(gpndat & (1<<4))

			gpmdat |= 1;

		else

			gpmdat &= 0;

		if(gpndat & (1<<5))

			gpmdat |= 1;

		else{

			gpmdat &= 0;

			return 0;

		}

	}

	return 0;

}

 

key_led.c :按键初始化函数。

 

整个程序功能:运行后,进入串口功能,按'q'退出进入key_led功能,按key1,key2,key3,key4点亮相应的led灯,按key5全部点亮,按key6进入led循环点亮,并使蜂鸣器响起。

转载于:https://my.oschina.net/u/729328/blog/93826

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值