|
ADC Sample Code Z8FS021A - Single Shot.. 1 Year, 5 Months ago
|
Karma: 1
|
|
Hi,
I am wondering if anyone has any sample code that they can share on doing a single shot ADC. I am developing a battery powered Zmotion application and would like to report back the voltage level of the battery when asked.
Currently planning on using Pin 16 - PC0/ANA4 as input to the voltage divider on the battery..
|
|
|
|
|
|
|
Re:ADC Sample Code Z8FS021A - Single Shot.. 1 Year, 5 Months ago
|
Karma: 1
|
I been working on sample code and haven't had much luck. Here is what I have so far. Any ideal of what I am doing wrong?
| Code: |
#include <ez8.h>
#include <defines.h>
#define ADCCTL0 (*(unsigned char volatile far*)0xF70) // Reset = 0x00 ADC Control 0
#define ADCCTL1 (*(unsigned char volatile far*)0xF71) // Reset = 0x00 ADC Control 1
#define ADCD_H (*(unsigned char volatile far*)0xF72) // Reset = 0xXX ADC Data High
#define ADCD_L (*(unsigned char volatile far*)0xF73) // Reset = 0xXX ADC Data Low
/**********************************************************************************************************
** init_PORTC0()
**
** Initialize Port C0 (ADA0) to be ADC for single shot.
**
** Step 1: Enable port for input
** Step 2: Write to ADC Contro / Status register. ADC
**
***********************************************************************************************************/
void init_PORTC0(void) {
PCADDR = 0x02; //Port C Alternate Function
PCCTL &= 0x02; //Select Alternate Function
PCADDR = 0x01; //Port C Data Direction
PCCTL |= 0x01; //Port C bit 1 is configured as Input
PCADDR = 0x00; // close off changes to PC
} /*init_PORTC0*/
/*******************************************************************************
** void main(void)
**
** Main Routine for the program. This program runs in conjunction with debug
** to view the data generated from the ADC.
**
********************************************************************************/
void main(void) {
UINT8 ADChigh=0x00;
UINT8 ADClow=0x00;
UINT16 ADCdata;
init_PORTC0();
ADCCTL1 &= 0x78; // 0XXX X000 (ANA0) :
// 7>REFSEL_H=0, 6:3>RESERVED, 2:0> BUFMODE=000 (single-ended, unbuffered)
ADCCTL0 = 0xC0; // 1100 0000 (ANA0) Internal 1v ref,
// 7>CEN = 1, 6>REFSEL_L=1, 5>REFOUT=0, 4>CONT=0, 3:0>000 (ANA0)
while(ADCCTL0 & 0x80); // Wait until ADC is finish (when CEN goes to low)
ADChigh = ADCD_H;
ADClow = ADCD_L;
if (!(ADClow & 0x01)) { // If OVF is not 1, then data is good.
ADCdata = (ADChigh <<8)| (ADClow); //ADC output word
ADCdata = (ADCdata >> 3) & 0xFFF; //12-bits ADC
} else { // Bad data.. set to FFFF.
ADCdata = 0xFFFF; // Max out
}
} // END OF MAIN
|
|
|
|
|
|
|
|
Re:ADC Sample Code Z8FS021A - Single Shot.. 1 Year, 5 Months ago
|
Karma: 1
|
I been working on sample code and haven't had much luck. Here is what I have so far. Any ideal of what I am doing wrong?
| Code: |
#include <ez8.h>
#include <defines.h>
#define ADCCTL0 (*(unsigned char volatile far*)0xF70) // Reset = 0x00 ADC Control 0
#define ADCCTL1 (*(unsigned char volatile far*)0xF71) // Reset = 0x00 ADC Control 1
#define ADCD_H (*(unsigned char volatile far*)0xF72) // Reset = 0xXX ADC Data High
#define ADCD_L (*(unsigned char volatile far*)0xF73) // Reset = 0xXX ADC Data Low
/**********************************************************************************************************
** init_PORTC0()
**
** Initialize Port C0 (ADA0) to be ADC for single shot.
**
** Step 1: Enable port for input
** Step 2: Write to ADC Contro / Status register. ADC
**
***********************************************************************************************************/
void init_PORTC0(void) {
PCADDR = 0x02; //Port C Alternate Function
PCCTL &= 0x02; //Select Alternate Function
PCADDR = 0x01; //Port C Data Direction
PCCTL |= 0x01; //Port C bit 1 is configured as Input
PCADDR = 0x00; // close off changes to PC
} /*init_PORTC0*/
/*******************************************************************************
** void main(void)
**
** Main Routine for the program. This program runs in conjunction with debug
** to view the data generated from the ADC.
**
********************************************************************************/
void main(void) {
UINT8 ADChigh=0x00;
UINT8 ADClow=0x00;
UINT16 ADCdata;
init_PORTC0();
ADCCTL1 &= 0x78; // 0XXX X000 (ANA0) :
// 7>REFSEL_H=0, 6:3>RESERVED, 2:0> BUFMODE=000 (single-ended, unbuffered)
ADCCTL0 = 0xC0; // 1100 0000 (ANA0) Internal 1v ref,
// 7>CEN = 1, 6>REFSEL_L=1, 5>REFOUT=0, 4>CONT=0, 3:0>000 (ANA0)
while(ADCCTL0 & 0x80); // Wait until ADC is finish (when CEN goes to low)
ADChigh = ADCD_H;
ADClow = ADCD_L;
if (!(ADClow & 0x01)) { // If OVF is not 1, then data is good.
ADCdata = (ADChigh <<8)| (ADClow); //ADC output word
ADCdata = (ADCdata >> 3) & 0xFFF; //12-bits ADC
} else { // Bad data.. set to FFFF.
ADCdata = 0xFFFF; // Max out
}
} // END OF MAIN
|
|
|
|
|
|
|
|
Re:ADC Sample Code Z8FS021A - Single Shot.. 1 Year, 5 Months ago
|
Karma: 4
|
Hi Don
Here is a really basic sample:
| Code: |
//Selected internal reference 2.0Volts default
void init_adc(void)
{
ADCCTL0 = 0x00; // ADC conversion disable,
//Select ANA0
//Internal reference voltage 2.0V
//Disable reference voltage out, single shot conversion
ADCCTL1 = 0x81; // Single-ended, buffered with unity gain
// Configure ANA0 - PB0 Alternate function 1
PBADDR = 0x02; //access to AF registers
PBCTL |= 0x01; //Turn on AF Subset 1 for PB0
PBADDR = 0x00; // release access
}
int get_adcval()
{
int val;
ADCCTL0 |= 0x80; //Start the conversion
while (ADCCTL0 & 0x80) ; //Wait until it is clear
val = (ADCD_H << 8) | ADCD_L;
return val;
}
void main()
{
int val;
init_adc();
while (1)
{
val = get_adcval() & 0x0FFF;
}
}
|
|
|
|
|
|
|
|
Re:ADC Sample Code Z8FS021A - Single Shot.. 1 Year, 5 Months ago
|
Karma: 4
|
|
Don,
I believe your problem is in your pin initialization.
PCADDR = 0x02;
PCCTL |= 0x01; //Set PC0 to alternate function (ANA4)
You are also initializing your ADC control registers differently that you comments in main().
ADCCTL1 = 0x00; //matches your comments
ADCCTL0 = 0xC4; //matches your comments only selecting ANA4
Let me know if this doesn’t help.
|
|
|
|
|
|
|
Re:ADC Sample Code Z8FS021A - Single Shot.. 1 Year, 5 Months ago
|
Karma: 1
|
|
Thanks for the feedback on my code. I have incorporate the suggestions and attached is the code. I think I got the ADC working, but the results are not what I am expecting.
When I wire the ADC to GND, I would expect to get 0x0000, however, I am getting 0x1FF8. When I connect the ADC to a AA battery, voltage 1.59v, I get 0x0AE1. I would expect with 2v reference, I would receive 0x0CB8.
My calculations are simple: INT( 1.59v / 2.0v (max) * 4096) ==> HEX = 0x0CB8.
Do I have something wrong with my code or my calculations for ADC value?
Using PC0 (ANA4):
/**********************************************************************************************************
** Initialize Port PC0 (ADA4) to be ADC for single shot.
**
** Step 1: Enable port for input
** Step 2: Write to ADC Control / Status register 1. ADCCTL1
**
** 1 X X X X 0 0 0 where X is unknown.
**
** Bit 7 - REFSEL_H = 1 (10 for 2v internal reference model)
** Bit 6:3 - RESERVED
** Bit 2:0 - BUFMODE - 000 - Single ended, unbuffered
**
**
** Step 3: Write to ADCCTL0 1010 0100
** 7>CEN = 1, 6>REFSEL_L=1, 5>REFOUT=0, 4>CONT=0, 3:0>100 (ANA4)
** Bit 7 - CEN = 1 to start the ADC conversion. When 0, it stops.
** Bit 6 - REFSEL_L = 1 - (01 lower part 01 for 1v internal ref)
** Bit 5 - REFOUT = 1 Internal Reference
** Bit 4 - CONT - Conversion 0 for single shot
** Bit 3:0 - Analog Input
**
** Step 4: CEN remains 1 until completion of conversion
**
** Step 5: CEN turns to 0 when completion of conversion, ADCD_H (7:0) & ADCD_L (7:3) = value of ADC
**********************************************************************************************************/
#include <ez8.h>
#include <defines.h>
#define ADCCTL0 (*(unsigned char volatile far*)0xF70) // Reset = 0x00 ADC Control 0
#define ADCCTL1 (*(unsigned char volatile far*)0xF71) // Reset = 0x00 ADC Control 1
#define ADCD_H (*(unsigned char volatile far*)0xF72) // Reset = 0xXX ADC Data High
#define ADCD_L (*(unsigned char volatile far*)0xF73) // Reset = 0xXX ADC Data Low
/**********************************************************************************************************
** init_adc()
**
** Initialize PORTC0 for input using alternate function and configure the ADC
**
***********************************************************************************************************/
void init_adc(void) {
ADCCTL0 = 0x00; // ADC conversion disable,
ADCCTL1 = 0x80; //
PCADDR = 0x02; //Port C Alternate Function
PCCTL |= 0x01; //Select Alternate Function for PC0
PCADDR = 0x00; // close off changes to PC
} /*init_PORTC0*/
/*******************************************************************************
** void get_adcval()
**
** Return the ADC value in an integer. Test using GND and 1.5v battery.
**
********************************************************************************/
int get_adcval(void)
{
UINT16 val;
ADCCTL0 = 0xA4; // Define ADC Control Register 1010 0100 = A4
// 7 - 1 CEN - Set to 1 to start ADC conversion
// 6 - 1 REFSELL - Value = 0 (lower of 10 for 2v conversion)
// 5 - 1 REFOUT - Value = 1 - Internal ADC reference
// 4 - 1 CONT - Value = 0 for single shot
// 3:0: Using ANA4 - Value = 0100;
while (ADCCTL0 & 0x80) ; //Wait until it is clear
val = (ADCD_H << 8) | ADCD_L;
val = val >> 3; // Mask off lower 3 bits and shift over 3 bits.
return val;
}
/*******************************************************************************
** void main(void)
**
** Main Routine for the program. This program runs in conjunction with debug
** to view the data generated from the ADC.
**
********************************************************************************/
void main(void) {
UINT16 val;
init_adc();
while (1)
{
val = get_adcval();
}
} // END OF MAIN
|
|
|
|
|
|
|