Any one tell me how these 2 code actually work,plz.

Go To Last Post
17 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi C experts,

I wrote a code to read and show val from ADC0 and ADC1 to the different line on LCD. But, surprising, I found something about string and memory stuff. Please see my code.

#include 
#include 
#include 
#include  
#include 
#include 
int j;

void adc_init(void)
{
      ADMUX = 0b01000000; //0x40
      ADCSRA |= 0x80;
}
int readadchan(char n)
{
//read ch n of internal 10 bit a/d
      int ad=0x0000;
      int buf;

      ADMUX = n;
      ADMUX |= 0x40;
      ADCSRA |= 0x44;

      while((ADCSRA & 0x40) !=0){}; //wait for conv complete
      ad = ad | ADCL;
      buf = ADCH & 0xFF00;
      ad |= buf;
      return ad;
}

int main(void)
{
      DDRA = 0x00;
      DDRD = 0xFF;
      PORTD = 0x00;
      LCD_init();
      
      unsigned char *k1;
      unsigned char *k2;
      unsigned char *m1;
      unsigned char *m2;
      k1="";
      k2="";
      
      LCD_Send_String("Read1 : ");
      LCD_Send(0xC0,0);
      LCD_Send_String("Read0 : ");
      
      int a0;
      int a1;
      int s;
      adc_init();
      
      while(1)
      {                 
            a1 = readadchan(0x01);  //Read from ADC1
            a0 = readadchan(0x00);  //Read from ADC0
 
            m1 = itoa(a1,k1,10);  //Convert 'a1' to string 'k1'
            m2 = itoa(a0,k2,10);  //Convert 'a0' to string 'k2'

           
            LCD_Send(0x88,0);   //Line1
            LCD_Send_String(k1);      
            LCD_Send(0xC8,0);   //Line2
            LCD_Send_String(k2);      
            _delay_ms(100000);
       }
}

It turns out to write the same number of what I read on ADC0 to both line, seem that 'k1' equals to 'k2'. :shock: :shock: :shock:

that I change code to

      while(1)
      {                 
            a1 = readadchan(0x01);
            a0 = readadchan(0x00);
 
            m1 = itoa(a1,k1,10);
           
            LCD_Send(0x88,0);
            LCD_Send_String(k1);      
            LCD_Send(0xC8,0);

            m1 = itoa(a0,k1,10);

            LCD_Send_String(k1);      
            _delay_ms(100000);
      }

It shows different numbers on both line, so it seperates the value. :? :? :?

I would like to see how both 2 code is actually works. Is there anyone can explain me?

Thank you for reading my long post.
Got

"Chill out with Atmel Corp."
- Scud88.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
      
      unsigned char *k1;
      unsigned char *k2;
      unsigned char *m1;
      unsigned char *m2;

No, don't think so. You need to create new strings and allocate space for each one of them, rather than use a pointer. If you use a pointer the strings would all be plonked into the first few bytes of RAM because they all start with the address NULL, or 0. Because they are all at the same address, converting your second number to a string overwrites the first number. M1, M2, K1 and K2 are all pointing to NULL (address 0), so when you read any of them you get the same result.

Try:

      
      unsigned char k1[5];
      unsigned char k2[5];
      unsigned char m1[5];
      unsigned char m2[5];

You will need to change the [5]'s to the maximum length of each string, plus a byte for the terminator. For example, if K1's maximum length is 8 bytes, put a 9 in the brackets for K1.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

scud88;

In the following:

int readadchan(char n)
{
//read ch n of internal 10 bit a/d
// int ad=0x0000;
// int buf;

ADMUX = n;
// ADMUX |= 0x40; //<--- ADLAR: 0x40, Why do you want to left justify?
ADCSRA |= 0x44; //<--- Auto trigger & CLK/16

while((ADCSRA & 0x40) !=0){}; //<--- Shouldn't this be ADIF: 0x10, not ADATE:: 0x40?
/* ad = ad | ADCL;
buf = ADCH & 0xFF00;
ad |= buf;
return ad;*/
return (ADC); //<--- How about this?
}

I haven't tested this because I don have an LCD set up but, I don't think you need or want to "Left Justify the ADC data and then try to convert it to ASCII.

If memory serves me correctly, you don't have to access the high and low bytes of the ADC independently. you can access the whole ADC integer using the generic ADC define.

You didn't say which compiler you are using. I am using ImageCraft ICCAVR 6.xx & 7.xx. I don't know if this will work on the complier that you are using. I only have experience with ImageCraft so these things may not apply.

Let me know if this helps.

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Also,

If ADIF should be the correct bit;:

while((ADCSRA & 0x40) !=0){}; //<--- Shouldn't this be ADIF: 0x10, not ADATE:: 0x40? ^

-----------------------------------------
should be:

while((ADCSRA & 0x40) ==0); //<--- Shouldn't this be ADIF: 0x10, not ADATE:: 0x40?

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Also,

If ADIF should be the correct bit;:

while((ADCSRA & 0x40) !=0){}; //<--- Shouldn't this be ADIF: 0x10, not ADATE:: 0x40?

should be:

while((ADCSRA & 0x40) ==0); //<--- Shouldn't this be ADIF: 0x10, not ADATE:: 0x40?

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Also,

If ADIF should be the correct bit;:

while((ADCSRA & 0x40) !=0){}; //<--- Shouldn't this be ADIF: 0x10, not ADATE:: 0x40?

should be:

while((ADCSRA & 0x10) ==0); //<--- Shouldn't this be ADIF: 0x10, not ADATE:: 0x40?

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

scud88,

Reading further:

int readadchan(char n)
{
//read ch n of internal 10 bit a/d

ADMUX = n;
ADCSRA |= 0x44; //<--- Auto trigger & CLK/16

while((ADCSRA & ADIF) ==0); //<--- Shouldn't this be ADIF: 0x10, not ADATE:: 0x40?
ADCSRA |= ADIF; // The ADIF flag bit needs to be written to a one to clear the ADIF flag.
return (ADC); //<--- How about this?
}

I cleaned the ADC function up a bit. I hope you don't mind

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

microcarl;

sorry for late response

I use WinAVR compiler.

Quote:

int readadchan(char n)
{
//read ch n of internal 10 bit a/d
// int ad=0x0000;
// int buf;

ADMUX = n;
// ADMUX |= 0x40; //<--- ADLAR: 0x40, Why do you want to left justify?
ADCSRA |= 0x44; //<--- Auto trigger & CLK/16

while((ADCSRA & 0x40) !=0){}; //<--- Shouldn't this be ADIF: 0x10, not ADATE:: 0x40?
/* ad = ad | ADCL;
buf = ADCH & 0xFF00;
ad |= buf;
return ad;*/
return (ADC); //<--- How about this?
}

ADMUX |= 0x40;

It is not a left justify, it said in the datasheet it REFS0 bit. I want the AVCC to be my reference voltage.

while((ADCSRA & 0x40) !=0){};

• Bit 6 – ADSC: ADC Start Conversion
In Single Conversion mode, write this bit to one to start each conversion. In Free Running
Mode, write this bit to one to start the first conversion. The first conversion after
ADSC has been written after the ADC has been enabled, or if ADSC is written at the
same time as the ADC is enabled, will take 25 ADC clock cycles instead of the normal
13. This first conversion performs initialization of the ADC.
ADSC will read as one as long as a conversion is in progress. When the conversion is
complete, it returns to zero. Writing zero to this bit has no effect.

So i think I get it right for this line.

return (ADC); //<--- How about this? 

Arhh it works.

Anyway thank you very much for suggestions.

"Chill out with Atmel Corp."
- Scud88.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, I was looking on page 246 of the mega64 datasheet.

I didn't know which Uc you were using, and this is what I'm using. I figured that the ADC would be pretty close between Uc's.

Ok! Re-reading again, I see! I missed the last statement for the ADSC usage. 2:00 am is a little late (or early) to be figuring this stuff out.

If I mis-lead you, I apologize.

I rarely use more then one ADC channel. And as such, I usually run the ADC in "Free Run" mode so I haven't a whole lot of experience with the other modes.

So, did you get it working? And if so, what does the code look like for the ADC?

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Scud88,

You'll find that abcminicomputer is correct. You need to allocate a buffer for your strings. In general though, try to brake down what you're doing into different steps. You're doing an ADC reading then a string conversion then writing it to the LCD. To start with ignore the LCD part and the ADC part. Just convert an integer then write it out the serial port. (I assume you've got a serial port routine already). Once you get that working THEN add in the ADC stuff. Once you get that working THEN add in the LCD stuff.

Dave.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

DaveAvr, nice to see someone backing me up. Usually I miss somthing and end up being plain wrong, and when microcarl (AvrFreaks god #8) didn't say anything I thought I was incorrect as usual. Apparently now that the holidays are over and i'm answering threads at times OTHER than 2am, my knowlege seems to have improoved ;).

And yes, "ADC" is defined as the concenation of the two ADC registers in GCC for convenience.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

abcminiuser,

Quote:
...and when microcarl (AvrFreaks god # didn't say anything I thought I was incorrect as usual.

God! I don't think so! I just love electronics and AVR's

The gods all have 5 & 6 stars. If you haven't noticed, I only have 3.

Scud88,

Quote:
while((ADCSRA & 0x40) !=0){};

I guess 0x20 doesn't equal 0x40.

I get up at about 6:00 am every morning, leave for work at about 11:30 am, work til mid-night, get home at 1:00 am go to bed at about 2:00 am, and do it all over again the next day. So I guess I am pretty much in the land of the Zombies all week.

Did you get the code working?

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Oh! Hey, I just noticed I have 4 stars... I wonder when that happened!!!

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I use WinAVR compiler.
======================
Dont they have a whole special forum for those questions? Procedure for getting free help step one: ask in right forum

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In the AVR-GCC forum, the moderators tend to take any questions about generic C concepts (such as the need to allocate sufficient buffers for strings), and questions about AVR hardware (such as the correct mapping of bits to functionality in the various AVR peripheral registers), and punt them back to the general AVR forum.

Last Edited: Tue. Oct 11, 2005 - 02:42 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Bob,

I wish they would setup a forum for ICCAVR!

I guess there aren't enough of us to warrent the time to set it up and the server space.

I have been thinking of setting up a Dev-board, just so I can work out some of the code questions presented on the forum. Some are pretty interesting. Others are simply educational for me. It's kind of like asking a question about "Task Switching". I am actually using a modified version of that.

They say:: If you think you know about something, teach it. Only then will you really learn and understand it.

I don't know if that is really true. I do know that if you really do know about something, you should be able to explain it.

But then effective communication depends on a lot of things...

For me, I like learning. Helping others solve their problems has a tendency to clarify what I already know. I also learn and realize things that I wouldn't have learned, otherwise.

Scud88 is one of those who presents good questions, so I find myself getting caught up in helping her. err! I think Scud88 is female. Sorry if you're not!!!

Others ask really dumb questions, or ask questions that have been asked a trillian times before, the answers of which, are located in multiple areas on the forum. Those questions tend to iritate me because, the person posing the question is just too lazy to do a search or, even try to learn the answer on their own.

Learning is a personal experience. I learned in college that, professors don't necsessarily teach about subject matter, they teach you about the discovery process, and how to teach yourself - learning techniques and where to find the neccessary information.

One this is for sure! What you take away from the educational experience is directly proportional to the effort that you put into it.

Geesh! I must be tired! Am I rambling, or what?

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Wise words, Microcarl. Teaching does help see exactly how much you know about the subject, and reinforces that knowlege.

Others ask really dumb questions, or ask questions that have been asked a trillian times before, the answers of which, are located in multiple areas on the forum. Those questions tend to iritate me because, the person posing the question is just too lazy to do a search or, even try to learn the answer on their own.

One would hope that i'm not guilty of this (I too get irrate with those STILL asking the "where is cbi and sbi" - and also "N00B! HELP ME URGENT!!!!!!!!" threads) although I apologise if I have done this in the past.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!