2

I am using ATmega16 in my project. I want to get the value=1023 when I give 5V as input, and 0 when input = 0. The readADC function reads the particular channel of micro-controller ADC. The frequency of my clock is 4MHz. But on reading the input, I'm getting 255 as the maximum value instead of 1023. Someone who knows about avr programming can help !!!

My code:

#include <avr/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>

unsigned char ReadADC(unsigned char ch)
{
   ch = ch&0b00000111;
   ADMUX&=0xF8;
   ADMUX |= ch;
   ADCSRA |= (1<<ADSC);
   while(ADCSRA & (1<<ADSC);   //wait for conversion to complete
   return(ADC);
}

int main(void)
{
   SegDataDDR = 0xFF;
   SegCntrlDDR = 0xF3;
   SegCntrlPort = 0xF3;
   SegDataPort = 0x00;

ADMUX = (1<<REFS0) | (0<<REFS1);
ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS0);   // ADEN set to turn ADC on
// clock frequency divided by 32 for operable 125KHz frequency

while(1) 
{ 
   ADCSRA |= (1<<ADSC);    // start conversion
   unsigned char value = ReadADC(0);    // Reads the value of the ADC
}
phuclv
  • 37,963
  • 15
  • 156
  • 475
Yash
  • 145
  • 9
  • 1
    1023 is too large to fit in an `unsigned char`. What you're getting is the least significant byte of 1023, which is 255. – Michael Jun 03 '15 at 11:18
  • Hint: try an `unsigned short` or `unsigned int` instead of `unsigned char` – Levi Jun 03 '15 at 11:19
  • I have tried float, int and others, but it doesn't work Please suggest appropriate datatype, if that is the only problem!!! – Yash Jun 03 '15 at 11:20
  • @Levi I have tried both unsigned int and unsigned short, but it doesn't worked – Yash Jun 03 '15 at 11:22
  • 1
    @Yash: Is it possible that the `ADC` register is only 8 bits long? That could be the issue – Levi Jun 03 '15 at 11:23
  • What do you mean by ADC register ?? Multiplying value will not increase the resolution. – Yash Jun 03 '15 at 11:25
  • 1
    @Yash Read a data sheet, specifying the processor's registers. The symbol `ADC` in your code is a reference to a hardware register, part of the A/D converter. – unwind Jun 03 '15 at 11:26
  • @Yash: [Here](http://www.atmel.com/images/doc2466.pdf) you go – Levi Jun 03 '15 at 11:27
  • @Levi - multiplication will not solve the problem of resolution. I want 10bit resolution, not 8 bit. – Yash Jun 03 '15 at 11:27
  • 1
    Maybe, in the future, have a look at your compiler warnings, see e.g. http://stackoverflow.com/questions/22198305/is-there-a-gcc-flag-to-catch-integer-truncation – JimmyB Jun 03 '15 at 12:08

2 Answers2

3

In your code, the line

unsigned char value = ReadADC(0);

is restricting you to only 8 bits. You need to change the type of value to something larger, like an unsigned short, which can hold 16 bits worth of data. If you make this change, you must also change the definition of ReadADC to

unsigned short ReadADC(unsigned char ch)
Levi
  • 1,921
  • 1
  • 14
  • 18
  • 1
    He will have to change `unsigned char ReadADC(unsigned char ch)` too. – JimmyB Jun 03 '15 at 12:09
  • There is one more problem, I am not able to set the maximum reference voltage. I have applied 5V at AVcc and a capicator to ground at Aref. But 5V output is also giving 1023 (max. value) and 3V output is also doing the same. – Yash Jun 04 '15 at 06:12
  • @Yash: That is an entirely different question, and is more suitable for [electronics stack exchange](http://electronics.stackexchange.com/) – Levi Jun 04 '15 at 06:17
-1

Replace unsigned char by unit16_t

Yash
  • 145
  • 9