Go Down

Topic: bug with declaring a variable (Read 630 times) previous topic - next topic


im getting some rather puzzling behaviour from my arduino, and was wondering if anyone has seen this, or has some insight into what is going on.  if i declare a single variable 0xffff at the beginning of my code, it gets loaded with 0x900f.  if i declare that same variable with any other number, it works fine.  if i declare more than one variable, it also works fine.  here is my code:

Code: [Select]

int counter = 0xffff; // bit mask
byte button; // button checking timer
byte last_state; // last rotary encoder state

void setup() {
  // setup input pins for rotary encoder
  DDRD &= ~(0x94); // make sure pins 2,4,7 are input
  PORTD |= 0x94; // turn on pullups for pins 2,4,7

  // setup ADC to sample on ADC2
  ADMUX = 0x62; // left adjust, adc2, internal vcc as reference
  ADCSRA = 0xe5; // turn on adc, ck/32, auto trigger
  ADCSRB =0x06; // timer1 overflow as trigger
  DIDR0 = 0x04; // turn off digital inputs for adc2

  // setup PWM to output at 31.25ksps
  TCCR1A = 0xa0; // set to compare mode to positive output
  TCCR1B = 0x11; // ck/1, phase and frequency correct mode, ICR1 as top
  TIMSK1 = 0x01; // turn on overflow interrupt
  ICR1H = 0x00; // clear temporary high byte register
  ICR1L = 0xff; // set top of counter
  DDRB |= 0x06; // set pwm outputs (pins 9,10) to output

void loop() {

ISR(TIMER1_OVF_vect) {
  // get ADC data
  byte temp1 = ADCL; // you need to fetch the low byte first
  byte temp2 = ADCH; // yes it needs to be done this way
  int input = ((temp2 << 8) | temp1) + 0x8000; // make a signed 16b value

/*  this section commented out for testing 
  button--; // check buttons every so often
  if (button == 0) {
    byte temp3 = (PIND & 0x94); // mask off and invert
    if (((last_state | temp3) & 0x08) == 0) { // falling edge
      if ((temp3 & 0x04) == 0) {
        if ((counter & 0x7fff) == 0) counter = 0x8000;
        else counter <<= 1;
      else counter >>= 1;
    last_state = (temp3 ^ 0x94);
    button = 0x20; // reset counter
  input &= counter;
  // output data
  OCR1AL = ((input + 0x8000) >> 8); // convert to unsigned and output high byte
  OCR1BL = input; // output the low byte

i did a diff on the outputted .cpp.hex file, and the actual microcontroller memory.  the only difference between the 2 files, was that 0x900f was sitting exactly where 0xffff should have been in the program memory.  this is also the last line of the .cpp.hex file.

what exactly happens to the .hex file before it gets loaded onto the arduino?  the line is consistently changed to the same thing, so its not like its just not writing it.  ive tried loading different code on, to change that memory location, and it gets written back to the same string.  its actually a 16b string that gets written after the main program ends, and the data begins.

another fun fact, this error does not occur on the dueminalove, only on the uno.


Not sure if it is related to the issue, but int is a signed variable. For a bitmask you should probably use either unsigned int or word (both are 16 bit unsigned). I suppose uint16_t would also work for those who prefer using terms closer to the base c++ and not macros provided by the Arduino environment.

Not sure where the 0x900F is coming from though... Positive max signed int should be 0x7FFF, and 0xFFFF should be -1 DEC...


i found the problem here.  AVRdude optimizes trailing FF's out of its transfer, as any block needs to be erased (set to FF) before being written.  but, it seems the bootloader on the UNO does NOT clear its temporary buffer to FF, and therefore writes that last content that was there, rather than FF as it should.  the duemilanove bootloader clears the buffer appropriately.

so, if any of the last variables you declare are 0xFFFF (bytes will work here, but ints and longs will not), they will not get written appropriately.

Go Up