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.
Hello all,
I need to send as well as receive data using msp430 mcu uart, i'm using the following code and it sends all the data correctly through TX, but I cannot write anything to send it into mcu, please tell me what is wrong here. The code is as follows:
#include <msp430g2553.h>
#include <stdbool.h>
////////////////Defines////////////////
#define LED1 BIT6
#define LED0 BIT0
#define Error BIT0
#define GND BIT4
#define DAT BIT5
#define VCC BIT0 //port P2.0
char buffer[4];
float temp,v;
int n_temp,r_temp;
////////////////Function Protos////////////////
static char *i2a(unsigned i, char *a, unsigned r)
{
if (i/r > 0) a = i2a(i/r,a,r);
*a = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i%r];
return a+1;
}
char *itoa(int i, char *a, int r)
{
if ((r < 2) || (r > 36)) r = 10;
if (i < 0)
{
*a = '-';
*i2a(-(unsigned)i,a+1,r) = 0;
}
else *i2a(i,a,r) = 0;
return a;
}
void TX(char *tx_message)
{
unsigned int i=0; //Define end of string loop int
char *message; // message variable
unsigned int message_num; // define ascii int version variable
message = tx_message; // move tx_message into message
while(1)
{
if(message[i]==0) // If end of input string is reached, break loop.
{break;}
message_num = (int)message[i]; //Cast string char into a int variable
UCA0TXBUF = message_num; // write INT to TX buffer
i++; // increase string index
__delay_cycles(10000); //transmission delay
if(i>50) //prevent infinite transmit
{
P1OUT |= Error;
break;
}
} // End TX Main While Loop
} // End TX Function
void m4302553_Init()
{
ADC10CTL0= ADC10ON + ADC10SHT_3+ADC10IE; ; //Temperature sensor supply REFON = 0, INCHx = 0Ah,
//only ISENSOR current as reference,64 clocks for sample HOLDING TIME
ADC10CTL1=INCH_10+ ADC10DIV_3; // ADC10clock/4, as 30 MicroSeconds is bare minimum
}
void lm_init()
{
/* Configure ADC Channel */
ADC10CTL0 = SREF_1+REFON+ADC10SHT_3 + ADC10ON + ADC10IE; //1.5v internal as reference
ADC10CTL1 = INCH_5 + ADC10DIV_3 ; // Channel 5, ADC10CLK/4
}
void opto101pj_init()
{
ADC10CTL0 = SREF_0 + ADC10SHT_3 + ADC10ON + ADC10IE; //Vcc & Vss as reference
ADC10CTL1 = INCH_7 + ADC10DIV_3 ; // Channel 5, ADC10CLK/4
}
void inputvcc_init()
{
ADC10CTL0 = SREF_1 +ADC10ON + REFON + REF2_5V + ADC10SHT_3+ADC10IE; // use internal ref, turn on 2.5V ref, set samp time = 64 cycles
ADC10CTL1 = INCH_11+ADC10DIV_3;
}
//void re200b_p_init()
//{
// /* Configure ADC Channel */
// ADC10CTL0 = SREF_0+ADC10SHT_3 + ADC10ON + ADC10IE; //vcc as reference
// ADC10CTL1 = INCH_3 + ADC10DIV_3 ; // Channel 3, ADC10CLK/4
//}
////////////////////////////////MAIN PROGRAM LOOP//////////////////////////////////////////////////
void main(void)
{
while(1)
////////////////Main Loop////////////////
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
BCSCTL1 = CALBC1_1MHZ; // Set DCO to 1MHz
DCOCTL = CALDCO_1MHZ;
////////////////USCI setup////////////////
P1SEL = BIT1 + BIT2; // Set P1.1 to RXD and P1.2 to TXD
P1SEL2 = BIT1 + BIT2; //
UCA0CTL1 |= UCSSEL_2; // Have USCI use SMCLK AKA 1MHz main CLK
UCA0BR0 = 104; // Baud: 9600, N= CLK/Baud, N= 10^6 / 9600
UCA0MCTL = UCBRS_1; // Modulation UCBRSx = 1
UCA0CTL1 &= ~UCSWRST; // Start USCI
IE2 |= UCA0RXIE;//enable rx interrupt
////////////////General GPIO Defines////////////////
P1DIR |= (LED1+GND+LED0); //Define GPIOs as outputs else GPIOs are inputs
P2DIR |=VCC+BIT1;
P1OUT&=~GND;
int value2,value,value1,value3,value4;
ADC10CTL0 &= ~ENC;
//vcc
inputvcc_init();
__delay_cycles(1000); // Wait for ADC Ref to settle
ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start
__bis_SR_register(CPUOFF + GIE); // LPM0 with interrupts enabled
value = ADC10MEM;
itoa( value , buffer, 10);
TX(buffer);
TX("/");
ADC10CTL0 &= ~ENC;
//LM35
lm_init();
__delay_cycles(1000);
P1OUT = LED0;
ADC10CTL0 |= ENC + ADC10SC;
__bis_SR_register(CPUOFF + GIE);
value4 = ADC10MEM;
itoa( value4 , buffer, 10);
TX(buffer);
TX("/");
ADC10CTL0&=~ENC;
//2553
m4302553_Init();
__delay_cycles(1000);
ADC10CTL0 |= ENC + ADC10SC;
__bis_SR_register(CPUOFF + GIE);
value2 = ADC10MEM;
itoa(value2, buffer, 10);
TX(buffer);
TX("/");
P1OUT &=~LED0;
ADC10CTL0&=~ENC;
//OPTO101
P1OUT =LED1;
opto101pj_init();
__delay_cycles(1000);
ADC10CTL0 |= ENC + ADC10SC;
__bis_SR_register(CPUOFF + GIE);
value3 = ADC10MEM;
itoa(value3, buffer, 10);
TX(buffer);
TX("/");
//
// //PIR sensor
// re200b_p_init();
// __delay_cycles(1000);
// ADC10CTL0 |= ENC + ADC10SC;
// __bis_SR_register(CPUOFF + GIE);
// value1 = ADC10MEM;
// itoa(value1, buffer, 10);
// TX(buffer);
P1OUT &=~LED1;
_delay_cycles(996000);//+4*1000 DELAYS MAKE APPROX 1 SEC TOTAL
} // End While
} // End Main Program
// ADC10 interrupt service routine
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR (void)
{
__bic_SR_register_on_exit(CPUOFF); // Return to active mode
}
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
if(UCA0RXBUF == 1) //Toggle LED if "1" RXed
{
P2OUT = BIT1;
}
if(UCA0RXBUF == 0) //Toggle LED if "0" RXed
{
P2OUT &=~ BIT1;
}
}
but it doesn't let me set high or low that pin 2.1, neither am I capable of sending anything to mcu using Hyperterminal or Tera Term, while data comes perfectly all the time. Please help :'\
Hi,
If I understand correctly, you can send and print the values uC sends on terminal on the PC, isn't it?, but you are supposing that there are not RX on the uC side.
To check that RX exists, set a breakpoint inside of ISR or the LED blinking out of the if's. If you press a key and the code stops in the breakpoint or LED blinks, the RX works.
For the code, it seems you want to press 1 on your keyboard to turn on the LED and 0 to turn off, isn't it? If I am right, use == '1' instead of == 1, since the characters are sent in ASCII format, that is to say, if you send a character 1 for your keyboard, UCA0RXBUF will receive a 0x31, it can be expressed in C as '1'.
It worked after setting the RX routine like this:
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready?
UCA0TXBUF = UCA0RXBUF; // Echo back received character
if(UCA0RXBUF == '1') //Toggle LED if "1" RXed
{
P2OUT = BIT1;
}
if(UCA0RXBUF == '0') //Toggle LED if "0" RXed
{
P2OUT &=~ BIT1;
}
}
Everything is fine now!
Debasish Banerjee said:__delay_cycles(10000); //transmission delay
You use a busy-waiting fixed delay to separate two byte transmissions. During this delay, the CPU is busy and cannot do anything else, like receiving something. What you need is a state machine that can do one thing independently from the other instead of waiting until one thing is done. One way of implementing such a state machine is using the MSPs internal interrupt mechanism, which lets the CPU check on every instruction whether it shall continue with main or execute code that completes a receive operation or provides new out put data for a send operation. Thsi is what you already did (even though you didn't do it only half-way).
If you don't want to use interrupts, you can do so with polling, something like this (symbolic writing, no actual source code):
Loop
if RXIFG is set
read incoming byte
else if TXIFG is set
write next outgoing byte
else
do something else
end loop
Just ensure that the whole loop executes faster than it takes to receive a byte (or you might get receive overflows). The else if ensures that only one of the three is executed per loop, with the receive check having highest priority.
I didn't make that out, was I supposed to use the IE2 for both RXIE and TXIE? Can I use an another Interrupt just like IE2 and write an ISR to do the TX part instead?Jens-Michael Gross said:Thsi is what you already did (even though you didn't do it only half-way).
IE2 is a register that holds 8 different interrupt enable flags. One of them is RXIE, another one is TXIE. Both can be set or cleared independently.
For the TX, you need another ISR (on 4x family, both, RX and TX, share one ISR but still have separate IE bits).
Note that when the TXBUF register is empty, it will cause an interrupt. THis happens immediately after clearing SWRST, so keep TXIE clear until you have something to send. Fill it into a buiffer, set TXIE and be happy. The ISR will be called each tiem TXBUF is empty, read the next byte from the buffer and send it, and when there is nothign more to send, it should clear the TXIE bit. So you can see by the disappearance of TXIE that sending is complete.
**Attention** This is a public forum