Jump to content

Project Help - Digital Command Control(DCC) Operation Using a timer

Recommended Posts

Hello, am relatively new to the MSP430 and my coding skills aren't that good yet, am using c on IAR. But am trying to produce this signal:http://www.modeltrainbuilder.com/DCC-operation.html . i kinda get the concept, but implementing it is a problem. I know you can set timer0 to a faster frequency, say 35KHz so that a period of 28us and then timer1 to output the signal. So for example if a bit is '1' Timer1 goes high for 2 timer0 periods and then low the same, and when a bit is '0' timer1 stays high for 4 timer0 periods and then low the same amount. An example code or anything really will be very helpful. 

Link to post
Share on other sites

Looking at the standard on the NMRA site (S-9.1 - http://www.nmra.org/sites/default/files/standards/sandrp/pdf/s-9.1_electrical_standards_2006.pdf), the timing isn't terribly tight.


If I were going to implement this, I'd use a single timerA and deal with the outputs in an  interrupt handler. Let the timer free run in continuous, and use CCR1 to set the interrupt time. Each entry to the interrupt, add the appropriate time to CCR1 and change the state of the output as appropriate. There are a number of ways to sequence the bits. I would probably not do it in the interrupt routine. I would use a semaphore to signal the main loop to prep the next bit, and place the value in a shared volatile.


I would run the timer from MCLK, and pretty much any calibrated speed would be fine for this... the timing is really not that tight (52-64us for each half of a `1' pulse) 8MHz clock is MORE than adequate, and 1MHz might even be OK, though the interrupt latency variability might make it sketchy for a receiver that isn't real tolerant. The `0' bits are so loose that timing for them isn't an issue (95 to 9900us for each half cycle, total less than 12000us) This is a perfect application for software handling of the data. For the 8MHz clock, I would set the timer to divide by 8, so it counts microseconds. Interrupt latency will be less than 3/4us (six processor clocks).


There are a number of standard samples showing the basic idea for using the interrupts this way, such as Example 1 in http://www.ccs.neu.edu/home/noubir/Courses/SWARM/S09/slides/msp430-clocks-timers.pdfor on pages23/24 of https://courses.cs.washington.edu/courses/cse466/11au/calendar/04-Interrupts-posted.pdf


A number of the timer examples in the TI MSP430 documents also use the same model.

Link to post
Share on other sites

There really isn't much to it.


In many contexts, it can get quite involved, but in a straightforward application on a small processor like the MSP430, you can keep it simple.


Def (working): Semaphore: A signal made available by one function for to indicatte a status or condition to one or more other functions, outside the standard call-return or exception models.


For your application, I would define an external (global; outside all functions) volatile (signal to the compiler that the variable can be changed from more than one place in an unsynchronized, unchecked, and independent manner, so that ANY access to the variable it via memory, not via temporary use of a processor register) integer that the interrupt handler sets to some value when a bit is complete, and the main loop watches to know when to prep the next bit.


For example: the semaphore value might also act as the timer increment, and the main loop looks for it to be reset to 0

// at header of code
// outside any function
volatile unsigned int nextbitcount=0;

// ...
// ...
// ...

// in main loop
// ...
// ...

// wit for the interrupt routine to be done with bit
   while (nextbitcount) { // nextbitcount!=0
      } // not ready for new value
   if (dataval &0x0080) { // is MSb of current byte a 1?
       nextbitcount = 58;
   } else {
       nextbitcount = 100;
   dataval = (dataval <<1);; // shift to bring next bit to MSb

// in interrupt handler
// ...
// ...
// the bit being used for output is in var outputbitmask
// if it is, for example, P1.5, outputbitmask is set by
// #define outputbitmask 0x20
   P1OUT ^= outputbitmask; // flip output bit
   CCR1 += nextbitcount; // time for next interrupt
   if (P1OUT & outputbitmask) { // was output set to high? lots of ways to test this
      // in second half cycle... time to update in main loop
      nextbitcount=0; // reset semaphore

This is not finished code, obviously. Note that there are three  parts: the external var that does double duty-- semaphore to signal condition to main and also communicates the data timing from main to the interrupt handler;the synch loop and bit handler in main (which is at best a model, as the main loop is unlikely to be be locked in a wait like this if it also needs to gather inputs, like throttle position, and sequence the data bytes and sync bits between them...but this is a model), and the interrupt handler, which may actually be pretty much written for you here.


This is a common model, and is used for a wide variety of tasks, including completely independent functions, such as when one interrupt handler needs to talk to another or two unsynchronized threads need to signal each other, though this is about the simplest application, and more by the time you get to multithreaded cases (not happening on the low end MSP430 in all likelyhood, but common in full operating systems like *nix) the signalling is generally done using a more involved library tool.

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Create New...