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.

UART Baudrate problem

Other Parts Discussed in Thread: MSP430G2553

Hi, I am using msp430g2553 with launchpad, editing with CCS. My problem is Baudrate. In the userguide:

it says UCBRx should be 1666 with UCBRSx 6 set for baudrate 9600. So it tells me that I should set 

UCA0BR0 = 0x82;
UCA0BR1 = 0x06;

UCA0MCTL = UCBRS_6;

however, when I do that, and oscillate with TXBUF= OxFF it oscillate at 953 Hz. (FF + 1 bit stop bit makes an oscillation at byte level) So baudrate is like 953x8=7624Hz. NOT 9600 Hz. So I can not communicate with Putty on my computer on 9600 Baudrate. However, I can communicate with my PC with uart using this code below:

#include <msp430g2553.h>
#include <string.h>
#include <stdio.h>
/*
 * main.c
 */

void uart_conf(void);
void clck_conf(void);
char byte_to_crc[20];
unsigned short crc;
unsigned int len;
unsigned int pos;
unsigned int i;
unsigned int request_indicator=0;
char received_frame[20];
char transmitted_frame[20];
unsigned int byte_count_to_receive;
unsigned int byte_count_to_transmit;
unsigned int received_byte_counter;
unsigned int transmitted_byte_counter;

char reg_add_hi;
char reg_add_lo;
char nop_hi;
char nop_lo;
char crc_hi;
char crc_lo;

unsigned short mod_rtu_crc(char*, int);    // generate crc
void read_holding_regs(char, char , unsigned short , unsigned short);   // reading holding regs function

void main(void) {
    WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timer
    clck_conf();
    uart_conf();
    read_holding_regs(0x00, 0x03, 0x0001, 0x0002);
	//IFG2 &= ~UCA0RXIFG;
	UC0IE |= UCA0TXIE | UCA0RXIE;
	__bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ int until Byte RXed

	while(1);
	

}


void uart_conf(void){

	UCA0CTL1 |= UCSWRST;         //Reset USCI
	UCA0CTL0 &= ~UCSYNC;  // Clear UCSYNC for UART communication;
	P1SEL |= (BIT1 | BIT2);       // Select for spec. function directions UART TX and RX
	P1SEL2 |= (BIT1 | BIT2);
	UCA0CTL1 |= UCSSEL_2;       // BTCL = SMCLK
	UCA0BR0 = 0xFF;
	UCA0BR1 = 0x05;                       // F_16MHZ / 1666 ~= 9600 KHz  0x0682 = 1666
	UCA0MCTL = UCBRS_6;    // Set modulation for minimum error rate (see spec...) 9600 Kps UCBRSx = 6 UcBRFx = 0;
	UCA0CTL1 &= ~UCSWRST;          // Un Reset USCI
	//UC0IE |= (UCA0RXIE | UCA0TXIE);     // enable interrupts



}

void clck_conf(void){

	BCSCTL1 = CALBC1_16MHZ; // Set DCO 16 MHz
	DCOCTL = CALDCO_16MHZ;

}

void read_holding_regs(char slave_add, char function, unsigned short reg_add, unsigned short nop){
	byte_to_crc[0] = slave_add;
	byte_to_crc[1] = function;
	reg_add_hi = reg_add >> 8;
	reg_add_lo = reg_add & 0x00ff;
	byte_to_crc[2] = reg_add_hi;
	byte_to_crc[3] = reg_add_lo;
	nop_hi = nop >> 8;
	nop_lo = nop & 0x00ff;
	byte_to_crc[4] = nop_hi;
	byte_to_crc[5] = nop_lo;

	len = 6;

	mod_rtu_crc(byte_to_crc, len);
	crc_hi = crc >> 8;
	crc_lo = crc & 0x00ff;

	transmitted_frame[0] = byte_to_crc[0];
	transmitted_frame[1] = byte_to_crc[1];
	transmitted_frame[2] = byte_to_crc[2];
	transmitted_frame[3] = byte_to_crc[3];
	transmitted_frame[4] = byte_to_crc[4];
	transmitted_frame[5] = byte_to_crc[5];
	transmitted_frame[6] = crc_lo;
	transmitted_frame[7] = crc_hi;

	received_byte_counter = 0;
	byte_count_to_receive = len + (int)nop + 2;    // + 2 for CRC and + No of Points because 2x nop comes back as response
	byte_count_to_transmit = len + 2;
	// start serial transmit
	__delay_cycles(64000);   //  Wait for 4 ms


}

// Compute the MODBUS RTU CRC
unsigned short mod_rtu_crc(char* bytes, int len)
{
	crc = 0xFFFF;

  for(pos = 0; pos < len; pos++){
    crc ^= (unsigned short)bytes[pos];          // XOR byte into least sig. byte of crc

    for(i = 8; i != 0; i--){    // Loop over each bit
      if((crc & 0x0001) != 0){      // If the LSB is set
        crc >>= 1;                    // Shift right and XOR 0xA001
        crc ^= 0xA001;
      }
      else{                            // Else LSB is not set
        crc >>= 1;                    // Just shift right
      }
    }
  // Note, this number has low and high bytes swapped, so use it accordingly (or swap bytes)

}
return crc;
}

#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{

	if(received_byte_counter != byte_count_to_receive-1){        //if receive is not over
		received_byte_counter++;
		received_frame[received_byte_counter]= UCA0RXBUF;
	}
	else{
		received_frame[received_byte_counter]= UCA0RXBUF;
		UC0IE &= ~UCA0RXIE;     // disable RX interrupts
	}

}


#pragma vector=USCIAB0TX_VECTOR
__interrupt void USCI0TX_ISR(void)
{
	if(transmitted_byte_counter != byte_count_to_transmit-1){        //if transmit is not over
		transmitted_byte_counter++;
		UCA0TXBUF = transmitted_frame[transmitted_byte_counter];
	}
	else{
		UCA0TXBUF = transmitted_frame[transmitted_byte_counter];
		UC0IE &= ~UCA0TXIE;     // disable RX interrupts
		//__delay_cycles(64000);   //  Wait for 4 ms
	}
}

AS you see, I changed the values to

	UCA0BR0 = 0xFF;
	UCA0BR1 = 0x05;   

And I surprisingly can communicate?! Why is that, did I read the user guide wrong? I am open to any sggestion. Thanks.
  • Have you double checked if your clock is running at 16MHz? You can configure P1.4 to output SMCLK.

    Your values for UCBR look correct, I would have taken the same:

    UCA0BR0 = 130; // 0x82
    UCA0BR1 = 6;   // 0x06

    This would be:

    (6 * 256) + 130 = 1536 + 130 = 1666

    Dennis

  • The UART data frames consist normally 1 START bit + 8 DATA bits + 1 STOP bits, in total 10-bits. When transmitting an 0xFF you will see on your logic analyzer only the START bit and your logic analyzer will give you a frequency of 960Hz. The difference between your measured 953Hz (~100uS/byte) consists off bit-clock error and software latency.

    To check the bit-clock frequency you need to measure the length of the START bit. Transmitting an 0xAA makes it easier to measure the bit-rate.
  • Istemihan,

    I tested the code with 0x82 and 0x06 and it works without problems. Your issue must be somewhere else.

    Dennis

  • 953Hz with the original setup means 9530Bd (as Leo said: UART is 10 or with parity even 11 bit per byte). Which is 0.7% error and well within the tolerable range. Also well in the tolerance range of the calibrated DCO values.
    There have been PC card whose baudrate was far off and outside the specs. But on LaunchPad, I guess you are using the USB/ser bridge ('Application UART') and this should be okay.
    Te 0x05FF factor results in 10423Bd. Which is >8% error.
    The only explanation that comes in mind is that your calibration values are wrong and the DCO runs on 14.7MHz instead of 16MHz.

**Attention** This is a public forum