Hello everyone,
First of all, thanks for providing such an informative and helpful forum. E2E and it's contributors are a fantastic reasource. Please bear with me as I am an analog guy, just (3 weeks) new to uC programming with C and the MSP430 launchpad, and very much enjoying myself.
I would like explore the feasibility of using an MSP430F5172 (with the high resolution Timer_D module) to control and measure pulse trains for a compact ultrasonic time-of-flight flowmeter. For the flowmeter measurement principle to work properly, I need to generate acoustic signals and determine their transit time down to +/-10ns.
My time crictical routine is:1) Write a sequence of deterministic pulses to 4 separate pins/channels to excite the transmit transducer2) Idle for yet-to-be-determined amount of time (~60us after first excite pulse) 3) Start Timer_D4) Capture 2 rising edges and 2 falling edges during the middle of an incoming, signal-conditioned pulse train sequence from my receive transducer5) Prevent the CCR registers from overflowingNote: My transducer frequency is 300kHz. So with MCLK = 25MHz, I should be able to service CCIFG interrupt and stop Timer_D within 39 clock cycles.
For this scheme to work, I have to know that my time-critical execution will always take the same number of MCLK cycles.
------------------------------------------------------------------------------Translated into pseudocode:
1) Disable all interrupts except for CCIFG in Timer_D2) Set up Timer_D: 200MHz, Up count, CCR1 capture rising edges, CCR0 falling edges, etc.
//Time T=0: ***Time-Critical execution of code starts here***P1OUT = 0x01; // Start of +HV pulse__delay_cycles(10)P1OUT = 0x00; // End of +HV pulse__delay cycles(HV+_delay) P1OUT = 0x02; // Start of -HV pulse__delay_cycles(HV-_length)P1OUT = 0x00; ... more P1OUT writes for other pulses ...__delay_cycles(until_arrival) // Delay until known midpoint of incoming pulsetrain
TDxCTL0 |= MC__CONTINOUS // Start Timer_Dwhile(1); // Wait for 2 rising edge and 2 falling edge captures, to trigger Timer D CCR interrupt
__interrupt void TIMER1_D0(void){ TDxCTL0 |= MC__STOP; // Stop TDR before any capture overflows, read arrival time of the acoustic pulses}
Here are the big questions:
Are there any "gotchas" that would cause +/- MCLK cycles of execution during my time cricial routine?
Outside of my time cricital routine I plan to do calculations and relay results over I2C/SPI. Would this affect my MSP's stack/heap/bus/flash/mojo and introduce uncertainty into my time-critical sequence exectution?
Will simple procedural code such as the above, with no branching, compile predictably, or do I need to learn assembly?
Thanks for your help!
-Thomas
Hi Thomas, your design can be more simple using the high resolution of C2000 series that can generate and measure pulse within GHz resolution too, last MSP series include a timer D subsystem and EVENT CONTROL performing similar measurement with less resolution.
If you wish to generate few pulses I don't understand why you are needing 4 pin or you wish shaping the pulse?
On the other way all timing generation delay and measurement must be done on the same timer to avoid jitter and misalignment of counter:
No need to learn assembly but just usage of hardware to reduce effort.
Regards
Roberto
Please login & click Verify Answer if this post answered your question.
Thanks, Roberto. Hmm. I'll take another look at the Piccolo F280xx family. I overlooked that they have high-res modules as well.
Yes, the reason I need 4 pin output is for pulse-shaping and transducer damping.
I also realize that I optimize this process with hardware resources (Timer_A or Timer_D2) to trigger events. However because I exceed the number of CCRs for my pulse shaping, I must depend on some clock-cycle consistent software execution.
I guess my question is more fundamental to the MSP430 architecture in the sense that if I write a subroutine of non-branching code (with all external interrupts disabled) to do simple port setting tasks, or set a tightly-controlled timer interrupt to wake the CPU from LPM0 and do some other simple task like starting Timer_D, can I depend on this code to always execute in the same number of clock cycles?
- Thomas
Thomas Ruschering Timer_D, can I depend on this code to always execute in the same number of clock cycles?
Hi Thomas, sorry for late answer, you depend on TAR of timer D to avoid jitter, a cpu intensive routine can drive the pulse shaping then arm the comparator channels and wait the complete transfer of echo pulses. DMA can help this process but another timer is needed to terminate acquire process.
About Piccolo, If the MSP resolution is enough you don't need it if more fine under nS resolution CC2xxx series or MSP and an FPGA is the solution.
Thanks Roberto.
I wrote some routines this weekend using both timerAs on the G2553 and confirmed that simple port-setting non-branching code (with interrupts disabled, of course) runs consistently down to the clock cycle. Given the architecture similarity, I have no reason to believe this same approach would not work on the F5712.
I plan to use a short cpu sequence to "pulse" 4 separate channels, then go to LPM0 (keeping a HF xtal running for accuracy), wake up on an interrupt 60us later and start timer_D.
Best, Thomas
Thomas Ruscher I plan to use a short cpu sequence to "pulse" 4 separate channels, then go to LPM0 (keeping a HF xtal running for accuracy), wake up on an interrupt 60us later and start timer_D.
I deducted your measurement are on liquid wave propagation so a small jitter error affect too much precision, not cpu intensive by itself but this way:
read TAR than add a value to be sure all code to pulse shaping is executed with some skew then do shaping in sync with tar values, this require no CC channel usages and Jiitter on shaping is no more than few cpu cycles too. If this is not enough try build some different precision hardware shaping by Compare logic then switch to capture for echos measurement.
example:
// time critical cpu intensive part, no irq can be allowed from here to avoid jiitter...
....IRQ_OFF...
TAR=0;
MyPulses=TAR+skew;
...preparing code....
while(TAR<Mypulses);
....pulse1....
Mypulses+=delay2pulse2;
....pulse2....
...repeat to pulse4...
switch to capture and arm end of sequence timer.
IRQ ON