S12ZVC_ multiple ADC channels

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

S12ZVC_ multiple ADC channels

Jump to solution
3,226 Views
sungyulchu
Contributor II

Hello,

 

I'd like to use two ADC channels simultaneously.

(MC9S12ZCV-Family)

(I have two different analog inputs and they are occured simultaneously.)

 

but according to ADC12B_LBA Block Diagram, ADC12B_LBA receives only one signal from the ext.channel MUX.

 

In this condition, Can't I get two ADC signal at the same time?

 

Should one Analog input signal wait the other signal until the other signal passes the ADC block?

 


Labels (1)
1 Solution
1,928 Views
iggi
NXP Employee
NXP Employee

Hi,

However, If two ADC channles are used,  the ADCCMD_1 register should be set whenever before each ADC channel is used.

(is it right?) and so ADCCMD_1 register should be seperated from the ADC_Init Code.

Yes, it is right.

You can define commands in the same way like variables and then use it in the main or ISRs etc.

Each command is actually the sum of 4 ADC command register. This gives 32-bit number (dword). For example:

volatile dword ADC_Command1 = 0x00CDA000;

     /* CMD0 = Normal Conversion no interrupts = 0x00

       * CMD1 = VRH1, VRL1, HVI (Internal 5)= 0xCD

       * CMD2 = 24 clock cycles = 0xA0

       * CMD3 = Index = 0x00

    */

You can have more of these defined (ADC_Command2, ADC_Command3,...). For each command you shoul have result variable defined as well (ADC_Result1, ADC_Result2,...)

A better way is to have two arrays defined: ADC Command List and ADC Result List. For example:

volatile char ADC0CL[3][4]  = {

      {0x00,0xD0,0x00,0x00},   // Normal Conversion + no int [C0], Analog Input Channel AN0 [D0], 4 clock cycles sample time [00], reserved [00]

      {0x00,0xD1,0x00,0x00},   // Normal Conversion]+ no int [C0], Analog Input Channel AN1 [D1], 4 clock cycles sample time [00], reserved [00]

      {0x00,0x00,0x00,0x00},    

}

volatile unsigned int ADC0RL[3]  = {0, 0, 0};

The module init function can be something like below:

void InitADC0(void)

{

     /*Set ADC0*/

       ADC0CTL_0 = 0x0D;     /*Dual access, trigger mode*/

       /*single CSL & RVL buffers, Normal access Automatic restart after stop*/

       ADC0CTL_1 = 0x10;    

       ADC0STS = 0x00;       /*Select CSL 0 & RVL 0*/

       ADC0TIM = 0x01;       /*Select 32MHz/(2*(1+1)) = 8MHz*/

       ADC0FMT = 0x82;       /*10Bits right justified*/

/////////////////////////////////////////////////////////////////

       /*Set the command pointers*/

       ADC0CBP = ADC0CL;

       /*Set the results pointer*/

       ADC0RBP = ADC0RL;

///////////////////////////////////////////////////////////////     

       /*Start Conversion*/

       ADC0CTL_0 |= 0x80;    /*Enable ADC*/

       ADC0FLWCTL = 0x20;    /*Trigger Restart event*/

}

As you can see there command base pointer register used to get the values which is then used to calculate the final address from which the conversion commands will be loaded.

And aslo result base pointer register which defines address in the RAM to which conversion results will be stored to at the end of a conversion.

See S12ZVx ref. manulal for detailed information.

I am preparing the SW example which wil demonstrate ADC conversions on the S12ZVM device. This should be posted on the community soon.

Regards,

iggi

View solution in original post

5 Replies
1,928 Views
iggi
NXP Employee
NXP Employee

Hi,

No you can't convert signals from two analog channels at the same time. The ADC block diagram is clear.

One ADC module samples one channel at the time. After conversion is done and value is stored to the memory, the module can proceed and sample again (another channel).

On some devices, there can be 2 ADC modules - ADC0 and ADC1 for example. You can enable both and use them simultaneously for two different channels, but still you won't get the same time conversion for two channels. CPU executes instructions one by one. I don't think both ADCs can be trigerred by one instruction and also store both conversion value at the same time.

Regards,

iggi

1,928 Views
sungyulchu
Contributor II

Thank you for your response.

I am confused of setting registers when I want to use two ADC channels.

To use two ADC channels,

ADCCMD_1 (ADC Comman Register 1) -> CH_SEL[5:0] bits are set to 010000 (AN0), 010001 (AN1).

Now, I have a ADC_Init Code which can set the registers and this ADC_Init code is executed once when Main() function starts.

So, When I use a single ADC channel (AN0), this method works well because ADCCMD_1 is needed to be set once as AN0.

However, If two ADC channles are used,  the ADCCMD_1 register should be set whenever before each ADC channel is used.

(is it right?) and so ADCCMD_1 register should be seperated from the ADC_Init Code.

I am trying to set ADCCMD_1 before each ADC channel is read. (ADC_Read function is in the Timer Interrupt code).

(ex.

ADC0CMD_1_CH_SEL=0x10 //AN0

ADC_Result=ADC_Read();

ADC0CMD_1_CH_SEL=0x11 //AN1

ADC_Result=ADC_Read();

)

But I wonder it may cause any unstable operation if register value is adjusted every time (in the timer interrupt).
Do you have any recommendation to set this code to use multiple channel ADC?

Best Regards,

Sung Yul Chu.

0 Kudos
Reply
1,929 Views
iggi
NXP Employee
NXP Employee

Hi,

However, If two ADC channles are used,  the ADCCMD_1 register should be set whenever before each ADC channel is used.

(is it right?) and so ADCCMD_1 register should be seperated from the ADC_Init Code.

Yes, it is right.

You can define commands in the same way like variables and then use it in the main or ISRs etc.

Each command is actually the sum of 4 ADC command register. This gives 32-bit number (dword). For example:

volatile dword ADC_Command1 = 0x00CDA000;

     /* CMD0 = Normal Conversion no interrupts = 0x00

       * CMD1 = VRH1, VRL1, HVI (Internal 5)= 0xCD

       * CMD2 = 24 clock cycles = 0xA0

       * CMD3 = Index = 0x00

    */

You can have more of these defined (ADC_Command2, ADC_Command3,...). For each command you shoul have result variable defined as well (ADC_Result1, ADC_Result2,...)

A better way is to have two arrays defined: ADC Command List and ADC Result List. For example:

volatile char ADC0CL[3][4]  = {

      {0x00,0xD0,0x00,0x00},   // Normal Conversion + no int [C0], Analog Input Channel AN0 [D0], 4 clock cycles sample time [00], reserved [00]

      {0x00,0xD1,0x00,0x00},   // Normal Conversion]+ no int [C0], Analog Input Channel AN1 [D1], 4 clock cycles sample time [00], reserved [00]

      {0x00,0x00,0x00,0x00},    

}

volatile unsigned int ADC0RL[3]  = {0, 0, 0};

The module init function can be something like below:

void InitADC0(void)

{

     /*Set ADC0*/

       ADC0CTL_0 = 0x0D;     /*Dual access, trigger mode*/

       /*single CSL & RVL buffers, Normal access Automatic restart after stop*/

       ADC0CTL_1 = 0x10;    

       ADC0STS = 0x00;       /*Select CSL 0 & RVL 0*/

       ADC0TIM = 0x01;       /*Select 32MHz/(2*(1+1)) = 8MHz*/

       ADC0FMT = 0x82;       /*10Bits right justified*/

/////////////////////////////////////////////////////////////////

       /*Set the command pointers*/

       ADC0CBP = ADC0CL;

       /*Set the results pointer*/

       ADC0RBP = ADC0RL;

///////////////////////////////////////////////////////////////     

       /*Start Conversion*/

       ADC0CTL_0 |= 0x80;    /*Enable ADC*/

       ADC0FLWCTL = 0x20;    /*Trigger Restart event*/

}

As you can see there command base pointer register used to get the values which is then used to calculate the final address from which the conversion commands will be loaded.

And aslo result base pointer register which defines address in the RAM to which conversion results will be stored to at the end of a conversion.

See S12ZVx ref. manulal for detailed information.

I am preparing the SW example which wil demonstrate ADC conversions on the S12ZVM device. This should be posted on the community soon.

Regards,

iggi

1,928 Views
sungyulchu
Contributor II

Thank you for your response.

I set ADC0CBP and ADC0RBP as you guided using ADC0CL and ADC0RL arrays.

volatile char ADC0CL[3][4]  = {

      {0x00,0xD0,0x00,0x00},   // Normal Conversion + no int [C0], Analog Input Channel AN0 [D0], 4 clock cycles sample time [00], reserved [00]

      {0x00,0xD1,0x00,0x00},   // Normal Conversion]+ no int [C0], Analog Input Channel AN1 [D1], 4 clock cycles sample time [00], reserved [00]

      {0x00,0x00,0x00,0x00},    

}

Q1)

In case of using two channels (AN0, AN1)

Why did you put third row

{0x00,0x00,0x00,0x00},    

?

What does it mean?

Q2)

If CMD_SEL is Normal conversion, only AN0 channel can convert ADC signals. (The other Channel, AN1 did not show any analog input)

So, I had to fix the CMD_SEL bits as belows.

volatile char ADC0CL[3][4]  = {

         {0x00,0xD0,0x00,0x00},   // Normal Conversion + no int [C0], Analog Input Channel AN0 [D0], 4 clock cycles sample time [00], reserved [00]

         {0x00,0xD2,0x00,0x00},   // Normal Conversion]+ no int [C0], Analog Input Channel AN1 [D1], 4 clock cycles sample time [00], reserved [00]

         {0xC0,0x00,0x00,0x00},    

   };

I set the CMD_SEL bits of the last row to 0xC0 (End of List.)

then two ADC channels begins to work.

Could you check your CMD_SEL bits?

Regards,

Sung Yul Chu.

1,928 Views
iggi
NXP Employee
NXP Employee

Q1) No meaning. You can delete if you don't need it.

Q2) I overlooked that. You can put 'end of list' in 2nd command as well, since it is the last command here.

0 Kudos
Reply