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_value
和 high_value
都是 8 位 (uint8_t
)。我要冒昧地说 ADC
是 16 位。对于 high_value
,您正在 and
ing 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。你有一些表现出来的错误
仅当打开优化时。这是典型的代码
产生未定义的行为:在关闭优化的情况下按预期工作,
然后在启用优化时会做一些奇怪的“无法解释”的事情。
我不确定在专门分配变量时是否会发生这种情况,但在调试汇编代码时,编译器会在挂起程序的地方执行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_value
和 high_value
都是 8 位 (uint8_t
)。我要冒昧地说 ADC
是 16 位。对于 high_value
,您正在 and
ing 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。你有一些表现出来的错误
仅当打开优化时。这是典型的代码
产生未定义的行为:在关闭优化的情况下按预期工作,
然后在启用优化时会做一些奇怪的“无法解释”的事情。