mrinverter 0 Posted October 3, 2014 Share Posted October 3, 2014 Hi guys, new around here and I am also a beginner (my only experience so far is withat needs your help to implement a UART interface for the FR5969. This is modified from an example from http://longhornengineer.com/projects/code/msp-430-launch-pad/uart-and-fifos/ that was implemented for the G2553. I tried to get it to work but can't seem to receive anything on my phone(Using BlueTerm). I am not sure if I missed anything out, or made a mistake and would like you guys to help me. #include "msp430.h" #include "uart.h" #define LED BIT0 #define RXD BIT6 #define TXD BIT5 volatile unsigned int tx_flag; //Mailbox Flag for the tx_char. volatile unsigned char tx_char; //This char is the most current char to go into the UART volatile unsigned int rx_flag; //Mailbox Flag for the rx_char. volatile unsigned char rx_char; //This char is the most current char to come out of the UART /*uart_init * Sets up the UART interface via USCI * INPUT: None * RETURN: None */ void uart_init(void) { P2SEL0 |= RXD + TXD; //Setup the I/O //P2SEL1 |= RXD + TXD; P1DIR |= LED; //P1.0 red LED. Toggle when char received. P1OUT |= LED; //LED off UCA1CTLW0 |= UCSSEL_2; //SMCLK //8,000,000Hz, 9600Baud, UCBRx=52, UCBRSx=0, UCBRFx=1 UCA1BR0 = 52; //8MHz, OSC16, 9600 UCA1BR1 = 0; //((8MHz/9600)/16) = 52.08333 UCA1MCTLW = 0x10|UCOS16; //CBRFx=1,UCBRSx=0, UCOS16=1 UCA1CTLW0 &= ~UCSWRST; //USCI state machine UCA1IE |= UCRXIE ; //Enable USCI_A1 RX interrupt rx_flag = 0; //Set rx_flag to 0 tx_flag = 0; //Set tx_flag to 0 return; } /*uart_getc * Get a char from the UART. Waits till it gets one * INPUT: None * RETURN: Char from UART */ unsigned char uart_getc() //Waits for a valid char from the UART { while (rx_flag == 0); //Wait for rx_flag to be set rx_flag = 0; //ACK rx_flag return rx_char; } /*uart_gets * Get a string of known length from the UART. Strings terminate when enter is pressed or string buffer fills * Will return when all the chars are received or a carriage return (\r) is received. Waits for the data. * INPUT: Array pointer and length * RETURN: None */ void uart_gets(char* Array, int length) { unsigned int i = 0; while((i < length)) //Grab data till the array fills { Array[i] = uart_getc(); if(Array[i] == '\r') //If we receive a \r the master wants to end { for( ; i < length ; i++) //fill the rest of the string with \0 nul. Overwrites the \r with \0 { Array[i] = '\0'; } break; } i++; } return; } /*uart_putc * Sends a char to the UART. Will wait if the UART is busy * INPUT: Char to send * RETURN: None */ void uart_putc(unsigned char c) { tx_char = c; //Put the char into the tx_char UCA1IE |= UCRXIE ; //Enable USCI_A1 TX interrupt while(tx_flag == 1); //Have to wait for the TX buffer tx_flag = 1; //Reset the tx_flag return; } /*uart_puts * Sends a string to the UART. Will wait if the UART is busy * INPUT: Pointer to String to send * RETURN: None */ void uart_puts(char *str) //Sends a String to the UART. { while(*str) uart_putc(*str++); //Advance though string till end return; } #pragma vector = USCI_TX_VECTOR_ //UART TX USCI Interrupt __interrupt void USCI0TX_ISR(void) { UCA1TXBUF = tx_char; //Copy char to the TX Buffer tx_flag = 0; //ACK the tx_flag UCA1IE = 0; //Turn off the interrupt to save CPU } #pragma vector = USCI_RX_VECTOR //UART RX USCI Interrupt. This triggers when the USCI receives a char. __interrupt void USCI0RX_ISR(void) { rx_char = UCA1RXBUF; //Copy from RX buffer, in doing so we ACK the interrupt as well rx_flag = 1; //Set the rx_flag to 1 P1OUT ^= LED; //Notify that we received a char by toggling LED } For more information I have this in my main program WDTCTL = WDTPW + WDTHOLD; //Stop WDT PM5CTL0 &= ~LOCKLPM5; // Disable the GPIO power-on default high-impedance mode to activate // previously configured port settings CSCTL1 = DCOFSEL0 + DCOFSEL1; // 8 MHz DCO (8 MHz is FRAM speed limit);Set DCO to 8Mhz uart_init(); //Initialize the UART connection __enable_interrupt(); //Interrupts Enabled I am also using a HC-05 Bluetooth module and have crossed the RXD and TXD.Thank you very much in advance. Quote Link to post Share on other sites
KatiePier 73 Posted October 3, 2014 Share Posted October 3, 2014 Hi @@mrinverter, There are a few things that jump out at me: 1. Your GPIO setting looks incorrect to me. You are using P2.5 + P2.6 for UCA1TXD/RXD. However, looking at the FR5969 datasheet http://www.ti.com/lit/gpn/msp430fr5969 on p. 88 table 6-52 I see this for the pin setup: You need to have P2SEL1 bit 5 and 6 set to 1, and P2SEL0 bit 5 and 6 set to 0. Right now, it looks like your code does the opposite: P2SEL0 |= RXD + TXD; //Setup the I/O//P2SEL1 |= RXD + TXD; So switch which line is commented out. 2. You are now using FR5969. This device has an eUSCI module (enhanced USCI) rather than USCI that was present on G2553. There are a few differences (for more detail please see the USCI to eUSCI migration guide http://www.ti.com/lit/pdf/slaa522). One thing is the interrupt vector is different on eUSCI so this needs to be changed. It should be the USCI_A1_VECTOR, and you should also modify the ISR to have a switch statement to handle and respond to the correct values for UCA1IV because this is different. You may want to look at some FR5969 code examples for a demonstration of this. Another thing is the baud rate generation. The eUSCI module provides a few more bits to get you better granularity and accuracy for generating baud rates - please check the FR5xx/6xx user's guide http://www.ti.com/lit/pdf/slau367 Table 21-5 for a list of recommended settings to generate different baud rates, and note the slight difference - you should change your code to match this (notably UCBSx = 0x49). There may be other things to change, but hopefully these tips will help! Regards, Katie Fred and mrinverter 2 Quote Link to post Share on other sites
Fred 453 Posted October 3, 2014 Share Posted October 3, 2014 I started typing a reply about checking for USART/USI/USCI differences and suggesting looking at the MSP430Ware examples. (Nowhere near as detailed as Katie's, of course.) However, then I checked the spec pages and saw they were both USCI. I didn't even notice the subtle eUSCI change! I guess that reinforces the point. It's usually the first thing I struggle with and starting from a working example usually speeds things up for me. Going back to the USART on an AFE253 was particularly painful recently. mrinverter 1 Quote Link to post Share on other sites
mrinverter 0 Posted October 4, 2014 Author Share Posted October 4, 2014 Thanks for the reply Katie and Fred, I will fix this and check out the link with the FR5969 code examples. Quote Link to post Share on other sites
mrinverter 0 Posted October 5, 2014 Author Share Posted October 5, 2014 Alright I have taken the advice and tried to understand how to use the eUSCI Interrupt Vectors, however I find it hard to understand and have instead made it worse.Was wondering if anyone can help me with this?Or perhaps point me to something easier to understand, thanks. #include "msp430.h" #include "uart.h" #define RXD BIT6 #define TXD BIT5 volatile unsigned int tx_flag = 0; //Mailbox Flag for the tx_char. volatile unsigned char tx_char; //This char is the most current char to go into the UART volatile unsigned int rx_flag = 0; //Mailbox Flag for the rx_char. volatile unsigned char rx_char; //This char is the most current char to come out of the UART /*uart_init * Sets up the UART interface via USCI * INPUT: None * RETURN: None */ void uart_init(void) { // Configure GPIO P2SEL1 |= RXD | TXD; // USCI_A1 UART operation P2SEL0 &= ~(RXD | TXD); // Configure USCI_A1 for UART mode UCA1CTLW0 = UCSWRST; // Put eUSCI in reset UCA1CTLW0 |= UCSSEL__SMCLK; // CLK = SMCLK // Baud Rate calculation // 8000000/(16*9600) = 52.083 // Fractional portion = 0.083 // User's Guide Table 21-4: UCBRSx = 0x04 // UCBRFx = int ( (52.083-52)*16) = 1 UCA1BR0 = 52; // 8000000/16/9600 UCA1BR1 = 0x00; UCA1MCTLW |= UCOS16 | UCBRF_1; UCA1CTLW0 &= ~UCSWRST; // Initialize eUSCI UCA1IE |= UCRXIE; // Enable USCI_A1 RX interrupt __bis_SR_register(LPM3_bits | GIE); // Enter LPM3, interrupts enabled UCA1IFG = ~(UCRXIFG + UCTXIFG); //Clear Flags return; } /*uart_getc * Get a char from the UART. Waits till it gets one * INPUT: None * RETURN: Char from UART */ unsigned char uart_getc() //Waits for a valid char from the UART { while(!(UCA1IFG & UCRXIFG)); //Wait for rx_flag to be set rx_flag = 0; //ACK rx_flag return rx_char; } /*uart_gets * Get a string of known length from the UART. Strings terminate when enter is pressed or string buffer fills * Will return when all the chars are received or a carriage return (\r) is received. Waits for the data. * INPUT: Array pointer and length * RETURN: None */ void uart_gets(char* Array, int length) { unsigned int i = 0; while((i < length)) //Grab data till the array fills { Array[i] = uart_getc(); if(Array[i] == '\r') //If we receive a \r the master wants to end { for( ; i < length ; i++) //fill the rest of the string with \0 nul. Overwrites the \r with \0 { Array[i] = '\0'; } break; } i++; } return; } /*uart_putc * Sends a char to the UART. Will wait if the UART is busy * INPUT: Char to send * RETURN: None */ void uart_putc(unsigned char c) { tx_char = c; //Put the char into the tx_char UCA1IE |= UCRXIE; //Enable USCI_A1 TX interrupt while(!(UCA1IFG & UCTXIFG)); //Have to wait for the TX buffer tx_flag = 1; //Reset the tx_flag return; } /*uart_puts * Sends a string to the UART. Will wait if the UART is busy * INPUT: Pointer to String to send * RETURN: None */ void uart_puts(char *str) //Sends a String to the UART. { while(*str) uart_putc(*str++); //Advance though string till end return; } #pragma vector = USCI_A1_VECTOR __interrupt void USCI_A1_ISR(void) { switch(__even_in_range(UCA1IV, USCI_UART_UCTXCPTIFG)) { case USCI_NONE: break; case USCI_UART_UCRXIFG: rx_char = UCA1RXBUF; //Copy from RX buffer, in doing so we ACK the interrupt as well rx_flag = 1; //Set the rx_flag to 1 break; case USCI_UART_UCTXIFG: UCA1TXBUF = tx_char; //Copy char to the TX Buffer tx_flag = 0; //ACK the tx_flag __bic_SR_register_on_exit(CPUOFF); // Exit LPM0 on reti break; case USCI_UART_UCSTTIFG: break; case USCI_UART_UCTXCPTIFG: break; } } Quote Link to post Share on other sites
zeke 693 Posted October 6, 2014 Share Posted October 6, 2014 It looks like the F5529 has the USCI just like the FR5969. Why not check out my source code over here and see if you can borrow some functionality for your project? mrinverter 1 Quote Link to post Share on other sites
Fred 453 Posted October 6, 2014 Share Posted October 6, 2014 I'm not entirely sure what you're doing with the UART once you have it set up. I can't see any code listed above that actually sends or receives anything. Apologies if I'm stating the obvious, but I'd suggest that you do the following: Take some sample code (whether TI's or zeke's) in its entirety and get that running. Debug it. Set breakpoints. Try to work out what it's doing. Strip it down so it has only what you need. Get something really simple going. (e.g. when you press the onboard button it sends "Hello" to your phone.) Work slowly from there, testing each simple step. I find borrowing and then understanding other people's code (along with reading "MSP430 Microcontroller Basics") is the best way to learn. Quote Link to post Share on other sites
mrinverter 0 Posted October 7, 2014 Author Share Posted October 7, 2014 Hi Fred,Apologies for the lack of information provided, I have debugged and tried various configuration and am fairly sure the issue with this is that I do not fully understand how the interrupts work(I can't seem to find good documentation I can understand.) What happens in the main is fairly simple: uart_puts sends a string of character; this can be used to output a message(e.g. uart_puts((char *)"Welcome"); // Prints a welcome message) uart_getc gets a character input, this can be used as a trigger(e.g. unsigned char c = uart_getc(); //Retrieves input character; c can then trigger a preset condition based on input) uart_putc does the same thing as uart_puts but prints a single character instead uart_gets does the same thing as uart_getc but get a whole string of character instead I have tested this before on an F2274 and it has worked. Anyways thanks for the advice, I'll keep it in mind.Also, thank you Zeke for providing your source code; I'll see how I can implement it. Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.