镜缘浮影 小人本住在 苏州的城外 家里有屋又有田 生活乐无边

ARM(二).KEY and LED

2017-03-15
wilmosfang
arm
原文地址 http://soft.dog/2017/03/15/arm-02-key-led/

前言

ARM 处理器是英国Acorn有限公司设计的低功耗低成本的一款RISC微处理器

ARM 全称为 Acorn RISC Machine

目前市面上的CPU有两大类别

  • RISC: 精简指令集计算机
  • CISC: 复杂指令集计算机

关于两者的差别网上有很多资料,这里简要列出几点

DIFF CISC RISC
理念 让每条指令能够完成比较复杂的功能 让每条指令只实现最基本的功能
指令数目 多(>200) 少(<100)
指令字长 不固定 固定(16/32)
指令使用频率 相差大(20/80) 相差小
各种指令执行时间 相差很大 相差不大(因为等长,绝大多数在一个周期内完成)
优化编译实现
功耗
CPU设计难度
应用代码量
应用开发时间

CISC的典型代表就是 Intel 和 AMD 系列芯片,RISC 的代表有IBM 的 Power(Power Optimization With Enhanced RISC),SUN 的SPARC,HP 的 PA-RISC 还有ARM

从两种架构的市场变化情况来看(鄙人愚见,欢迎拍砖)

DIFF CISC RISC
以前 电子消费领域(PC) 服务器领域(各种小型机,大型机)
现在 服务器领域(PC服务器) 电子消费领域(手机,游戏机,嵌入式)
未来 取决于能源成本和储能比(成正比) 取决于能源成本和储能比(成反比)

ARM 处理器本身是32位设计,但也配备16位指令集,一般来讲比等价32位代码节省达35%(也就是代码密度更高),却能保留32位系统的绝大部分优势

因为价格与能耗上的明显优势,在手持设备与嵌入式领域大放异彩,可以说目前的绝大部分便携或手持电子消费品都是用的ARM芯片

Tip: 当然还有更弱的终端由单片机(PC51一类的)来实现,ARM具备更复杂和强劲的控制与处理能力,价格也相对更贵


概要


平台环境与工具

应用的开发无法脱离具体的平台与环境,即便声称为跨平台的框架,在现实情况中,同样一套代码,在不同的平台与环境中也不一定会获得相同的效果

Note: 对于嵌入式来说,尤为如此,因为硬件配置不同,极大可能根本无法正常运行

这里使用如下平台与开发环境

  • Windows 7 32位旗舰版
  • 天嵌2440V2开发板
  • 三星 ARM920T 芯片
  • H-JTAG v2.1
  • Keil uVision4.10

Tip: 都不是最新的,但能用,原理相通

Windows 7 32位旗舰版

win7_x86_32.png

天嵌2440V2开发板

tq2440.png

三星 ARM920T 芯片

arm920t.png

H-JTAG v2.1

j_tag_v2.1.png

Keil uVision4.10

keil_v4.1.0.png


按键控制 LED 灯

要求

  • 使用ARM板的按键控制LED灯

KEY电路原理图

key.png

LED电路原理图

led.png

创建项目

创建项目的总体过程就

  • 新建文件夹
  • 创建项目文件
  • 项目中添加入源代码

只有以下几个方式稍微注意一下

选择三星 S3C2440A芯片

Device 选项卡中确保是正确的设备选型(和头文件相关,寄存器的正确地址决定于此)

S3C2440A.png

设定时钟频率和栈大小

Target 选项卡中确保时钟频率和板载一致

正确设定内存(只读栈和读写栈,也就是代码区与数据区的大小)

memory.png

选择H-JTAG ARM 模式

选择正确的模式

HJTAG_ARM.png

使用外部工具

External_tool.png

代码示例

asm_key_led.s

;;;
;LED电路原理图
;LED1-GPB5
;LED2-GPB6
;LED3-GPB7
;LED4-GPB8
;0-On,1-Off
;芯片针脚配置寄存器
;GPBCON-0x56000010
;GPBDAT-0x56000014
;GPBUP -0x56000018
;KEY电路原理图
;K1-EINT1/GPF1
;K2-EINT4/GPF4
;K3-EINT2/GPF2
;K4-EINT0/GPF0
;DOWN-0,UP-1
;芯片针脚配置寄存器
;GPFCON-0x56000050
;GPFDAT-0x56000054
;GPFUP -0x56000058

	AREA    RESET, CODE, READONLY ;定义一个名为RESET的只读代码段
	CODE32 ;CODE32伪指令指示汇编编译器后面的指令为32位的ARM指令
	ENTRY ;ENTRY伪指令用于指定程序的入口点,一个程序(可以包含多个源文件)中至少要有一个ENTRY,可以有多个ENTRY,但一个源文件中最多只有一个ENTRY

START ;不是关键词,只是一个标号,可以修改
;关看门狗相关配置
	LDR		R0, =0x53000000 ;0x53000000是看门狗定时器的控制寄存器地址,LDR是将这个地址加载到R0寄存器中
	LDR		R1, =0         	;LDR将0这个立即数,加载到R1寄存器中
	STR		R1, [R0]	;STR将R1寄存器中的值(0)存到R0寄存器中地址所指代的寄存器中,在这里,总体来讲就是关闭了看门狗

;配置与按键相连接的IO端口为输入GPF{1,4,2,0},00代表输入
	LDR		R0, =0x56000050 ;0x56000050是GPF的控制寄存器地址,LDR是将这个地址加载到R0寄存器中
	LDR		R1, =0        	;LDR将0这个立即数,加载到R1寄存器中
	STR		R1, [R0]	;STR将R1寄存器中的值(0)存到R0寄存器中地址所指代的寄存器中,在这里,总体来讲就是将所有的GPF针脚都设定成了输入模式,00代表输入

;配置与LED相连接的IO端口为输出GPB{5,6,7,8},01代表输出
	LDR		R2, =0x56000010	;0x56000010是GPB的控制寄存器地址,LDR是将这个地址加载到R2寄存器中
	LDR		R3, =0x00015400 ;LDR将0x00015400这个数,加载到R3寄存器中,0x00015400代表0001 0101 0100 0000 0000,[17-10]分别为01010101,代表GPB{5,6,7,8}设定为输出,01代表输出
	STR		R3, [R2]	;STR将R3寄存器中的值(0x00015400)存到R2寄存器中地址所指代的寄存器中,在这里,总体来讲就是将GPB{5,6,7,8}设定为输出,01代表输出

;熄灭全部LED灯
	LDR		R2, =0x56000014	;0x56000014是GPB的数据寄存器地址,LDR是将这个地址加载到R2寄存器中
	LDR		R3, =0x000001E0 ;LDR将0x000001E0这个数加载到R3寄存器中,0x000001E0代表0001  1110 0000,代表GPB{5,6,7,8}的位置为高电位 
	STR		R3, [R2]	;STR将R3寄存器中的值(0x000001E0)存到R2寄存器中地址所指代的寄存器中,在这里,总体来讲就是将GPB{5,6,7,8}设定为高电位,高电位LED灯就灭了

LOOP
;读取按键状态
	LDR		R0, =0x56000054	;0x56000054是GPFDAT寄存器的地址,LDR将0x56000054这个地址加载到R0寄存器中
	LDR		R1, [R0]	;LDR将R0寄存器中地址所指代的寄存器中的值加载到R1
;LED初始状态为熄灭				
	LDR		R3, =0x000001E0	;LDR将0x000001E0(0001 1110 0000)加载到R3中
;判断K1是否按下
	TST		R1, #0x00000002	;TST指令将寄存器R1的值与0x00000002(0000 0010)的值按位作逻辑“与”操作,根据操作的结果更新CPSR中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行,此操作类似于 if((GPFDAT & 0x00000002) == 0){},TST指令与ANDS指令的区别在于TST指令不保存运算结果,TST指令通常与EQ/NE条件码配合使用,当所有测试位均为0时,EQ有效,而只要有一个测试位不为0,则NE有效
	BICEQ	R3, #0x00000020		;如果上一步的结果为EQ,则此步的操作就是将R3寄存器中值的第5位(从0位开始数)值清零,BIC指令将寄存器R3的值与0x00000020(0010 0000)的反码(1101 1111)作逻辑“与”操作,结果保存到R3寄存器中;GPB5 
;判断K2是否按下
	TST		R1, #0x00000010	;TST指令将寄存器R1的值与0x00000010(0001 0000)的值按位作逻辑“与”操作,根据操作的结果更新CPSR中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行,此操作类似于 if((GPFDAT & 0x00000010) == 0){},TST指令与ANDS指令的区别在于TST指令不保存运算结果,TST指令通常与EQ/NE条件码配合使用,当所有测试位均为0时,EQ有效,而只要有一个测试位不为0,则NE有效
	BICEQ	R3, #0x00000040		;如果上一步的结果为EQ,则此步的操作就是将R3寄存器中值的第6位(从0位开始数)值清零,BIC指令将寄存器R3的值与0x00000040(0100 0000)的反码(1011 1111)作逻辑“与”操作,结果保存到R3寄存器中;GPB6
;判断K3是否按下
	TST		R1, #0x00000004	;TST指令将寄存器R1的值与0x00000004(0000 0100)的值按位作逻辑“与”操作,根据操作的结果更新CPSR中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行,此操作类似于 if((GPFDAT & 0x00000004) == 0){},TST指令与ANDS指令的区别在于TST指令不保存运算结果,TST指令通常与EQ/NE条件码配合使用,当所有测试位均为0时,EQ有效,而只要有一个测试位不为0,则NE有效
	BICEQ	R3, #0x00000080		;如果上一步的结果为EQ,则此步的操作就是将R3寄存器中值的第7位(从0位开始数)值清零,BIC指令将寄存器R3的值与0x00000080(1000 0000)的反码(0111 1111)作逻辑“与”操作,结果保存到R3寄存器中;GPB7
;判断K4是否按下
	TST		R1, #0x00000001	;TST指令将寄存器R1的值与0x00000001(0000 0001)的值按位作逻辑“与”操作,根据操作的结果更新CPSR中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行,此操作类似于 if((GPFDAT & 0x00000001) == 0){},TST指令与ANDS指令的区别在于TST指令不保存运算结果,TST指令通常与EQ/NE条件码配合使用,当所有测试位均为0时,EQ有效,而只要有一个测试位不为0,则NE有效
	BICEQ	R3, #0x00000100		;如果上一步的结果为EQ,则此步的操作就是将R3寄存器中值的第8位(从0位开始数)值清零,BIC指令将寄存器R3的值与0x00000100(0001 0000 0000)的反码(1110 1111 1111)作逻辑“与”操作,结果保存到R3寄存器中;GPB8
;控制LED显示
	STR		R3, [R2]	;STR将R3寄存器中的值存到R2寄存器中地址所指代的寄存器中,在这里,总体来讲就是将GPB{5,6,7,8}设定为相应电位,高电位LED灯就灭了,低电位灯就亮了
	B		LOOP 		;不断循环

	END				;汇编结束

编译执行

[Build]->[Debug]->[Run]

编译执行过程中没有报错,从结果来看,符合预期

依次按下K1 到 K4 ,相应的 LED1 到 LED4 灯也被点亮

原文地址 http://soft.dog/2017/03/15/arm-02-key-led/

评论