右移一个负数 #包括 #包括 int main() { DDRB |=0x82; DDRC=0x00; DDRD=0xFF; TCNT1H=(-640)>>8; TCNT1L=(-640); TCCR1A=0X00; TCCR1B=0X01; TIMSK=(18;TCNT1L=(-640);code.。这真的很让人困惑,因为我一直在使用0-256之间的值。

右移一个负数 #包括 #包括 int main() { DDRB |=0x82; DDRC=0x00; DDRD=0xFF; TCNT1H=(-640)>>8; TCNT1L=(-640); TCCR1A=0X00; TCCR1B=0X01; TIMSK=(18;TCNT1L=(-640);code.。这真的很让人困惑,因为我一直在使用0-256之间的值。,c,avr,bit-shift,avr-gcc,twos-complement,C,Avr,Bit Shift,Avr Gcc,Twos Complement,这个问题的答案是和 在上面的代码中,-640只是编写位模式11111111111001000 0000的一种奇特(且不直观)的方式,而>8部分是一种常用的切断低位8位的习惯用法 这可能不是在C中设置AVR定时器寄存器的最干净的方法,因为至少第二个赋值TCNT1L=(-640);取决于编译器将丢弃8个最低有效位以上的所有位的假设。(我猜大多数(?)编译器(包括AVR gcc)实际上会做到这一点,但这并不保证,而且依赖于实现的行为也会发生。)这个问题的答案是和 在上面的代码中,-640只是编写位模

这个问题的答案是和

在上面的代码中,-640只是编写位模式
11111111111001000 0000
的一种奇特(且不直观)的方式,而
>8
部分是一种常用的切断低位8位的习惯用法



这可能不是在C中设置AVR定时器寄存器的最干净的方法,因为至少第二个赋值
TCNT1L=(-640);
取决于编译器将丢弃8个最低有效位以上的所有位的假设。(我猜大多数(?)编译器(包括AVR gcc)实际上会做到这一点,但这并不保证,而且依赖于实现的行为也会发生。)

这个问题的答案是和

在上面的代码中,-640只是编写位模式
11111111111001000 0000
的一种奇特(且不直观)的方式,而
>8
部分是一种常用的切断低位8位的习惯用法



这可能不是在C中设置AVR定时器寄存器的最干净的方法,因为至少第二个赋值
TCNT1L=(-640);
取决于编译器将丢弃8个最低有效位以上的所有位的假设。(我猜大多数(?)编译器(包括AVR gcc)实际上会做到这一点,但这并不能保证,而且依赖于实现的行为也会发生。)

在AVR中,
TCNT1L
TCNT1H
是8位值的硬件地址。它们被定义为uint8_t,因此即使不首先强制转换到uint8_t,这个习惯用法也会起作用。实际上,现在我仔细观察,
-640
并不是不直观的。很清楚这意味着什么:当时钟计数时,溢出中断发生,
>TCNT
,滚动到0。中断处理程序将计数重置为-640(或2^16-640),这样它将在另一个640个周期后再次启动。(不过,您仍然可以获得向上投票。)完全同意……它实际上相当优雅!我会天真地设置
OCR1A
,并使用
TIMER1\u-vect
(时间会更长).thx指出这一点!我也认为这是一个糟糕的编程。为了使它更优雅,你应该在宏中隐藏对正确类型的“-”和强制转换的添加。加上一些解释性的注释。@vega8对我来说,
OCR1A
方法更可取,因为1.这是
OCR
中断和2的预期用途之一
TCNT1
可以同时用于其他目的,因为
OCR1B
和TOI仍然可以独立使用(除了计时器的频率之外,它们都必须共享)。在AVR中,
TCNT1L
TCNT1H
是8位值的硬件地址。它们被定义为uint8\t,因此即使不首先强制转换为uint8\t,这个习惯用法也会起作用。实际上,现在我仔细看看,
-640
并不是不直观的。很清楚这意味着什么:当时钟上的计数时,
TC发生溢出中断NT
,滚动到0。中断处理程序将计数重置为-640(或2^16-640),这样它将在另一个640个周期后再次启动。(不过,您仍然会得到一个向上投票。)完全同意……它实际上相当优雅!我会天真地设置
OCR1A
,并使用
计时器1\u-vect
(时间会更长).thx指出这一点!我也认为这是一个糟糕的编程。为了使它更优雅,你应该在宏中隐藏对正确类型的“-”和强制转换的添加。加上一些解释性的注释。@vega8对我来说,
OCR1A
方法更可取,因为1.这是
OCR
中断和2的预期用途之一
TCNT1
可以同时用于其他目的,因为
OCR1B
和TOI仍然可以独立使用(除了计时器的频率之外,它们都必须共享)。您可以代替
TCNT1H
TCNT1L
。您可以代替
TCNT1H
TCNT1L
#include <avr/io.h>
#include <avr/interrupt.h>
int main()
{           
  DDRB|=0x82;
  DDRC=0x00;
  DDRD=0xFF;
  TCNT1H=(-640)>>8;
  TCNT1L=(-640);
  TCCR1A=0X00;
  TCCR1B=0X01;
  TIMSK=(1<<TOIE0)|(1<<TOIE1)
  sei();
  PORTD=PINC;
}

ISR(TIMER1_OVF_vect)
{
  TCNT1H=(-640)>>8;
  TCNT1L=(-640);
  PORTB^=0X80;
}