📄 printfuart.h
字号:
/*
* Copyright (c) 2005
* The President and Fellows of Harvard College.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Writes printf like output to the UART.
* This works only on the AVR and MSP430 Microcontrollers!
* <p>
* Note: For AVR we explicitly place the print statements in ROM; for
* MSP430 this is done by default! For AVR, if we don't place it
* explicitely in ROM, the statements will go in RAM, which will
* quickly cause a descent size program to run out of RAM. By default
* it doesn't disable the interupts; disabling the interupts when
* writing to the UART, slows down/makes the mote quite unresponsive,
* and can lead to problems! If you wish to disable all printfs to
* the UART, then comment the flag: <code>PRINTFUART_ENABLED</code>.
* <p> <pre>
* How to use:
* // (1) Call printfUART_init() from your initialization function
* // to initialize the UART
* printfUART_init();
* // (2) Set your UART client to the correct baud rate. Look at
* // the comments in printfUART_init(), to figure out what
* // baud to use for your particular mote
*
* // (3) Send printf statements like this:
* printfUART("Hello World, we are in year= %i\n", 2004);
*
* Examples and caveats:
* // (1) - If no parameters are passed, then the second quotes
* are required because of how the macro is defined
* printfUART("Timer fired\n", "");
* // (2) - Must use curly braces in single section statements
* if (x < 3)
* {printfUART("The value of x is %i\n", x);}
* // (3) - Otherwise it more or less works like regular printf
* printfUART("\nThe value of x=%i, and y=%i\n", x, y);
* </pre>
* <pre>URL: http://www.eecs.harvard.edu/~konrad/projects/motetrack</pre>
* @author Konrad Lorincz
* @version 2.0, January 5, 2005
*/
#ifndef PRINTFUART_H
#define PRINTFUART_H
#include <stdarg.h>
//#include <stdio.h>
// Comment out the line below to DISABLE printf statements.
#define PRINTFUART_ENABLED
// -------------------------------------------------------------------
#ifdef PRINTFUART_ENABLED
#define DEBUGBUF_SIZE 256
char debugbuf[DEBUGBUF_SIZE];
char debugbufROMtoRAM[DEBUGBUF_SIZE];
#if defined(PLATFORM_MICAZ) || defined(PLATFORM_MICA2) || defined(PLATFORM_MICA2DOT)
#define printfUART(__format, __args...) { \
static const char strROM[] PROGMEM = __format; \
strcpy_P((char*) &debugbufROMtoRAM, (PGM_P) &strROM); \
sprintf(debugbuf, debugbufROMtoRAM, __args); \
writedebug(); \
}
#else // assume MSP430 architecture (e.g. TelosA, TelosB, etc.)
#define printfUART(__format, __args...) { \
sprintf(debugbuf, __format, __args); \
writedebug(); \
}
#endif
#else
#define printfUART(__format, __args...)
void printfUART_init() {}
#endif
#define NOprintfUART(__format, __args...)
/** Used for terminating the program from a non-nesc file. Calling <code>exit(1)</code>
* from a non-nesc file doesn't terminate the program immeditely
*/
static int EXIT_PROGRAM = 0;
// -------------------------------------------------------------------
#ifdef PRINTFUART_ENABLED
/**
* Initialize the UART port. Call this from your startup routine.
*/
#define printfUART_init() {atomic printfUART_init_private();}
void printfUART_init_private()
{
#if defined(PLATFORM_MICAZ) || defined(PLATFORM_MICA2)
// 56K baud
outp(0,UBRR0H);
outp(15, UBRR0L); //set baud rate
outp((1<<U2X),UCSR0A); // Set UART double speed
outp(((1 << UCSZ1) | (1 << UCSZ0)) , UCSR0C); // Set frame format: 8 data-bits, 1 stop-bit
inp(UDR0);
outp((1 << TXEN) ,UCSR0B); // Enable uart reciever and transmitter
#else
#if defined(PLATFORM_MICA2DOT)
// 19.2K baud
outp(0,UBRR0H); // Set baudrate to 19.2 KBps
outp(12, UBRR0L);
outp(0,UCSR0A); // Disable U2X and MPCM
outp(((1 << UCSZ1) | (1 << UCSZ0)) , UCSR0C);
inp(UDR0);
outp((1 << TXEN) ,UCSR0B);
#else // assume TelosA, TelosB, etc.
//9.6K baud
uint16_t l_br = 0;
uint8_t l_mctl = 0;
uint8_t l_ssel = 0;
TOSH_SEL_UTXD1_MODFUNC();
TOSH_SEL_URXD1_MODFUNC();
UCTL1 = SWRST;
UCTL1 |= CHAR; // 8-bit char, UART-mode
U1RCTL &= ~URXEIE; // even erroneous characters trigger interrupts
UCTL1 = SWRST;
UCTL1 |= CHAR; // 8-bit char, UART-mode
if (l_ssel & 0x80) {
U1TCTL &= ~(SSEL_0 | SSEL_1 | SSEL_2 | SSEL_3);
U1TCTL |= (l_ssel & 0x7F);
}
else {
U1TCTL &= ~(SSEL_0 | SSEL_1 | SSEL_2 | SSEL_3);
U1TCTL |= SSEL_ACLK; // use ACLK, assuming 32khz
}
if ((l_mctl != 0) || (l_br != 0)) {
U1BR0 = l_br & 0x0FF;
U1BR1 = (l_br >> 8) & 0x0FF;
U1MCTL = l_mctl;
}
else {
U1BR0 = 0x03; // 9600 baud
U1BR1 = 0x00;
U1MCTL = 0x4A;
}
ME2 &= ~USPIE1; // USART1 SPI module disable
ME2 |= (UTXE1 | URXE1); // USART1 UART module enable
U1CTL &= ~SWRST;
IFG2 &= ~(UTXIFG1 | URXIFG1);
IE2 &= ~(UTXIE1 | URXIE1); // interrupt disabled
#endif
#endif
}
#if defined(PLATFORM_MICAZ) || defined(PLATFORM_MICA2) || defined(PLATFORM_MICA2DOT)
#else // assume AVR architecture (e.g. TelosA, TelosB)
bool isTxIntrPending()
{
if (U1TCTL & TXEPT) {
return TRUE;
}
return FALSE;
}
#endif
/**
* Outputs a char to the UART.
*/
void UARTPutChar(char c)
{
if (c == '\n')
UARTPutChar('\r');
#if defined(PLATFORM_MICAZ) || defined(PLATFORM_MICA2) || defined(PLATFORM_MICA2DOT)
loop_until_bit_is_set(UCSR0A, UDRE);
outb(UDR0,c);
#else // assume AVR architecture (e.g. TelosA, TelosB)
U1TXBUF = c;
while( !isTxIntrPending() )
continue;
#endif
}
/**
* Outputs the entire debugbuf to the UART, or until it encounters '\0'.
*/
void writedebug()
{
uint16_t i = 0;
while (debugbuf[i] != '\0' && i < DEBUGBUF_SIZE)
UARTPutChar(debugbuf[i++]);
}
/**
* Simplified sprintf
*/
#define SCRATCH 16
int sprintf(uint8_t *buf, const uint8_t *format, ...)
{
uint8_t scratch[SCRATCH];
uint8_t format_flag;
uint32_t u_val=0, base;//modified by Andre Cunha
uint8_t *ptr;
va_list ap;
//memset(scratch, 0, SCRATCH);
buf[0] = '\0'; // KLDEBUG - fixes subtle bug ...
va_start (ap, format);
for (;;){
while ((format_flag = *format++) != '%'){ // Until '%' or '\0'
if (!format_flag) {va_end (ap); return (0);}
*buf = format_flag; buf++; *buf=0;
}
switch (format_flag = *format++){
case 'c':
format_flag = va_arg(ap,int);
default:
*buf = format_flag; buf++; *buf=0;
continue;
case 'S':
case 's':
ptr = va_arg(ap,char *);
strcat(buf, ptr);
continue;
case 'o':
base = 8;
*buf = '0'; buf++; *buf=0;
goto CONVERSION_LOOP;
case 'i':
if (((int)u_val) < 0){
u_val = - u_val;
*buf = '-'; buf++; *buf=0;
}
base = 10;
goto CONVERSION_LOOP;
// no break -> run into next case
case 'd'://added by Andre Cunha
if (((int32_t)u_val) < 0){
u_val = - u_val;
*buf = '-'; buf++; *buf=0;
}
base = 10;
goto CONVERSION_LOOP32;
case 'u':
base = 10;
goto CONVERSION_LOOP;
case 'x':
base = 16;
goto CONVERSION_LOOP;
case 'y'://unsigned int 32 bits hexadecimal//added by Andre Cunha
base = 16;
goto CONVERSION_LOOP32;
CONVERSION_LOOP:
u_val = va_arg(ap,int);
ptr = scratch + SCRATCH;
*--ptr = 0;
do {
char ch = u_val % base + '0';
if (ch > '9')
ch += 'a' - '9' - 1;
*--ptr = ch;
u_val /= base;
} while (u_val);
strcat(buf, ptr);
buf += strlen(ptr);
break;
CONVERSION_LOOP32:
u_val = va_arg(ap,int32_t);
ptr = scratch + SCRATCH;
*--ptr = 0;
do {
char ch = u_val % base + '0';
if (ch > '9')
ch += 'a' - '9' - 1;
*--ptr = ch;
u_val /= base;
} while (u_val);
strcat(buf, ptr);
buf += strlen(ptr);
}
}
}
#endif // PRINTFUART_ENABLED
// -------------------------------------------------------------------
#endif // PRINTFUART_H
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -