EmbeddedRelated.com
Forums

SW uart using TimerA and HFxtal 8MHz

Started by Martijn Broens June 21, 2002

Hi,

 

Did anyone ever do a SW usart using a HF xtal (8MHz) on XT2?? Or is there any one who can tell me where I can find more info on using Timer A for usart app's other than SLAC049.??

 

Martijn



Beginning Microcontrollers with the MSP430

I just got TimerA UARTs working yesterday, using the MSP430F149 with an
8MHz crystal on LFXT1 (shouldn't be any difference other than the TimerA
clock source configuration).  I just did a bit of hacking to the SLAC049 appnote
code to get 3 UARTs working simultaneously.  The code below is by no means
complete but it'll at least start echoing characters.  It worked for me up
to 57600bps.  At 115200 bps the last few bits weren't echoed properly for
some reason, haven't yet figured that out.  A total of 5 serial ports on
the F149 - thats hard to beat on a uC.
 
matt b.
 
 
#define BAUD    57600L
#define ACLK 8000000L
 
#define BitTime (1.0/(float)BAUD)
#define TICSPERBITTIME ((unsigned int)(BitTime * (float)ACLK))
#define TICSPERHALFBITTIME (TICSPERBITTIME / 2) 
 
unsigned long ulbaud;
unsigned int RXTXData;
unsigned char BitCnt;
unsigned char UARTA_Dir[3];
 
void TX_Byte (int Port);
void RX_Ready (int Port);
 
#include <msp430x14x.h>
 
/** local definitions **/
#define TACCTL              ((unsigned int*) CCTL0_) /* Timer A Capture/Compare
Control Register (for C) */
#define TACCR               ((unsigned int*) CCR0_) /* Timer A Capture/Compare
Register (for C) */
#define TBCCTL              ((unsigned int*) TBCCTL0_) /* Timer B
Capture/Compare Control Register (for C) */
#define TBCCR               ((unsigned int*) TBCCR0_) /* Timer B Capture/Compare
Register (for C) */
 
/* UART0/1 Source Clock Definitions */
#define UASSEL_UCLK         0x00
#define UASSEL_ACLK         0x10
#define UASSEL_SMCLK        0x20            

void main (void)
{
 unsigned int i;
 WDTCTL = WDTPW + WDTHOLD;             // Stop watchdog timer
 
 BCSCTL1 |= XTS;                       // ACLK = LFXT1 = HF XTAL
 
 do 
 {
  IFG1 &= ~OFIFG;                       // Clear OSCFault flag
  for (i = 0xFF; i > 0; i--);           // Time for flag to set
 }
 while ( IFG1 & OFIFG );               // OSCFault flag still set?          
     
 
 BCSCTL2 |= SELM1+SELM0;               // MCLK = LFXT1 (safe)
 
 TACTL = TASSEL0+MC1;                  // ACLK, continous mode
 
 TACCTL[0] = OUT;                          // TXD Idle as Mark 
 TACCTL[1] = OUT;                          // TXD Idle as Mark 
 TACCTL[2] = OUT;                          // TXD Idle as Mark 

 //         Rx  Tx
 // UARTA0 - P2.2  P1.1   (same as bootstrap loader)
 // UARTA1 - P1.2 P2.3
 // UARTA2 - P1.3    P2.4
 
 P1SEL = 0x0e; // 0b00001110;
 P1DIR = 0x02; // 0b00000010;
 P2SEL = 0x1c; // 0b00011100;
 P2DIR = 0x18; // 0b00011000;
 
 ulbaud = ACLK / TICSPERBITTIME;
 
 // Mainloop
 while (1)
 {
    // Echo the Recieved char on all three ports
//  RX_Ready(0);                           // UART ready to RX one Byte
  RX_Ready(1);                           // UART ready to RX one Byte
//   RX_Ready(2);                           // UART ready to RX one Byte
  _BIS_SR(CPUOFF+GIE);                  // Enter LPM0 Until character RXed
  i = RXTXData;
  TX_Byte(0);                            // TX Back RXed Byte Received
  RXTXData = i;
  TX_Byte(1);                            // TX Back RXed Byte Received
  RXTXData = i;
  TX_Byte(2);                            // TX Back RXed Byte Received
 }
}
 

// Function Transmits Character from RXTXData Buffer
void TX_Byte (int port)
{
 BitCnt = 0xA;                         // Load Bit counter, 8data + ST/SP
 TACCR[port] = TAR;                           // Current state of TA counter
 TACCR[port] += TICSPERBITTIME;               // Some time till first bit
 RXTXData |= 0x100;                    // Add mark stop bit to RXTXData 
 RXTXData <<= 1;                // Add space start bit
 UARTA_Dir[port] = 0;
 TACCTL[port] = OUTMOD0+CCIE;     // TXD = mark = idle
 while ( TACCTL[port] & CCIE );               // Wait for TX completion
}
 

// Function Readies UART to Receive Character into RXTXData Buffer
void RX_Ready (int port)
{
 BitCnt = 0x8;                         // Load Bit counter
 if (port == 0)
  TACCTL[port] = SCS+CCIS0+OUTMOD0+CM1+CAP+CCIE;   // Sync,
Neg Edge, Capture, CCIxB
 else
  TACCTL[port] = SCS+OUTMOD0+CM1+CAP+CCIE;   // Sync, Neg Edge,
Capture, CCIxA
 UARTA_Dir[port] = 1;
}
 

// Timer A0 interrupt service routine
interrupt[TIMERA0_VECTOR] void Timer_A0 (void)
{
 CCR0 += TICSPERBITTIME;               // Add Offset to CCR0
 
 // RX
 if (UARTA_Dir[0] == 1)                    // RX on CCI0B?
 {
  if( CCTL0 & CAP )                   // Capture mode = start bit edge 
  {
   CCTL0 &= ~ CAP;                     // Switch from capture to compare
mode 
   CCR0 += TICSPERHALFBITTIME;
  }
  else
  {
   RXTXData >>= 1;           
   if (CCTL0 & SCCI)                 // Get bit waiting in receive latch
    RXTXData |= 0x80;                 
   BitCnt --;                        // All bits RXed?
   if ( BitCnt == 0)
   //>>>>>>>>>> Decode of Received Byte Here
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
   {
    CCTL0 &= ~ CCIE;                  // All bits RXed, disable interrupt
    _BIC_SR_IRQ(CPUOFF);              // Clear LPM0 bits from 0(SR)
   }
   //>>>>>>>>>> Decode of Received Byte Here
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  }
 }
 // TX
 else
 {
  if ( BitCnt == 0)
   CCTL0 &= ~ CCIE;                    // All bits TXed, disable interrupt
  else
  {
   CCTL0 |=  OUTMOD2;                  // TX Space
   if (RXTXData & 0x01)                 
    CCTL0 &= ~ OUTMOD2;                 // TX Mark
   RXTXData >>= 1;
   BitCnt --;
  }
 }
}
 

// Timer A1 interrupt service routine
interrupt[TIMERA1_VECTOR] void Timer_A1 (void)
{
 int nCCR = TAIV >> 1;
 
 TACCR[nCCR] += TICSPERBITTIME;               // Add Offset to CCR0
 
 // RX
 if (UARTA_Dir[nCCR] == 1)
 {
  if( TACCTL[nCCR] & CAP )                   // Capture mode = start bit
edge 
  {
   TACCTL[nCCR] &= ~ CAP;                     // Switch from capture to
compare mode 
   TACCR[nCCR] += TICSPERHALFBITTIME;
  }
  else
  {
   RXTXData = RXTXData >> 1;           
   if (TACCTL[nCCR] & SCCI)                 // Get bit waiting in receive
latch
    RXTXData |= 0x80;                 
   BitCnt --;                        // All bits RXed?
   if ( BitCnt == 0)
   //>>>>>>>>>> Decode of Received Byte Here
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
   {
    TACCTL[nCCR] &= ~ CCIE;                  // All bits RXed, disable
interrupt
    _BIC_SR_IRQ(CPUOFF);              // Clear LPM0 bits from 0(SR)
   }
   //>>>>>>>>>> Decode of Received Byte Here
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  }
 }
 // TX
 else
 {
  if ( BitCnt == 0)
   TACCTL[nCCR] &= ~ CCIE;                    // All bits TXed, disable
interrupt
  else
  {
   TACCTL[nCCR] |=  OUTMOD2;                  // TX Space
   if (RXTXData & 0x01)                 
    TACCTL[nCCR] &= ~ OUTMOD2;                 // TX Mark
   RXTXData = RXTXData >> 1;
   BitCnt --;
  }
 }
}


-----Original Message-----
From: Martijn Broens [mailto:martijn@mart...]
Sent: Friday, June 21, 2002 2:13 AM
To: 'msp430@'msp...'
Subject: [msp430] SW uart using TimerA and HFxtal 8MHz



Hi,

 

Did anyone ever do a SW usart using a HF xtal (8MHz) on XT2?? Or is there any
one who can tell me where I can find more info on using Timer A for usart
app's other than SLAC049.??

 

Martijn



 <http://www.fastweb.com/ib/yahoo-79f>" target="_blank" rel="nofollow">http://rd.yahoo.com/M8320.2150041.3600347.1829184/D=egroupweb/S05005378:HM/A9988/R=0/*http://www.fastweb.com/ib/yahoo-79f>
	
 
<http://us.adserver.yahoo.com/l?M8320.2150041.3600347.1829184/D=egroupmail/S05005378:HM/A9988/rand0458455>
	

.



">http://docs.yahoo.com/info/terms/> . 



hallo Martijn,
 
I assume you've had a look at the user's guide ?
Case you don't have hardcopy, SLAU049.
If not, Timer_A chapter has more info on how a capture/compare channel is deployed
to do soft UART.
I personally haven't had an app where it was the way to go, it still requires INTs at bit level,
rather than character level, defeats purpose a bit, unless baudrates are quite low.
(ie say up to 9600 bps)
 
At least you still can build up an INT driven second "UART" in a F13X part..
 
While on subject of USARTs (well actually just UART) :
 
I'd been considering taking off a few hours to "play" around and setup
a UART with an SPI port to an MCU in a CPLD.
It'd be in VHDL, and would have a "bare-bones" UART implementation, so
say a 32 macocell CPLD with 100-200 product terms should be able to hold
a half/full (?) duplex UART.
 
Anyone has any suggestions what they still would require as a minimum ?
I'd upload it as free VHDL code to one of the VHDL sites like in Hamburg.
 
This is to get an idea of what resources/product terms would be needed.
 
For example, in many MCU apps I did, getting a "Frame error" or "overrrun"
flag is all good and well - but -
what do you generally do when a frame error tells you your stop bit was "0" on ASYNC ?
Many times not much you can at character level I guess..............
 
Hence the request for anyone's input.
I would post it for free, anyone can use it.
A "bussed" version would be optional, but the general concept would be
that a fully funtional UART is "tacked on" to an MCU if need be, and that you
talk to it via an SPI line. (or bit banged).
 
Say, a typical 32/64 macrocell PLCC Xilinx Coolrunner has about 32 I/O lines, hence there
might be a few extra "SPI commands" to read/write say 3 extra 8 I/O "ports " on the CPLD.
For a few $ you'd have an expansion of 1/2 UARTs and 3 x 8 bit I/O ports via SPI at very low
current.
RTS/CTS might be useful ...?
 
Any input ?
 
Kris.
 
 
 
----- Original Message -----
From: Martijn Broens
To: 'msp430@yahoogroups.com'
Sent: Friday, June 21, 2002 4:13 PM
Subject: [msp430] SW uart using TimerA and HFxtal 8MHz

Hi,

 

Did anyone ever do a SW usart using a HF xtal (8MHz) on XT2?? Or is there any one who can tell me where I can find more info on using Timer A for usart app's other than SLAC049.??

 

Martijn



">msp430-unsubscribe@egroups.com



">Yahoo! Terms of Service.


Thanks for the reply i'm trying it now

 

Martijn

 

-----Oorspronkelijk bericht-----
Van: Matthew Bivans [mailto:mbivans@rpco2.com]
Verzonden: vrijdag 21 juni 2002 14:08
Aan: msp430@yahoogroups.com
Onderwerp: RE: [msp430] SW uart using TimerA and HFxtal 8MHz

 

I just got TimerA UARTs working yesterday, using the MSP430F149 with an 8MHz crystal on LFXT1 (shouldn't be any difference other than the TimerA clock source configuration).  I just did a bit of hacking to the SLAC049 appnote code to get 3 UARTs working simultaneously.  The code below is by no means complete but it'll at least start echoing characters.  It worked for me up to 57600bps.  At 115200 bps the last few bits weren't echoed properly for some reason, haven't yet figured that out.  A total of 5 serial ports on the F149 - thats hard to beat on a uC.

matt b.


#define BAUD    57600L
#define ACLK 8000000L

#define BitTime (1.0/(float)BAUD)
#define TICSPERBITTIME ((unsigned int)(BitTime * (float)ACLK))
#define TICSPERHALFBITTIME (TICSPERBITTIME / 2)

unsigned long ulbaud;
unsigned int RXTXData;
unsigned char BitCnt;
unsigned char UARTA_Dir[3];

void TX_Byte (int Port);
void RX_Ready (int Port);

#include <msp430x14x.h>

/** local definitions **/
#define TACCTL              ((unsigned int*) CCTL0_) /* Timer A Capture/Compare Control Register (for C) */
#define TACCR               ((unsigned int*) CCR0_) /* Timer A Capture/Compare Register (for C) */
#define TBCCTL              ((unsigned int*) TBCCTL0_) /* Timer B Capture/Compare Control Register (for C) */
#define TBCCR               ((unsigned int*) TBCCR0_) /* Timer B Capture/Compare Register (for C) */

/* UART0/1 Source Clock Definitions */
#define UASSEL_UCLK         0x00
#define UASSEL_ACLK         0x10
#define UASSEL_SMCLK        0x20           

void main (void)
{
unsigned int i;
WDTCTL = WDTPW + WDTHOLD;             // Stop watchdog timer

BCSCTL1 |XTS;                       // ACLK = LFXT1 = HF XTAL

do
{
  IFG1 &~OFIFG;                       // Clear OSCFault flag
  for (i = 0xFF; i > 0; i--);           // Time for flag to set
}
while ( IFG1 & OFIFG );               // OSCFault flag still set?               

BCSCTL2 |SELM1+SELM0;               // MCLK = LFXT1 (safe)

TACTL TASSEL0+MC1;                  // ACLK, continous mode

TACCTL[0] OUT;                          // TXD Idle as Mark
TACCTL[1] OUT;                          // TXD Idle as Mark
TACCTL[2] OUT;                          // TXD Idle as Mark

//         Rx  Tx
// UARTA0 - P2.2  P1.1   (same as bootstrap loader)
// UARTA1 - P1.2 P2.3
// UARTA2 - P1.3    P2.4

P1SEL = 0x0e; // 0b00001110;
P1DIR = 0x02; // 0b00000010;
P2SEL = 0x1c; // 0b00011100;
P2DIR = 0x18; // 0b00011000;

ulbaud = ACLK / TICSPERBITTIME;

// Mainloop
while (1)
{
    // Echo the Recieved char on all three ports
//  RX_Ready(0);                           // UART ready to RX one Byte
  RX_Ready(1);                           // UART ready to RX one Byte
//   RX_Ready(2);                           // UART ready to RX one Byte
  _BIS_SR(CPUOFF+GIE);                  // Enter LPM0 Until character RXed
  i = RXTXData;
  TX_Byte(0);                            // TX Back RXed Byte Received
  RXTXData = i;
  TX_Byte(1);                            // TX Back RXed Byte Received
  RXTXData = i;
  TX_Byte(2);                            // TX Back RXed Byte Received
}
}


// Function Transmits Character from RXTXData Buffer
void TX_Byte (int port)
{
BitCnt 0xA;                         // Load Bit counter, 8data + ST/SP
TACCR[port] = TAR;                           // Current state of TA counter
TACCR[port] +TICSPERBITTIME;               // Some time till first bit
RXTXData |0x100;                    // Add mark stop bit to RXTXData
RXTXData <<1;                // Add space start bit
UARTA_Dir[port] = 0;
TACCTL[port] OUTMOD0+CCIE;     // TXD = mark = idle
while ( TACCTL[port] & CCIE );               // Wait for TX completion
}


// Function Readies UART to Receive Character into RXTXData Buffer
void RX_Ready (int port)
{
BitCnt 0x8;                         // Load Bit counter
if (port == 0)
  TACCTL[port] SCS+CCIS0+OUTMOD0+CM1+CAP+CCIE;   // Sync, Neg Edge, Capture, CCIxB
else
  TACCTL[port] SCS+OUTMOD0+CM1+CAP+CCIE;   // Sync, Neg Edge, Capture, CCIxA
UARTA_Dir[port] = 1;
}


// Timer A0 interrupt service routine
interrupt[TIMERA0_VECTOR] void Timer_A0 (void)
{
CCR0 +TICSPERBITTIME;               // Add Offset to CCR0

// RX
if (UARTA_Dir[0] == 1)                    // RX on CCI0B?
{
  if( CCTL0 & CAP )                   // Capture mode = start bit edge
  {
   CCTL0 &= ~ CAP;                     // Switch from capture to compare mode
   CCR0 += TICSPERHALFBITTIME;
  }
  else
  {
   RXTXData >>1;          
   if (CCTL0 & SCCI)                 // Get bit waiting in receive latch
    RXTXData |0x80;                
   BitCnt --;                        // All bits RXed?
   if ( BitCnt == 0)
   //>>>>>>>>>> Decode of Received Byte Here <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
   {
    CCTL0 &= ~ CCIE;                  // All bits RXed, disable interrupt
    _BIC_SR_IRQ(CPUOFF);              // Clear LPM0 bits from 0(SR)
   }
   //>>>>>>>>>> Decode of Received Byte Here <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  }
}
// TX
else
{
  if ( BitCnt == 0)
   CCTL0 &= ~ CCIE;                    // All bits TXed, disable interrupt
  else
  {
   CCTL0 |=  OUTMOD2;                  // TX Space
   if (RXTXData & 0x01)                
    CCTL0 &= ~ OUTMOD2;                 // TX Mark
   RXTXData >>= 1;
   BitCnt --;
  }
}
}


// Timer A1 interrupt service routine
interrupt[TIMERA1_VECTOR] void Timer_A1 (void)
{
int nCCR = TAIV >> 1;

TACCR[nCCR] +TICSPERBITTIME;               // Add Offset to CCR0

// RX
if (UARTA_Dir[nCCR] == 1)
{
  if( TACCTL[nCCR] & CAP )                   // Capture mode = start bit edge
  {
   TACCTL[nCCR] &= ~ CAP;                     // Switch from capture to compare mode
   TACCR[nCCR] += TICSPERHALFBITTIME;
  }
  else
  {
   RXTXData = RXTXData >> 1;          
   if (TACCTL[nCCR] & SCCI)                 // Get bit waiting in receive latch
    RXTXData |0x80;                
   BitCnt --;                        // All bits RXed?
   if ( BitCnt == 0)
   //>>>>>>>>>> Decode of Received Byte Here <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
   {
    TACCTL[nCCR] &= ~ CCIE;                  // All bits RXed, disable interrupt
    _BIC_SR_IRQ(CPUOFF);              // Clear LPM0 bits from 0(SR)
   }
   //>>>>>>>>>> Decode of Received Byte Here <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  }
}
// TX
else
{
  if ( BitCnt == 0)
   TACCTL[nCCR] &= ~ CCIE;                    // All bits TXed, disable interrupt
  else
  {
   TACCTL[nCCR] |=  OUTMOD2;                  // TX Space
   if (RXTXData & 0x01)                
    TACCTL[nCCR] &= ~ OUTMOD2;                 // TX Mark
   RXTXData = RXTXData >> 1;
   BitCnt --;
  }
}
}


-----Original Message-----
From: Martijn Broens [mailto:martijn@abiom.nl]
Sent: Friday, June 21, 2002 2:13 AM
To: 'msp430@yahoogroups.com'
Subject: [msp430] SW uart using TimerA and HFxtal 8MHz



Hi,



Did anyone ever do a SW usart using a HF xtal (8MHz) on XT2?? Or is there any one who can tell me where I can find more info on using Timer A for usart app's other than SLAC049.??



Martijn


Yahoo! Groups Sponsor     

ADVERTISEMENT
<http://www.fastweb.com/ib" target="_blank" rel="nofollow">http://rd.yahoo.com/M8320.2150041.3600347.1829184/D=egroupweb/S05005378:HM/A9988/R=0/*http://www.fastweb.com/ib/yahoo-79f>      
  <
http://us.adserver.yahoo.com/l?M8320.2150041.3600347.1829184/D=egroupmail/S05005378:HM/A9988/rand0458455

>      





">Yahoo! Terms of Service.