打印
[PIC®/AVR®/dsPIC®产品]

AVR 8位单片机汇编——GPIO操作

[复制链接]
742|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 JackTang1994 于 2022-1-13 09:43 编辑

#技术资源# #申请原创#

要求:最好有学习过C语言

AVR汇编器使用文档:https://ww1.microchip.com/downloads/en/DeviceDoc/40001917A.pdf
AVRASM2汇编器下载:http://www.vfx.hu/avr/download/avrasm2.zip
AVR指令集文档:https://www.microchip.com/DS40002198
ATmega4809 Curiosity Nano开发板:https://ww1.microchip.com/downloads/en/DeviceDoc/ATmega4809_Curiosity_Nano_Schematics.pdf

软件环境:MPLAB X IDE v5.5,AVRSAM2汇编器
硬件环境:ATmega4809 Curiosity Nano开发板

汇编文件组成
伪指令:操作汇编器的指令,不会被编译到代码中
代码指令:操作MCU的指令,真正执行的代码。
注释:注释符号有";",有些汇编器支持"//"和"/**/"
符号标签:用于标识地址,类似于C语言中的函数名
以下代码为一个完整的汇编示例,包含上述所列的部分
.include <m4809def.inc>

Start_main:   
   
    ldi r23, 0x20 ; Toogle PF5
    out PORTF_OUTTGL, r23

    rjmp Start_main  

什么是伪指令?
答:伪指令,其实不是汇编指令编译后不会被编译成代码。它是用来指导汇编器进行汇编操作的,不同的汇编器使用的伪指令不一样。
什么是指令?
答:指令就是实实在在的代码程序,用于操作处理器(MCU)的。

汇编指令类型
数据传输(内存操作):数据读取,外设操作
程序流程操作(跳转指令):函数调用、跳转等
逻辑、算术运算:+、-、*、/和与、或、非、异或等运算
位操作:左移、右移等操作MCU操作指令:BREAK、NOP等
具体的指令说明需要查看AVR指令集文档

汇编文件格式
*.asm、*.s、*.S、*.850、*.v800等

汇编与C语言区别?
答:汇编代码执行速度快和具体芯片内核有关,不同的芯片内核所使用的汇编指令不同。汇编代码运行环境简单,占用空间少,移植性差。
C语言移植性好与具体的芯片内核无关,易于阅读,占用空间比汇编大些,C语言运行需要相关环境(最简单需要栈空间,复杂的需要堆以及库函数等).汇编语言对硬件的操作性是最灵活的可以任意操作硬件。汇编语言一般用于MCU底层的开发如:启动代码、操作系统底层实现等。C语言可移植性好,一般用于外设驱动的开发如:串口、SPI、网口、USB等驱动。

先不讲AVR的指令集,而是通过一个具体的实例来解释。这样应该更容易让人接受,好的接下来就开始写代码。  
程序的主流程很简单:每隔0.5秒翻转一次LED引脚的电平。


程序比较完整的流程图:延时0.5秒的代码分成了两层循环,因为一层循环延时时间不够。



C语言实现
#include <iom4809.h>

int main(void)
{
    uint16_t i = 1000;
    uint8_t j = 100;

    PORTF_DIR = 0x20;

    while(1)
    {
        PORTF_OUTTGL = 0x20;
        j = 100;
        while(j--)
        {
            i = 1000;
            while(i--);
        }
    }  
}

将C语言转换成汇编实现
从上面C语言代码中,我们可以得到"循环"、”条件判断“、”变量名定义“等部分,而汇编与之对应的指令分别如下:


循环:使用跳转指令和标签
条件判断:使用带条件跳转指令、状态寄存器、标签
变量名定义:使用.def汇编伪指令、普通寄存器
具体代码实现如下:
    ; code by jack
    .include <m4809def.inc>        ; 包含ATmega4809头文件。头文件路径可以从我上一篇**了解,可以使用文本编辑工具打开它查看里面的内容。
   
    ; default system clock : 20/6 = 3.333MHZ ATmega4809芯片默认的时钟为内部20MHZ,默认分频系数为6
   
    ; .def汇编器伪指令。此处用于定义寄存器的别名,后续可以再次用.def修改其名称。
    .def mask = r16
    .def ledR = r17


    .def outLoopR = r18            ; 外层循环数值的数值保存寄存器
    .def innLoopRL = r24    ; 内层循环数值的数值高8位数保存寄存器
    .def innLoopRH = r25    ; 内层循环数值的数值低8位数保存寄存器
   
    ; .equ汇编器伪指令。定义常量,后续不可以再修改类似C语言的const。
    .equ oVal = 208     ; 外层循环数值
    .equ iVal = 1999    ; 内层循环数值
   
   
    ; .CSEG汇编器伪指令。表示将以下代码放置在代码段。
    .CSEG
    .ORG 0x00 ; code space开始地址。这个地址可以从芯片手册的Memory章节获取。后续会解释下
   
    ; 初始化LED使用的IO引脚
    ; PF5
    ; output mode
    ldi r23, 0x20   ; 将0x20加载到r23寄存器。PF5对应第PortF控制寄存器中的第6位
    sts PORTF_DIR, r23        ; 设置为输出模式
   
Start_main:    ; 符号标签,可以自定名称。这个相当于C语言中的函数名称。它可以表示地址
    ; Toogle PF5。翻转LED相应的IO引脚电平
    ldi r23, 0x20   ; 1 cycle。将0x20数据加载到r23寄存器中
    sts PORTF_OUTTGL, r23   ; 2 cycle。将r23寄存器中为数值写入到Data space空间

    ldi outLoopR, oVal        ; 1 cycle。将oVal数据(208)加载到r23寄存器中
Delay_ms: ; 符号标签,可以自定名称。这个相当于C语言中的函数名称。它可以表示地址
    ; delay 500ms
    ldi innLoopRL, LOW(iVal) ; 1 cycle。 LOW为汇编器内置的函数,只取iVal的低8位数据
    ldi innLoopRH, HIGH(iVal) ; 1 cycle  HIGH为汇编器内置的函数,只取iVal的高8位数据
    ; delay ms

delay_us: ; 符号标签,可以自定名称。这个相当于C语言中的函数名称。它可以表示地址
    ; 2 cycle
    ; sbiw指令为字操作指令,它能操作两个连续的寄存器且会自动操作Carry位。简单讲就是可以操作16bit的数据,只需要给它低的寄存器
    ; 因为iVal为16位的数据,上面代码已经将它的低8位和高8位分别保存到了r24,r25寄存器中了。所以这里只需要给r24寄存器。sbiw指令会
    ; 处理完低8位的数据后自动将r25寄存器中的数据进行减1运算。
    sbiw innLoopRL, 1 ; sbiw减法运算。这里表示减1
    brne delay_us ; 1 or 2 cycle。条件跳转,判断上一条指令sbiw innLoopRL, 1结果是否不等0
   
    dec outLoopR ; 1 cycle。 自减1。相当于C语言中i--操作
    brne Delay_ms ; 1 or 2 cycle。条件跳转,判断上一条指令dec outLoopR, 1结果是否不等0
   
    rjmp Start_main    ; 2 cycle。跳转到Start_main标签符号处
关于.ORG伪指令后为什么是0x00地址?
从数据手册的Memory章节可以的Memory map图中可以看出,在Code Space中Flash的开始地址为0x0000

个人理解:关于Code Space与Data Space的区别主要是使用指令的不同,有些指令只能操作Flash。而ATmega4809将Flash区域映射到了Data Space所以可以使用Data Space的指令来操作Flash.
关于汇编器内置的函数有哪些?
这个可以从AVR汇编使用手册中第7章节可以查询到。比如:上述代码中使用到的LOW()、HIGH()函数



实际效果:





使用特权

评论回复
沙发
tpgf| | 2022-2-3 16:02 | 只看该作者
汇编器都是内置的吗

使用特权

评论回复
板凳
keaibukelian| | 2022-2-3 16:13 | 只看该作者
这个伪指令的作用是什么呢

使用特权

评论回复
地板
labasi| | 2022-2-3 16:23 | 只看该作者
现在用的是不是比较少了啊

使用特权

评论回复
5
paotangsan| | 2022-2-3 16:31 | 只看该作者
首先我读不懂汇编语言啊

使用特权

评论回复
6
renzheshengui| | 2022-2-3 16:39 | 只看该作者
几个要素都很全面

使用特权

评论回复
7
wakayi| | 2022-2-3 16:47 | 只看该作者
有专用的转换器吗

使用特权

评论回复
8
JackTang1994|  楼主 | 2022-2-8 10:38 | 只看该作者
tpgf 发表于 2022-2-3 16:02
汇编器都是内置的吗

单独下载或者从MicroChip Studio安装目录中获取,MPLAB X IDE中没有带这个AVR汇编器

使用特权

评论回复
9
JackTang1994|  楼主 | 2022-2-8 10:38 | 只看该作者
paotangsan 发表于 2022-2-3 16:31
首先我读不懂汇编语言啊

看看就清楚了,不需要记住每一个指令。不同就查汇编指令文档即可

使用特权

评论回复
10
JackTang1994|  楼主 | 2022-2-8 10:39 | 只看该作者
keaibukelian 发表于 2022-2-3 16:13
这个伪指令的作用是什么呢

指导汇编器的,伪指令不会产生代码

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

27

主题

60

帖子

0

粉丝