ATMEL AVR微控制器的开发方案

发布者:epsilon15最新更新时间:2012-01-20 关键字:AVR微控制器  RISC寄存器 手机看文章 扫描二维码
随时随地手机看文章

微控制器开发团队与编译器开发人员的合作成果是生成的代码效率更高,性能更好。本文介绍的是为了使ATMEL AVR微控制器系列更适合C编译器,开发者在编译器开发阶段对微控制器架构和指令集所进行的调整。

AVR架构的核心是一个可快速访问RISC寄存器文件。该文件由32个8位通用寄存器构成。微控制器可在一个单时钟周期内加载该文件中的任意两个寄存器到算术逻辑单元(Arithmetic Logical Unit, ALU),完成所要求的操作,将结果写回到任意一个寄存器。ALU支持寄存器间或某一寄存器与一个常数之间的运算和逻辑功能,单寄存器操作也是在ALU中执行的。微控制器使用一个哈佛(Harvard)架构,在该架构中,程序存储器空间与数据存储器空间是相互隔离的。程序存储器采用单级管道访问技术,当一条指令被执行的同时,下一条指令已从程序存储器中被预先提取。由于其算术和逻辑操作都真正地在单周期内完成,因此AVR微控制器的性能达到每MHz一个MIPS。

图1 AVR 架构

细调微控制器
采用高级语言(High Level Languange, HLL)代替汇编语言来开发微控制器应用程序有许多优势,但一直都有一个重大缺点,即代码量不断增加。我们在开发AVR微控制器时考虑了使用C语言来开发应用,使得我们有可能为器件构建出一个高效C编译器。为了进一步提升这项特性,我们在AVR的架构和指令集未完成前就开始着手C编译器的开发。我们先让瑞典 IAR Systems的编译器专业开发人员对我们的AVR架构和指令集进行评测,最后开发出非常适合运行C编译器生成代码的微控制器。

寻址模式
为让编译器生成高效的代码,重要的是让寻址模式匹配C语言的需要。AVR架构原来配了两个指针寄存器(Pointer Register)。这两个指针可用于间接寻址、算后增量(post increment)间接寻址、算前减量(pre-decrement)间接寻址,以及带位移(displacement)的间接寻址,能够很好地支持指针操作。此外,还有一个用于访问数据存储器中变量的页面直接寻址模式。

指针位移
带位移的间接寻址是一种非常有用的寻址模式,即使从C编译器的角度亦如此。例如,将指针指向某一结构(struct)的第一个成员,就可以访问该结构内位移量所允许的其他任何位置,无须变更16位指针。带位移的间接寻址模式也常常用于访问软件堆栈上的变量。函数参数和autos常常放在软件堆栈上,这样,不用变更指针就可进行读写操作。位移寻址在定位数组成员(addressing elements in an array)时也非常有用。

尽管位移模式在许多情况下非常有用,但仍存在一个位移受限的问题。位移原本被限制在16个位置以内,而实际应用往往超出该数量。这样,在位移模式无法访问的位置,就必须加载一个新的指针。为扩展位移模式的访问范围,我们不得不改变指令集的其他部分,以获得足够的编码空间。同时,我们还得知,C编译器很难使用页面直接寻址模式。于是,取消了页面直接寻址模式,使用腾出的空间将位移模式扩展为64个位置,足以满足大多数间接寻址的要求。原来的页面直接寻址模式变成一个两个字长的非页面直接寻址模式。

存储器指针数
AVR微控制器原来配置了两个16位存储器指针。如要采用C编译器,那么其中一个指针必须专门用作软件堆栈,这样,就只剩一个存储器指针。在许多情况下,需要将存储器从一个区域复制到另一个区域。但由于只有一个指针,需要读1字节,设置指针,确定写入目标位置,写入这字节,然后再将指针设回数据源位置。如果增加第三个存储器指针(精简功能),完成存储器区域复制就不需要设置指针。如下例所示,只要使用算后增量间接寻址模式就可构建非常高效的存储器读写循环(假设:将指针Z指向源的第一字节,X指向目标的第一字节):

 LDI R16,0x60  ;Load byte count
loop:  LD R17,Z+  ;Load byte,    
 increment pointer
  ST X+,R17  ;Store  
 byte, increment pointer
  SUBI R16,1 ;Decrement
 counter
 BRNE loop ; Branch
 if more bytes
具备指针算后增量(post increment)、算前减量(pre-decrement) (+1、-1)操作的可能性对于实现堆栈也非常有效。这当然也可用于软件运行时间堆栈。

直接寻址
如在指针位移一节所述, AVR原来有一个页面直接寻址模式,但是,对于编译器该模式难于使用,且效率较低。由于我们需要更多的编码空间来增加位移量,因此取消了页面直接寻址模式。不过,如果完全没有直接寻址模式,代码效率也会降低,因为在有些情况下需要访问存放在数据存储器中的变量。尤其是处理静态字符时,代码开销将会很大(达到50%),因为静态变量必须保存在数据存储器中,不能自动放置到寄存器中。为了克服代码效率低下的问题,我们占用一个16位地址来增加一些非页面直接寻址指令。这样,就可用一条指令来完成64KB数据空间的寻址。要访问如此大的一个存储器区域,访问指令必须是两个16位字。

如果访问的字节数少(例如读取一个字符),使用这种寻址方式的效率高于指针方式。对于较大的区域,可能仍然是使用间接寻址比较有效(参见下面的示例)。

Loading of a character:
  Indirect addressing (6 Bytes):   Direct addressing (4 Bytes):
 LDI R30,LOW(CHARVAR)   LDS R16,CHARVAR
 LDI R31,HIGH(CHARVAR)
   LD R16, Z
Loading of a long integer:
 Indirect addressing (12 Bytes)   Direct addressing (16 Bytes)
 LDI R30,LOW(LONGVAR)   LDS R0,LONGVAR
 LDI R31,HIGH(LONGVAR)   LDS R1,LONGVAR+1
   LDD R0,Z     LDS R2,LONGVAR+2
   LDD R1,Z+1     LDS R3,LONGVAR+3
   LDD R2,Z+2
   LDD R3,Z+3

零标志传播
为实现条件转移,需要使用一些指令来操作由一些标志(flag)构成的AVR状态寄存器。跟在这类指令之后的条件转移指令(conditional branch instruction)是否执行转移,取决于这些标志的设置。使用运算指令操作这些标志,就可检查一个数A与另一个数B之间的大小关系。当被检查的数为8位的数时,不存在什么问题,因为所有标志都依赖一条指令设置的标志值。当被检查的数为16位或32位的数时(这在C语言中是常有的情况),问题就有点棘手了,例如一个32位减法操作就相当于要连续进行4个8位减法操作,而每做一次8位减法,就会产生一组新的标志。

为传播进位标志,大多数处理器都包含一些能处理进位标志先前设置值的指令。例如,带进位的减法(SBC)指令;执行SBC A,B语句就相当于将A变成进位位。但要正确完成所有的条件转移操作,这里还有另一个标志需要传播,即零标志。

示例:
   A=R3:R2:R1:R0,  
   B=R7:R6:R5:R4

我们打算从A中减去B,并如果A=B就跳转到一个指定位置。如果这个零标志只依赖于最后的运算指令,那么下面的指令将不会执行:


   SUB R0,R4
   SBC R1,R5
   SBC R2,R6
   SBC R3,R7  ; R3=R7
   => Zero flag set
   BREQ destination

这是因为BREQ指令使用的标志值只取决于最后的SBC指令设置的标志值。如果大多数高位直接相等,即便32位数不相等,零标志也将被置位,而转移也会被执行。这种问题也会出现在其他的条件转移上。

有两种办法可以解决这个问题。一是保存每个指令产生的标志,然后在第四个减法完成后检查所有的零标志。另一个更精细的方法是在进位指令中传播零标志(参见下面方式):

Znew =Not(R7) AND
   Not(R6) AND
   ...
   Not(R0) AND
   Zold

使用这种方式传播零标志,所有条件转移在最后一个减法操作完成后都会被执行,因为参与标志(溢出和正数标志)所剩部分只取决于最高位字节。

 

关键字:AVR微控制器  RISC寄存器 引用地址:ATMEL AVR微控制器的开发方案

上一篇:基于AVR单片机电风扇360度内摇头角度自由调节装置的实现
下一篇:在Proteus进行ICCAVR调试的方法

推荐阅读最新更新时间:2024-03-16 12:51

使用AVR单片机驱动舵机
1.舵机驱动的基本原理   (可以参考http://blog.sina.com.cn/s/blog_8240cbef01018hu1.html)    控制信号由接收机的通道进入信号调制芯片,获得直流偏置电压。它内部有一个基准电路,产生周期为20ms,宽度为1.5ms的基准信号,将获得的直流偏置电压与电位器的电压比较,获得电压差输出。最后,电压差的正负输出到电机驱动芯片决定电机的正反转。当电机转速一定时,通过级联减速齿轮带动电位器旋转,使得电压差为0,电机停止转动。 简单的来讲,就是输出一个周期为20Ms,不同的占空比对应舵机转过不同的角度。 难点主要在于 舵机控制信号需要保持,这样就比用脉冲控制步进电机要复杂一些。 你需要
[单片机]
使用<font color='red'>AVR</font><font color='red'>单片机</font>驱动舵机
单片机51到AVR程序的移植
将 C51 向 ICCAVR的转换进行一次总结 1、 头文件 对C51中定义寄存器的头文件如 reg51.h at89x51.h等替换成相应的 AVR头文件 如 io8515.h io2313.h等 2、 中断处理函数 在 C51 中以 interrupt 关键字来说明某一个函数为中断处理函数 在 ICCVAR 中可采用#pragma interrupt_handler预处理命令在程序开始处声明 具体用法如下: #pragma interrupt_handler 中断处理函数名 中断向量号 注意 对原 C51 源程序中的 interrupt 和 using关键字应当删除 3 、对 C51 中的 bit 和 sbit 数据
[单片机]
关于AVR单片机I/O口使用注意事项
1. 先正确设置DDRx方向寄存器,再进行I/O口的读写操作。 2. I/O口复位后的初始状态全部为输入工作方式,内部上拉电阻无效,外部引脚呈现三态高阻输入状态。 3. 当I/O口工作在输入方式时,且要读取外部引脚上的电平时,应读取PINxn的值,而不是PORTxn的值。 4. 当I/O工作在输入方式时,要根据实际情况使用或不使用内部的上拉电阻。 5. 一旦将I/O口的工作方式由输出设置成输入方式后,必须等待1个时钟周期后才能正确读到外部引脚PINxn的值。
[单片机]
为什么AVR单片机需要写1作为清0中断标志位
关于“为何AVR使用写1作为清0中断标志位的手段”这个问题我看过很多的相关资料。在AVR的手册中并没有给出为什么的解释,只是强调了“写1清0中断标志位”。同时我也看到很多新的芯片,如DSP等,也是采用写1清零标志位的。但没有找到更专业的,或从根源上的说明,如果那位有这方面的知识或资料,欢迎深入的讨论学习。 下面是我个人的分析和解释,供参考。 1、首先从硬件上的考虑,通常的读写处理单元是以8BIT字节为单位的,因为数据总线一般是8位的倍数。这样对位的操作就不方便,不能直接写1位(会改变其它的位),需要先读到寄存器,然后改动1位,最后回写,需要更多的时间。 2、对于RAM操作一般采用直接写的方式,所以对RAM基本上没有直接的位操作
[单片机]
为什么<font color='red'>AVR</font><font color='red'>单片机</font>需要写1作为清0中断标志位
avr单片机 Mega16定时器实验报告
1、实验目的 通过实验,掌握定时器的使用方法。着重掌握定时中断的使用! 2、实验内容 1 使用Mega16单片机的timer0产生1ms间隔的定时中断(建议采用application builder,既可以用Normal工作模式也可以使用CTC模式),(1)在定时中断中实现4位数码管的动态刷新。(2)在1ms的定时中断中设计100mS的时间标志位,在主程序中查询时间标志位,实现LED闪烁。 2 重新配置TImer0工作在PWM模式,用按键改变PWM的占空比,调节电机转速; 3、实验预习要求 仔细阅读教材中定时中断的范例; 4、实验步骤 1 启动ICCAVR,创建一个工程文件,配置timer0,实现10ms
[单片机]
<font color='red'>avr</font><font color='red'>单片机</font> Mega16定时器实验报告
avr单片机串口多机通讯及实例
在多机通信过程中,所有设备的 RS232接口是并在通信线上的,其中只能有一个设备为主机,其他为从机,通信由主机发起。数据帧一般采用1位起始位、9位数据位,其中第9位(RXB8)被用作为表征该帧是地址帧还是数据帧。当帧类型表征位为 1 时,表示该帧数据为一个地址帧;当帧类型表征位为 0 时,表示这个帧为一个数据帧。   在AVR中,通过设置从机的UCSRA寄存器中标志位MPCM,可以使能USART接收器对接收的数据帧进行过滤的功能。如果使能了过滤功能,从机接收器对接收到的那些不是地址信息帧的数据帧将进行过滤,不将其放入接收缓冲器中,这在多机通信中有效的方便了从机MCU处理数据帧程序的编写(同标准51 结构相比)。而发送器则不受MP
[单片机]
AVR单片机GCC编程:外部中断基本操作
#include avr/io.h #include avr/interrupt.h #include avr/signal.h int main(void) { MCUCR |= (1 ISC11); //INT1 下降沿触发 MCUCR |= ((1 ISC00) | (1 ISC01)); //INT0 上升沿触发 GICR |= ((1 INT1) | (1 INT0)); //INT0, INT1 使能 sei(); //全局中断使能SREG.I //中断发生时, 通用中断标志寄存器GIFR中相应INTF0,INTF1置位,时入中断服务程序后自动清零,也可以人为清零. } SIGNAL(SIG_INTERR
[单片机]
AVR单片机视觉智能寻迹车设计与实现
0 引 言 智能运输系统是未来交通运输系统发展的趋势,智能汽车在智能运输系统中扮演着十分重要的角色。作者提出智能寻迹车作为构建未来智能交通运输系统中重要部分,针对未来交通运输系统有导航线的环境命题假设下智能汽车的自主寻迹问题,提出一种基于视觉的智能寻迹车模设计方案,作为该假设问题的解决方案。 基于视觉的智能寻迹车模设计方案能够在线型复杂,转弯半径不确定性大的情况下,利用视觉自主寻迹前进,分级精确转向。 1 系统总体设计 基于视觉的智能寻迹车模系统以AVR单片机MEGAl6为核心,由单片机模块、路径识别模块、直流电机驱动模块、舵机驱动模块等组成,如图1所示。 直流电动机为车辆的驱动装置,转向电动机用于控
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
  • ARM裸机篇--按键中断
    先看看GPOI的输入实验:按键电路图:GPF1管教的功能:EINT1要使用GPF1作为EINT1的功能时,只要将GPFCON的3:2位配置成10就可以了!GPF1先配 ...
  • 网上下的--ARM入门笔记
    简单的介绍打今天起菜鸟的ARM笔记算是开张了,也算给我的这些笔记找个存的地方。为什么要发布出来?也许是大家感兴趣的,其实这些笔记之所 ...
  • 学习ARM开发(23)
    三个任务准备与运行结果下来看看创建任务和任运的栈空间怎么样的,以及运行输出。Made in china by UCSDN(caijunsheng)Lichee 1 0 0 ...
  • 学习ARM开发(22)
    关闭中断与打开中断中断是一种高效的对话机制,但有时并不想程序运行的过程中中断运行,比如正在打印东西,但程序突然中断了,又让另外一个 ...
  • 学习ARM开发(21)
    先要声明任务指针,因为后面需要使用。 任务指针 volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • 学习ARM开发(20)
  • 学习ARM开发(19)
  • 学习ARM开发(14)
  • 学习ARM开发(15)
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved