So I have been trying to incorporate the tiny printf() function I found from msp430launchpad.com into my code and I am having some strange issues.
http://www.msp430launchpad.com/2012/06/using-printf.html
Most of the time it will not print strings from ROM (FLASH) correctly (they end up as the first character of the string followed by . but will print integers (long and short, signed and unsigned) and hex values fine. See my attached code named "blink.c".
The only way it will work is if the program has been loaded onto the IC and I disconnect the power (via the JTAG connector), reconnect it, and close and then reopen Tera Term.
Does anyone have any idea why this isn't working properly?
/******************************************************************************
* MSP430G2553 printf() Tests
*
* Description: A modified version of the test code for testing oPossum's
* tiny printf() function. More information on the printf()
* function can be found at the following link.
*
* http://www.43oh.com/forum/viewtopic.php?f=10&t=1732
*
* This specific code tests the printf() function using
* the hardware UART on the MSP430G2553 with a baud rate
* of 9600. Once the character 't' is received, the test
* sequence is started.
*
* This code was originally created for "NJC's MSP430
* LaunchPad Blog".
*
* Author: Nicholas J. Conn - http://msp430launchpad.com
* Email: webmaster at msp430launchpad.com
* Date: 06-07-12
******************************************************************************/
#include "msp430g2553.h"
#include "stdarg.h"
// Define flags used by the interrupt routines
#define TX BIT0
// Flag register
volatile unsigned char FLAGS = 0;
void sendByte(unsigned char);
void printf(char *, ...);
void initTimer(void);
void initUART(void);
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
initTimer();
initUART();
// Initialize values to display
char *s = "NJC's MSP430 LaunchPad Blog";
char c = '!';
int i = -12345;
unsigned u = 4321;
long int l = -123456780;
long unsigned n = 1098765432;
unsigned x = 0xABCD;
while(1) {
//switch(FLAGS) {
// case 0: // No flags set
// __bis_SR_register(LPM3_bits + GIE); // Enter LPM3
// break;
//case TX: // Values need to be transmitted
// Display all the different types of values
printf("String %s\r\n", s);
printf("Char %c\r\n", c);
printf("Integer %i\r\n", i);
printf("Unsigned %u\r\n", u);
printf("Long %l\r\n", l);
printf("uNsigned loNg %n\r\n", n);
printf("heX %x\r\n", x);
FLAGS &= ~TX; // Clear transmit flag
break;
//}
}
}
/**
* Initializes the timer to call the interrupt every 1 second
*/
void initTimer(void) {
/*
* BCSCTL2: Basic Clock System Control 2
*
* SELM_0 -- DCOCLK (main clock [MCLCK] source select)
* DIVM_0 -- Divide by 1 (Division of MCLCK)
* ~SELS -- DCOCLK (source select for subsystem clk [SMCLCK])
* DIVS_0 -- Divide by 1 (Division for SMCLCK]
* ~DCOR -- DCO uses internal resistor (
*
* Note: ~<BIT> indicates that <BIT> has value zero
* PAGE 289 in MSP430x2xxx
*/
BCSCTL2 = SELM_0 + DIVM_0 + DIVS_0;
//Checking if there is data in DCO Oscillator Calibration Register
if (CALBC1_8MHZ != 0xFF) {
/* Follow recommended flow. First, clear all DCOx and MODx bits. Then
* apply new RSELx values. Finally, apply new DCOx and MODx bit values.
*/
DCOCTL = 0x00; //clearing frequency select and modulation selection
BCSCTL1 = CALBC1_8MHZ; /* Set DCO to 8MHz */
DCOCTL = CALDCO_8MHZ;
}
//External (LFXT1) LF CLK INITIALIZATION (BCSCTL3)
//BCSCTL3 = XT2S_0 + LFXT1S_2 + XCAP_1;
}
/**
* Initializes the UART for 9600 baud with a RX interrupt
**/
void initUART(void) {
P1DIR = BIT0;
//Sets all the pins on Port 1 to I/O
P1SEL = 0;
P1SEL2 = 0;
//For UART Steps see pg 424
UCA0CTL1 = UCSWRST;
//UCSWRST = 1;
//int i = 0;
//UCSWRST = 0x00;
UCA0CTL0 = 0x0;
UCA0CTL1 |= BIT6+BIT7; //Take UART out of RESET (toggle 1st bit of UCA0CTL1)
//Select clock source for UART (6th and 7th bit in UCA0CTL1)
// (UCCSEL) --- 2^7 = 0x80h & 2^0 = 0x01h => 0x81
//Baud rate settings for 8MHz (9600bps)
//Refer to table on page 435 in MSP430x2xxx document
UCA0BR1 = 0x03; //load UCA0BR with 833(dec)= 0x341h
UCA0BR0 = 0x41; //UCA0BR is UCA0BR0 and UCA0BR1 where BR1 is the high byte
//UCOS16 = 0 and UCBRF0 = 0 and UCBRS0 = 2 UCBR0 = 833 (see table on page 435)
UCA0MCTL = 0x04; //Baud rate settings for 8MHz (9600bps)
//Setting port pins
P1DIR |= BIT2;
P1SEL |= BIT2; // Primary peripheral module function is selected.
// With the following line commented out (//P1SEL2 = BIT2;)
P1SEL2 |= BIT2; // Secondary peripheral module function is selected.
// (if P1SEL and P1SEL2 are set high)
UCA0CTL1 &= (0xFF - UCSWRST);//Clearing RESET bit
//UCA0CTL1 |= UCSSEL_2; //Select clock source for UART (6th and 7th bit in UCA0CTL1)
//UCBRS = 0x02;
//UCA0BRS0
//UCA0CTL0 = 0x00;
//UCA0MCTL = 0x00;
//UCA0TXIE = i;
//UTXEx = 1;
}
/**
* puts() is used by printf() to display or send a string.. This function
* determines where printf prints to. For this case it sends a string
* out over UART, another option could be to display the string on an
* LCD display.
**/
void puts(char *s) {
char c;
// Loops through each character in string 's'
while (c = *s++) {
sendByte(c);
}
}
/**
* puts() is used by printf() to display or send a character. This function
* determines where printf prints to. For this case it sends a character
* out over UART.
**/
void putc(unsigned b) {
sendByte(b);
}
/**
* Sends a single byte out through UART
**/
void sendByte(unsigned char byte )
{
while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready?
UCA0TXBUF = byte; // TX -> RXed character
}
/**
* Interrupt routine for receiving a character over UART
**/
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
char r = UCA0RXBUF; // Get the received character
//if (r == 't') // 'u' received?
{
FLAGS |= TX; // Set flag to transmit data
__bic_SR_register_on_exit(LPM3_bits); // Wake-up CPU
}
}
/**
* Timer A0 interrupt service routine, is called every second
**/
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A (void)
{
P1OUT ^= BIT0; // Toggle LED
}