MC9S12XEP100 ADC question

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 
已解决

MC9S12XEP100 ADC question

跳至解决方案
1,823 次查看
roberthiebert
Senior Contributor I

MC9S12XEP100, Code Warrior V5.9.0 Build 5294 Special Edition, Absolute Assembler, Freescale USBDM.

I have a program where I would like to read the ADC channels separately. Rather than hold the program up while the conversions are being done, I would rather that it trigger an interrupt when the conversion is complete. Then I can service the interrupt from the main loop to process the result of the reading.

I have written a simple test program to read the first two ADC channels. The program runs but the variables that are supposed to hold the readings are not being written to. It looks like the interrupt is not being triggered. I have attached the program to see if anyone can suggest where am going wrong.

Thanks,

Robert Hiebert

0 项奖励
回复
1 解答
1,534 次查看
roberthiebert
Senior Contributor I

Hi Ladislav,

Thanks again for your detailed response. After thinking more about the FFC issues I decided to not enable it and do my flag clearing manually. That seemed to solve my problems, but I admit there may have been other things that got fixed in the process.

As for the question about conversion times, I did an experiment to measure the time it took from when I commanded a channel read to when it was completed. I am using 8,3MHz frequency with 24 conversions (for maximum accuracy), 10 bit resolution  and cap discharge. 

I set a flag when I commanded the read. Then I cleared the SCF flag. Then I wrote to ATD0CTL5. Then I waited for the flag to be set again. Then I read ATD0DR0H:ATD0DR0L and copied it to a variable. Then I set another flag for use in the main loop. Finally I set another flag to mark the finish point.

According to my digital signal processor, the whole procedure took 8.5 uS, which is considerably less time than I expected, but very good news (unless I made an error).

Anyway, it looks like I can continue developing my main program now. Thanks again for your patience and all your help.

Regards,

Robert

 

在原帖中查看解决方案

0 项奖励
回复
8 回复数
1,800 次查看
lama
NXP TechSupport
NXP TechSupport

Hi,

Like Lenin said "learn, learn, learn" we can say "debug, debug, debug".

 

The solution where one channel is converted, and data is read in an interrupt has one drawback. The previous measurement is interrupted by the next one if it was not completed before the next one is started. (RM states, ATDCTL5-Writes to this register will abort current conversion sequence and start a new conversion sequence.)

So, sometimes is not suitable to step some code but run to breakpoint is better.

In addition, if the interrupt is blocked by another with a higher priority and the next one is started then the data from the previous one is lost. Simply starting the next one at an inappropriate moment will cause the data from the previous measurement to be lost. Of course, it is possible to ensure that the new conversion will not be started before the previous one is processed - some kind of "measurement in progress" flag. I think it is a better solution to start a continuous conversion where both channels are measured constantly in a loop in the background and data can be read at any time from the ATDDR0 and ATDDDR1 registers. Interrupt is unnecessary in such solution.

 

Please look at the example I attached (one channel measured, data is read in an isr).

The example is very similar to yours just adjusted to my board.

; While debugging, pay attention to what is displayed in the memory window or

; the variables window, as fast clearing of the ATD flag is used, so reading

; ATDCTL by the debugger will clear the flag.

; In the example, I recommend first setting a breakpoint at RTI in

; the ATD0isr function and then running the code.

; you will see how atdChan and atdActiveChan work.

lama_0-1748085755455.png

 

You change adcChan sooner than data is read so there is incorrect input for data read.

 

Best regards,

Ladislav

0 项奖励
回复
1,762 次查看
roberthiebert
Senior Contributor I

Hi Ladislav,

I was able to run your program and it works flawlessly. I was able t set break points and follow along with what it does and it all makes sense..

My original program has the flaw that you pointed out. I was asking for the second read before the first one was finished. After studying your code I decided to simplify mine even more and just do one conversion on one channel, but I still couldn't get it to trigger the interrupt on completion.

I tied inserting this after loading ATD0CTL5, but the program would just hang at that point.

    brclr ATD0STAT0,ATD0STAT0_SCF,* ; Loop here until conversion is complete.

I don't know why it should hang here.

Just as an experiment I added a timer after I had set ATD0CTL5 to to read CH0. When the timer timed out I read the result and copied it to my variable. That worked, so I know the conversion was done, but the interrupt is not being triggered.

I'm pretty sure I have the ATD0 ISR configured correctly so I really don't know what is causing this. I'm attaching my latest attempt.

Regards,

Robert

0 项奖励
回复
1,713 次查看
lama
NXP TechSupport
NXP TechSupport

Hi,

as I wrote before the FFC feature is always "a little bit" problematic to debug. The flag can be deleted from anywhere by reading so it newer be 1. Try to use polling method for test you will see. (Never combine both methods ... AFFFC and manual flag clearing) The reading can be also from memory window or debugger vs MCU timing synchronization or ...I do not know.

Because of this I selected a breakpoint at specific place and only run it and checked behavior at this point. (selected chanel, converted chanel,...)

I know, it is a little bit confusing but reality for FFC.

Best regards,

Ladislav

0 项奖励
回复
1,690 次查看
roberthiebert
Senior Contributor I

Hi Ladislav,

I was thinking that perhaps I really don't have much, if any benefit in using the interrupt.

In table A-15, page 1219 of the manual, it states that the maximum conversion time (per channel?) is 41 clock cycles assuming 24 samples and capacitor discharge. If the ATD is running at 8.3MHz that works out to a 0.1248 uS period x 41 = 4.939 uS per channel conversion. I'll do some testing to see what my main loop times are to see if the conversion time is acceptable.

Is my conversion time calculation correct?

Regards,

Robert

 

 

0 项奖励
回复
1,619 次查看
lama
NXP TechSupport
NXP TechSupport

Hi,

I would like to ask you to open a new thread in the case of a new question which is not absolutely continuing previous topic ... like this one.

The answer is:

It is not only conversion time if you use also interrupt. Jump to subroutine means…the last instruction must be finished and then jump is probably 1us. Plus command start, data processing.

Because of this I used a lot of times continuous conversion if the number of channel was suitable to create acceptable loop time and just read data. Also, processing can be done on XGATE which can move data to variable used by CPU. Just necessary to know XGATE and semaphores.

 

However, your question was different…

 

From Table A-15. ATD Operating Characteristics we can get conversion time:

(Noteunder table….The minimum time assumes a sample time of 4 ATD clock cycles. The maximum time assumes a sample time of 24 ATD clock cycles and the discharge feature (SMP_DIS) enabled, which adds 2 ATD clock cycles.)

 

Conversion fATD Cycles min, 8bit resolution = 17 - 4 – 0 =13

Conversion fATD Cycles min, 10bit resolution = 19 - 4 – 0 =15

Conversion fATD Cycles min, 12bit resolution = 20 - 4  – 0 =16

Proof with max number of cycles:

Conversion fATD Cycles min, 8bit resolution = 39 - 24 – 2 =13

Conversion fATD Cycles min, 10bit resolution = 41 - 24 – 2 =15

Conversion fATD Cycles min, 12bit resolution = 42 - 24 – 2 =16

 

Sample fATD cycles … SMP[2..0]…=  {4;6;8;10;12;16;20;24}

 

Conversion fATD clocks = Sample fATD cycles + Conversion Cycles for X-bit resolution + discharge clocks=

= {4;6;8;10;12;16;20;24} + {13;15;16} + {0;2}

fATDCLK = fBUS / (2xPRS + 1)

and finally

Conversion period =  Conversion fATD clocks / fATDCLK

 

Best regards,

Ladislav

 

0 项奖励
回复
1,535 次查看
roberthiebert
Senior Contributor I

Hi Ladislav,

Thanks again for your detailed response. After thinking more about the FFC issues I decided to not enable it and do my flag clearing manually. That seemed to solve my problems, but I admit there may have been other things that got fixed in the process.

As for the question about conversion times, I did an experiment to measure the time it took from when I commanded a channel read to when it was completed. I am using 8,3MHz frequency with 24 conversions (for maximum accuracy), 10 bit resolution  and cap discharge. 

I set a flag when I commanded the read. Then I cleared the SCF flag. Then I wrote to ATD0CTL5. Then I waited for the flag to be set again. Then I read ATD0DR0H:ATD0DR0L and copied it to a variable. Then I set another flag for use in the main loop. Finally I set another flag to mark the finish point.

According to my digital signal processor, the whole procedure took 8.5 uS, which is considerably less time than I expected, but very good news (unless I made an error).

Anyway, it looks like I can continue developing my main program now. Thanks again for your patience and all your help.

Regards,

Robert

 

0 项奖励
回复
1,761 次查看
roberthiebert
Senior Contributor I

I'll try the attachment again

0 项奖励
回复
1,779 次查看
roberthiebert
Senior Contributor I

Hi Ladislav,

Thanks so much for your detailed response. The thought crossed my mind that perhaps my test code was asking for the second conversion too soon after I asked for the first, so I tried just doing one conversion, which didn't seem to work.

In my main code I am asking for single channel conversions at timed intervals, which will vary, but the shortest interval I expect to see would be 600 uS.

I will study your response and your attached code in detail and get back to you with what it has taught me.

Once again, I really appreciate that you have taken the time to help me with this.

Regards,

Robert

0 项奖励
回复