ARM(一).LED and BEEP

前言

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

RISC全称为 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 uVision v4.10

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

Windows 7 32位旗舰版

天嵌2440V2开发板

三星 ARM920T 芯片

H-JTAG v2.1

Keil uVision v4.10

LED 灯与蜂鸣器

要求

  • 使用ARM板开启LED灯和蜂鸣器

创建项目

创建项目的总体过程就是

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

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

选择三星 S3C2440A芯片

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

设定时钟频率和栈大小

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

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

选择H-JTAG ARM 模式

选择正确的模式

使用外部工具

代码示例

S3C2440.s

;;
;LED1-GPB5 根据原理图搜索,这里使用的天嵌开发板,不同板子不一样
;LED2-GPB6
;LED3-GPB7
;LED4-GPB8
;在ARM的汇编里 ‘;’ 代表注释

;0-On 低电位 
;1-Off 高电位
;

;GPBCON-0x56000010 GPB的控制寄存器地址,R/W
;GPBDAT-0x56000014 GPB的数据寄存器地址,R/W
;GPBUP -0x56000018 GPB的上拉电阻寄存器地址,R/W 0:开启,1:关闭
    

	AREA    RESET, CODE, READONLY
	;AREA 伪指令用于定义一个代表段或数据段,ARM汇编程序设计采用分段式设计,一个ARM源程序至少需要一个代码段,大的程序可以包含多个代码段及数据段
	;RESET 是代码段或数据段的名称
	;CODE 定义为代码段
	;READONLY 指定本段为只读,代码段的默认属性为只读
	
	ENTRY	;ENTRY伪指令用于指定程序的入口点,一个程序(可以包含多个源文件)中至少要有一个ENTRY,可以有多个ENTRY,但一个源文件中最多只有一个ENTRY
	

	CODE32
	;CODE32伪指令指示汇编编译器后面的指令为32位的ARM指令

	IMPORT CtrlLED ;IMPORT伪指令指示编译器当前的符号不是在本源文件中定义的,而是在其它源文件中定义的,在本源文件中可能引用该符号
	IMPORT CtrlBEEP ;CtrlLED CtrlBEEP 两个符号都是在另一个文件中定义的

	PRESERVE8 ;PRESERVE8伪指令指示当前文件保持堆栈为8字节对齐

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

	LDR		SP, =0x1000	;将堆栈指针指向0x1000的地址,为什么是0x1000呢?我人为的设定了IROM1的范围为 0x0-0x800,IRAM1的范围为0x800-0x1000,那么前0x800Byte的空间就用来存代码了,后面的0x800就用来放数据了,然而堆栈是从大地址往小地址移动,所以从0x1000开始存储数据,故将SP指向0x1000的初始位置

	BL 		CtrlLED 	;跳转到CtrlLED执行
	BL 		CtrlBEEP 	;跳转到CtrlBEEP执行

 
	END 		;汇编结束

led_beep.C

#include   //这个文件由汇编器提供,里面的内容全都是S3C2440芯片的寄存器地址宏

void CtrlLED(void) //CtrlLED函数定义
{
	GPBCON = (1 << 10) | (1 << 12) | (1 << 14) | (1 << 16);	// 通过GPBCON对BPB进行配置,[11,10]位为BPB5配置位,[13,12]位为BPB6配置位,[15,14]位为BPB7配置位,[17,16]位为BPB8配置位,01为输出模式,就是将BPB{5,6,7,8}配置为输出模式,为什么是BPB{5,6,7,8}呢,因为从原理图中可以得知,它们分别与LED{1,2,3,4}直连
	GPBDAT = (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8);	//将BPB{5,6,7,8}配置为高电平的时候就使LED{1,2,3,4}灯灭
	GPBDAT = (0 << 5) | (0 << 6) | (0 << 7) | (0 << 8);	//将BPB{5,6,7,8}配置为低电平的时候就使LED{1,2,3,4}灯亮
}
 
 void delay(int n) //延时函数定义
 {
    int i,j; 
 	for(i=0;i<n;i++)   //第一层循环n次
	for(j=0;j<n;j++);	//第二层循环n次,所以总共有n*n次空操作

 }

 void CtrlBEEP(void) //CtrlBEEP函数定义
 {	 

    GPBCON |= 0x01;	// 将GPB0配置为输出,为什么配置GPB0呢,因为BPB0直连着蜂鸣器,并且如果输出高电平,就联通
	
    while(1) //死循环
	{
		GPBDAT &= 0xfffffffe;	//将0位置0,低电平,所以不会响
		delay(100); 			//适当延时10000个处理周期
		GPBDAT |= 1;	   		//将0位置1,高电平,所以会响
		delay(100);				//适当延时10000个处理周期
	}
 }

编译执行

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

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

灯全亮,蜂鸣器也响了

镜缘浮影稿源:镜缘浮影 (源链) | 关于 | 阅读提示

本站遵循[CC BY-NC-SA 4.0]。如您有版权、意见投诉等问题,请通过eMail联系我们处理。
酷辣虫 » 综合技术 » ARM(一).LED and BEEP

喜欢 (0)or分享给?

专业 x 专注 x 聚合 x 分享 CC BY-NC-SA 4.0

使用声明 | 英豪名录