2018年10月

硬件电路设计

电路图如下:
Annotation.png
(在线电路图绘制安利:https://lceda.cn/editor
当电压U1大于电压U2 1V以上时,二极管导通发光。当导通电流大于5mA时,人的眼睛就可以明显观察到二极管的发光,导通电流越大,亮度越高。一般导通电流不要超过10mA,否则将导致二极管的烧毁或I/O引脚的烧毁。因此在设计硬件电路时,要在LED二极管电路中串接一个限流电阻,阻值在300Ω~1kΩ之间,调节阻值的大小可以控制发光二极管的发光亮度。
导通电流与限流电阻之间的关系由下面的计算公式确定:

I=\frac{U_1-U_2-V_{LED}}{R}

式中VLED为LED的导通电压。
由于AVR的I/O口输出“0”时,可以吸收最大40mA的电流,因此采用控制发光二极管负极的设计比较好。8个LED发光二极管控制系统的硬件电路如下所示。图中ATmega16的PA口工作在输出方式下,8个引脚分别控制8个发光二极管。当I/O口输出“0”时,LED导通发光;输出“1”时,LED截止熄灭。
Annotation.png
(话说没找到怎么在输入文本的时候正确输入单位,直接输入Ω的话会丢失,粗略看了下文档貌似没看到)
(画个图还是有点花时间,细节多)

软件设计

下面的程序代码的功能是8个LED逐一循环发光1s,构成走马灯。

/******
File name            :demo_6_1.c
Chip type            :ATmega16
Program type         :Application
Clock frequency      :4.000000MHz
Memory model         :Small
External SRAM size   :0
Data Stack size      :256
******/
#include<mega16.h>
#include<delay.h>

void main(void)
{
    unsigned char position = 0;        //position为控制位的位置
    PORTA = 0xFF;                      //PA口输出全“1”,LED全灭
    DDRA = 0xFF;                       //PA口工作为输出方式

    while(1)
    {
        PORTA = ~(1 << position);      //1左移0次、1次、...、7次,逐位非传给PORTA
        if(++position >= 8) position = 0;//8个灯(位置)依次点亮
        delay_ms(1000);                //延迟1000ms
    };
}

思考与实践

Q:调整程序中的delay_ms(),延时时间为1ms,彩灯的闪亮有何变化?为什么?
A:彩灯看起来不会闪亮,而是一直保持亮着。因为延时时间过短,闪亮的频率太高,以至于人眼无法分辨彩灯是不是熄灭过。一般来说人眼能分辨的能力是1000ms/24帧,也就是大概需要长达每40ms熄灭一次,人眼才能看得出彩灯(单个)在闪烁。

Q:计算并验证当延时小于多少ms时,“走马灯”的效果会变成“全亮”?给出计算方法。
A:按照实际研究,延时大约小于40ms/8(灯轮流点亮),即小于5ms时就会是“全亮”的效果。验证的方法可以通过更改程序延时,运行程序实际观察可以看出。

Q:设计一个4种闪烁方式交替循环的彩灯,闪烁方式如下:

  1. 8个LED灯逐一点亮0.5s,左移循环2轮(16次),控制初值=0b11111110
  2. 8个LED灯逐一点亮0.5s,右移循环2轮(16次),控制初值=0b01111111
  3. 8个LED灯逐一点亮0.5s,明暗交替16次,控制初值=0b10101010
  4. 8个LED灯随机点亮,每次0.5s,共16次,控制初值=随机数
  5. 再次从头循环

A:主程序代码如下:

#include<mega16.h>
#include<delay.h>

void light_1(unsigned char position)
{
    while(i <= 2)
    {
        PORTA = 0xFF << position;
        if(++position >= 8)
            {
                position = 0;
                i++;
            }
        delay_ms(500);
    };
}

void light_2(unsigned char position)
{
    i = 0;
    while(i <= 2)
    {
        PORTA = 0xFF >> position;
        if(++position >= 8)
            {
                position = 0;
                i++;
            }
        delay_ms(500);
    };
}

void light_3(void)
{
    i = 0;
    while(i <= 16)
    {
        if(++i % 2)
            {
                PORTA = 0x55;
            }
        else
            {
                PORTA = 0xAA;
            }
        delay_ms(500);
    };
}

void light_4(void)
{
    i = 0;
    while(i <= 16)
    {
        PORTA = rand() % (256) + 0;
        i++;
        delay_ms(500);
    };
}

void main(void)
{
    unsigned char position = 0;        //position为控制位的位置
    PORTA = 0xFF;                      //PA口输出全“1”,LED全灭
    DDRA = 0xFF;                       //PA口工作为输出方式
    int i = 0;
    while(1)
    {
        light_1(position);
        light_2(position);
        light_3();
        light_4();
    }
}

I/O口的基本结构

AVR单片机每组I/O口配备3个8位寄存器,它们分别是方向控制寄存器DDRx、数据寄存器PORTx和输入引脚寄存器PINx(x=A/B/C/D)。
DDRx=1时,I/O口处于输出工作方式。此时数据寄存器PORTx中的数据通过一个推挽电路输出到外部引脚。
AVR的输出采用推挽电路是为了提高I/O口的输出能力,当PORTx=1时,I/O口引脚呈现高电平,同时可提供输出20mA的电流;而当PORTx=0时,I/O引脚呈现低电平,同时可吸纳20mA电流。
当DDRx=0时,I/O口处于输入工作方式。此时引脚寄存器的PINx中的数据就是外部引脚的实际电平(PINx的读取最好是等待一个时钟读取,读取PORTx的值无法得到外部引脚电平,不要搞混),通过读I/O指令可将物理引脚的真实数据读入MCU。此外,当I/O口定义为输入时,通过PORTx的控制,可使用或不使用内部的上拉电阻。

DDRXnPORTXnPUDI/O方式内部上拉电阻引脚状态说明
00X输入无效三态(高阻)
01/00输入有效/无效有效时外部引脚拉低输出电流(μA)
0X1输入无效三态(高阻)
10X输出无效推挽0输出,吸收电流(20mA)
11X输出无效推挽1输出,输出电流(20mA)

表中的PUD为寄存器SFIOR中的一位,它的作用相当于AVR全部I/O口内部上拉电阻总开关。
当PUD=1时,AVR所有I/O内部上拉电阻都不起作用;
当PUD=0时,各个I/O口内部上拉电阻取决于PORTn的设置。
AVR通用I/O口的主要特点如下:

  • 双向可独立位控的I/O口。ATmega16的PA、PB、PC、PD 4个接口都是8位双向I/O口,每一位引脚都可以单独进行定义,相互不受影响。
  • Push-Pull大电流驱动(最大40mA)。每个I/O口输出方式均采用推挽式缓冲器输出,提供大电流的驱动,可以输出(吸入)20mA的电流,因而能直接驱动LED显示器。
  • 可控制的引脚内部上拉电阻。每一位引脚内部都有独立的、可通过编程设置的,设定为上拉有效或无效的内部上拉电阻。当I/O口用于输入状态,且内部上拉电阻激活(有效)时,如果外部引脚被拉低,则构成电流源输出电流(μA量级)。
  • DDRx可控的方向寄存器。

I/O接口寄存器

ATmega16的4个8位接口都有各自对应的3个I/O口寄存器,它们占用了I/O空间的12个地址。

名称I/O空间地址RAM地址作用
PORTA$1B0x003BA口数据寄存器
DDRA$1A0x003AA口方向寄存器
PINA$190x0039A口输入引脚寄存器
PORTB$180x0038B口数据寄存器
DDRB$170x0037B口方向寄存器
PINB$160x0036B口输入引脚寄存器
PORTC$150x0035C口数据寄存器
DDRC$140x0034C口方向寄存器
PINC$130x0033C口输入引脚寄存器
PORTD$120x0032D口数据寄存器
DDRD$110x0031D口方向寄存器
PIND$100x0030D口输入引脚寄存器

PORTx支持读和写,复位后默认为0;
DDRx支持读和写,复位后默认为0;
PINx支持读,没有默认值(本身用于读取外部电压的);

注意:

  • 使用AVR的I/O口要注意,要先正确设置DDRx方向寄存器,再进行I/O口的读/写操作。
  • AVR的I/O口复位后的初始状态全部为输入工作方式,内部上拉电阻无效。因此,外部引脚呈现三态高阻输入状态。
  • 用户程序首先需要对要使用的I/O口进行初始化设置,然后根据实际需要设定使用I/O口的工作方式。放设定为输入方式时,还要考虑是否使用上拉电阻。
  • 在硬件电路设计时,如果利用AVR内部I/O的上拉电阻,则可节省外部的上拉电阻。

通用数字I/O接口的设置与编程

在AVR汇编指令系统中,直接用于对I/O寄存器的操作指令有以下3类,全部为单周期指令:

  • IN/OUT指令:实现了32个通用寄存器与I/O寄存器之间的数据交换,格式为:
IN Rd,A     ;从I/O寄存器A读取数据到通用寄存器Rd
OUT A,Rr    ;通用寄存器Rr数据送I/O寄存器A
  • SBI/CBI指令:实现了对I/O寄存器中指定位的置1或清0,格式为:
SBI A,b    ;将I/O寄存器A的第b位置1
CBI A,b    ;将I/O寄存器A的第b位清0
  • SBIC/SBIS指令:为转移类指令,它根据I/O寄存器中指定位的数值实现跳行转移,格式为:
SBIC A,b    ;I/O寄存器A的第b位为0时,跳行执行
SBIC A,b    ;I/O寄存器A的第b位为1时,跳行执行

汇编语言语句格式

汇编语言程序是由一系列汇编语句组成的。AVR的汇编语句的标准格式有以下4种:

  • [标号:]伪指令[操作数][;注释]
  • [标号:]指令[操作数][;注释]
  • [;注释]
  • 空行

括号部分表示可以缺省

  1. 标号。标号是语句地址的标记符号,用于引导对该语句的访问和定位。使用标号的目的是为了跳转和分支指令,以及在程序存储器、数据存储器SRAM和EEPROM中定义变量名。

    • 标号一般由ASCII字符组成,第一个字符为字母;
    • 同一标号在一个独立的程序中只能定义一次;
    • 不能使用汇编语言中已定义的符号(保留字),如指令字、寄存器名、伪指令等等。
  2. 伪指令。伪指令不属于CPU指令集,编译时并不产生实际的目标机器操作代码,只是用于在汇编程序中对地址、寄存器、数据、常量等进行定义说明,以及对编译过程进行某种控制。
  3. 指令。指令是汇编程序中主要的部分,汇编程序中使用AVR指令集中的全部指令。
  4. 操作数。集指令操作时所需要的数据或地址。就是指令。操作时所需要的数据和地址。汇编程序完全支持指令系统所定义的操作数格式。但指令系统采用的操作数格式通常为数字形式,在编写程序时使用起来不太方便,因此,在编译器的支持下,可以使用多种形式的操作数,如数字、标识符、表达式等。
  5. 注释。注释部分仅用于对程序和语句进行说明,帮助程序设计人员阅读、理解和修改程序。注释内容长度不限,换行时也需要分号。
  6. 其他字符。在汇编语句中,“;”用于标号之后;空格用于指令字和操作数的分隔;指令有两个操作数时用“,”分隔两个操作数;“;”用于注释之前;“[]”中的内容表示可选项。

汇编器伪指令

AVR汇编系统使用的伪指令有18条:

序号伪指令说明
1BYTE在RAM中定义预留存储单元
2CSEG声明代码段
3DB定义字节常数
4DEF定义寄存器富符号名
5DEVICE指定为何器件生成汇编代码
6DSEG声明数据段
7DW定义字常数
8EQU定义标识符常量
9ESEG声明EEPROM段
10EXIT退出文件
11INCLUDE包含指定的文件
12MACRO宏定义开始
13ENDMACRO宏定义结束
14LISTMAC列表宏表达式
15LIST列表文件生成允许器
16NOLIST关闭列表文件生成
17ORG设置程序起始位置
18SET赋值给标识符

表达式

  • 操作数

    • 用户定义的标号,该标号给出了放置标号位置的定位计数器的值。
    • 用户用SET伪指令定义的变量
    • 用户用EQU伪指令定义的常数
    • 整数常数(比如十进制、十六进制、二进制数)
    • PC——程序存储器定位计数器当前的值
  • 函数

    • LOW(表达式) 返回一个表达式值的最低字节
    • HIGH(表达式) 返回一个表达式值的第2个字节
    • BYTE2(表达式) 与HIGH函数相同
    • BYTE3(表达式) 返回一个表达式值的第3个字节
    • BYTE4(表达式) 返回一个表达式值的第4个字节
    • LWRD(表达式) 返回一个表达式值的0~15位
    • HWRD(表达式) 返回一个表达式值的16~31位
    • PAGE(表达式) 返回一个表达式值的16~21位
    • EXP2(表达式) 返回一个表达式值2次幂的值
    • LOG2(表达式) 返回log2(表达式值)的整数部分
  • 运算符
    部分运算符如下表,优先级数越高的运算符,其优先级也越高,表达式可以用小括号括起来,并且与括号外其他任意的表达式再组合成表达式。
序号运算符名称优先级说明
1!逻辑非14一元运算符,表达式是0返回1;表达式是返回0
2~逐位非14一元运算符,将表达式的值按位取反
3-负号14一元运算符,使表达式为算术负
4*乘法13二进制运算符,两个表达式相乘
5/除法13二进制运算符,左边表达式除以右边表达式,得整数的商值
6+加法12二进制运算符,两个表达式相加
7-减法12二进制运算符,左边表达式减去右边表达式
8<<左移11二进制运算符,左边表达式值左移右边表达式所给出的次数
9>>右移11二进制运算符,左边表达式值右移右边表达式所给出的次数
10<小于10二进制运算符,左边带符号表达式值小于右边带符号表达式值,则为1;否则为0
11<=小于等于10二进制运算符,左边带符号表达式值小于或等于右边带符号表达式值,则为1;否则为0
12>大于10二进制运算符,左边带符号表达式值大于右边带符号表达式值,则为1;否则为0
13>=大于等于10二进制运算符,左边带符号表达式值大于或等于右边带符号表达式值,则为1;否则为0
14==等于9二进制运算符,左边带符号表达式值等于右边带符号表达式值,则为1;否则为0
15!=不等于9二进制运算符,左边带符号表达式值不等于右边带符号表达式值,则为1;否则为0
16&逐位与8二进制运算符,两个表达式之间逐位与
17^逐位异或7二进制运算符,两个表达式之间逐位异或
18|逐位或6二进制运算符,两个表达式之间逐位或
19&&逻辑与5二进制运算符,两个表达式之间逻辑与,全非0则为1;否则为0
20||逻辑或4二进制运算符,两个表达式之间逻辑或,非0则为1;全0则为0

器件定义头文件m16def.inc

略...

带进位逻辑操作指令

  • 寄存器逻辑左移
LSL Rd    0≤d≤31
说明:寄存器Rd中所有位左移1位,第0位清0,第7位移到SREG中的C标志位。该指令完成一个无符号数乘以2的操作。
操作:C←b7b6b5b4b3b2b1b0←0    PC←PC+1
  • 寄存器逻辑右移
LSR Rd    0≤d≤31
说明:寄存器Rd中所有位右移1位,第7位清0,第0位移到SREG中的C标志位。该指令完成一个无符号数除以2的操作,C标志用于结果舍入。
操作:C→b7b6b5b4b3b2b1b0→0    PC←PC+1
  • 带进位位的寄存器逻辑循环左移
ROL Rd    0≤d≤31
说明:寄存器Rd的所有位左移1位,C标志被移到Rd的第0位,Rd的第7位移到C标志位。
操作:C←b7b6b5b4b3b2b1b0←C    PC←PC+1
  • 带进位位的寄存器逻辑循环右移
ROR Rd    0≤d≤31
说明:寄存器Rd的所有位右移1位,C标志被移到Rd的第7位,Rd的第0位移到C标志位。
操作:C→b7b6b5b4b3b2b1b0→C    PC←PC+1
  • 寄存器算术右移
ASR Rd    0≤d≤31
说明:寄存器Rd的所有位右移1位,而第7位保持原逻辑值,第0位装入SREG的C标志位。这个操作实现2的补码值除以2,而不改变符号,进位标志用于结果的舍入。
操作:b7→b7b6b5b4b3b2b1b0→C    PC←PC+1
  • 寄存器半字节交换
SWAP Rd    0≤d≤31
说明:寄存器Rd的高半字节与低半字节交换。
操作:b7b6b5b4←→b3b2b1b0    PC←PC+1

位变量传送指令

  • 寄存器中的位存储到SREG中的T标志
BST Rr,d    0≤d≤31,0≤b≤7
说明:把寄存器Rr中的位b存储到SREG状态寄存器中的T标志位。
操作:T←Rr(b)    PC←PC+1
  • SREG中的T标志位值装入寄存器Rd中的某一位
BLD Rd,b    0≤d≤31,0≤b≤7
说明:复制SREG状态寄存器的T标志到寄存器Rd中的位b。
操作:Rr(b)←T    PC←PC+1

位变量修改指令

  • 状态寄存SREG的指定位置位
BSET s    0≤s≤7
说明:置位状态寄存器SREG的某一位标志。
操作:SREG(s)←1    PC←PC+1
  • 状态寄存SREG的指定位清0
BCLR s    0≤s≤7
说明:清0状态寄存器SREG的某一位标志。
操作:SREG(s)←0    PC←PC+1
  • I/O寄存器的指定位置位
SBI P,b    0≤P≤31,0≤b≤7
说明:对P指定的I/O寄存器的指定位置位。该指令只在32个I/O寄存器内操作,I/O寄存器地址为0~31。
操作:I/O(P,b)←1    PC←PC+1
  • I/O寄存器的指定位清0
CBI P,b    0≤P≤31,0≤b≤7
说明:对P指定的I/O寄存器的指定位清0。该指令只在32个I/O寄存器内操作,I/O寄存器地址为0~31。
操作:I/O(P,b)←0    PC←PC+1
  • 置进位位
SEC
说明:置位SREG状态寄存器中的进位标志C。
操作:C←1    PC←PC+1
  • 清进位位
CLC
说明:清0 SREG状态寄存器中的进位标志C。
操作:C←0    PC←PC+1
  • 置负标志位
SEN
说明:置位SREG状态寄存器中的负数标志N。
操作:N←1    PC←PC+1
  • 清负标志位
CLN
说明:清0 SREG状态寄存器中的负数标志N。
操作:N←0    PC←PC+1
  • 置零标志位
SEZ
说明:置位SREG状态寄存器中的零标志Z。
操作:Z←1    PC←PC+1
  • 清零标志位
CLZ
说明:清0 SREG状态寄存器中的零标志Z。
操作:Z←0    PC←PC+1
  • 使能全局中断位
SEI
说明:置位SREG状态寄存器中的全局中断标志I。
操作:I←1    PC←PC+1
  • 禁止全局中断位
CLI
说明:清0 SREG状态寄存器中的全局中断标志I。
操作:I←0    PC←PC+1
  • 置S标志位
SES
说明:置位SREG状态寄存器中的符号标志S。
操作:S←1    PC←PC+1
  • 清S标志位
CLS
说明:清0 SREG状态寄存器中的符号标志S。
操作:S←0    PC←PC+1
  • 置溢出标志位
SEV
说明:置位SREG状态寄存器中的溢出标志V。
操作:V←1    PC←PC+1
  • 清溢出标志位
CLV
说明:清0 SREG状态寄存器中的溢出标志V。
操作:V←0    PC←PC+1
  • 置T标志位
SET
说明:置位SREG状态寄存器中的T标志。
操作:T←1    PC←PC+1
  • 清T标志位
CLT
说明:清0 SREG状态寄存器中的T标志。
操作:T←0    PC←PC+1
  • 置半进位标志
SEH
说明:置位SREG状态寄存器中的半进位标志H。
操作:H←1    PC←PC+1
  • 清半进位标志
CLH
说明:清0 SREG状态寄存器中的半进位标志H。
操作:H←0    PC←PC+1

MCU控制指令

  • 空操作指令
NOP
说明:该指令完成一个周期空操作
操作:无
  • 进入休眠方式指令
SLEEP
说明:该指令使MCU进入休眠方式运行。休眠模式由MCU控制寄存器定义。当MCU在休眠状态下由一个中断唤醒时,在中断程序执行后,紧跟在休眠指令后的指令将被执行。
操作:PC←PC+1
  • 清0看门狗计数器
WDR
说明:该指令清0看门狗定时器。在允许使用看门狗定时器情况下,系统程序在正常运行中必须在WD预定比例器给出的限定时间内执行一次该指令,以防止看门狗定时器溢出,造成系统复位。
操作:PC←PC+1

直接寻址数据传送指令

  • 工作寄存器间传送数据
MOV Rd,Rr    0≤d≤31,0≤r≤31
说明:该指令将一个寄存器内容送到另一个寄存器中,源寄存器的Rr的内容不改变,而目的寄存器Rd复制了Rr的内容。
操作:Rd←Rr    PC←PC+1
  • SRAM数据直接送寄存器
LDS Rd,K    0≤d≤31,0≤k≤65535
说明:把SRAM中一个存储单元的内容(字节)装入到寄存器中,其中k为该存储单元的16位地址。
操作:Rd←(k)    PC←PC+2
  • 寄存器数据直接送SRAM
STS k,Rr    0≤r≤31,0≤k≤65535
说明:将寄存器的内容直接存储到SRAM中,其中k为存储单元的16位地址。
操作:k←(Rd)    PC←PC+1
  • 立即数送寄存器
LDI Rd,k    16≤r≤31,0≤k≤255
说明:将一个8位立即数传送到寄存器R16~R31中。
操作:Rd←k    PC←PC+1
  • 寄存器字复制(扩展指令,仅部分AVR芯片支持,ATmega16支持该指令)
MOVM Rd+1;Rd←Rr+1    PC←PC+1
说明:将一个寄存器对的内容复制到另一个寄存器对中(16位传送)

间接寻址数据传送指令

使用X指针寄存器间接寻址传送数据

  • 使用地址指针寄存器X间接寻址将SRAM内容装入到指定寄存器
1) LD Rd,X    0≤d≤31
说明:将指针为X的SRAM中的数送寄存器,指针不变。
操作:Rd←(X)    PC←PC+1
2) LD Rd,X+    0≤d≤31
说明:先将指针为X的SRAM中的数送寄存器,然后X指针加1。
操作:Rd←(X),X←X+1    PC←PC+1
1) LD Rd,-X    0≤d≤31
说明:X指针减1,将指针为X的SRAM中的数送寄存器。
操作:X←X-1,Rd←(X)    PC←PC+1
  • 使用地址指针寄存器X间接寻址将SRAM内容存储到SRAM
1) ST X,Rr    0≤d≤31
说明:将寄存器内容送X为指针的SRAM中,X的指针不变。
操作:(X)←Rr    PC←PC+1
2) ST X+,Rr    0≤d≤31
说明:先将寄存器内容送X为指针的SRAM中,然后X指针加1。
操作:(X)←Rr,X←X+1    PC←PC+1
3) ST -X,Rr    0≤d≤31
说明:X指针减1,将寄存器内容送指针为X的SRAM中。
操作:X←X-1,(X)←Rr    PC←PC+1

使用Y指针寄存器间接寻址传送数据

  • 使用地址指针寄存器Y间接寻址将SRAM中的内容装入寄存器
1) LD Rd,Y    0≤d≤31
说明:将指针为Y的SRAM中的数送寄存器,Y指针不变。
操作:Rd←(Y)    PC←PC+1
2) LD Rd,Y+    0≤d≤31
说明:先将指针为Y的SRAM中的数送寄存器,然后Y指针加1.
操作:Rd←(Y),Y←Y+1    PC←PC+1
3) LD Rd,-Y    0≤d≤31
说明:先将Y指针减1,然后将指针为Y的SRAM中的数送寄存器。
操作:Y←Y-1,Rd←(Y)    PC←PC+1
4) LDD Rd,Y+q    0≤d≤31,0≤q≤63
说明:将指针为Y+q的SRAM中的数送寄存器,Y指针保持不变。
操作:Rd←(Y+q)    PC←PC+1
  • 使用地址指针寄存器Y的间接寻址将寄存器内容存储到SRAM
1) ST Y,Rr    0≤d≤31
说明:将寄存器内容送指针为Y的SRAM中,Y指针不变。
操作:(Y)←Rr    PC←PC+1
2) ST Y+,Rr    0≤d≤31
说明:先将寄存器内容送指针为Y的SRAM中,然后Y指针加1。
操作:(Y)←Rr,Y←Y+1    PC←PC+1
3) ST -Y,Rr    0≤d≤31
说明:先将Y指针减1,然后将寄存器内容送指针为Y的SRAM中。
操作:Y←Y-1,(Y)←Rr    PC←PC+1
4) STD Y+q,Rr    0≤d≤31,0≤q≤63
说明:将寄存器内容送指针为Y+q的SRAM中。
操作:(Y+q)←Rr    PC←PC+1

使用Z指针寄存器间接寻址传送数据

  • 使用地址指针寄存器Z间接寻址将SRAM中的内容装入到指定寄存器
1) LD Rd,Z    0≤d≤31
说明:将指针为Z的SRAM中的数送寄存器,Z指针不变。
操作:Rd←(Z)    PC←PC+1
2) LD Rd,Z+    0≤d≤31
说明:先将指针为Z的SRAM中的数送寄存器,然后Z指针加1.
操作:Rd←(Z),Z←Z+1    PC←PC+1
3) LD Rd,-Z    0≤d≤31
说明:先将Z指针减1,然后将寄存器内容送指针为Z的SRAM中。
操作:Z←Z-1,(Z)←Rr    PC←PC+1
4) LDD Rd,Z+q    0≤d≤31,0≤q≤63
说明:将指针为Z+q的SRAM中的数送寄存器,Z指针保持不变。
操作:Rd←(Z+q)    PC←PC+1
  • 使用地址指针寄存器Z的间接寻址将寄存器内容存储到SRAM
1) ST Z,Rr    0≤d≤31
说明:将寄存器内容送指针为Z的SRAM中,Z指针不变。
操作:(Z)←Rr    PC←PC+1
2) ST Z+,Rr    0≤d≤31
说明:先将寄存器内容送指针为Z的SRAM中,然后Z指针加1。
操作:(Z)←Rr,Z←Z+1    PC←PC+1
3) ST -Z,Rr    0≤d≤31
说明:先将Z指针减1,然后将寄存器内容送指针为Z的SRAM中。
操作:Z←Z-1,(Z)←Rr    PC←PC+1
4) STD Z+q,Rr    0≤d≤31,0≤q≤63
说明:将寄存器内容送指针为Z+q的SRAM中。
操作:(Z+q)←Rr    PC←PC+1

从程序存储器中取数装入寄存器指令

  • 从程序存储器中取数装入寄存器R0
LPM
说明:将Z指向的程序存储器空间的1字节装入寄存器R0
操作:R0←(Z)    PC←PC+1
  • 从程序存储器中取数装入寄存器Rd
LPM Rd,Z    0≤d≤31
说明:将Z指向的程序存储器空间的1字节装入寄存器Rd
操作:Rd←(Z)    PC←PC+1
  • 带后增量的从程序存储器中取数装入寄存器Rd
LPM Rd,Z+    0≤d≤31
说明:将Z指向的程序存储器空间的1字节装入寄存器Rd
操作:Rd←(Z),Z←Z+1    PC←PC+1
  • 从程序存储器中取数装入寄存器R0(扩展指令,仅部分AVR芯片支持,ATmega16不支持该指令)
ELPM
说明:将RAMPZ:Z指向的程序存储器空间的1字节装入寄存器R0
操作:R0←(RAMPZ:Z)    PC←PC+1
  • 从程序存储器中取数装入寄存器(扩展指令,仅部分AVR芯片支持,ATmega16不支持该指令)
ELPM Rd,Z    0≤d≤31
说明:将RAMPZ:Z指向的程序存储器空间的1字节装入寄存器Rd
操作:Rd←(RAMPZ:Z)    PC←PC+1
  • 带后增量的从程序存储器中取数装入寄存器(扩展指令,仅部分AVR芯片支持,ATmega16不支持该指令)
ELPM Rd,Z+    0≤d≤31
说明:将RAMPZ:Z指向的程序存储器空间的1字节装入寄存器Rd,然后RAMPZ:Z指针加1。
操作:Rd←(RAMPZ:Z)    RAMPZ:Z←RAMPZ:Z+1    PC←PC+1

写程序存储器指令

  • 写程序存储器
SPM
说明:将寄存器R1:R0的内容(16位字)写入Z指向的程序存储器空间。
操作:(Z)←R1:R0    PC←PC+1

I/O口数据传送指令

  • I/O口数据装入寄存器
IN Rd,P    0≤d≤31,0≤P≤63
说明:将I/O空间(端口、定时器、配置寄存器等)的数据传送到寄存器区中的寄存器Rd中。
操作:Rd←P    PC←PC+1
  • 寄存器数据送I/O口
OUT P,Rr    0≤r≤31,0≤P≤63
说明:将寄存器区中Rr的数据传送到I/O空间(端口、定时器、配置寄存器等)。
操作:P←Rr    PC←PC+1

堆栈操作指令

  • 进栈指令
PUSH Rr    0≤d≤31
说明:该指令存储寄存器Rr的内容到堆栈。
操作:STACK←Rr,SP←SP-1    PC←PC+1
  • 出栈指令
POP Rd    0≤d≤31
说明:该指令将堆栈中的字节装入到寄存器Rd中。
操作:SP←SP+1,Rd←STACK    PC←PC+1