카테고리 없음 2007. 3. 12. 19:49

GCC-AVR library를 이용한, standard IO test..

GCC-AVR의 기본 library에는 printf나 scanf류의 함수들이 있다.

이들 함수는 putchar와 getchar만 define해 주면 바로 사용할 수 있다.

예제:

=========


#include <stdint.h>
#include <stdio.h>
#include <avr/io.h>
#include <avr/delay.h>
#define RX_BUFSIZE 80


void   uart_init(void);
int    uart_putchar(char c, FILE *stream);
int    uart_getchar(FILE *stream);


FILE uart_str = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);

int
main(void)
{
// unsigned int addr;
 unsigned int value;
 uint8_t* addr;
 char buf[80];
 uart_init();

 stderr = stdout = stdin = &uart_str;

 printf("SKA_MON start\n");
 while(1)
 {
  printf("$>");
  if (fgets(buf, sizeof(buf) - 1, stdin) == NULL)break;

  switch (tolower(buf[0]))
  {
   default:
    printf("Unknown command: %s\n", buf);
    break;
   case '\n':
    break;
   case 'w':
    if (sscanf(buf, "%*c %x %x", &addr, &value) > 0)
    {
     printf( "Write 0x%x, 0x%x\n", addr, value);
     *addr = (uint8_t)value;
    }
    else printf("sscanf() failed\n");
    break;
   case 'r':
    if (sscanf(buf, "%*c %x", &addr) > 0)
    {
     printf("value at 0x%x = 0x%x\n", addr, *addr);
    }
    else printf("sscanf() failed\n");
    break;
  }
 }
 return 0;
}


/*
* Initialize the UART to 9600 Bd, tx/rx, 8N1.
*/
void
uart_init(void)
{
 UBRRL =25;                                    // baud rate..
 UCSRA = _BV(U2X);
 UCSRB = _BV(TXEN) | _BV(RXEN);                // enable uart tx & tx_int & rx & rx_int
}


/*
* Send character c down the UART Tx, wait until tx holding register
* is empty.
*/
int
uart_putchar(char c, FILE *stream)
{
 if (c == '\a')
 {
  fputs("*ring*\n", stderr);
  return 0;
 }
 if (c == '\n') uart_putchar('\r', stream);
 loop_until_bit_is_set(UCSRA, UDRE);
 UDR = c;
 return 0;
}

// getchar는 echo때문에 조금 복잡하다.
int
uart_getchar(FILE *stream)
{
 uint8_t c;
 char *cp, *cp2;
 static char b[RX_BUFSIZE];
 static char *rxp;
 if (rxp == 0)
  for (cp = b;;)
 {
  loop_until_bit_is_set(UCSRA, RXC);
  if (UCSRA & _BV(FE))
   return _FDEV_EOF;
  if (UCSRA & _BV(DOR))
   return _FDEV_ERR;
  c = UDR;
  /* behaviour similar to Unix stty ICRNL */
  if (c == '\r') c = '\n';

  if (c == '\n')
  {
   *cp = c;
   uart_putchar(c, stream);
   rxp = b;
   break;
  }
  else if (c == '\t')
   c = ' ';
  if ((c >= (uint8_t)' ' && c <= (uint8_t)'\x7e') ||
   c >= (uint8_t)'\xa0')
  {
   if (cp == b + RX_BUFSIZE - 1)
    uart_putchar('\a', stream);
   else
   {
    *cp++ = c;
    uart_putchar(c, stream);
   }
   continue;
  }
  switch (c)
  {
   case 'c' & 0x1f:
    return -1;
   case '\b':
   case '\x7f':
    if (cp > b)
    {
     uart_putchar('\b', stream);
     uart_putchar(' ', stream);
     uart_putchar('\b', stream);
     cp--;
    }
    break;
   case 'r' & 0x1f:
    uart_putchar('\r', stream);
    for (cp2 = b; cp2 < cp; cp2++)
     uart_putchar(*cp2, stream);
    break;
   case 'u' & 0x1f:
    while (cp > b)
    {
     uart_putchar('\b', stream);
     uart_putchar(' ', stream);
     uart_putchar('\b', stream);
     cp--;
    }
    break;
   case 'w' & 0x1f:
    while (cp > b && cp[-1] != ' ')
    {
     uart_putchar('\b', stream);
     uart_putchar(' ', stream);
     uart_putchar('\b', stream);
     cp--;
    }
    break;
  }
 }
 c = *rxp++;
 if (c == '\n')
  rxp = 0;
 return c;
}