I am having difficulty with ATD on Dragon 12-plus

cancel
Showing results for 
Search instead for 
Did you mean: 

I am having difficulty with ATD on Dragon 12-plus

1,700 Views
skatingdisaster
Contributor I

I am providing the code that I have so far.  Ignore the commented sections because I am not complete with it at the moment.  My goal here is to read from three ports, PAD01 - 03 with the input from an Accelerometer.  In the function for ATD0CTL5 register, I want to read in from each output of the accelerometer, X, Y, and Z which should give me values for each axis.  I am not sure if I wrote it in the code correctly though.  I believe I have it set up for only to read in for PAD02 but I am not sure the proper procedure to write it for three sequences of input.

 

// accelerometer

#include <mc9s12dp256.h>
#include <stdio.h>
extern int _textmode;

// globals
unsigned char dvalues[3]; // array to hold digitized values from one sequence

// function prototype
void init_ATD0(void);
void load_ADC0interrupt_addr(void);
//load ADC Interrupt vector into vector table
void convert(void);
void ADC0_handler(void);
void delayvar(int multiplier);

// main start here
void main (void){
// unsigned char x=0;
// unsigned char y=0;

/*load_ADC0interrupt_addr( ); // load ADC Interrupt vector into vector table
init_ATD0( );
convert( ); // start conversion
delayvar(5);
*/


while(1){
/*
if(lowVx < x-input > highVx)
// printf("Value x=%d\n\r",x-input);
// Send interrupt because tilt is out of range

if(lowVy < y-input > highVy)
// printf("Value y=%d\n\r",y-input);
// Send interrupt because tilt is out of range
*/

} // End while
} // End main

// functions
void delayvar(int multiplier){ // a variable delay: multiplier = 125 is ~5 sec.
unsigned int i,j,k;
for(i=0;i<multiplier;i++){
for(j=0;j<0xFF;j++){
for(k=0;k<0xFF;k++){
asm("nop");
}
}
}
}
// End delayvar
void init_ATD0( ){
ATD0CTL2 = 0x82;
// turn on ADC unit 0, FFCA=1, ASCIE=1(enables ATD0 interrupt) 11000010
delayvar(3); // stabilize ADC unit electronics
ATD0CTL3 = 0x18; // 0001 1000 = 3 conversions/sequence
ATD0CTL4 = 0x8B; // 8-bit resolution, 2 A/D clk/conv., 1 MHz conv. frequency
}
void convert(void){
ATD0CTL5 = 0x32;
// left justify, unsigned, scan multi, Ch. 2&3, begin sampling, uses AN2-> PAD02
while((ATD0STAT & 0X80) == 0){
}
dvalues[0] = ATD0DR0H;
dvalues[1] = ATD0DR1H;
dvalues[2] = ATD0DR2H;
}

/*
void load_ADC0interrupt_addr( ){
asm("pshx");
asm("ldx #_ADC0_handler");
asm("stx $3e52"); // loads the isr for the ADC0_handler into the...
asm("pulx"); // ..pseudo-vector table
}

#pragma interrupt_handler ADC0_handler( )

void ADC0_handler(void){ //reads out results from ATD0DRx regs. and stores them
unsigned char *ptr = &dvalues[0]; //variable pointer to storage area 4 results
// puts("\nProgram Interrupted\n\r"); //comment out: causes delay & affects data
asm("sei"); // mask further interrupts until this service finishes
ptr[0] = ATD0DR0H;
ptr[1] = ATD0DR1H;
asm("cli"); // reenable interrupt in order get next sequence
}
*/

Labels (1)
0 Kudos
4 Replies

154 Views
Fonsi
Contributor I

in order to get 3 ADC channel's result values, you have to turn the multiplexer to route the signal or potential to the correct internal channel. It that has to be done one step at a time for each of the channels used. What you show in your init routine seems to be writing the correct control bits. However, your convert routine needs to take a channel number and write to the control register to start the analog convertion sequence on 3 channels. ie in polled mode.

word result1, result2, result3;

 

result1 Convert(channel 3); 

result2 Convert(channel 4);

result3 Convert(channel 5); 

result=result1+result2+result3;

 

i hope, i understood what you were trying to do and came up with the correct explanation.

 

Good luck. 

0 Kudos

154 Views
skatingdisaster
Contributor I

So how should I change the dvalues array?  Should I make it larger?
I am still confused on how the conversions and sequences come into play.  What do the conversions in a sequence represent?


For the ATD0CTL2, I should have 0xC2 instead correct?  ( 1100 0010 ) so the flag is cleared.

 

And the delay I saw in one of the older programs I had for a lab.  The comment it gave was  to stablize ADC unit electronics.  The delay function is from an older lab as well.  In the older programs I saw, they all used a 5us delay.

 

I also think I may have to use a nonFIFO mode.  I think when I do that, the data in the array will be reset once it completes a sequence.  So for ATD0CTL3 register, would I use 0xxxx000?

I am not positive on how to implement the conversions for sequence.

0 Kudos

154 Views
Lundin
Senior Contributor IV
Declare it as

volatile unsigned char dvalues[3];

If you don't understand why, I'd strongly recommend to read a beginner book about embedded programming. Here is a good online one:

http://users.ece.utexas.edu/~valvano/embed/toc1.htm
0 Kudos

154 Views
Lundin
Senior Contributor IV
You have a fatal bug here:

unsigned char dvalues[3];

Since this is shared by the ISR, it must be volatile. This seems like a likely cause of the problem.


ATD0CTL2 = 0x82; // turn on ADC unit 0, FFCA=1, ASCIE=1(enables ATD0 interrupt) 11000010

Despite your comment, you do not set the AFFC. This means you must clear the flag manually, which you don't seem to do anywhere in the ISR.

As a parenthesis, I wonder if the delay between the write to ATD0CTL2 and ATD0CTL3 is necessary. Where did you read that?

0 Kudos