Hi.
I´m using launchpad and microcontroller MSP430G2553, for my aplication I need 4 pins UART. I have to program 2 pins like UART by software. Is there a code??? help me
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hi.
I´m using launchpad and microcontroller MSP430G2553, for my aplication I need 4 pins UART. I have to program 2 pins like UART by software. Is there a code??? help me
Hello Viviana,
You can look at a similar post that used to create a software UART. http://e2e.ti.com/support/microcontrollers/msp430/f/166/p/108181/382093.aspx#382093
Also, the wiki has similar information.
An external site also has this implemented with code. http://www.msp430launchpad.com/2010/08/half-duplex-software-uart-on-launchpad.html
Although these are not the exact chip, you can change the ports as required.
Thanks,
The LaunchPad demo code for the other G series MSPs (not the G2553) use a software UART with support of the timer.Viviana Monroy said:I have to program 2 pins like UART by software. Is there a code???
However, this softwar eUART requires the exact same two pins as the hardware UART fo the 2553. So you waste comfort (and a timer) and gain nothing. :)
Doing a software UART in plain software (not using timer hardware) isn't recommended because of the huge timing errors that surely will happen. It might be good for 300 or 1200Bd but for anything above, the timings likely won't be precise enough. Especially for someone who ha to ask for code for this task (those experienced enough to do it are surely experienced enough to do it without code examples)
thank you.
I think other option, use 2 microcontroller. It´s not better option but it´s more reliable.
Thank you so much.
f you don't need them at the same time, you may use an external multiplexer chip, like the 74HC4053.Viviana Monroy said:a pair of 2 wire UART´s.
If both connections have the same baudrate, you can even listen to one side while sending to the other. Else you have to change the baudrate when switching both connections.
I use this method for the ATMega128, where at programming time, the hardware serial port is connected to the flashing tool while at operation, it is connected to an RS232 connector.
Hello Viviana,
might be a bit late, but here is my solution. In my case I have to collect analog data from all analog inputs P1.0-P1.7, (hence the UART pins are not accessible), and transmit to the host device. Thankfully there are two timers in G2553, so one of them with CCR0 can be sacrificed for soft UART operation. The trick is to determine the appropriate TACCR0 value for required baud rate. Below is the code. Just pass the byte to transmit to uartTx(char). BiTcntr = 0 indicates that transmitter is ready for the new character.
This code is for UART transmitter ONLY. I'm working on Receiver as well. Will post when it's ready.
/* Soft UART on TA1-CCR0 */ /* A. Norman */ #define Uchar unsigned char #define TxD BIT7 //P2.7, XOUT on Launchpad #define Baudrate 0x80 //0x680 for 9600; 0x80 for 115200 Uchar buff_Tx[64]; Uchar *ptr_Tx; Uchar BiTcntr;
Uchar txByte; /* Somwhere in main() */ ptr_Tx = (Uchar *)buff.Tx_Data; /********************************/ void initIO(void); void initTA1(void); void uartTx(Uchar byte); void initIO(void){ P2SEL &= ~TxD; P2SEL2 &= ~TxD; P2DIR |= TxD; P2OUT |= TxD; } void initTA1(void){ TA1CTL = TACLR; TA1CTL = TASSEL_2 + ID_0; TA1CCR0 = Baudrate; TA1CCTL0 |= CCIE; } void uartTx(Uchar byte){ *(ptr_Tx) = byte; BiTcntr = 9; TA1CTL |= MC_1; } #pragma vector=TIMER1_A0_VECTOR __interrupt void Timer1_A0(void){ switch (BiTcntr){ case 9: P2OUT &= ~TxD; //uart operation txByte = *(ptr_Tx); BiTcntr--; break; default: if (txByte & 0x01){ P2OUT |= TxD; //uart operation }else{ P2OUT &= ~TxD; //uart operation } txByte = txByte>>1; BiTcntr--; break; case 0: ptr_Tx++; P2OUT |= TxD; //uart operation TA1CTL &= ~MC_1; // _BIC_SR_IRQ(CPUOFF); // Exit LPM0 Use if needed break; } }
/* Soft UART on TA1-CCR0 */ /* A. Norman */ #define Uchar unsigned char #define TxD BIT7 //P2.7, XOUT on Launchpad #define Baudrate 0x80 //0x680 for 9600; 0x80 for 115200 Uchar buff_Tx[64]; Uchar *ptr_Tx; Uchar BiTcntr; /* Somwhere in main() */ ptr_Tx = (Uchar *)buff.Tx_Data; /********************************/ void initIO(void); void initTA1(void); void uartTx(Uchar byte); void initIO(void){ P2SEL &= ~TxD; P2SEL2 &= ~TxD; P2DIR |= TxD; P2OUT |= TxD; } void initTA1(void){ TA1CTL = TACLR; TA1CTL = TASSEL_2 + ID_0; TA1CCR0 = Baudrate; TA1CCTL0 |= CCIE; } void uartTx(Uchar byte){ *(ptr_Tx) = byte; BiTcntr = 9; TA1CTL |= MC_1; } #pragma vector=TIMER1_A0_VECTOR __interrupt void Timer1_A0(void){ switch (BiTcntr){ case 9: P2OUT &= ~TxD; //uart operation txByte = *(ptr_Tx); BiTcntr--; break; default: if (txByte & 0x01){ P2OUT |= TxD; //uart operation }else{ P2OUT &= ~TxD; //uart operation } txByte = txByte>>1; BiTcntr--; break; case 0: ptr_Tx++; P2OUT |= TxD; //uart operation TA1CTL &= ~MC_1; // _BIC_SR_IRQ(CPUOFF); // Exit LPM0 Use if needed break; } }
Fantastic work Arsen. Do you by any chance have the receiver code as well? I am working on something similar. But I just can't get it up and running.
Hi Alok,
no, sorry, not yet. I started it though, up to the point when I capture the START bit on P2 ISR. I'm planning to use P2.7 XIN on launchpad. The algorithm in mind is such:
1. Capture the START bit (1-0 transition), set the bitcount to 9, start the timer. Disable the P2.7 ISR.
2. On the timer CCR ISR, on every occurrence set the LSB of RxByte to P2.7 value, and shift RxByte left 1. Do bitcount--.
3. On bitcount==0 you have the full byte. stop the timer. Enable the P2.7 ISR. Use switch/case/default, as it's elegant.
The CCR0 value should match or be slightly less that the pulse width at selected baud rate. Use Tx example value to stat with. I was also thinking of doing half pulse width shift in the START bit and capture the bit value right in the middle. Then you might want to use CCR1. Please share the code, I'd like to see if it works. (Some might think of it as a waste of a Timer ;)
Hello Hudson,
the "somewhere in main" line of code is where the pointer initialized to the buffer of TX data. Come to think of it, there is an error in it! Here is the right way to do it:
uchar buff_Tx[64];
uchar *ptr_Tx;
uchar BiTcntr;Uchar txByte;
/* Somwhere in main() */
ptr_Tx = (uchar *)buff_Tx;
/********************************/
And by "somewhere in main" I mean literally somewhere in main(){...}, could be right where you initialize the IO port pins, or timer. Or even better, it can be initialized right in declaration like this:
uchar buff_Tx[64];
uchar *ptr_Tx=(uchar *)buff_Tx;
uchar BiTcntr;
uchar txByte;
and you can skip the commented lines in main.
IMPORTANT, you would need to find a right value for Baudrate constant line 30, otherwise it's 0, and the timer never kicks in. For that I would transmit 0x55, or 'U', and fine-tune the
Baudrate
value to have the square-wave as close as possible to similar transmitted from classical COM port. You would need an O-scope for that. For MSP430G2553 at 16 MHz I used 0x680.
Hit me with your next question!
Cheers,
Arsen
Oh, yeah
#define uchar unsigned char
Arsen,
Thanks for your reply! I ended up getting the code to work. My main method is as follows:
int main(void) {
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
DCOCTL = CALDCO_16MHZ;
BCSCTL1 = CALBC1_16MHZ;
initIO();
initTA1();
_BIS_SR(GIE); //without this nothing works!
uartTx('H');
uartTx('U');
uartTx('D');
}
In order to get multiple consecutive transmissions to work, I modified your uartTx method as follows:
void uartTx(Uchar byte){
while(BiTcntr != 10); //my addition
*(ptr_Tx) = byte;
BiTcntr = 9;
TA1CTL |= MC_1;
}
and changed the case 0 of your interrupt routine as follows:
case 0:
ptr_Tx++;
P2OUT |= TxD; //uart operation
TA1CTL &= ~MC_1;
BiTcntr = 10; //my addition
//_BIC_SR_IRQ(CPUOFF); // Exit LPM0 Use if needed
break;
Simply checking if bitcntr is 0 was insufficient, as this would start transmitting the next character before the stop bit had been sent for the previous character.
Anyways, thanks for your help! Did you ever end up finishing the receive method that you mentioned? That is the next step for my work.
- Hudson
Thanks for update Hudson! The forum is much more useful with followups on posts, especially with bug fixes.
My bad, I omitted the Enable Interrupt (and a few other things) in main() function.
As far as "soft receiver", no, did not have a chance, but I got a few ideas you might want to try:
*: An interrupt (ISR) handler detects start on negative edge and starts a counter. The ISR edge is toggled.
*: The next edge is detected. (Counter ±threshold) value indicates the number of bits. The value of the bits is the ISR edge polarity.
I'd start experimenting with receiving 'U' (0x55 or b01010101) shown on the O-scope capture below @9600bps. The bit shifting and other house kipping I'll leave to your imagination.
A Timer Capture input can be used as well with a different method.
A similar approach was used in Manchester Code detector, and it works just fine. I used Timer capture input, that somewhat limits the receiver being "soft".
Arsen
**Attention** This is a public forum