Jump to content
43oh

msp430g2452 simple UART


Recommended Posts

Hi all,

 

I am trying to implement/edit an UART library (https://github.com/wendlers/msp430-softuart) on 2452 to run on MCLK 8MHz and SMCLK at 8MHz (by /8 divider).

    BCSCTL1 = CALBC1_1MHZ;
    DCOCTL = CALDCO_1MHZ;

Then I changed the MCLK to 8MHz and divided the SMCLK to 1MHz, but even after some magic with USB ports (I am using debian) or restarts I can't get it working as in the initial version (which still works when I reflash the chip).

The changed snippet in 2452_echo.c:

    BCSCTL1 = CALBC1_8MHZ;
    DCOCTL = CALDCO_8MHZ;

    /* set sub-main clock to 1MHz */
    //BCSCTL2 = DIVS_3;
    BCSCTL2 = SELM_0 | DIVM_0 | DIVS_3;

Any hints?
Thank you, b

Link to post
Share on other sites

Forgot to add the code..

 

2452_code.c


/* echos back received bytes */
#include <msp430g2452.h>
#include <stdint.h>

#include "uart.h"


#define UART_TXD BIT1
#define UART_RXD BIT2

#define RED_LED BIT0
#define GRN_LED BIT6


uint16_t wdtCounter = 0;


inline static void init_clock(void) {
    /* set main clock to 8MHz */
    DCOCTL = 0x00;
    BCSCTL1 = CALBC1_8MHZ;
    DCOCTL = CALDCO_8MHZ;

    /* set sub-main clock to 1MHz */
    //BCSCTL2 = DIVS_3;
    BCSCTL2 = SELM_0 | DIVM_0 | DIVS_3;
//    BCSCTL2 &= ~SELM0;  // MCLK comes from DCO
//    BCSCTL2 &= ~SELM1;
//    BCSCTL2 &= ~SELS;   // Sub main clock comes from DCO
//    BCSCTL2 |= DIVS0 + DIVS1;   // SMCLK = 1 MHz (DC0/8)
}


inline static void init_timers(void) {
    /* watchdog */
    WDTCTL = WDT_MDLY_32;   /* set watchdog timer interval to 32ms */
    IE1 |= WDTIE;   /* enable interrupts for the watchdog timer */
}


inline static void init_IO(void) {
    /* configure LED pins on port 1 as output pins */
    P1DIR |= RED_LED | GRN_LED;
    /* make sure leds are turned on */
    P1OUT |= RED_LED | GRN_LED;

    uart_init();
}



int main(void) {
    uint8_t c;

    /* init */    __delay_cycles(128);

    init_timers();
    init_IO();

    __enable_interrupt();

    for(; {   /* infinite loop */
        if (uart_getc(&c)) {
            if (c == '\r') {
                uart_putc('\n');
                uart_putc('\r');
                P1OUT ^= RED_LED;
            } else {
                uart_putc('-');
                uart_putc(c);
                uart_putc('-');
                P1OUT ^= GRN_LED;
            }
        }
    }
}



void watchdog_timer(void) __attribute__((interrupt(WDT_VECTOR)));
void watchdog_timer(void)
{
    wdtCounter++;

    if(wdtCounter == 20) {
        wdtCounter = 0; /* reset counter */
    }
}

    init_clock();

uart.c

/******************************************************************************
 * Software UART example for MSP430.
 *
 * Stefan Wendler
 * sw@kaltpost.de
 * http://gpio.kaltpost.de
 *
 * ****************************************************************************
 * The original code is taken form Nicholas J. Conn example:
 *
 * http://www.msp430launchpad.com/2010/08/half-duplex-software-uart-on-launchpad.html
 *
 * Origial Description from Nicholas:
 *
 * Half Duplex Software UART on the LaunchPad
 *
 * Description: This code provides a simple Bi-Directional Half Duplex
 * Software UART. The timing is dependant on SMCLK, which
 * is set to 1MHz. The transmit function is based off of
 * the example code provided by TI with the LaunchPad.
 * This code was originally created for "NJC's MSP430
 * LaunchPad Blog".
 *
 * Author: Nicholas J. Conn - http://msp430launchpad.com
 * Email: webmaster at msp430launchpad.com
 * Date: 08-17-10
 * ****************************************************************************
 * Includes also improvements from Joby Taffey and fixes from Colin Funnell
 * as posted here:
 *
 * http://blog.hodgepig.org/tag/msp430/
 ******************************************************************************/

#include <msp430.h>
#include <legacymsp430.h>
#include <stdbool.h>

#include "uart.h"

/**
 * TXD on P1.1
 */
#define TXD             BIT1

/**
 * RXD on P1.2
 */
#define RXD             BIT2

/**
 * Clock freq.
 */
#define CLK_FREQ        1000000

/**
 * Baudrate
 */#define BAUDRATE        9600

/**
 * Bit time
 */
#define BIT_TIME        (CLK_FREQ / BAUDRATE)

/**
 * Half bit time
 */
#define HALF_BIT_TIME   (BIT_TIME / 2)

/**
 * Bit count, used when transmitting byte
 */
static volatile uint8_t bitCount;

/**
 * Value sent over UART when uart_putc() is called
 */
static volatile unsigned int TXByte;

/**
 * Value recieved once hasRecieved is set
 */
static volatile unsigned int RXByte;

/**
 * Status for when the device is receiving
 */
static volatile bool isReceiving = false;

/**
 * Lets the program know when a byte is received
 */
static volatile bool hasReceived = false;

void uart_init(void)
{
    P1SEL |= TXD;
    P1DIR |= TXD;

    P1IES |= RXD;   // RXD Hi/lo edge interrupt
    P1IFG &= ~RXD;  // Clear RXD (flag) before enabling interrupt
    P1IE |= RXD;    // Enable RXD interrupt
}

bool uart_getc(uint8_t *c)
{
    if (!hasReceived) {
        return false;
    }

    *c = RXByte;
    hasReceived = false;

    return true;
}

void uart_putc(uint8_t c)
{
    TXByte = c;

    while (isReceiving) {}                   // Wait for RX completion

    TACCTL0 = OUT;                            // TXD Idle as Mark
    TACTL = TASSEL_2 | MC_2;                // SMCLK, continuous mode

    bitCount = 0xA;                         // Load Bit counter, 8 bits + ST/SP
    TACCR0 = TAR;                             // Initialize compare register

    TACCR0 += BIT_TIME;                       // Set time till first bit
    TXByte |= 0x100;                        // Add stop bit to TXByte (which is logical 1)
    TXByte = TXByte << 1;                   // Add start bit (which is logical 0)

    TACCTL0 = CCIS_0 | OUTMOD_0 | CCIE | OUT; // Set signal, intial value, enable interrupts

    while (TACCTL0 & CCIE) {}                 // Wait for previous TX completion
}

void uart_puts(const char *str)
{
    if (*str != 0) {
        uart_putc(*str++);
    }

    while (*str != 0) {
        uart_putc(*str++);
    }
}

/**
 * ISR for RXD
 */
interrupt(PORT1_VECTOR) PORT1_ISR(void)
{
    isReceiving = true;

    P1IE &= ~RXD;               // Disable RXD interrupt
    P1IFG &= ~RXD;              // Clear RXD IFG (interrupt flag)

    TACTL = TASSEL_2 | MC_2;    // SMCLK, continuous mode
    TACCR0 = TAR;                 // Initialize compare register
    TACCR0 += HALF_BIT_TIME;      // Set time till first bit
    TACCTL0 = OUTMOD_1 | CCIE;    // Disable TX and enable interrupts

    RXByte = 0;                 // Initialize RXByte
    bitCount = 9;               // Load Bit counter, 8 bits + start bit
}

/**
 * ISR for TXD and RXD
 */
interrupt(TIMER0_A0_VECTOR) TIMERA0_ISR(void)
{
    if (!isReceiving) {
        TACCR0 += BIT_TIME;                       // Add Offset to CCR0

        if (bitCount == 0) {                    // If all bits TXed
            TACTL = 0;                   // SMCLK, timer off (for power consumption)
            TACCTL0 &= ~CCIE;                   // Disable interrupt
        } else {
            if (TXByte & 0x01) {
                TACCTL0 = ((TACCTL0 & ~OUTMOD_7) | OUTMOD_1);  //OUTMOD_7 defines the 'window' of the field.
            } else {
                TACCTL0 = ((TACCTL0 & ~OUTMOD_7) | OUTMOD_5);  //OUTMOD_7 defines the 'window' of the field.
            }

            TXByte = TXByte >> 1;
            bitCount--;
        }
    } else {
        TACCR0 += BIT_TIME;                       // Add Offset to CCR0

        if (bitCount == 0) {
            TACTL = 0;                   // SMCLK, timer off (for power consumption)
            TACCTL0 &= ~ CCIE ;                   // Disable interrupt

            isReceiving = false;

            P1IFG &= ~RXD;                      // clear RXD IFG (interrupt flag)
            P1IE |= RXD;                        // enabled RXD interrupt

            if ((RXByte & 0x201) == 0x200) {    // Validate the start and stop bits are correct
                RXByte = RXByte >> 1;           // Remove start bit
                RXByte &= 0xFF;                 // Remove stop bit
                hasReceived = true;
            }
        } else {
            if ((P1IN & RXD) == RXD) {          // If bit is set?
                RXByte |= 0x400;                // Set the value in the RXByte
            }

            RXByte = RXByte >> 1;               // Shift the bits down
            bitCount--;
        }
    }
}



uart.h is the same as in the linked library..

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...