C程序在分配变量时停止执行

C program stops execution when assigning variable

我不确定在专门分配变量时是否会发生这种情况,但在调试汇编代码时,编译器会在挂起程序的地方执行RJMP $+0000

编辑:如果相关,我添加了包含的库

#define __DELAY_BACKWARD_COMPATIBLE__
#define F_CPU 8000000UL
#include <avr/io.h>
#include <avr/delay.h>
#include <stdint.h> 

void ReadTemp(uint8_t address){
    
    ADCSRA = ADCSRA | 0b10000111;       //enable ADC, CLK/128 conversion speed
    ADMUX  = ADMUX | 0b01000000;        //Use internal 2.56V Vref and PA0 as input, right-hand justified
        
    ADCSRA |= (1 << ADSC);              //start conversion
        
    while(!(ADCSRA & (1 << ADIF))) {}   // wait until process is finished;

    uint8_t  low_value = ADC & 0x00FF;
// or low_value = ADCL;
    uint8_t high_value = ADC & 0xFF00;   //problem here
...
}

我不知道这是在做什么,但我确实在按位数学中看到一个错误。

uint8_t  low_value = ADC & 0x00FF;
uint8_t high_value = ADC & 0xFF00;   //problem here

low_valuehigh_value 都是 8 位 (uint8_t)。我要冒昧地说 ADC 是 16 位。对于 high_value,您正在 anding ADC 与 0xFF00 然后将值截断为 8 位。 high_value 将始终为零。

应该做的是:

uint8_t high_value = (ADC & 0xFF00) >> 8;

这将获取 ADC 的左字节并将其右移 8 位,然后将其分配给 high_value 字节存储,从而为您提供正确的值。

您的做法 low_value 是正确的。事实上,你可以简单地做:

uint8_t low_value = ADC;

这里有些地方不太理想:

uint8_t low_value = ADC & 0x00FF;

您正在阅读 ADC,这是一个 16 位寄存器,实现为一对 8位寄存器。如反汇编所示,这需要两个 in 指令,一个字节。然后你只是扔掉了其中的一个 那些字节。您可能认为编译器足够聪明,可以避免 读取它要立即丢弃的字节。不幸的是,它 不能这样做,因为 I/O 寄存器被声明为 volatile。这 编译器被迫访问寄存器的次数与源代码访问的次数相同 代码确实如此。

如果你只想要低字节,你应该只读那个字节:

uint8_t low_value = ADCL;

您随后写道:

uint8_t high_value = ADC & 0xFF00;

如上一个答案所述,high_value 将为零。然而 编译器将不得不再次读取这两个字节,因为 I/O 寄存器 是 volatile。如果要读高字节,读ADCH.

但是为什么要一个一个地读取这两个字节呢?是不是放 它们重新组合成一个 16 位变量?如果是这样的话,那么 无需单独阅读。相反,只需读取 16 位 以最 straight-forward 的方式注册:

uint16_t value = ADC;

很久以前,gcc 不知道如何处理 16 位寄存器,并且 人们不得不求助于一个字节一个字节地读取,然后粘合 他们在一起。您可能仍会在 Internet 上找到非常古老的示例代码 那样做。今天,绝对没有继续下去的理由 以这种方式编程。

然后你写道:

//problem here

不,问题不在这里。那不是生成 rjmp 的原因 操作说明。问题可能就在代码中的那一行之后 您选择不 post。你有一些表现出来的错误 仅当打开优化时。这是典型的代码 产生未定义的行为:在关闭优化的情况下按预期工作, 然后在启用优化时会做一些奇怪的“无法解释”的事情。