单片机论坛

 找回密码
 立即注册

QQ登录

只需一步£¬快速开始

搜索
查看: 2577|回复: 0
收起左侧

LPC2000系列Proteus仿真+代码 菜鸟的ARM学习笔记

[复制链接]
zhang779065972 发表于 2018-11-15 17:50 | 显示全部楼层 |阅读模式
lpc2000系列proteus仿真+代码£¬新手自取

菜鸟的ARM学习笔记
下面就是我学习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£¬转换数据以及标志的暂存¡£
基于ProteusARM实验目录
菜鸟的ARM学习笔记£¨第一阶段£©
  • LEDÉ了¸¡ª¡ªARM的Proteus实验
  • 开关控制LED¡ª¡ªARM的Proteus实验
  • LCD¡ª¡ªARM的Proteus实验
  • UART¡ª¡ªARM的Proteus实验
  • Eint1外部中断¡ª¡ªARM的Proteus实验
  • 多个外部中断¡ª¡ªARM的Proteus实验
  • 中断结合串口¡ª¡ªARM的Proteus实验
  • 定时器¡ª¡ªARM的Proteus实验
  • SPI通信¡ª¡ªARM的Proteus实验
  • SPI通信£¨多从设备£©¡ª¡ªARM的Proteus实验
  • ADC数模转换¡ª¡ªARM的Proteus实验
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 <LPC21xx.H>                        
/*******************************************************************************
**函数名: 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 <LPC21xx.H>
#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  <LPC21XX.H>
#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 !='\0'){
                            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();
                }              
}
4¡¢UART¡ª¡ªARM的Proteus实验
实验原理
ARM的P0.0口接LED£¬串口接Proteus的虚拟终端¡£每隔一¶问±间改变一次LED的状态£¬并Ç以Ú串口上输出LED的当前状态¡£
Proteus仿真电路图
C语言源程序
#include <LPC21xx.H>
#include "uart.h"
#define CR 0x0D
char ledDown[]={"The LED is down!\n"};
char ledUp[]={"The LED is up!\n"};
int putchar (int ch)  {/* 向串口输出一个×址û */
  if (ch == '\n')  {
    while (!(U1LSR & 0x20));
    U1THR = CR;              a
  }
  while (!(U1LSR & 0x20));
  return (U1THR = ch);
}
void delay (void)  {                        
  unsigned volatile long i,j;
  for(i=0;i<60000;i++)
  for(j=0;j<5;j++)
  ;
}
void serialPuts(char *p){/* 向串口输出×址û串 */
  while (*p != '\0'){
                putchar(*p++);
  }
}
int main (void)  {
/* 开始初始化串口 */
  PINSEL0 = 0x00050000;/* 设置引脚£¬开串口功能 */
  U1LCR = 0x83;/* 8位数据£¬无效验£¬一个停止位 */
  U1DLL = 97;/* VPB 15MHz的时候波特率为9600 */
  U1LCR = 0x03;/* DLAB = 0 */
/* 结束初始化串口 */
  IO0DIR = 0x000001;/*将P0.0设置为输出 */
  while (1)  {
                IO0CLR = 0x000001;
              serialPuts(ledUp);
              delay();
                IO0SET = 0x000001;
              serialPuts(ledDown);
              delay();
  }
}                              
5¡¢Eint1外部中断¡ª¡ªARM的Proteus实验
实验原理
ARM的P0.25接一个LED£¬引脚设置时连接EINT1功能£¬按钮触发中断¡£中断服务程序另LED快速É了¸¡£
Proteus仿真电路图
C语言源程序
#include <LPC21XX.H>
#define LEDCON 0x02000000/*LED接在P0.25上*/
typedef unsigned int uint32;
void IRQ_Eint1(void) __attribute__ ((interrupt));/*声明某函数为中断服务子程序的方法*/
uint32 times = 100;/*循环´问ý默认为100*/
void IRQ_Eint1(void){
  times = 5;
  while((EXTINT&0x02)!=0){
                EXTINT=0x02;                   //清除EINT1中断标志
  }
  VICVectAddr=0;
}
void delay100(void)  {                        
  unsigned volatile long i,j;
  for(i=0;i<10000;i++)
  for(j=0;j<times;j++)
  ;
  if(times > 100){
                times--;
  }else if(times <100){
                times++;
  }
}
int  main(void)
              {
              IO0DIR = LEDCON;
              PINSEL0 = 0x20000000;/*引脚选中EINT1功能*/
              PINSEL1 = 0x00000000;
/*以下为中断控制部分*/                           
              VICIntSelect=0;/*全部中断设置为IRQ£¬若某位为1是FIQ*/
              VICIntEnable=0x00008000;/*使能EINT1£¬EINT为第15位*/
              VICVectCntl1=0x2F;/*0xF,15号中断*/
              VICVectAddr1=(int)IRQ_Eint1;/*设置中断服务子程序*/
              EXTINT=0x07;              
                while (1)  {
                              IO0CLR = LEDCON;
                            delay100();
                              IO0SET = LEDCON;
                            delay100();
                }
}
6¡¢多个外部中断¡ª¡ªARM的Proteus实验
实验原理
ARM开启两个中¶显´Eint1与Eint2£¬分别用一个按钮来控制¡£在没有中¶系Ä时候两个LED都缓慢É了¸£¬当任何一个中断被出发的时候£¬对应的LED会急促É了¸£¬逐渐回复正常¡£
Proteus仿真电路图
C语言源程序
#include <LPC21XX.H>
#define LED1 0x02000000/*LED1接在P0.25上*/
#define LED0 0x01000000/*LED0接在P0.24上*/              
typedef unsigned int uint32;
void Eint1_ISR(void) __attribute__ ((interrupt));/*声明某函数为中断服务子程序的方法*/
void Eint0_ISR(void) __attribute__ ((interrupt));
uint32 times = 40;/*循环´问ý默认为40*/
void delay40(void)  {                        
  unsigned volatile long i,j;
  for(i=0;i<10000;i++)
  for(j=0;j<times;j++)
  ;
  if(times > 40){
                times-=2;
  }else if(times <40){
                times+=2;
  }
}
void Eint0_ISR(void){  
  times = 0;
  while(times!=40){
              IO0CLR = LED0;
              delay40();
              IO0SET = LED0;
              delay40();               
  }
  while((EXTINT&0x01)!=0){
   EXTINT=0x01;/*清除EINT0中断标志*/
  }
  VICVectAddr=0x00;
}
void Eint1_ISR(void){
  times = 0;
  while(times!=40){
              IO0CLR = LED1;
              delay40();
              IO0SET = LED1;
              delay40();               
  }
  while((EXTINT&0x02)!=0){
                EXTINT=0x02;/*清除EINT1中断标志*/
  }
  VICVectAddr=0;
}
int  main(void)
              {
              IO0DIR = LED1|LED0;
              PINSEL0 = 0x20000000;/*引脚选中EINT1功能*/
              PINSEL1 = 0x00000001;/*引脚选中EINT0功能*/
/*以下为中断控制部分*/                           
              VICIntSelect=0;/*全部中断设置为IRQ£¬若某位为1是FIQ*/
              VICIntEnable=0x0000C000;/*使能EINT1¡¢0£¬EINT1为第15位£¬0为14位*/
              VICVectCntl0=0x2E;/*EINT0最高优先级*/
              VICVectAddr0=(int)Eint0_ISR;/*设置EINT0向量地址*/
              VICVectCntl1=0x2F;/*0xF,15号中断*/
              VICVectAddr1=(int)Eint1_ISR;/*设置中断服务子程序*/
              EXTINT=0x07;              
                while (1)  {/*无中断时£¬两灯一起缓慢É了¸*/
                              IO0CLR = LED1|LED0;
                            delay40();
                              IO0SET = LED1|LED0;
                            delay40();
                }
}
7¡¢中断结合串口¡ª¡ªARM的Proteus实验
实验原理
同上多中¶显´实验相同£¬ARM开启两个中¶显´Eint1与Eint2£¬分别用一个按钮来控制¡£在没有中¶系Ä时候两个LED都缓慢É了¸£¬当任何一个中断被出发的时候£¬对应的LED会急促É了¸£¬逐渐回复正常¡£
此外£¬使用一个串口来发送当前状态£¬在无中¶系Ä时候发送正常状态报告£¬当有中¶系Ä时候£¬串口发送中¶显础£
Proteus仿真电路图
C语言源程序
文件一£ºmain.c
#include <LPC21XX.H>
#include "uart0.h"
#define LED1 0x02000000/*LED1接在P0.25上*/
#define LED0 0x01000000/*LED0接在P0.24上*/
typedef unsigned int uint32;
void Eint1_ISR(void) __attribute__ ((interrupt));/*声明某函数为中断服务子程序的方法*/
void Eint0_ISR(void) __attribute__ ((interrupt));
uint32 times = 40;/*循环´问ý默认为40*/
char status[] = "Everytnig is fine.";
char eint0Str[] = "Interruption EINT0 activated!!!";
char eint1Str[] = "Interruption EINT1 activated!!!";
void delay40(void)  {                        
  unsigned volatile long i,j;
  for(i=0;i<10000;i++)
  for(j=0;j<times;j++)
  ;
  if(times > 40){
                times-=2;
  }else if(times <40){
                times+=2;
  }
}
void Eint0_ISR(void){  
  times = 0;
  while(times!=40){
              IO0CLR = LED0;
              delay40();
              IO0SET = LED0;
              delay40();
              serialPuts(eint0Str);                              
  }
  while((EXTINT&0x01)!=0){
   EXTINT=0x01;/*清除EINT0中断标志*/
  }
  VICVectAddr=0x00;
}
void Eint1_ISR(void){
  times = 0;
  while(times!=40){
              IO0CLR = LED1;
              delay40();
              IO0SET = LED1;
              delay40();
              serialPuts(eint1Str);               
  }
  while((EXTINT&0x02)!=0){
                EXTINT=0x02;/*清除EINT1中断标志*/
  }
  VICVectAddr=0;
}
int  main(void)
              {
              IO0DIR = LED1|LED0;
              PINSEL0 = 0x20000005;/*引脚选中EINT1功能,开串口UART0*/
              PINSEL1 = 0x00000001;/*引脚选中EINT0功能*/
/*以下为中断控制部分*/                           
              VICIntSelect=0;/*全部中断设置为IRQ£¬若某位为1是FIQ*/
              VICIntEnable=0x0000C000;/*使能EINT1¡¢0£¬EINT1为第15位£¬0为14位*/
              VICVectCntl0=0x2E;/*EINT0最高优先级*/
              VICVectAddr0=(int)Eint0_ISR;/*设置EINT0向量地址*/
              VICVectCntl1=0x2F;/*0xF,15号中断*/
              VICVectAddr1=(int)Eint1_ISR;/*设置中断服务子程序*/
              EXTINT=0x07;
              uart0Init();              
                while (1)  {/*无中断时£¬两灯一起缓慢É了¸*/
                              IO0CLR = LED1|LED0;
                            delay40();
                              IO0SET = LED1|LED0;
                            delay40();
                            serialPuts(status);
                }  
}
文件二£ºuart0.c
#include <LPC21XX.H>
#include "uart0.h"
#define CR 0x0D
int putchar (int ch)  {/* 向串口输出一个×址û */
  if (ch == '\n')  {
    while (!(U0LSR & 0x20));
    U0THR = CR;
  }
  while (!(U0LSR & 0x20));
  return (U0THR = ch);
}
void serialPuts(char *p){/* 向串口输出×址û串 */
  while (*p != '\0'){
                putchar(*p++);
  }
  putchar('\n');
}
void uart0Init(void){
  U0LCR = 0x83;/* 8位数据£¬无效验£¬一个停止位 */
  U0DLL = 97;/* VPB 15MHz的时候波特率为9600 */
  U0LCR = 0x03;/* DLAB = 0 */
}
8¡¢定时器¡ª¡ªARM的Proteus实验
实验原理
ARM的定时器实验£¬定时改变LED的状态¡£
Proteus仿真电路图
C语言源程序
#include <LPC21xx.H>
#define LED 0x000001
typedef unsigned int uint32;
typedef unsigned char uint8;
void timer0_ISR (void) __attribute__ ((interrupt));
uint8 timer0Times = 0;
void timer0Init (void) {
    T0MR0 = 119999;/*匹配寄存器£¬120000-1£¬12000000为1秒*/
    T0MCR = 3;/*产生中断£¬重置TC*/
    T0TCR = 1;/*使能定时计数器0*/
    VICVectAddr0 = (unsigned long)timer0_ISR;        
    VICVectCntl0 = 0x20 | 4;/*定时器计数器0为4号中断*/
    VICIntEnable = 0x00000010;/*开定时计数器0中断*/
}
void timer0_ISR (void) {
              timer0Times++;
              uint32  i;
              if(timer0Times == 10){
                            i=IO0SET;                         //读出当前LED2控制值
                            if((i&LED)==0){
                                          IO0SET=LED;
                            }else{
                                          IO0CLR=LED;
                            }
                            timer0Times = 0;
              }
    T0IR = 1;/*清除定时器0中断*/
    VICVectAddr = 0;                       
}
int main(void) {
  PINSEL0 = 0;/*设置引脚为GPIO */
  IO0DIR = LED;/*将P0.0设置为输出 */
  IO0SET = LED;/*将P0.0置1£¬也就是让led灭 */
  timer0Init();
  while (1)  {
  }
}
9¡¢SPI通信¡ª¡ªARM的Proteus实验
实验原理
使用SPI协议£¬利用ARM控制数码显示管显示1到F£¬用串口检验发送的数据是否正确¡£
Proteus仿真电路图
C语言源程序
下面是主程序文件£¬串口部分的程序代码与¡°中断结合串口¡±相同£¬所以省略¡£
#include <LPC21XX.H>
#include "uart0.h"
#define   HC595_CS    0x00000100/*P0.8口为74HC595的片选*/
typedef unsigned int uint32;
typedef unsigned char uint8;
char status[] = "Everytnig is fine.";
uint8 const DISP_TAB[16]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,
0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E};
uint8 rcv_data;
void delay(void)  {                        
  unsigned volatile long i,j;
  for(i=0;i<10000;i++)
  for(j=0;j<30;j++)
  ;
}
void spiInit(void){
  S0SPCCR=0x52;           //设置SPI时钟分频
  S0SPCR=0x30;            //设置SPI接口模式
}
uint8 spiChar(uint8 data){
  IO0CLR=HC595_CS;                             //片选
  S0SPDR=data;
  while(0==(S0SPSR&0x80));                      //等待SPIF置位,即等待数据发送完毕
  IO0SET=HC595_CS;
  return(S0SPDR);
}
int  main(void){
  uint8 i;
  PINSEL0 = 0x00005505;/*引脚开串口SPI¡¢UART0*/              
  IO0DIR=HC595_CS;
  spiInit();/*初始化SPI接口*/
  uart0Init();
  while(1){
    for (i=0;i<16;i++) {
                            if(i<10){putchar(i+'0');}
                                          else{putchar(i+7+'0');}
                            rcv_data=spiChar(DISP_TAB[ i]);/*发送显示数据*/
                            delay();
    }
              serialPuts(status);
  }
}
[ i]
10¡¢SPI通信£¨多从设备£©¡ª¡ªARM的Proteus实验
实验原理
使用SPI协议£¬利用ARM控制数码显示管1显示1到F£¬数码显示管2则从F到1倒计数£¬数码显示管则一直显示0¡£该连接方法使用片选来激活不同的SPI从设备£¨HC595£©¡£
Proteus仿真电路图
C语言源程序
下面是主程序文件£¬串口部分的程序代码与¡°中断结合串口¡±相同£¬所以省略¡£
#include <LPC21XX.H>
#include "uart0.h"
#define   HC595_CS     0x00000100/*P0.8口为第一个74HC595的片选*/
#define   HC595_CS2    0x00000200/*P0.9口为第二个74HC595的片选*/
#define   HC595_CS3    0x00000400/*P0.10口为第三个74HC595的片选*/
typedef unsigned int uint32;
typedef unsigned char uint8;
char status[] = "Everytnig is fine.";
uint8 const DISP_TAB[16]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E};
uint8 rcv_data;
void delay(void)  {                        
  unsigned volatile long i,j;
  for(i=0;i<10000;i++)
  for(j=0;j<30;j++)
  ;
}
void spiInit(void){
  S0SPCCR=0x52;/*设置SPI时钟分频*/
  S0SPCR=0x30;/*设置SPI接口模式*/
}
uint8 spiChar(uint8 data){
  IO0CLR=HC595_CS;/*SPI1片选*/
  S0SPDR=data;
  while(0==(S0SPSR&0x80));/*等待SPIF置位,即等待数据发送完毕*/
  IO0SET=HC595_CS;
  return(S0SPDR);
}
uint8 spi2Char(uint8 data){
  IO0CLR=HC595_CS2;/*SPI2片选*/
  S0SPDR=data;
  while(0==(S0SPSR&0x80));
  IO0SET=HC595_CS2;
  return(S0SPDR);
}
uint8 spi3Char(uint8 data){
  IO0CLR=HC595_CS3;/*SPI3片选*/
  S0SPDR=data;
  while(0==(S0SPSR&0x80));
  IO0SET=HC595_CS3;
  return(S0SPDR);
}
int  main(void){
  uint8 i;
  PINSEL0 = 0x00005505;/*引脚开SPI¡¢UART0*/              
  IO0DIR=HC595_CS|HC595_CS2|HC595_CS3;
  spiInit();/*初始化SPI接口*/
  uart0Init();
  while(1){
    for (i=0;i<16;i++) {
                            if(i<10){putchar(i+'0');}
                                          else{putchar(i+7+'0');}
                            rcv_data=spiChar(DISP_TAB[ i]);/*发送显示数据到数码显示管1*/
                            rcv_data=spi2Char(DISP_TAB[15-i]);/*数码显示管2*/
                            rcv_data=spi3Char(DISP_TAB[0]);/*数码显示管2*/
                            delay();
    }
              serialPuts(status);
  }
}
[ i]
11¡¢ADC数模转换¡ª¡ªARM的Proteus实验
实验原理
使用ARM微处理器内置的AD转换£¬将电压值转换为数字量后直接输出到串口UART0¡£
Proteus仿真电路图
C语言源程序
main.c
#include <LPC21XX.H>
#include "uart0.h"
typedef unsigned int uint32;
void delay(void)  {                        
  unsigned volatile long i,j;
  for(i=0;i<10000;i++)
  for(j=0;j<50;j++)
  ;
}
void adcRead (void) {                     
  unsigned int val;
  ADCR |= 0x01000000;/* 开始AD转换 */
  do {
    val = ADDR;/* 读取AD转换数据寄存器 */
  } while ((val & 0x80000000) == 0);/* 等待AD转换结束 */
  ADCR &= ~0x01000000;/* 结束AD转换 */
  val = (val >> 6) & 0x03FF;/* 设置数据格式并且按照16进制输出 */
  putstr ("\nAIN0 Result = 0x");         
  puthex((val >> 8) & 0x0F);               
  puthex((val >> 4) & 0x0F);               
  puthex (val & 0x0F);                     
}
int  main(void)
              {
              ADCR   = 0x002E0401;/* Setup A/D: 10-bit AIN0 @ 3MHz */
              PINSEL0 = 0x20000005;/*引脚选中EINT1功能,开串口UART0*/
              PINSEL1 = 0x00000001;/*引脚选中EINT0功能*/
              uart0Init();              
              while (1)  {              
                            adcRead();
                            delay();
              }  
}
uart0.c
#include <LPC21XX.H>
#include "uart0.h"
#define CR 0x0D
int putchar (int ch)  {/* 向串口输出一个×址û */
  if (ch == '\n')  {
    while (!(U0LSR & 0x20));
    U0THR = CR;
  }
  while (!(U0LSR & 0x20));
  return (U0THR = ch);
}
void serialPuts(char *p){/* 向串口输出×址û串 */
  while (*p != '\0'){
                putchar(*p++);
  }
  putchar('\n');
}
void uart0Init(void){
  U0LCR = 0x83;/* 8位数据£¬无效验£¬一个停止位 */
  U0DLL = 97;/* VPB 15MHz的时候波特率为9600 */
  U0LCR = 0x03;/* DLAB = 0 */
}                             
void puthex (int hex) {/* Write Hex Digit to Serial Port  */
  if (hex > 9) putchar('A' + (hex - 10));
  else         putchar('0' +  hex);
}
void putstr (char *p) {/* Write string */
  while (*p) {
    putchar(*p++);
  }
}


完整的Word格式文档51黑下载地址£º
菜鸟的ARM学习笔记proteus仿真.zip (183.92 KB, 下载´问ý: 30)
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|单片机论坛 |51Hei单片机16群 联系QQ:125739409;技术交流QQ群7344883

Powered by 单片机½坛Ì网

快速回复 返回顶部 返回列表
ÈÕ±¾Ò»¼¶‹hƬÈÕ±¾¸ßÇåÊÓƵ ÈÕ±¾±¾¸ßÇåÊÓƵɫÇéwww ÇéÂÂÈÕ±¾¸ßÇåÊÓƵ:É«Çé