在Arduino UNO上运行汇编程序
在Microchip Studio中运行Arduino的汇编语言代码,你可以按照以下步骤进行:
-
安装和打开Microchip Studio:首先,确保你已经安装了Microchip Studio,这是Microchip提供的集成开发环境,用于嵌入式系统的开发,包括对AVR单片机的支持。
-
新建项目:在Microchip Studio中,选择“File”->“New”->“Project”,创建一个新的项目。选择项目类型为“Assembler(汇编)”项目。
-
选择设备类型:在新建项目时,选择对应的Arduino板子对应的MCU型号,例如,如果使用的是Arduino Uno R3,那么对应的MCU型号为ATmega328P。
-
编写汇编代码:在新建的项目中,将你的汇编代码写入到
main.asm
文件中。例如,你可以编写控制LED闪烁的汇编代码。 -
配置项目:在项目属性中,确保选择了正确的工具链和优化设置。如果需要仿真,还需要设置仿真器。
-
编译代码:配置完成后,选择“Build”->“Build Solution”来编译你的汇编代码。编译成功后,会生成HEX文件,这是烧录到Arduino板子上的文件。
-
烧录程序:使用AVRDUDE工具将编译生成的HEX文件烧录到Arduino板子上。你可以在Microchip Studio中配置External Tools参数,或者在命令行中使用AVRDUDE命令进行烧录。
-
调试和运行:烧录完成后,你可以将Arduino板子连接到计算机,并在Microchip Studio中进行调试和运行。
请注意,这个过程可能需要根据你的具体硬件和软件环境进行适当的调整。确保你的Microchip Studio版本支持你的Arduino板子,并且你有正确的AVRDUDE配置文件和路径设置。
一、AVRDUDE的下载
AVRDUDE(AVR Downloader Uploader)是一个用于下载和上传Microchip的AVR微控制器芯片内存的程序。它可以编程Flash和EEPROM,并且在编程协议支持的情况下,它还可以编程熔丝位和锁定位。AVRDUDE还提供了一个直接指令模式,允许用户向AVR芯片发出任何编程指令,无论AVRDUDE是否实现了某个特定芯片的特定功能。
在https://github.com/avrdudes/avrdude/releases/tag/v8.0中下载AVRDUDE v8.0,下载的文件是avrdude-v8.0-windows-x64.zip,并将其解压。avrdude-v8.0-windows-x64.zip对应的是Windows MSVC 64 bit。
二、配置MicroChip Studio开发环境
Atmel公司被MicroChip公司收购以后,Atmel Studio 就改名为MicroChip Studio软件,在Arduino Uno上配置汇编语言程序运行环境和运行汇编语言程序的过程基本没有什么变化。
1. 在External Tools中配置AVRDUDE运行环境
(1)打开MicroChip Studio软件,然后选择Tools下的External Tools菜单项,如图1所示。 弹出External Tools窗体如图2所示。
(2)设置图2中窗体的各项内容如下:
- Title:Arduino UNO avrdude
- Command: D:\atmel studio\avrdude-v8.0-windows-x64\avrdude.exe
- Arguments: -v -P COM3 -c arduino -e -p m328p -U flash:w:$(TargetName).hex
- Initial Directory: $(TargetDir)
然后,勾选Use Output Window复选框。其中,Command项的设置为下载并解压的avrdude.exe文件所在路径,根据文件解压路径进行修改。Arguments中的各参数如下所示:
- -v:启用详细输出。
- -P:连接Arduino Uno的串行端口号(COM端口)
- -c:编程器硬件类型。
- -e:在编程之前擦除目标MCU的闪存和EEPROM存储器。 这是强制性的。
- -p:要编程的器件的短名称
- -U:memtype:op:filename [:format]:将指定的十六进制文件的内容写入闪存
本例中,“COM3”是Arduino Uno控制器连接到计算机后的COM端口号,可以在设备管理器中查询,如图3所示。
设置后的External Tools窗体上的各项内容如图所示。点击OK,保存设置的各项参数。
(3)设置完成后,打开Tools菜单,则Arduino UNO avrdude出现在菜单中,如图5所示。
(4)运行Arduino UNO avrdude
选择菜单File>New>Project,弹出的窗口中的installed选项下选择Assembler,如图6所示。点击OK按钮,弹出Device Selectin窗体,在Device Family中选择ATmega328P,如图7所示。再点击OK按钮,进入编辑界面。
(5)打开Tools菜单,点击Arduino UNO avrdude项,则出现如图所示的提示。
Avrdude version 8.0
Copyright see https://github.com/avrdudes/avrdude/blob/main/AUTHORS
System wide configuration file is D:\atmel studio\avrdude-v8.0-windows-x64\avrdude.conf
Using port : COM6
Using programmer : arduino
AVR part : ATmega328P
Programming modes : SPM, ISP, HVPP, debugWIRE
Programmer type : Arduino
Description : Arduino bootloader using STK500 v1 protocol
HW Version : 3
FW Version : 4.4
AVR device initialized and ready to accept instructions
Device signature = 1E 95 0F (ATmega328P, ATA6614Q, LGT8F328P)
Erased chip
Reading 32 bytes for flash from input file AssemblerApplication4.hex
in 1 section [0, 0x1f]: 1 page and 96 pad bytes
Writing 32 bytes to flash
Writing | ################################################## | 100% 0.04s
Reading | ################################################## | 100% 0.02s
32 bytes of flash verified
Avrdude done. Thank you.
表明avrdude已经配置成功。
二、汇编语言程序的编译和烧录
1. 汇编语言程序的编译
在main.asm中输入如下代码。
main:
sbi 0x04, 5 ; PORTB5 output
loop: ; main loop begin
sbi 0x05, 5 ; PORTB5 high
call delay_1000ms ; delay 1s
cbi 0x05, 5 ; 5 PORTB5 low
call delay_1000ms ; delay 1s
rjmp loop ; main loop
delay_1000ms: ; subroutine for 1s delay
; initialize counters
ldi r18, 0xFF ; 255
ldi r24, 0xD3 ; 211
ldi r25, 0x30 ; 48
inner_loop:
subi r18, 0x01 ; 1
sbci r24, 0x00 ; 0
sbci r25, 0x00 ; 0
brne inner_loop
ret
选择“Build”->“Build Solution”来编译你的汇编代码。编译成功后,会生成HEX文件,这是烧录到Arduino板子上的文件。编译结果如图8所示。
在output窗口输出如下:
Build started.
Project "AssemblerApplication1.asmproj" (default targets):
Target "PreBuildEvent" skipped, due to false condition; ('$(PreBuildEvent)'!='') was evaluated as (''!='').
Target "CoreBuild" in file "D:\atmel studio\7.0\Vs\Assembler.targets" from project "c:\users\78468\Documents\Atmel Studio\7.0\AssemblerApplication1\AssemblerApplication1\AssemblerApplication1.asmproj" (target "Build" depends on it):
Task "RunAssemblerTask"
D:\atmel studio\7.0\toolchain\avr8\avrassembler\avrasm2.exe -fI -o "AssemblerApplication1.hex" -m "AssemblerApplication1.map" -l "AssemblerApplication1.lss" -S "AssemblerApplication1.tmp" -W+ie -I"D:/atmel studio\7.0\Packs\atmel\ATmega_DFP\1.3.300\avrasm\inc" -im328pdef.inc -d "c:\users\78468\Documents\Atmel Studio\7.0\AssemblerApplication1\AssemblerApplication1\Debug\AssemblerApplication1.obj" "c:\users\78468\Documents\Atmel Studio\7.0\AssemblerApplication1\AssemblerApplication1\main.asm" -I "D:\atmel studio\7.0\toolchain\avr8\avrassembler\Include"
AVRASM: AVR macro assembler 2.2.7 (build 69 Jul 26 2017 16:25:06)
Copyright (C) 1995-2017 ATMEL Corporation
[builtin](2): Including file 'D:/atmel studio\7.0\Packs\atmel\ATmega_DFP\1.3.300\avrasm\inc\m328pdef.inc'
[builtin](2): Including file 'D:/atmel studio\7.0\Packs\atmel\ATmega_DFP\1.3.300\avrasm\inc\m328pdef.inc'
"ATmega328P" memory use summary [bytes]:
Segment Begin End Code Data Used Size Use%
---------------------------------------------------------------
[.cseg] 0x000000 0x000020 32 0 32 32768 0.1%
[.dseg] 0x000100 0x000100 0 0 0 2048 0.0%
[.eseg] 0x000000 0x000000 0 0 0 1024 0.0%
Assembly complete, 0 errors. 0 warnings
Done executing task "RunAssemblerTask".
Done building target "CoreBuild" in project "AssemblerApplication1.asmproj".
Target "PostBuildEvent" skipped, due to false condition; ('$(PostBuildEvent)' != '') was evaluated as ('' != '').
Target "Build" in file "D:\atmel studio\7.0\Vs\Avr.common.targets" from project "c:\users\78468\Documents\Atmel Studio\7.0\AssemblerApplication1\AssemblerApplication1\AssemblerApplication1.asmproj" (entry point):
Done building target "Build" in project "AssemblerApplication1.asmproj".
Done building project "AssemblerApplication1.asmproj".
Build succeeded.
========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ==========
2. 烧录程序
使用AVRDUDE工具将编译生成的HEX文件烧录到Arduino板子上。点击菜单Tools->Arduino UNO avrdude,使用AVRDUDE命令进行烧录。烧录结束后,output窗口显示如下结果,表明烧录成功。
Avrdude version 8.0
Copyright see https://github.com/avrdudes/avrdude/blob/main/AUTHORS
System wide configuration file is D:\atmel studio\avrdude-v8.0-windows-x64\avrdude.conf
Using port : COM3
Using programmer : arduino
AVR part : ATmega328P
Programming modes : SPM, ISP, HVPP, debugWIRE
Programmer type : Arduino
Description : Arduino bootloader using STK500 v1 protocol
HW Version : 3
FW Version : 4.4
AVR device initialized and ready to accept instructions
Device signature = 1E 95 0F (ATmega328P, ATA6614Q, LGT8F328P)
Erased chip
Reading 32 bytes for flash from input file AssemblerApplication1.hex
in 1 section [0, 0x1f]: 1 page and 96 pad bytes
Writing 32 bytes to flash
Writing | ################################################## | 100% 0.04s
Reading | ################################################## | 100% 0.02s
32 bytes of flash verified
Avrdude done. Thank you.
烧录成功后,arduino Uno的板载LED会闪烁。
3. 汇编程序的解释
这段代码是用汇编语言编写的,用于AVR微控制器。它的作用是控制一个连接到PORTB5(即PORTB的第5位)的LED灯,使其以1秒的间隔闪烁。下面是代码的逐行解释:
main:
sbi 0x04, 5 ; 设置PORTB的第5位为输出模式
loop: ; 主循环开始
sbi 0x05, 5 ; 将PORTB的第5位设置为高电平(1),点亮LED
call delay_1000ms ; 调用1秒延时子程序
cbi 0x05, 5 ; 将PORTB的第5位设置为低电平(0),熄灭LED
call delay_1000ms ; 再次调用1秒延时子程序
rjmp loop ; 无限循环回到主循环开始处
delay_1000ms: ; 1秒延时子程序
; 初始化计数器
ldi r18, 0xFF ; 将寄存器r18设置为255
ldi r24, 0xD3 ; 将寄存器r24设置为211
ldi r25, 0x30 ; 将寄存器r25设置为48
inner_loop:
subi r18, 0x01 ; r18减1
sbci r24, 0x00 ; r24减0(因为subi可能影响进位标志,所以用sbci)
sbci r25, 0x00 ; r25减0(同上)
brne inner_loop ; 如果结果不是零,则跳回inner_loop继续循环
ret ; 返回到调用延时子程序的地方
这段代码中,sbi
(Set Bit)和cbi
(Clear Bit)指令分别用于设置和清除特定的端口位。ldi
(Load Immediate)指令用于将立即数加载到寄存器中。subi
(Subtract Immediate)和sbci
(Subtract with Carry Immediate)指令用于减法操作,其中sbci
考虑了进位标志。brne
(Branch if Not Equal)指令用于在寄存器值不为零时跳转到指定的标签。
delay_1000ms
子程序通过三次嵌套的循环来实现大约1秒的延时。这种延时方法依赖于微控制器的时钟频率,因此实际的延时时间可能会因不同的时钟设置而异。在实际应用中,这种延时方法不够精确,通常会使用定时器中断来实现更准确的延时。
在arduino Uno上运行汇编语言的门槛较高,比较小众。若深入了解微控制器的工作原理,还是可以深入学习的。后面列出了3本书可供参考。其他可自行在道客巴巴上查找,这个网站山峰的英文原版书确实很好!