Miljö: Winavr med AVRStudio 4.
Processor: Atmega48
Jag vet inte vad jag gör för fel, men tokfel blir det.
Jag anropar en rutin som läser in ett 16-bitars tal från SPI och skriver ut talet med en egen rutin printD(...) som kan skriva ut heltal upp till 32 bitar. Men nånstans på vägen tror GCC att jag bara har 8 bitar och förlorar därmed höga byten på vägen. Kan inte fatta varför!
Ska försöka få med all relevant kod:
Först kommer funktionen som skickar ut en instruktion och läser in två bytes.
Kod: Markera allt
uint16_t adc_read_data(void) {
// läser 16 bitar data
// channel = CHANNEL1 eller CHANNEL2
adc_wait();
volatile uint16_t value;
device = DEVICE_ADC; // för att välja chip-select
SPI_start(device, ADC_DATA | READ | channel);
SPI_ReceiveByte(); // dummybyte
value = ((uint16_t)SPI_ReceiveByte() << 8); // bit 15-8 **
value |= SPI_ReceiveLastByte(); // bit 7-0
return value;
}
För att göra det idiotsäkert har jag förenklat SPI_receiveByte() och SPI_ReceiveLastByte() till att bara returnera ett konstant värde, 3 samt 22 - vilket borde ge value = 790. Det blir det också, ända tills det ska skickas vidare till printD() i main():
Kod: Markera allt
uint16_t nummer;
...
nummer = adc_read_data();
put = UART;
printD(nummer+1000); // skicka ut acd-värde på UART
Men när talet 1000 ska adderas till "nummer", så raderas höga byten i nummer:
Kod: Markera allt
Disassembler: addera 1000 till R24:r25:
159: printD(nummer+1000); // skicka ut acd-värde på UART
+00000105: E090 LDI R25,0x00 Load immediate
+00000106: 5188 SUBI R24,0x18 Subtract immediate
+00000107: 4F9C SBCI R25,0xFC Subtract immediate with carry
Anledningen till att jag adderar 1000 var att jag ville försäkra mig om att printD verkligen tog emot 16 bitar. Och det gör den - den skriver ut talet 1022. Men den borde alltså skriva ut 1790.
Inne i själva funktionen adc_read_data() verkar den göra helt rätt: den flyttar den först inlästa byten till "hög byte" i två processor-register och nollställer "låg" byte. Sedan läses andra värdet in, låg byte, och görs om till 16-bitars det också genom att hög byte nollställs. sedan OR-as båda 16-bitars-talen och resultatet 0x0316 returneras (i r24:r25). SPI-fukntionerna returnerar uint8_t.