几个月前,如果我定义了ISR,我用C语言编写的闪烁程序在Arduino R3 Uno上闪存到ATmega328p上,为什么总是失败.我最终将问题缩小到Makefile的编写方式(我在avr-gccavrdude中使用它),并通过将代码复制粘贴到Arduino IDE中并使用内置工具上载来绕过它.

现在,我想回到过go ,确切地了解Makefile失败的原因.我已经浏览了avr-gccavrdude的文档,我相信我已经将问题缩小到我正在写入的内存区域.我正在使用的示例C项目如下:

int main(void)
{
    // set the data direction for the pin connected to
    // onboard LED
    DDRB |= _BV(DDB5);
    PORTB |= _BV(PORTB5);

    // no-op loop
    while (1) ;;

    // keep compiler happy
    return 0;
}

该程序故意很简单;它只需打开板载LED并保持亮起.此时,使用下面的make文件可以很好地工作:

AVRFLAGS = -F -v -p m328p -c arduino -P /dev/ttyACM0 -U flash:w:blink.hex


default: blink.elf
    avr-objcopy -O ihex blink.elf blink.hex

blink.o:
    avr-gcc -g -Os -DF_CPU=16000000UL -mmcu=atmega328p -c -o blink.o blink.c

blink.elf: blink.o
    avr-gcc -o blink.elf blink.o

flash:
    sudo avrdude ${AVRFLAGS} blink.hex

clean:
    rm -rf *.o *.hex *.elf

HOWEVER,当我将ISR添加到文件顶部时:

ISR (TIMER1_COMPA_vect)
{
  PORTB ^= _BV(PORTB5);
}

并试图闪光,一切都崩溃了.我已经try 过使用和不使用定时器/计数器1设置代码(出于演示目的而在此处编辑),我不认为它会影响闪存的成功.我已经使用了这个完全相同的ISR--和计时器/计数器1完全相同的设置代码--在其他运行良好的程序中,provided I flash them using the Arduino IDE built-in tool;否则,Arduino Uno闪烁它正在接收数据,然后板载LED开始闪烁并保持闪烁.每当任何程序的闪存不佳时,都会出现完全相同的闪存模式.我收集了-j .text -j .data.eeprom和其他选项,但都无济于事.

我只想知道为什么这失败了.

推荐答案

你忘了通过-mmcu=atmega328p进入链接阶段.如果没有此选项,则不会添加CRT和中断向量表.虽然您只有一个main()函数,但它从地址0(重置向量)开始,一切似乎都正常.由于您添加了ISR,现在ISR代码位于地址0.

对于GNU make,您可以使用COMPILE.cLINK.c内置变量来获得正确的编译和链接命令.

C++相关问答推荐

使用SWI—Prolog的qsave_program生成二进制文件有什么好处?'

什么C代码将确定打开的套接字正在使用的网络适配器?

C/SDL程序,渲染不使用我的渲染器

ZED for SDL上的C语言服务器

将整数的.csv文件解析为C语言中的二维数组

C由四个8位整数组成无符号32位整数

初始变量重置后,char[]的赋值将消失

struct -未知大小

进程在写入管道时挂起

';\n&39;和';\r&39;中的';\n&39;之间有什么关系?

在C++中允许使用字符作为宏参数

我应该在递归中使用全局变量吗

强制GCC始终加载常量(即只读),即使启用了优化

我正在使用c学习数据 struct ,在学习堆栈时,我试图将中缀转换为后缀,并编写了这段代码.代码未给出输出

在C中使用字符串时是否不需要内存分配?

DennisM.Ritchie的C编程语言一书中关于二进制搜索的代码出现错误?

通过GTK';传递回调参数;s g_signal_connect()导致C中出现意外值

模仿 memmove 的行为

保存有符号整数结果的变量是否会溢出(后增量的副作用),并且此后从未在任何表达式中使用过它,是否会导致 UB?

在 C 中的 scanf() 格式说明符中使用宏获取字符串长度