This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Help with code creation for ADuC847 in C

Hey everyone,

I recently purchased an ADuC847 eval board, and am very green when it comes to coding in assembly and/or C. I have several questions when it comes to figuring out the code syntax, and small details which I'm most likely missing. I'm trying to figure out how to take three different analog measurements and output them (~1sec delay) in an ASCII character string such as (AxxxxxByyyyyCzzzzz). I've got the output looking like this so far: AxxxxxxByyyyyyCzzzzzz. If someone could advise me on how to reduce the x,y,z outputs from 6 to 5, hopefully without causing inaccurate readings, that would be great. 

The other issue I'm having is that I am struggling with turning on the other analog inputs of the device, or if I turn them on, its displaying the same measurement three times. The code that I have placed below is very basic, and was started with the example code that came with the software.

I've also tried to write a delay program, but insofar I've only got it to freeze after outputting the string. Thoughts? The code doesn't include an attempt to turn on the other analog inputs, I originally tried it in using only ASM51, but have since switched to C and am not sure how to proceed with accomplishing that task.

My code is as follows:  

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <ADuC847.h> //Some of these include files may not be necessary

sbit LED = 0x0B4;

void delay(int);

void ADC_int () interrupt 6
{
LED ^= 1;
printf("\n\n");
printf("A%bX%bX%bX",ADC0H,ADC0M,ADC0L); //This will output 21 ASCII digits.
printf("B%bX%bX%bX",ADC0H,ADC0M,ADC0L); //Needs to be reduced to 19 characters
printf("C%bX%bX%bX",ADC0H,ADC0M,ADC0L); //Need to reduce from 21 characters to 19

for(;;)
{
P3 ^= 0x10;
delay(10);
}
}
void delay(int length)
{
while (length >=0)
length--;
}
void main (void)
{
//Configure UART
PLLCON = 0x90;
T3CON = 0x82; //115200 Baud rate
T3FD = 0x2D;
SCON = 0x52;

//CONFIGURE ADC AND START CONVERTING....
ICON = 0x01; //Turn on IEXC1 source to drive RTD.
SF = 0x200;
ADC0CON1 = 0x22; //Full Buffer, Unipolar, 80mV range.
ADC0CON2 = 0x4A; //Refin+/-, Ain1->Ain2
EADC = 1; //Enable ADC Interrupt
EA = 1; //Enable Global Interrupts
ADCMODE = 0x23; // continuous conversion on Main channel on main channel

//WAIT FOR INTERRUPTS....
while(1);
}

The following is the output:

The A,B,C are required as part of my task so I cannot simply rid my code of the output here.

I'll do what I can to answer any questions you all have. Thanks for your time.

Parents
  • Your suggestions have been immensely helpful! I've taken a lot of your pseudo code, and turned them into functions. There are a few problems I'm still having, and so I have a few more questions if you don't mind:

    1. For starting the ADC, that is done by simply placing a value into the ADCMODE register correct? When I change the analog channel that I'm reading from do I really need to reenable the ADCMODE again? I figured it would still be converting, but just from a different channel now. Here's the code that I have that enables which port I want to read from, and starts the conversions:

    void selectChannel1()
    {
    	ADC0CON2 = 0x40;
    	ADCMODE = 0x23; //ADC enabled, CHOP enabled, continuous conversion
    }
    
    void selectChannel2()
    {
    	ADC0CON2 = 0x81;
    	ADCMODE = 0x23; //ADC enabled, CHOP enabled, continuous conversion
    }
    
    void selectChannel5()
    {
    	ADC0CON2 = 0x04;
    	ADCMODE = 0x23; //ADC enabled, CHOP enabled, continuous conversion
    }

    My next question is about buffering the data from these inputs. I'm unsure of how to get that done, I've programmed the register ADC0CON1 to be a full buffer, Unipolar, 2.56V, but I'm sure there's more to it. Could you point me in the right direction here?

    Your suggestion for using the (ADC0L >> 4) command was a godsend. I've posted my code below with descriptions of what's going on:

    This is the main body of the code, I've been slowly including functions as I figure out how to create them, and the ones that still need work are commented out:

    sbit LED = 0x0B4;
    
    void main (void)
    {
    	//Configure the board to communicate 115200 baud
    	baud();
    	
    	//Initialize the ADC
    	ADC();
    	
    	while(1)
    	{
    		printf("\n\n");
    		selectChannel1();	//selects which pin to read analog signals from.
    		//startADC();
    		//wait_for_ADC_conversion();
    		//Place data in buffer
    		printf("A%bX%bX%bX",ADC0H,ADC0M,(ADC0L >> 4)); //prints Axxxxx data
    		selectChannel2();
    		//startADC();
    		//wait_for_ADC_conversion();
    		//place data in buffer
    		printf("B%bX%bX%bX",ADC0H,ADC0M,(ADC0L >> 4)); //prints Byyyyy data
    		selectChannel5();
    		//startADC();
    		//wait_for_ADC_conversion();
    		//place data in buffer
    		//send data packet
    		printf("C%bX%bX%bX",ADC0H,ADC0M,(ADC0L >> 4)); //prints Czzzzz data
    		delay(150);	//~1 sec delay
    	}

    This is the function that sets my baud rate to 115200:

    void baud ()
    {
    	PLLCON = 0x90;
    	T3CON = 0x82;
    	T3FD = 0x2D;
    	SCON = 0x52;
    }
    	

    This function initializes the ADC:

    void ADC()
    {
    	ICON = 0x01; 	//Turn on IEXC1 source to drive RTD
    	SF = 0x45;		//Initialize the special function registers
    	ADC0CON1 = 27;//Full Buffer, Bipolar, +/-2.56V range	
    	EADC = 1;		//Enable ADC Interrupt
    	EA = 1;			//Enable Global Interrupts
    	//ADCMODE = 0x23; //ADC enabled, CHOP enabled, continuous conversion
    }

    Again, thanks for any and all help you may provide!

Reply
  • Your suggestions have been immensely helpful! I've taken a lot of your pseudo code, and turned them into functions. There are a few problems I'm still having, and so I have a few more questions if you don't mind:

    1. For starting the ADC, that is done by simply placing a value into the ADCMODE register correct? When I change the analog channel that I'm reading from do I really need to reenable the ADCMODE again? I figured it would still be converting, but just from a different channel now. Here's the code that I have that enables which port I want to read from, and starts the conversions:

    void selectChannel1()
    {
    	ADC0CON2 = 0x40;
    	ADCMODE = 0x23; //ADC enabled, CHOP enabled, continuous conversion
    }
    
    void selectChannel2()
    {
    	ADC0CON2 = 0x81;
    	ADCMODE = 0x23; //ADC enabled, CHOP enabled, continuous conversion
    }
    
    void selectChannel5()
    {
    	ADC0CON2 = 0x04;
    	ADCMODE = 0x23; //ADC enabled, CHOP enabled, continuous conversion
    }

    My next question is about buffering the data from these inputs. I'm unsure of how to get that done, I've programmed the register ADC0CON1 to be a full buffer, Unipolar, 2.56V, but I'm sure there's more to it. Could you point me in the right direction here?

    Your suggestion for using the (ADC0L >> 4) command was a godsend. I've posted my code below with descriptions of what's going on:

    This is the main body of the code, I've been slowly including functions as I figure out how to create them, and the ones that still need work are commented out:

    sbit LED = 0x0B4;
    
    void main (void)
    {
    	//Configure the board to communicate 115200 baud
    	baud();
    	
    	//Initialize the ADC
    	ADC();
    	
    	while(1)
    	{
    		printf("\n\n");
    		selectChannel1();	//selects which pin to read analog signals from.
    		//startADC();
    		//wait_for_ADC_conversion();
    		//Place data in buffer
    		printf("A%bX%bX%bX",ADC0H,ADC0M,(ADC0L >> 4)); //prints Axxxxx data
    		selectChannel2();
    		//startADC();
    		//wait_for_ADC_conversion();
    		//place data in buffer
    		printf("B%bX%bX%bX",ADC0H,ADC0M,(ADC0L >> 4)); //prints Byyyyy data
    		selectChannel5();
    		//startADC();
    		//wait_for_ADC_conversion();
    		//place data in buffer
    		//send data packet
    		printf("C%bX%bX%bX",ADC0H,ADC0M,(ADC0L >> 4)); //prints Czzzzz data
    		delay(150);	//~1 sec delay
    	}

    This is the function that sets my baud rate to 115200:

    void baud ()
    {
    	PLLCON = 0x90;
    	T3CON = 0x82;
    	T3FD = 0x2D;
    	SCON = 0x52;
    }
    	

    This function initializes the ADC:

    void ADC()
    {
    	ICON = 0x01; 	//Turn on IEXC1 source to drive RTD
    	SF = 0x45;		//Initialize the special function registers
    	ADC0CON1 = 27;//Full Buffer, Bipolar, +/-2.56V range	
    	EADC = 1;		//Enable ADC Interrupt
    	EA = 1;			//Enable Global Interrupts
    	//ADCMODE = 0x23; //ADC enabled, CHOP enabled, continuous conversion
    }

    Again, thanks for any and all help you may provide!

Children
  • 1. For starting the ADC, that is done by simply placing a value into the ADCMODE register correct?

    I did not read the manual of this device in detail, but I think you are right. However, in your functions 'selectChannel1/2/5' you select the right channel, but different reference voltages. Do you do this intentionally? Directly after these functions are left, you output the values with a printf. This will for sure not work, because the ADC will need time for the conversion. You should check the RDY0 in the ADCSTAT register if the ADC has finished the conversion.

    When I change the analog channel that I'm reading from do I really need to reenable the ADCMODE again?

    Yes, I think so, but I'm not an expert for this ADC.

    This function initializes the ADC:

    In this function you enable the interrupt for the ADC. I think this is wrong because your don't use ISRs to collect the values.

    My next question is about buffering the data from these inputs. I'm unsure of how to get that done,

    What I meant is that you should read the ADC0H/M/L registers when the conversion is completed and copy these values into local or global variables before you start the next conversion. This way, the values are consistent before you output them via printf.

  • Thanks! I've reworked the code and got it almost perfect! There are a few issues I'm still having, but I have some potential solutions before coming here for more questions. The delays between the data acquisitions worked flawlessly, and I've made sure that the delay is long enough to allow for the conversion to be completed. Thanks again for your help.