EmbeddedRelated.com
Forums

TI Example on msp430F2012 UART

Started by jpfrolic October 14, 2008
There has been some discussion on the UART using the DCO. And a
little more which got a little on the unfriendly side so was a bit
shy getting into this but what the heck!

I have had several problems with the software example provided by TI
in the sample code in C.

I cannot get the receive section to work and in desperation I just
wrote my own bit bang code which does not take advantage of the low
power savings but works. My code clip shows the addition of a
message "Hello World!' I used this snippet to isolate my problem,
which it did. The code as presented displays the message "Hello
World!" , but when I transmit a key closure on my TTY device I get
garbage characters. I think the code starts out in the receive mode
but ends up immediately in the echo mode. Any solutions so I can use
the low power mode?

You can see my addition of the "Hello World!". Also had to enable GIE

I wrote this code a bit ago and when I saw the recent topics I
thought I would give a try to see if one group members has an answer.
Also, can any one explain this warning? It is part of the TI
original code for the 2012 appearing in front of

Warning! while (CCR0 != TAR) Prevent async capture Warning[Pa082]:
undefined behavior: the order of volatile accesses is undefined

The "C" code is as follows:

// M. Buccini / L. Westlund
// Texas Instruments Inc.
// October 2005
// Built with IAR Embedded Workbench Version: 3.40A
//*******************************************************************
#define RXD 0x02 // RXD on P1.1
#define TXD 0x20 // TXD on P1.5

// Conditions for 2400 Baud SW UART, ACLK = 32768

#define Bitime_5 0x06 // ~ 0.5 bit length +
small adjustment
#define Bitime 0x0E // 427us bit length ~
2341 baud

unsigned int RXTXData;
unsigned char BitCnt;

void TX_Byte (void);
void RX_Ready (void);

#include

void main (void)
{
char *message;
message="\n\rHello World! \r\n";
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
CCTL0 = OUT; // TXD Idle as Mark
TACTL = TASSEL_1 + MC_2; // ACLK, continuous mode
P1SEL = TXD + RXD; //
P1DIR = TXD;

_BIS_SR(GIE);//enable interrupts

// Mainloop
for (;;)
{
while (*message != 0)
{
RXTXData=*message++;
TX_Byte();
}// end of while messsage

RX_Ready(); // UART ready to RX one Byte
_BIS_SR(LPM3_bits + GIE); // Enter LPM3 w/ interr
until char RXed
TX_Byte(); / TX Back RXed Byte Received
}
}
// Function Transmits Character from RXTXData Buffer
void TX_Byte (void)
{
BitCnt = 0xA; // Load Bit counter, 8data + ST/SP
while (CCR0 != TAR) // Prevent async capture
CCR0 = TAR; // Current state of TA
CCR0 += Bitime; // Some time till first bit
RXTXData |= 0x100; // Add mark stop bit to RXTXData
RXTXData = RXTXData << 1; // Add space start bit
CCTL0 = CCIS0 + OUTMOD0 + CCIE; // TXD = mark = idle
while ( CCTL0 & CCIE ); // Wait for TX completion
}
// Function Readies UART to Receive Character into RXTXData Buffer
void RX_Ready (void)
{
BitCnt = 0x8; // Load Bit counter
CCTL0 = SCS + OUTMOD0 + CM1 + CAP + CCIE; // Sync, Neg Edge, Cap
}

// Timer A0 interrupt service routine
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{
CCR0 += Bitime; // Add Offset to CCR0

// TX
if (CCTL0 & CCIS0) // TX on CCI0B?
{
if ( BitCnt == 0)
CCTL0 &= ~ CCIE; // All bits TXed, disable interrupt
else
{
CCTL0 |= OUTMOD2; // TX Space
if (RXTXData & 0x01)
CCTL0 &= ~ OUTMOD2; // TX Mark
RXTXData = RXTXData >> 1;
BitCnt --;
}
}
// RX
else
{
if( CCTL0 & CAP ) // Capture mode = start bit edge
{
CCTL0 &= ~ CAP; // Switch from capture to compare mode
CCR0 += Bitime_5;
}
else
{
RXTXData = 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(LPM3_bits); // Clear LPM3 bits from 0(SR)
}
//>>>>>>>>>> Decode of Received Byte Here
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
}
}
}

Beginning Microcontrollers with the MSP430

TI has many examples. I do not know exactly which example you are
talking about, but it looks like the F20xx example using TimerA (not
an UART) and 32768Hz ACLK (not DCO clock) for 2400 b/s echo. If that
is indeed the case, it should work as is except that the bit rate is
not exactly 2400 b/s but about -2.5% off.

--- In m..., "jpfrolic" wrote:
>
> There has been some discussion on the UART using the DCO. And a
> little more which got a little on the unfriendly side so was a bit
> shy getting into this but what the heck!
>
> I have had several problems with the software example provided by TI
> in the sample code in C.
>
> I cannot get the receive section to work and in desperation I just
> wrote my own bit bang code which does not take advantage of the low
> power savings but works. My code clip shows the addition of a
> message "Hello World!' I used this snippet to isolate my problem,
> which it did. The code as presented displays the message "Hello
> World!" , but when I transmit a key closure on my TTY device I get
> garbage characters. I think the code starts out in the receive mode
> but ends up immediately in the echo mode. Any solutions so I can use
> the low power mode?
>
> You can see my addition of the "Hello World!". Also had to enable GIE
>
> I wrote this code a bit ago and when I saw the recent topics I
> thought I would give a try to see if one group members has an answer.
> Also, can any one explain this warning? It is part of the TI
> original code for the 2012 appearing in front of
>
> Warning! while (CCR0 != TAR) Prevent async capture Warning[Pa082]:
> undefined behavior: the order of volatile accesses is undefined
>
> The "C" code is as follows:
>
> // M. Buccini / L. Westlund
> // Texas Instruments Inc.
> // October 2005
> // Built with IAR Embedded Workbench Version: 3.40A
> //*******************************************************************
> #define RXD 0x02 // RXD on P1.1
> #define TXD 0x20 // TXD on P1.5
>
> // Conditions for 2400 Baud SW UART, ACLK = 32768
>
> #define Bitime_5 0x06 // ~ 0.5 bit length +
> small adjustment
> #define Bitime 0x0E // 427us bit length ~
> 2341 baud
>
> unsigned int RXTXData;
> unsigned char BitCnt;
>
> void TX_Byte (void);
> void RX_Ready (void);
>
> #include
>
>
> void main (void)
> {
> char *message;
> message="\n\rHello World! \r\n";
> WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
> CCTL0 = OUT; // TXD Idle as Mark
> TACTL = TASSEL_1 + MC_2; // ACLK, continuous mode
> P1SEL = TXD + RXD; //
> P1DIR = TXD;
>
> _BIS_SR(GIE);//enable interrupts
>
> // Mainloop
> for (;;)
> {
> while (*message != 0)
> {
> RXTXData=*message++;
> TX_Byte();
> }// end of while messsage
>
>
> RX_Ready(); // UART ready to RX one Byte
> _BIS_SR(LPM3_bits + GIE); // Enter LPM3 w/ interr
> until char RXed
> TX_Byte(); / TX Back RXed Byte Received
> }
> }
> // Function Transmits Character from RXTXData Buffer
> void TX_Byte (void)
> {
> BitCnt = 0xA; // Load Bit counter, 8data + ST/SP
> while (CCR0 != TAR) // Prevent async capture
> CCR0 = TAR; // Current state of TA
> CCR0 += Bitime; // Some time till first bit
> RXTXData |= 0x100; // Add mark stop bit to RXTXData
> RXTXData = RXTXData << 1; // Add space start bit
> CCTL0 = CCIS0 + OUTMOD0 + CCIE; // TXD = mark = idle
> while ( CCTL0 & CCIE ); // Wait for TX completion
> }
> // Function Readies UART to Receive Character into RXTXData Buffer
> void RX_Ready (void)
> {
> BitCnt = 0x8; // Load Bit counter
> CCTL0 = SCS + OUTMOD0 + CM1 + CAP + CCIE; // Sync, Neg Edge, Cap
> }
>
> // Timer A0 interrupt service routine
> #pragma vector=TIMERA0_VECTOR
> __interrupt void Timer_A (void)
> {
> CCR0 += Bitime; // Add Offset to CCR0
>
> // TX
> if (CCTL0 & CCIS0) // TX on CCI0B?
> {
> if ( BitCnt == 0)
> CCTL0 &= ~ CCIE; // All bits TXed, disable interrupt
> else
> {
> CCTL0 |= OUTMOD2; // TX Space
> if (RXTXData & 0x01)
> CCTL0 &= ~ OUTMOD2; // TX Mark
> RXTXData = RXTXData >> 1;
> BitCnt --;
> }
> }
> // RX
> else
> {
> if( CCTL0 & CAP ) // Capture mode = start bit edge
> {
> CCTL0 &= ~ CAP; // Switch from capture to compare mode
> CCR0 += Bitime_5;
> }
> else
> {
> RXTXData = 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(LPM3_bits); // Clear LPM3 bits from 0(SR)
> }
> //>>>>>>>>>> Decode of Received Byte Here
> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
> }
> }
> }
>

My fault in assuming that one was familiar with TI's low cost USB
development system introduce about 1 and 1/2 years ago. Yes, it uses
timer A. I added the crystal as the published code expected for it
specifically states that it is based on the 32K crystal. The
published code by TI mentions CCIOB when it transmits which
obviously is wrong. It uses CCIOA. The code does transmit properly
and the timming values must be correct since the message "Hello
World!" appears without a glitch. The half bit time should have a
huge slack since we are to avoid reading at transitions at times
when a bit value may change from mark to space, or space to mark. It
is collecting something, but not the key pressed. This is my
problem. One would assume that TI verified thr released code. IT
DOES NOT WORK AS WRITTEN. And then there is that warning message. I
tried to Google on yhat to no avail.

And what about the warning message?

I tried a slew of values, gave up, and wrote my own. As mmentioned,
I would like to use the low power mode since my application is power
critical. I can work around this however. The point being, TI
published this code for this device. As written, if a novice tried
the example he would have nothing happen. I was such a novice. It is
because I wrote my own routines I was able to give the published
code a second try. That is how I discovered that the transmit does
work. Because of writting code outside of TI's example I noticed
that the GIE had to be enabled. Then The transmit portion was proven
to be functional. The RX is not.

--- In m..., "old_cow_yellow"
wrote:
>
> TI has many examples. I do not know exactly which example you are
> talking about, but it looks like the F20xx example using TimerA
(not
> an UART) and 32768Hz ACLK (not DCO clock) for 2400 b/s echo. If
that
> is indeed the case, it should work as is except that the bit rate
is
> not exactly 2400 b/s but about -2.5% off.
>
> --- In m..., "jpfrolic" wrote:
> >
> > There has been some discussion on the UART using the DCO. And a
> > little more which got a little on the unfriendly side so was a
bit
> > shy getting into this but what the heck!
> >
> > I have had several problems with the software example provided
by TI
> > in the sample code in C.
> >
> > I cannot get the receive section to work and in desperation I
just
> > wrote my own bit bang code which does not take advantage of the
low
> > power savings but works. My code clip shows the addition of a
> > message "Hello World!' I used this snippet to isolate my
problem,
> > which it did. The code as presented displays the message "Hello
> > World!" , but when I transmit a key closure on my TTY device I
get
> > garbage characters. I think the code starts out in the receive
mode
> > but ends up immediately in the echo mode. Any solutions so I can
use
> > the low power mode?
> >
> > You can see my addition of the "Hello World!". Also had to
enable GIE
> >
> > I wrote this code a bit ago and when I saw the recent topics I
> > thought I would give a try to see if one group members has an
answer.
> >
> >
> > Also, can any one explain this warning? It is part of the TI
> > original code for the 2012 appearing in front of
> >
> > Warning! while (CCR0 != TAR) Prevent async capture Warning
[Pa082]:
> > undefined behavior: the order of volatile accesses is undefined
> >
> > The "C" code is as follows:
> >
> >
> >
> > // M. Buccini / L. Westlund
> > // Texas Instruments Inc.
> > // October 2005
> > // Built with IAR Embedded Workbench Version: 3.40A
>
> //*****************************************************************
**
> >
> >
> > #define RXD 0x02 // RXD on P1.1
> > #define TXD 0x20 // TXD on P1.5
> >
> > // Conditions for 2400 Baud SW UART, ACLK = 32768
> >
> > #define Bitime_5 0x06 // ~ 0.5 bit length
+
> > small adjustment
> > #define Bitime 0x0E // 427us bit length
~
> > 2341 baud
> >
> > unsigned int RXTXData;
> > unsigned char BitCnt;
> >
> > void TX_Byte (void);
> > void RX_Ready (void);
> >
> >
> >
> > #include
> >
> >
> >
> >
> > void main (void)
> > {
> > char *message;
> > message="\n\rHello World! \r\n";
> >
> >
> > WDTCTL = WDTPW + WDTHOLD; // Stop watchdog
timer
> > CCTL0 = OUT; // TXD Idle as Mark
> > TACTL = TASSEL_1 + MC_2; // ACLK, continuous
mode
> > P1SEL = TXD + RXD; //
> > P1DIR = TXD;
> >
> > _BIS_SR(GIE);//enable interrupts
> >
> > // Mainloop
> > for (;;)
> > {
> > while (*message != 0)
> > {
> > RXTXData=*message++;
> > TX_Byte();
> > }// end of while messsage
> >
> >
> > RX_Ready(); // UART ready to RX one
Byte
> > _BIS_SR(LPM3_bits + GIE); // Enter LPM3 w/ interr
> > until char RXed
> > TX_Byte(); / TX Back RXed Byte
Received
> > }
> > }
> >
> >
> > // Function Transmits Character from RXTXData Buffer
> > void TX_Byte (void)
> > {
> > BitCnt = 0xA; // Load Bit counter, 8data + ST/SP
> > while (CCR0 != TAR) // Prevent async capture
> > CCR0 = TAR; // Current state of TA
> > CCR0 += Bitime; // Some time till first bit
> > RXTXData |= 0x100; // Add mark stop bit to
RXTXData
> > RXTXData = RXTXData << 1; // Add space start
bit
> > CCTL0 = CCIS0 + OUTMOD0 + CCIE; // TXD = mark = idle
> > while ( CCTL0 & CCIE ); // Wait for TX
completion
> > }
> >
> >
> > // Function Readies UART to Receive Character into RXTXData
Buffer
> > void RX_Ready (void)
> > {
> > BitCnt = 0x8; // Load Bit counter
> > CCTL0 = SCS + OUTMOD0 + CM1 + CAP + CCIE; // Sync, Neg Edge,
Cap
> > }
> >
> > // Timer A0 interrupt service routine
> > #pragma vector=TIMERA0_VECTOR
> > __interrupt void Timer_A (void)
> > {
> > CCR0 += Bitime; // Add Offset to CCR0
> >
> > // TX
> > if (CCTL0 & CCIS0) // TX on CCI0B?
> > {
> > if ( BitCnt == 0)
> > CCTL0 &= ~ CCIE; // All bits TXed, disable
interrupt
> > else
> > {
> > CCTL0 |= OUTMOD2; // TX Space
> > if (RXTXData & 0x01)
> > CCTL0 &= ~ OUTMOD2; // TX Mark
> > RXTXData = RXTXData >> 1;
> > BitCnt --;
> > }
> > }
> > // RX
> > else
> > {
> > if( CCTL0 & CAP ) // Capture mode = start bit
edge
> > {
> > CCTL0 &= ~ CAP; // Switch from capture to compare
mode
> > CCR0 += Bitime_5;
> > }
> > else
> > {
> > RXTXData = 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(LPM3_bits); // Clear LPM3 bits from 0
(SR)
> > }
> > //>>>>>>>>>> Decode of Received Byte Here
> > <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
> > }
> > }
> > }
>