我花了很长时间用我的AVR开发系统设置了完整的GCC工具链(一切都是最新的当前稳定版本),我用它解决了大多数问题.
以下代码给出了一个我没有得到的错误.AVR汇编手册指出sbi指令可以接受0-7作为常量表达式,但它仍然在我身上出错.谁能解释为什么这样做呢?
#ifndef __AVR_ATmega168__
#define __AVR_ATmega168__
#endif
#include <avr/io.h>
rjmp Init
Init:
ser r16
out DDRB, r16
out DDRD, r16
clr r16
out PORTB, r16
out PORTD, r16
Start:
sbi PORTB, 0
rjmp Start
Run Code Online (Sandbox Code Playgroud)
有问题的线是sbi PORTB,0.
编译/组装:
avr-gcc ledon.S -mmcu = atmega168
我想将两个ASCII字节转换为一个十六进制字节.例如.
0x30 0x43 => 0x0C , 0x34 0x46 => 0x4F ...
ASCII字节是介于0和9之间的数字A和F(和大写字母之间)之间的字母,所以介于0x30...... 0x39和0x41... 之间0x46
我知道如何0x4F用数字0x34和"构建"0x46 : 0x4F = 0x34 * 0x10 + 0x46
所以,实际上,我想以十六进制值转换一个ASCII字节.
为此,我可以构建和数组以将十六进制值分配给ASCII字符:
0x30 => 0x00
0x31 => 0x01
...
0x46 => 0x0F
Run Code Online (Sandbox Code Playgroud)
但是,也许它有一个最"适当"的解决方案.
该程序将在AVRμC上运行并使用avr-gcc,因此scanf()/ printf()解决方案不适用.
你有个主意吗?谢谢
我正在开发一种可以测试大量电线(最多360个)的嵌入式系统 - 本质上是一个连续性检查系统.系统通过在测试向量中计时并从另一端读取输出来工作.然后将输出与存储结果(将在SD卡上)进行比较,该结果告诉输出应该是什么.测试向量只是一个步行,所以不需要将它们存储在任何地方.这个过程有点像:
我的硬件包含一个大型移位寄存器,用于输入AVR微控制器.对于每个测试向量(也可能是360位),我需要读取360位.因此,对于360线,数据总量将是360*360 = 16kB左右.我已经知道我不能在一个通做到这一点(即读取整个数据,然后进行比较),所以它必须通过测试向量测试向量.
由于没有固有类型可以容纳如此大的数字,我打算使用长度为360位的位数组.现在,我的问题是,我应该如何将这个位数组存储在txt文件中?
一种方法是存储原始值,即在每行存储我从移位寄存器读入的原始二进制数据.因此,对于8线,它将是0b10011010.但是对于高达360线的线路来说这可能会变得很难看 - 每条线路都包含360个字节.
另一种方法是存储十六进制值 - 这只是8位的两个字符(上面的9A)和360位的大约90个字符.这会,但是,需要我在文本阅读 - 逐行 - 并转换位阵列中表示的十六进制值,不知何故.
那么这个问题的最佳解决方案是什么?我需要解决方案完全"确定性" - 我不能调用malloc等.从我读过的内容来看,它们在嵌入式系统中有点禁忌.
摘要
我需要存储无法用任何传统变量类型表示的大值.目前我打算将这些值存储在一个bitarray中.将这些值存储在SD卡上的文本文件中的最佳方法是什么?
我只是玩弄了一些字段,遇到了一些我无法弄清楚如何绕过的东西.
(关于平台的注意事项:int的大小= 2bytes,long = 4bytes,long long = 8bytes - 认为值得一提,因为我知道它可以变化.'byte'类型被定义为'unsigned char')
我希望能够创建一个包含两个36位变量的数组,并将它们放入一个9字节数组的联合中.这就是我想出的:
typedef union {
byte bytes[9];
struct {
unsigned long long data:36;
} integers[2];
} Colour;
Run Code Online (Sandbox Code Playgroud)
我正在研究这样的理论,即编译器会意识到应该有两个位域作为匿名结构的一部分,并将它们放在9个字节的空间中.然而事实证明它们在字节边界处对齐,因此并集占用了10个字节而不是9个字节,这非常有意义.
那么问题是,有没有办法创建像这样的两个位字段的数组?我考虑了'packed'属性,但编译器只是忽略它.
虽然这按预期工作(sizeof()返回9):
typedef union {
byte bytes[9];
struct {
unsigned long long data0:36;
unsigned long long data1:36;
} integers;
} Colour;
Run Code Online (Sandbox Code Playgroud)
最好让它可以作为数组访问.
编辑:感谢cdhowie解释为什么这不起作用.
幸运的是,我想到了一种实现我想要的方法:
typedef union {
byte bytes[9];
struct {
unsigned long long data0:36;
unsigned long long data1:36;
unsigned long long data(byte which){
return (which?data1:data0);
}
void data(byte which, unsigned …Run Code Online (Sandbox Code Playgroud) 您好,我是 avr asm 编程的新手,在下面的示例中,我有几个问题:
1)标签是8位还是16位长?
2)为什么需要2的乘法标签?
3) 指令 LPM 将其结果放入寄存器 R0 中?如果是的话,这和Z有什么关系?
4)您能否解释一下所提供链接中引用的文字:
“如果地址没有乘以 2 并且标签位于字节地址 0x60(字地址 0x30),Z 将指向存储在那里的代码。我希望这能澄清寻址问题。其他版本是”
ldi ZL, low(2*label)
ldi ZH, high(2*label)
label:
.db "Hello world", 0
lpm
Run Code Online (Sandbox Code Playgroud)
谢谢。
我正在AVR ATmega328P微控制器上使用avr-libc开发一个C应用程序.由于我没有ICE调试器,因此我按照这些说明和本教程进行了诸如能够使用硬件UART等功能.stdio.hprintfstdout
这是有效的,我可以看到连接到我的目标板的PC终端上的输出,但奇怪的是:当我只有一个printf在主,但在主循环之前有什么导致处理器重置,而如果我有一个printf只在主循环内部或主循环之前和循环内部它工作正常.像这样的东西:
#include <stdio.h>
/* stream definitions for UART input/output */
FILE uart_output = FDEV_SETUP_STREAM(uart_drv_send_byte, NULL, _FDEV_SETUP_WRITE);
FILE uart_input = FDEV_SETUP_STREAM(NULL, uart_drv_read_byte, _FDEV_SETUP_READ);
int main() {
/* Definition of stdout and stdin */
stdout = &uart_output;
stdin = &uart_input;
/* Configures Timer1 for generating a compare interrupt each 1ms (1kHz) */
timer_init()
/* UART initialization */
uart_drv_start(UBRRH_VALUE, UBRRL_VALUE, USE_2X, &PORTB, 2);
/* Sets the sleep …Run Code Online (Sandbox Code Playgroud) 我有多个C和H文件
在main.c我定义一个宏,并在ws_driver.c我想使用它.
ws_driver.h包括在内main.c.
main.c中
#define WS_PORT PORT_D8
#define WS_BIT D8
#define WS_DDR DDR_D8
#include "ws_driver.h"
Run Code Online (Sandbox Code Playgroud)
在ws_dirver.c我有两个检查:
ws_driver.c
#include "ws_driver.h"
#ifndef WS_PORT
# error "WS_PORT not defined!"
#endif
#ifndef WS_BIT
# error "WS_BIT not defined!"
#endif
Run Code Online (Sandbox Code Playgroud)
两者都失败了.
$ avr-gcc -std=gnu99 -mmcu=atmega328p -DF_CPU=16000000UL -Os -I. -I -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wno-main -Wno-strict-prototypes -Wno-comment -g2 -ggdb -ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--relax -std=gnu99 main.c ws_driver.c --output main.elf
ws_driver.c:10:3: error: #error "WS_PORT not defined!"
# …Run Code Online (Sandbox Code Playgroud) 我有堆栈初始化行的问题,因为avr-gcc返回
LED_Blink.asm:10:错误:行尾的垃圾
在线:
ldi r17, low(RAMEND)
ldi r17, high(RAMEND)
Run Code Online (Sandbox Code Playgroud)
我很困惑.我已经定义了RAMEND.我在这个命令中使用了avr-gcc:
avr-gcc -x assembler -mmcu = atmega328p LED_Blink.asm
我的汇编代码:
.equ SPL, 0x3d
.equ SPH, 0x3e
.equ RAMEND, 0x8ff
.equ PORTB, 0x05
.equ DDRB, 0x04
.org 0x000000
rjmp main
main:
ldi r17, low(RAMEND)
out SPL, r17
ldi r17, high(RAMEND)
out SPH, r17
ldi r16, 0xff
out DDRB, r16
out PORTB, r16
loop:
ldi r16, 32
rcall outer_loop
cbi PORTB, 5
ldi r16, 32
rcall outer_loop
sbi PORTB, 5
rjmp loop
outer_loop:
clr …Run Code Online (Sandbox Code Playgroud) 我正在使用platform.io作为编程AVR MCU的IDE.我正在开始AVR编程(我有一个C/C++的背景和OS上的编程,而不是嵌入式,虽然我过去做了一些Arduino的东西)并且使用PlatformIO给我代码完成寄存器/引脚,这就是为什么我用它.
我似乎无法在没有丢失代码完成的情况下将框架从Arduino切换到PlatformIO中的avr-gcc.
我想知道将Arduino作为框架存在任何缺点吗?
我知道Arduino在后面使用了avr-gcc,但我读到它仍然会在用户不知情的情况下进行一些设置(例如Timer0设置延迟,我需要它,因为我将它用作USI的时钟源在我的ATTiny85).
否则,在PlatformIO中是否仍然保持代码完成并使用avr-gcc而不是Arduino?
谢谢!
编辑:我在OSX或Linux(ubuntu)上.
我目前正在Atmel Studio中为Atmega328P(Arduino UNO)开发一个引导加载程序,从反汇编中我发现了以下代码(我的引导加载程序从0x3800开始):
--- ../../../../crt1/gcrt1.S ---------------------------------------------------
00003800 JMP 0x00003834 Jump
00003802 JMP 0x00003979 Jump
00003804 JMP 0x00003979 Jump
00003806 JMP 0x00003979 Jump
00003808 JMP 0x00003979 Jump
0000380A JMP 0x00003979 Jump
0000380C JMP 0x00003979 Jump
0000380E JMP 0x00003979 Jump
--- ../../../../crt1/gcrt1.S ---------------------------------------------------
00003810 JMP 0x00003979 Jump
00003812 JMP 0x00003979 Jump
00003814 JMP 0x00003979 Jump
00003816 JMP 0x00003979 Jump
00003818 JMP 0x00003979 Jump
0000381A JMP 0x00003979 Jump
0000381C JMP 0x00003979 Jump
0000381E JMP 0x00003979 Jump
00003820 JMP 0x00003979 Jump
00003822 JMP 0x00003979 …Run Code Online (Sandbox Code Playgroud)