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.
Can anyone help me in setting baud rate on BRCLK Frequency = 1,048,576 (1.05Mhz) on launchpad MSP430G2xx3 board? I modified TI example code to include changes for 1.05 Mhz clock but I don't see any change when analyzed through oscilloscope, basically signal width remains same between 1Mhz to 1.05 Mhz.. i.e., 104us.
Modified TI example code.
#include <msp430.h>
#define BAUDRATE 9600
//------------------------------------------------------------------------------
// Hardware-related definitions
//------------------------------------------------------------------------------
#define UART_TXD 0x02 // TXD on P1.1 (Timer0_A.OUT0)
#define UART_RXD 0x04 // RXD on P1.2 (Timer0_A.CCI1A)
//------------------------------------------------------------------------------
// Conditions for BAUDRATE Baud SW UART, SMCLK = 1MHz
//------------------------------------------------------------------------------
#define UART_TBIT_DIV_2 (1000000 / (BAUDRATE * 2))
#define UART_TBIT (1000000 / BAUDRATE)
//------------------------------------------------------------------------------
// Global variables used for full-duplex UART communication
//------------------------------------------------------------------------------
unsigned int txData; // UART internal variable for TX
unsigned char rxBuffer; // Received UART character
//------------------------------------------------------------------------------
// Function prototypes
//------------------------------------------------------------------------------
void TimerA_UART_init(void);
void TimerA_UART_tx(unsigned char byte);
void TimerA_UART_print(char *string);
int k = 0;
//------------------------------------------------------------------------------
// main()
//------------------------------------------------------------------------------
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
if (CALBC1_1MHZ==0xFF) // If calibration constant erased
{
while(1); // do not load, trap CPU!!
}
DCOCTL = 0; // Select lowest DCOx and MODx settings
BCSCTL1 = CALBC1_1MHZ; // Set DCOCLK to 1MHz
DCOCTL = CALDCO_1MHZ;
UCA0CTL1 |= UCSSEL_2; // SMCLK
UCA0BR0 = 109; // 1.05MHz 9600
UCA0BR1 = 0; // 1.05MHz 9600
UCA0MCTL = UCBRS0; // Modulation UCBRSx = 1
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
P1OUT = 0x00; // Initialize all GPIO
P1SEL = UART_TXD + UART_RXD; // Timer function for TXD/RXD pins
P1DIR = 0xFF & ~UART_RXD; // Set all pins but RXD to output
P2OUT = 0x00;
P2SEL = 0x00;
P2DIR = 0xFF;
__enable_interrupt();
TimerA_UART_init(); // Start Timer_A UART
// TimerA_UART_print("Hello Krishna\r\n");
// TimerA_UART_print("How are you ?.\r\n");
for (;;)
{
// Wait for incoming character
// __bis_SR_register(LPM0_bits);
// Echo received character
TimerA_UART_tx('U');
for(k = 0; k<100; k++);
}
// TimerA_UART_tx(0x0f);
}
//------------------------------------------------------------------------------
// Function configures Timer_A for full-duplex UART operation
//------------------------------------------------------------------------------
void TimerA_UART_init(void)
{
TACCTL0 = OUT; // Set TXD Idle as Mark = '1'
TACCTL1 = SCS + CM1 + CAP + CCIE; // Sync, Neg Edge, Capture, Int
TACTL = TASSEL_2 + MC_2; // SMCLK, start in continuous mode
}
//------------------------------------------------------------------------------
// Outputs one byte using the Timer_A UART
//------------------------------------------------------------------------------
void TimerA_UART_tx(unsigned char byte)
{
while (TACCTL0 & CCIE); // Ensure last char got TX'd
TACCR0 = TAR; // Current state of TA counter
TACCR0 += UART_TBIT; // One bit time till first bit
TACCTL0 = OUTMOD0 + CCIE; // Set TXD on EQU0, Int
txData = byte; // Load global variable
txData |= 0x100; // Add mark stop bit to TXData
txData <<= 1; // Add space start bit
}
//------------------------------------------------------------------------------
// Prints a string over using the Timer_A UART
//------------------------------------------------------------------------------
void TimerA_UART_print(char *string)
{
while (*string) {
TimerA_UART_tx(*string++);
}
}
//------------------------------------------------------------------------------
// Timer_A UART - Transmit Interrupt Handler
//------------------------------------------------------------------------------
#pragma vector = TIMER0_A0_VECTOR
__interrupt void Timer_A0_ISR(void)
{
static unsigned char txBitCnt = 10;
TACCR0 += UART_TBIT; // Add Offset to CCRx
if (txBitCnt == 0) { // All bits TXed?
TACCTL0 &= ~CCIE; // All bits TXed, disable interrupt
txBitCnt = 10; // Re-load bit counter
}
else {
if (txData & 0x01) {
TACCTL0 &= ~OUTMOD2; // TX Mark '1'
}
else {
TACCTL0 |= OUTMOD2; // TX Space '0'
}
txData >>= 1;
txBitCnt--;
}
}
//------------------------------------------------------------------------------
// Timer_A UART - Receive Interrupt Handler
//------------------------------------------------------------------------------
#pragma vector = TIMER0_A1_VECTOR
__interrupt void Timer_A1_ISR(void)
{
static unsigned char rxBitCnt = 8;
static unsigned char rxData = 0;
switch (__even_in_range(TA0IV, TA0IV_TAIFG)) { // Use calculated branching
case TA0IV_TACCR1: // TACCR1 CCIFG - UART RX
TACCR1 += UART_TBIT; // Add Offset to CCRx
if (TACCTL1 & CAP) { // Capture mode = start bit edge
TACCTL1 &= ~CAP; // Switch capture to compare mode
TACCR1 += UART_TBIT_DIV_2; // Point CCRx to middle of D0
}
else {
rxData >>= 1;
if (TACCTL1 & SCCI) { // Get bit waiting in receive latch
rxData |= 0x80;
}
rxBitCnt--;
if (rxBitCnt == 0) { // All bits RXed?
rxBuffer = rxData; // Store in global variable
rxBitCnt = 8; // Re-load bit counter
TACCTL1 |= CAP; // Switch compare to capture mode
__bic_SR_register_on_exit(LPM0_bits); // Clear LPM0 bits from 0(SR)
}
}
break;
}
}
//------------------------------------------------------------------------------
Hello Raj,
From first glance, it appears that you're missing the P1SEL2. Since you're using the UART TX and RX you need to make sure you're using P1SEL and P1SEL2:
P1SEL = UART_TXD + UART_RXD;
P1SEL2 = UART_TXD + UART_RXD;
I hope this helps.
Regards,
S.
Hi,
Adding P1SEL2 = UART_TXD + UART_RXD; stopped communication to UART.
How can we select 9600 baud rate at 1.05 Mhz clock?
I think the problem is I haven't set system clock to 1.05Mhz , i.e.,
BCSCTL1 = CALBC1_1MHZ;
DCOCTL = CALDCO_1MHZ;
How to manually calibrate and use BCSCTL1 & DCOCTL registers to 1.05 Mhz?
Raj,
Based off the setting you had initally, you had P.1 and P.2 configured as capture/compare pins:
I missed one other thing; you also need to modify the UCBRSx bits in the UCAxMCTL register. You currently have it set to 0 which would explain why you're not receiving anything from the UART. In order to receive the modulation scheme to get 1.05 MHz @ 9600 bauds from the UART, you will need to change this value what listed in the table you attached (2):
UCA0CTL1 |= UCSSEL_2; // SMCLK
UCA0BR0 = 109; // 1.05MHz 9600
UCA0BR1 = 0; // 1.05MHz 9600
UCA0MCTL = UCBRS2; // Modulation UCBRSx = 1
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
Regards,
S.A.
No, it stopped the communicaiton with the timer. Because the code you posted is using the timer to do a software UART. It doesn't use the hardware UART (USCI) at all.Raj P said:Adding P1SEL2 = UART_TXD + UART_RXD; stopped communication to UART.
Jens,
What is difference between timer based UART and hardware UART? I believed timer based UART still uses hardware UART functionality for Rx & Tx functionality. Please correct me if I am wrong.
Thanks for detailed reply, I made changes to two definitions in source code ..
#define UART_TBIT_DIV_2 (1048576/ (BAUDRATE * 2))
#define UART_TBIT (1048576/ BAUDRATE)
I get data on serial port but I see some sort of noise at regular intervals. Is there any mistake?
No. It uses a timer to generate the individual bits by digital I/O. In case of the MSP, the tiemr can directly generate an output signal change when the time is up, which supports the software and adds some precision. However, it works without hardware UART (and was designed for the G2xx family members which only have an USI module without UART capability).Raj P said:I believed timer based UART still uses hardware UART functionality
Thanks Jeans.
The last question I had was about DCO clock settings, on launchpad boards the maximum frequency that could be set is 1 Mhz (CALBC1_1MHZ) , I need to operate my UART at 1.05 Mhz baud rate , does this mean even DCO should be set for 1.05Mhz? or DCO can still run at 1 Mhz but UART can be configured to run at 1.05Mhz irrespective of DCO clock frequency?
I am asking this since I don't see any document which describes how to set DCO clock frequecy above 1 Mhz.
Appreciate your feedback.
No. Teh DCO can be programmed to, well, depends on MSP but for all but 1x family, the limit is far above the maximum CPU frequency.Raj P said:the maximum frequency that could be set is 1 Mhz (CALBC1_1MHZ)
It's just that a certain bit combination in the DCO registers results in different output frequencies on each individual MSP. So CALBC1_1MHz is a factory-provided value that sets the DCO registers to a value that results in 1MHz (as close as possible) on this specific MSP. The calue of CALBC1_1MHZ is different for each MSP. It is nto a constant, but points to a memory location (INFOA) where this value was stored at prduction time. Some MSPs also carry this informaiton for 2,4,8, 12 or 16MHz. See the datasheet for available values.
If you want to use a different frequency, you need to calibrate it on your own. You can simply use try and error (try different values and output SMCLK to a port pin and check it) or you put a self-calibraiton function into your code that compares the current DCO frequeency to a known reference, such as a 32768Hz crystal. Sample code was posted somewhere in the forum.
On 4x and 5x/6x family, this feature is available in hardware. On 5x/6x family, you don't even need an external crystal if the precision of the internal REFO is good for you.
The users guide tells you how the DCO registers work and the datasheet contains a table telling you the frequency range of different DCO configurations.Raj P said:I am asking this since I don't see any document which describes how to set DCO clock frequecy above 1 Mhz.
**Attention** This is a public forum