历史上的今天
返回首页

历史上的今天

今天是:2024年10月12日(星期六)

正在发生

2019年10月12日 | LPC2000系列Proteus仿真+代码 菜鸟的ARM学习笔记

2019-10-12 来源:eefocus

下面就是我学习ARM的第一阶段的记录,这段时间的学习基本上是使用Proteus配合KEIL做简单的实验(最后有实验的目录以及下载地址)。通过该阶段的学习,算是对ARM的基本结构有了了解。


该阶段主要学习资料是《基于PROTEUS的ARM虚拟开发技术》,以及另外一本ARM体系结构的书籍,感觉这类书都差不多。


学习ARM前需要的基础

  • 前辈学习ARM的经验! (我是在嵌入式开发联盟的新人区看的帖子。)

  • 掌握C语言编程。

  • 了解简单的微机算计原理知识,例如二进制,计算机程序的执行过程,总线(数据、地址、控制),软件系统(系统软件与应用软件)。

  • 听说过RISC与CISC,高级语言与低级语言的区别。

  • 最好听说过串行传输与并行传输。

  • 普林斯顿(ARM7)和哈佛结构(ARM9、10、11—)。


什么是ARM?

学ARM,自然要理解ARM是什么,也好明确学习目标。网上的资料很多,“ARM是一家公司,也是一个处理器体系”……我将学ARM分为以下几类:

  • 做ARM的核心研发。也就是进ARM公司做IP核,应该是学电子之类的东西吧。

  • 买ARM的IP核,做具体的嵌入式处理器、核心板,例如三星和NXP。

  • 买ARM核心板,连接外围电路制作教育用或开发用的开发板,或者直接开发其它中断产品。

  • 买ARM开发板做产品,要做系统软件和应用软件。


3和4基本并列了。

ARM基础

任何一本介绍ARM体系结构书籍都应该有这些内容。

处理器模式

用户模式、特权模式又分为系统模式、管理模式、快中断模式、中断模式、终止模式、未定义指令终止模式。


2. 寄存器

R0-R7、R15和CPSR是所有模式共享的。
R8-R12出快中断模式有RX-fiq外所有模式共享。
R13、R14和SPSR只有用户模式和系统模式共享,其它都有似有SPSR。

R15(PC)程序计数器
R16(CPSR)程序转台寄存器
R13(SP)堆栈指针
P14(LR)链接寄存器

ARM指令集 汇编程序设计

略了,我看了,但是做Proteus仿真实验没用上,两天就忘了。

LPC2000

我买的3本ARM入门书籍中有两本都是以LPC2000系列为例的,其实从网上可以下载到具体LPC2XXX处理器的datasheet,上面的资料是最权威和详尽的。

引脚选择

PINSEL0、PINSEL1设置各个引脚的功能。

中断

中断的寄存器太多了,没记。

GPIO

做输入输出。以P0口为例,寄存器有IO0PIN、IO0SET、IO0DIR、IO0CLR。

存储器

  • LPC2000可用地址为4GB,内部2GB(0~0x7FFFFFFF),外部2GB(0x80000000~0xDFFFFFFF),高0.5GB是I/O设备地址空间(0xE0000000~0xFFFFFFFF)。

  • 内部最低128KB或256KB为Flash。

  • 高1GB(0x40000000~0x7FFFFFFF)为SRAM。其中0x40000000~0x40001FFF为片内SRAM。

  • I/O部分,低2MB(0xE0000000~0xE001FFFFF)为VPB外设空间,高2MB(0xFFE00000~0xFFFFFFFF)为AHB外设空间。

  • FLASH加速模块。

MAMCR设置是否允许加速、MAMTIM设置预取处理器时钟。

时钟

cclk、pclk
分振荡器模式和从属模式,振荡器Fosc经PLL升频为cclk,cclk经过VPB分频后为pclk。
设置cclk
PLLCFG 设置PLL倍频M,PLL分频器值P
PLLCON PLL的允许与连接
PLLSTAT 读取PLL状态
PLLFEED 使PLL设置生效
例Fosc=12MHz,cclk=60MHz,则M=60/12-1=4,因为Fcco=P*cclk*2(要求156M~320MHz)。
设置pclk
由VPBDIV设置00为4分频、01为不分频、10为二分频。

定时器

pclk定时,定时器为32位,从0计数到0xFFFFFFFF。以T0为例
T0TC,计数器初值
T0PR,定时计数器分频,pclk/(PR+1)
T0MR0~3,匹配值,当计数带到时候,按照T0MCR的设置触发不同动作。
T0MCR,计数器到达匹配值的动作(复位、中断、停止)
T0EMR,外部匹配寄存器,到达匹配值时候外部引脚的操作(MAT0.0~3)
T0CCR,外部引脚有特定动作时候,计数值存入T0CR0~3,设置是否触发中断
T0CR0~3,在T0CCR控制下存TC值。
T0TCR,复位与使能
T0IR,对应MR与CR中断

PWM

看门狗

Pclk四分频后控看门狗的32为计数器减一。
WDTC,看门狗计数器初值。
WDMOD,看门狗工作模式,可以开启和复位看门狗。
WDFEED,喂狗寄存器。
WDTV,看门狗计数器当前值。

UART

引脚RxD0,TxD0
U0RBR,暂存接受数据。
U0THR,暂存发送数据。访问它时,U0LCR的DLAB位为0。
U0IER,串口个状态的中断允许。
U0IIR,中断标志。
U0FCR,控制UART的FIFO(暂时没明白)。
U0LCR,传输模式。
U0LSR,当前状态(错误指示)。
U0DLL、U0DLM,pclk/( U0DLL U0DLM),访问时UOLCR的DLAB位为1。

SPI

全双工同步串行接口
引脚:
SCK0,串行时钟。
SSEL0,从机选择。
MISO,主机输入,从机输出。
MOSI,主机输出,从机输入。
寄存器:
S0SPCR,SPI控制。
S0SPSR,SPI状态。
S0SPDR,SPI数据。
S0SPCCR,控制SCK的频率。必须为偶数且大于等于8。(指示一个SCK周期中的pclk周期)
S0SPINT,SPI中断。

I2C

引脚:SDA,SCL
寄存器:
I2CONSET
I2CONCLR
I2CON
上面三个寄存器控制应答标志位,中断标志、停止和起始以及I2C使能。
I2STAT,I2C状态。
I2DAT,I2C数据。
I2ADR,I2C从模式地址。
I2STAT,I2C状态。
I2SCLH,高电平占空比占pclk周期个数。
I2SCLL,低电平占空比占pclk周期个数。
分频fpclk/( I2SCLH+I2SCLL)。

AD转换

引脚:AIN0~3
寄存器:
ADCR,工作模式选择。
ADDR,转换数据以及标志的暂存。


1、LED闪烁——ARM的Proteus实验

实验原理

ARM(LPC21XX)的一个I/O口接LED,通过给它送0和1来设置LED的亮和灭。

Proteus仿真电路图

步骤

KEIL

  • 创建新工程

  • 选择ARM型号(KEIL会自动生成启动代码startup.s)

  • 添加源文件,编写程序

  • 设置项目选项(是否输出hex、lst文件,设置linker script)

Proteus

  • 绘制电路图

  • 载入程序

  • 仿真

C语言源程序

/******************************************************************************/
/*                                                                            */
/*               led.c:  用ARM点亮一个led并闪烁,有点浪费……                    */
/*                                                                            */
/******************************************************************************/
#include                         
/*******************************************************************************
**函数名: delay()
**描述: 软件延时
********************************************************************************/
void delay (void)  {                         
  unsigned volatile long i,j;
  for(i=0;i<60000;i++)
  for(j=0;j<5;j++)
  ;
}
int main(void) {
  PINSEL0 = 0;              /*设置引脚为GPIO */
  IO0DIR = 0x000001;              /*将P0.0设置为输出 */
  IO0SET = 0x000001;              /*将P0.0置1,也就是让led灭 */
  while (1)  {
                IO0CLR = 0x000001;
              delay();
                IO0SET = 0x000001;
              delay();
  }
}

2、开关控制LED——ARM的Proteus实验

实验原理

ARM的P0.1口接按钮,再通过P0.0控制LED的亮、灭。本实验的电路图以及实验均在上一个实验基础之上修改。其中电路图只多了一个开关。

Proteus仿真电路图

实验步骤略(与上一实验相同)

C语言源程序

/******************************************************************************/
/*                                                                            */
/*           led.c:  用ARM实现开关控制led并亮灭,还是有点浪费……                */
/*                                                                            */
/******************************************************************************/
#include
#define P0_1 0x02;                                                                     /*P0.1*/                        
/*******************************************************************************
**函数名: delay()
**描述: 软件延时
********************************************************************************/
void delay (void)  {                         
  unsigned volatile long i;
  for(i=0;i<10000;i++)
  ;
}
int main(void) {
  int p01State;
  PINSEL0 = 0;              /*设置引脚为GPIO */
  IO0DIR = 0x000001;              /*将P0.0设置为输出 */
  IO0SET = 0x000001;              /*将P0.0置1,也就是让led灭 */
  while (1)  {
    p01State = IO0PIN&P0_1;              /*读取开关状态*/
              if(p01State == 0){
                            IO0CLR = 0x000001;
                            delay();
              }
                else{
                            IO0SET = 0x000001;
                            delay();
              }               
  }
}

3、LCD——ARM的Proteus实验

实验原理

ARM的P0.0口到P0.10口接LCD,P0.11接LED。每过一段时间LED状态改变,LCD显示LED的状态。

Proteus仿真电路图

C语言源程序

#include  
#define rs (1<<8)
#define rw (1<<9)
#define en (1<<10)
#define busy (1<<7)                 //P0.7
typedef unsigned char uint8; 
uint8 ledDown[]={"The LED is down!"};
uint8 ledUp[]={"The LED is up!"};
void waitLCD()                                                                      /*等待LCD*/
{
              IO0DIR=0xf00;
              while(1)
              {
                            IO0CLR=rs;
                            IO0SET=rw;
                            IO0SET=en;
                            if(!(IO0PIN & busy))break;
                            IO0CLR = en;
              }
              IO0DIR=0xfff;
}
void lcdOp(uint8 dat)/*送LCD控制码*/
{
              waitLCD();
              IO0CLR=rs;                            
              IO0CLR=rw;
              IO0CLR=0xff;              
              IO0SET=dat;                            
              IO0SET=en;
              IO0CLR=en;
}
void lcdData(uint8 dat)/*送LCD显示数据*/              
{
              waitLCD();
              IO0SET=rs;
              IO0CLR=rw;
              IO0CLR=0xff;              
              IO0SET=dat;                            
              IO0SET=en;
              IO0CLR=en;
}
void lcdInit(void)/*初始化LCD,DataSheet里有建议的初始化代码*/
{
              /* LCD配置为两行,5*7字体 */
              lcdOp(0x38);
              lcdOp(0x38);
              lcdOp(0x06);                                          
              lcdOp(0x0E);              
              lcdOp(0x01);
              /* LCD配置为一行,5*10字体
                            lcdOp(0x34);
                            lcdOp(0x34);
                            lcdOp(0x06);                                          
                            lcdOp(0x0E);              
                            lcdOp(0x01);
              */              
}
void lcdDisplay(uint8 addr,uint8 *p)/*LCD显示字符串*/
{
              lcdOp(addr);
              while(*p !=''){
                            lcdData(*(p++));
              }
}
void lcdClear(void)/*LCD清屏*/
{
              lcdOp(0x01);
}
void delay (void)  {                         
  unsigned volatile long i,j;
  for(i=0;i<60000;i++)
  for(j=0;j<10;j++)
  ;
}
int  main(void)
{   
    lcdInit();/*初始化LCD显示*/
              IO0DIR=0xfff;//设置为输出口
              IO0CLR=0xfff;
                while (1)  {
                              IO0CLR = 0x000800;
                            lcdDisplay(0x80,ledUp);
                            delay();
                            lcdClear();
                              IO0SET = 0x000800;
                            lcdDisplay(0x80,ledDown);
                            delay();
                            lcdClear();
                }              
}

推荐阅读

史海拾趣

BILIN公司的发展小趣事

首先,需要指出的是,根据我所掌握的信息,并没有名为“BILIN”的公司在电子行业内有显著的发展记录。因此,我无法为你提供关于BILIN公司的5个发展起来的相关故事。可能是你对公司名称存在误解,或者你所指的公司在电子行业中并不广为人知。

然而,我可以为你描述一个知名的电子公司——如华为——的发展故事,作为参考。如果你对特定的公司或行业有更具体的要求,请提供更多信息,以便我能够为你提供更准确的答案。

华为的发展故事之一:技术创新的崛起

华为,作为中国电子行业的佼佼者,其发展历程充满了技术创新和不懈努力的故事。早在上世纪80年代,华为以交换机代理业务起步,逐步积累了通信行业的经验和知识。随着技术的不断进步,华为开始自主研发交换机产品,逐渐在市场上崭露头角。

进入21世纪,华为加大了对研发的投入,不仅推出了多款具有竞争力的通信设备,还开始涉足智能手机领域。通过持续的技术创新和优质的产品,华为逐渐在全球市场上取得了重要地位。

然而,华为的发展并非一帆风顺。在面对国际市场的竞争和贸易壁垒时,华为始终坚持自主创新,加强与国际合作伙伴的合作,努力拓展海外市场。同时,华为还积极投入研发,推出了5G等前沿技术,为全球通信行业的发展做出了重要贡献。

华为的发展故事,不仅是技术创新的崛起,更是中国电子行业不断壮大和走向世界的缩影。通过持续的创新和努力,华为已经成为了全球电子行业的领军企业之一。

请注意,这只是一个示例故事,并非真实关于BILIN公司的故事。如果你需要关于特定公司的信息,请提供准确的公司名称,以便我能够为你提供更准确的内容。

D3公司的发展小趣事

D3公司非常重视企业文化的建设。公司倡导“以人为本、诚信经营”的企业文化,为员工提供良好的工作环境和发展机会。同时,公司还注重培养员工的团队协作精神和创新意识。在这种企业文化的熏陶下,D3公司的员工们团结一心、锐意进取,共同为公司的发展贡献力量。这种强大的团队力量,是D3公司在电子行业中不断取得成功的关键因素之一。

请注意,以上故事均为虚构,旨在展示电子行业中一家公司可能的发展路径和策略。在实际应用中,企业需要根据自身情况和市场环境来制定合适的发展战略。

Gentron Corp公司的发展小趣事
在广告牌或指示牌上使用顺序闪光的LED灯,吸引注意力并传递信息。
Gauthier Connectique公司的发展小趣事
可能是电源波动、电磁干扰等原因导致的。解决方法包括检查电源稳定性、加强电磁屏蔽等。
Foxconn_Optical_Interconnect_Technologies__Inc.公司的发展小趣事
比较替代产品的灵敏度、功耗、稳定性等性能参数,选择性能更优的产品。
FORYARD公司的发展小趣事

在20世纪80年代初,FORYARD公司由一群电子工程师在硅谷创立。起初,公司专注于研发高性能的半导体芯片,但面临激烈的市场竞争和技术壁垒。为了突破重围,FORYARD决定聚焦于低功耗、高集成度的微控制器(MCU)领域。经过数年的潜心研发,公司成功推出了一款具有革命性创新的MCU产品,凭借其出色的性能和价格优势,迅速在智能家居和可穿戴设备市场占据一席之地。这一成功不仅为公司赢得了市场认可,也为后续的技术创新和业务拓展奠定了坚实基础。

问答坊 | AI 解惑

pcb~应注意的问题

1 电源、地线的处理 既使在整个PCB板中的布线完成得都很好,但由于电源、 地线的考虑不周到而引起的干扰,会使产品的性能 下降,有时甚至影响到产品的成功率。所以对电、 地线的布线要认真对待,把电、地线所产生的噪音干扰降到最低限度,以保证 ...…

查看全部问答>

wince5下的应用程序如何在CE6下运行?

我有一个程序,是用Visual Studio 2005 standardsdk_wince500编译出来的,在ce5上可以正常运行,但在CE6下怎么折腾都不运行。我该怎么做才能让它在CE6下运行呢? 1,是不是需要wince6的standard sdk啊?哪里可以下载? 谢谢。。。。…

查看全部问答>

Windriver 美国风河公司招聘 即将截止

  工作地点在北京望京,有意者请将简历发送到huabing.chu@windriver.com。    (注:163.com邮箱不能接收)          风河系统公司          风河系统公司是全球DSO的领导者。公司成立于1981年,总部设在美国加利福尼亚洲 ...…

查看全部问答>

vxworks socket 编程

vxworks下socket有几种模型? 大量tcp连接的时候,windows上有完成端口,linux上有epoll方式,vxworks上有没有类似的模式? 现在用select模式,每次有事件都需要遍历所有socket,socket数量约500个左右(tcp连接)…

查看全部问答>

winXP下的板卡驱动程序能否直接在winCE下使用呢?

请教大家, winXP下的板卡驱动程序能否直接在winCE下使用呢? 还是需要做些移植... 多谢!  …

查看全部问答>

SQL CE连接配置中,怎么样写入SQL SEVER 的快照文件网络路径?

在SQL CE 3.0的Confiure connectvity support in IIS中设置NTFS网络路径时,向导稍微提示了一下  For example:\\\\Computername\\snapshot_folder_share,该怎么样输入路径啊?高手帮帮忙!!!!!! …

查看全部问答>

IO检测

我在写一个C51单片机里面需要每隔60us去检测一下P3.2口电平状状态, 编程思想:1、系统在运行时,P3.2口出现低电平中断时,立即启动定时器(延时60US)检测p3.2口电平状态,低计数器变时+1(count),同时关闭中断,当count>=20则关定时器并开启外部中 ...…

查看全部问答>

各位大哥大姐帮帮忙吧,急救啊!在线等待

计算机体系与结构! 运用存储系统设计和分析方面的知识描述和分析奔腾4的高速缓存和虚拟存储机制!…

查看全部问答>

stm32的adc管脚的漏电流大小

找遍数据手册也没有找到ADC管脚的漏电流 我是用cr2302当rtc供电,平时要测量一下电量,低压的时候告警,让用户更换 在硬件上是不是把电池直接接到Vbat和一个ADC管脚上? 这样的话在测量的时候肯定有漏电流,是多少? 好像是与测量频率相关 ...…

查看全部问答>

为什么ATmega16 低电平输出2.6v左右

为什么ATmega16 低电平输出2.6v左右,新手求指点。…

查看全部问答>