Subversion Repositories HomeAutomation

Rev

Rev 69 | Rev 127 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. /*************************************************************************
  2. Title:     Interrupt UART library with receive/transmit circular buffers
  3. Author:    Peter Fleury <pfleury@gmx.ch>   http://jump.to/fleury
  4. File:      $Id: uart.c,v 1.5.2.2 2004/02/27 22:00:28 peter Exp $
  5. Software:  AVR-GCC 3.3
  6. Hardware:  any AVR with built-in UART,
  7.            tested on AT90S8515 at 4 Mhz and ATmega at 1Mhz
  8. Extensions:- uart_puti by M. Thomas 9/2004
  9.            - uart_puthex_nibble and _byte by M.T. 9/2004
  10.            - uart_putbin_byte by M.T. 1/2005
  11.  
  12. DESCRIPTION:
  13.     An interrupt is generated when the UART has finished transmitting or
  14.     receiving a byte. The interrupt handling routines use circular buffers
  15.     for buffering received and transmitted data.
  16.    
  17.     The UART_RX_BUFFER_SIZE and UART_TX_BUFFER_SIZE variables define
  18.     the buffer size in bytes. Note that these variables must be a
  19.     power of 2.
  20.    
  21. USAGE:
  22.     Refere to the header file uart.h for a description of the routines.
  23.     See also example test_uart.c.
  24.  
  25. NOTES:
  26.     Based on Atmel Application Note AVR306
  27.                    
  28. *************************************************************************/
  29. #include <stdlib.h>
  30. #include <stdio.h>
  31.  
  32. #include <avr/io.h>
  33. #include <avr/interrupt.h>
  34. #include <avr/pgmspace.h>
  35.  
  36. #include <uart.h>
  37.  
  38.  
  39. static int uart_putchar(char c, FILE *stream);
  40.  
  41. static FILE myStdOut = FDEV_SETUP_STREAM(uart_putchar, NULL,_FDEV_SETUP_WRITE);
  42.  
  43. static int uart_putchar(char c, FILE *stream) {
  44.     if (c == '\n') uart_putchar('\r', stream);
  45.     uart_putc(c);
  46.     return 0;
  47. }
  48.  
  49.  
  50. /*
  51.  *  constants and macros
  52.  */
  53.  
  54. /* size of RX/TX buffers */
  55. #define UART_RX_BUFFER_MASK ( UART_RX_BUFFER_SIZE - 1)
  56. #define UART_TX_BUFFER_MASK ( UART_TX_BUFFER_SIZE - 1)
  57.  
  58. #if ( UART_RX_BUFFER_SIZE & UART_RX_BUFFER_MASK )
  59. #error RX buffer size is not a power of 2
  60. #endif
  61. #if ( UART_TX_BUFFER_SIZE & UART_TX_BUFFER_MASK )
  62. #error TX buffer size is not a power of 2
  63. #endif
  64.  
  65. #if defined(__AVR_AT90S2313__) \
  66.  || defined(__AVR_AT90S4414__) || defined(__AVR_AT90S4434__) \
  67.  || defined(__AVR_AT90S8515__) || defined(__AVR_AT90S8535__)
  68.  /* old AVR classic with one UART */
  69.  #define AT90_UART
  70.  #define UART0_RECEIVE_INTERRUPT   SIG_UART_RECV
  71.  #define UART0_TRANSMIT_INTERRUPT  SIG_UART_DATA
  72.  #define UART0_STATUS   USR
  73.  #define UART0_CONTROL  UCR
  74.  #define UART0_DATA     UDR  
  75.  #define UART0_UDRIE    UDRIE
  76. #elif defined(__AVR_AT90S2333__) || defined(__AVR_AT90S4433__)
  77.  /* old AVR classic with one UART */
  78.  #define AT90_UART
  79.  #define UART0_RECEIVE_INTERRUPT   SIG_UART_RECV
  80.  #define UART0_TRANSMIT_INTERRUPT  SIG_UART_DATA
  81.  #define UART0_STATUS   UCSRA
  82.  #define UART0_CONTROL  UCSRB
  83.  #define UART0_DATA     UDR
  84.  #define UART0_UDRIE    UDRIE
  85. #elif  defined(__AVR_ATmega8__)  || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__) \
  86.   || defined(__AVR_ATmega8515__) || defined(__AVR_ATmega8535__) \
  87.   || defined(__AVR_ATmega323__)
  88.   /* ATMega with one USART */
  89.  #define ATMEGA_USART
  90.  #define UART0_RECEIVE_INTERRUPT   SIG_UART_RECV
  91.  #define UART0_TRANSMIT_INTERRUPT  SIG_UART_DATA
  92.  #define UART0_STATUS   UCSRA
  93.  #define UART0_CONTROL  UCSRB
  94.  #define UART0_DATA     UDR
  95.  #define UART0_UDRIE    UDRIE
  96. #elif defined(__AVR_ATmega163__)
  97.   /* ATMega163 with one UART */
  98.  #define ATMEGA_UART
  99.  #define UART0_RECEIVE_INTERRUPT   SIG_UART_RECV
  100.  #define UART0_TRANSMIT_INTERRUPT  SIG_UART_DATA
  101.  #define UART0_STATUS   UCSRA
  102.  #define UART0_CONTROL  UCSRB
  103.  #define UART0_DATA     UDR
  104.  #define UART0_UDRIE    UDRIE
  105. #elif defined(__AVR_ATmega162__)
  106.  /* ATMega with two USART */
  107.  #define ATMEGA_USART0
  108.  #define ATMEGA_USART1
  109.  #define UART0_RECEIVE_INTERRUPT   SIG_USART0_RECV
  110.  #define UART1_RECEIVE_INTERRUPT   SIG_USART1_RECV
  111.  #define UART0_TRANSMIT_INTERRUPT  SIG_USART0_DATA
  112.  #define UART1_TRANSMIT_INTERRUPT  SIG_USART1_DATA
  113.  #define UART0_STATUS   UCSR0A
  114.  #define UART0_CONTROL  UCSR0B
  115.  #define UART0_DATA     UDR0
  116.  #define UART0_UDRIE    UDRIE0
  117.  #define UART1_STATUS   UCSR1A
  118.  #define UART1_CONTROL  UCSR1B
  119.  #define UART1_DATA     UDR1
  120.  #define UART1_UDRIE    UDRIE1
  121. #elif defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__)
  122.  /* ATMega with two USART */
  123.  #define ATMEGA_USART0
  124.  #define ATMEGA_USART1
  125.  #define UART0_RECEIVE_INTERRUPT   SIG_UART0_RECV
  126.  #define UART1_RECEIVE_INTERRUPT   SIG_UART1_RECV
  127.  #define UART0_TRANSMIT_INTERRUPT  SIG_UART0_DATA
  128.  #define UART1_TRANSMIT_INTERRUPT  SIG_UART1_DATA
  129.  #define UART0_STATUS   UCSR0A
  130.  #define UART0_CONTROL  UCSR0B
  131.  #define UART0_DATA     UDR0
  132.  #define UART0_UDRIE    UDRIE0
  133.  #define UART1_STATUS   UCSR1A
  134.  #define UART1_CONTROL  UCSR1B
  135.  #define UART1_DATA     UDR1
  136.  #define UART1_UDRIE    UDRIE1
  137. #elif defined(__AVR_ATmega103__)
  138.  /* ATMega with one UART */
  139.  #error "AVR ATmega103 currently not supported by this libaray !"
  140. #elif defined(__AVR_ATmega161__)
  141.  /* ATmega with UART */
  142.  #error "AVR ATmega161 currently not supported by this libaray !"
  143. #elif defined(__AVR_ATmega169__)
  144.  #error "AVR ATmega169 currently not supported by this libaray !"
  145. #endif
  146.  
  147.  
  148. /*
  149.  *  module global variables
  150.  */
  151. static volatile unsigned char UART_TxBuf[UART_TX_BUFFER_SIZE];
  152. static volatile unsigned char UART_RxBuf[UART_RX_BUFFER_SIZE];
  153. static volatile unsigned char UART_TxHead;
  154. static volatile unsigned char UART_TxTail;
  155. static volatile unsigned char UART_RxHead;
  156. static volatile unsigned char UART_RxTail;
  157. static volatile unsigned char UART_LastRxError;
  158.  
  159.  
  160.  
  161. ISR(UART0_RECEIVE_INTERRUPT)
  162. /*************************************************************************
  163. Function: UART Receive Complete interrupt
  164. Purpose:  called when the UART has received a character
  165. **************************************************************************/
  166. {
  167.     unsigned char tmphead;
  168.     unsigned char data;
  169.     unsigned char usr;
  170.     unsigned char lastRxError;
  171.  
  172.  
  173.     /* read UART status register and UART data register */
  174.     usr  = UART0_STATUS;
  175.     data = UART0_DATA;
  176.    
  177.     /* */
  178. #if defined( AT90_UART )
  179.     lastRxError = (usr & (_BV(FE)|_BV(DOR)) );
  180. #elif defined( ATMEGA_USART )
  181.     lastRxError = (usr & (_BV(FE)|_BV(DOR)) );
  182. #elif defined( ATMEGA_USART0 )
  183.     lastRxError = (usr & (_BV(FE0)|_BV(DOR0)) );
  184. #elif defined ( ATMEGA_UART )
  185.     lastRxError = (usr & (_BV(FE)|_BV(DOR)) );
  186. #endif
  187.        
  188.     /* calculate buffer index */
  189.     tmphead = ( UART_RxHead + 1) & UART_RX_BUFFER_MASK;
  190.    
  191.     if ( tmphead == UART_RxTail ) {
  192.         /* error: receive buffer overflow */
  193.         lastRxError = UART_BUFFER_OVERFLOW >> 8;
  194.     }else{
  195.         /* store new index */
  196.         UART_RxHead = tmphead;
  197.         /* store received data in buffer */
  198.         UART_RxBuf[tmphead] = data;
  199.     }
  200.     UART_LastRxError = lastRxError;
  201. }
  202.  
  203.  
  204. ISR(UART0_TRANSMIT_INTERRUPT)
  205. /*************************************************************************
  206. Function: UART Data Register Empty interrupt
  207. Purpose:  called when the UART is ready to transmit the next byte
  208. **************************************************************************/
  209. {
  210.     unsigned char tmptail;
  211.  
  212.    
  213.     if ( UART_TxHead != UART_TxTail) {
  214.         /* calculate and store new buffer index */
  215.         tmptail = (UART_TxTail + 1) & UART_TX_BUFFER_MASK;
  216.         UART_TxTail = tmptail;
  217.         /* get one byte from buffer and write it to UART */
  218.         UART0_DATA = UART_TxBuf[tmptail];  /* start transmission */
  219.     }else{
  220.         /* tx buffer empty, disable UDRE interrupt */
  221.         UART0_CONTROL &= ~_BV(UART0_UDRIE);
  222.     }
  223. }
  224.  
  225.  
  226.  
  227. /**
  228.  * Wrapper function for uart_init.
  229.  */
  230. void UartInit() {
  231.     uart_init((UART_BAUD_SELECT((BAUD),F_OSC)));
  232.     stdout = &myStdOut;
  233. }
  234.  
  235.  
  236. /*************************************************************************
  237. Function: uart_init()
  238. Purpose:  initialize UART and set baudrate
  239. Input:    baudrate using macro UART_BAUD_SELECT()
  240. Returns:  none
  241. **************************************************************************/
  242. void uart_init(unsigned int baudrate)
  243. {
  244.     UART_TxHead = 0;
  245.     UART_TxTail = 0;
  246.     UART_RxHead = 0;
  247.     UART_RxTail = 0;
  248.    
  249. #if defined( AT90_UART )
  250.     /* set baud rate */
  251.     UBRR = (unsigned char)baudrate;
  252.  
  253.     /* enable UART receiver and transmmitter and receive complete interrupt */
  254.     UART0_CONTROL = _BV(RXCIE)|_BV(RXEN)|BV(TXEN);
  255.  
  256. #elif defined (ATMEGA_USART)
  257.     /* Set baud rate */
  258.     UBRRH = (unsigned char)(baudrate>>8);
  259.     UBRRL = (unsigned char) baudrate;
  260.  
  261.     /* Enable USART receiver and transmitter and receive complete interrupt */
  262.     UART0_CONTROL = _BV(RXCIE)|(1<<RXEN)|(1<<TXEN);
  263.    
  264.     /* Set frame format: asynchronous, 8data, no parity, 1stop bit */
  265.     #ifdef URSEL
  266.     UCSRC = (1<<URSEL)|(3<<UCSZ0);
  267.     #else
  268.     UCSRC = (3<<UCSZ0);
  269.     #endif
  270.    
  271. #elif defined (ATMEGA_USART0 )
  272.     /* Set baud rate */
  273.     UBRR0H = (unsigned char)(baudrate>>8);
  274.     UBRR0L = (unsigned char) baudrate;
  275.  
  276.     /* Enable USART receiver and transmitter and receive complete interrupt */
  277.     UART0_CONTROL = _BV(RXCIE0)|(1<<RXEN0)|(1<<TXEN0);
  278.    
  279.     /* Set frame format: asynchronous, 8data, no parity, 1stop bit */
  280.     #ifdef URSEL0
  281.     UCSR0C = (1<<URSEL0)|(3<<UCSZ00);
  282.     #else
  283.     UCSR0C = (3<<UCSZ00);
  284.     #endif
  285.  
  286. #elif defined ( ATMEGA_UART )
  287.     /* set baud rate */
  288.     UBRRHI = (unsigned char)(baudrate>>8);
  289.     UBRR   = (unsigned char) baudrate;
  290.  
  291.     /* Enable UART receiver and transmitter and receive complete interrupt */
  292.     UART0_CONTROL = _BV(RXCIE)|(1<<RXEN)|(1<<TXEN);
  293.  
  294. #endif
  295.  
  296. }/* uart_init */
  297.  
  298.  
  299. /*************************************************************************
  300. Function: uart_getc()
  301. Purpose:  return byte from ringbuffer  
  302. Returns:  lower byte:  received byte from ringbuffer
  303.           higher byte: last receive error
  304. **************************************************************************/
  305. unsigned int uart_getc(void)
  306. {    
  307.     unsigned char tmptail;
  308.     unsigned char data;
  309.  
  310.  
  311.     if ( UART_RxHead == UART_RxTail ) {
  312.         return UART_NO_DATA;   /* no data available */
  313.     }
  314.    
  315.     /* calculate /store buffer index */
  316.     tmptail = (UART_RxTail + 1) & UART_RX_BUFFER_MASK;
  317.     UART_RxTail = tmptail;
  318.    
  319.     /* get data from receive buffer */
  320.     data = UART_RxBuf[tmptail];
  321.    
  322.     return (UART_LastRxError << 8) + data;
  323.  
  324. }/* uart_getc */
  325.  
  326.  
  327. /*************************************************************************
  328. Function: uart_putc()
  329. Purpose:  write byte to ringbuffer for transmitting via UART
  330. Input:    byte to be transmitted
  331. Returns:  none          
  332. **************************************************************************/
  333. void uart_putc(unsigned char data)
  334. {
  335.     unsigned char tmphead;
  336.  
  337.    
  338.     tmphead  = (UART_TxHead + 1) & UART_TX_BUFFER_MASK;
  339.    
  340.     while ( tmphead == UART_TxTail ){
  341.         ;/* wait for free space in buffer */
  342.     }
  343.    
  344.     UART_TxBuf[tmphead] = data;
  345.     UART_TxHead = tmphead;
  346.  
  347.     /* enable UDRE interrupt */
  348.     UART0_CONTROL    |= _BV(UART0_UDRIE);
  349.  
  350. }/* uart_putc */
  351.  
  352.  
  353. /*************************************************************************
  354. Function: uart_puts()
  355. Purpose:  transmit string to UART
  356. Input:    string to be transmitted
  357. Returns:  none          
  358. **************************************************************************/
  359. void uart_puts(const char *s )
  360. {
  361.     while (*s)
  362.       uart_putc(*s++);
  363.  
  364. }/* uart_puts */
  365.  
  366.  
  367. /*************************************************************************
  368. Function: uart_puts_p()
  369. Purpose:  transmit string from program memory to UART
  370. Input:    program memory string to be transmitted
  371. Returns:  none
  372. **************************************************************************/
  373. void uart_puts_p(const char *progmem_s )
  374. {
  375.     register char c;
  376.    
  377.     while ( (c = pgm_read_byte(progmem_s++)) )
  378.       uart_putc(c);
  379.  
  380. }/* uart_puts_p */
  381.  
  382. /*************************************************************************
  383. Function: uart_puti()
  384. Purpose:  transmit integer as ASCII to UART
  385. Input:    integer value
  386. Returns:  none
  387. This functions has been added by Martin Thomas <eversmith@heizung-thomas.de>
  388. Don't blame P. Fleury if it doesn't work ;-)
  389. **************************************************************************/
  390. void uart_puti( const int val )
  391. {
  392.     char buffer[sizeof(int)*8+1];
  393.    
  394.     uart_puts( itoa(val, buffer, 10) );
  395.  
  396. }/* uart_puti */
  397.  
  398. /*************************************************************************
  399. Function: uart_puthex_nibble()
  400. Purpose:  transmit lower nibble as ASCII-hex to UART
  401. Input:    byte value
  402. Returns:  none
  403. This functions has been added by Martin Thomas <eversmith@heizung-thomas.de>
  404. Don't blame P. Fleury if it doesn't work ;-)
  405. **************************************************************************/
  406. void uart_puthex_nibble(const unsigned char b)
  407. {
  408.     unsigned char  c = b & 0x0f;
  409.     if (c>9) c += 'A'-10;
  410.     else c += '0';
  411.     uart_putc(c);
  412. } /* uart_puthex_nibble */
  413.  
  414. /*************************************************************************
  415. Function: uart_puthex_byte()
  416. Purpose:  transmit upper and lower nibble as ASCII-hex to UART
  417. Input:    byte value
  418. Returns:  none
  419. This functions has been added by Martin Thomas <eversmith@heizung-thomas.de>
  420. Don't blame P. Fleury if it doesn't work ;-)
  421. **************************************************************************/
  422. void uart_puthex_byte(const unsigned char  b)
  423. {
  424.     uart_puthex_nibble(b>>4);
  425.     uart_puthex_nibble(b);
  426. } /* uart_puthex_byte */
  427.  
  428. /*************************************************************************
  429. Function: uart_putbin_byte()
  430. Purpose:  transmit byte as ASCII-bin to UART
  431. Input:    byte value
  432. Returns:  none
  433. This functions has been added by Martin Thomas <eversmith@heizung-thomas.de>
  434. Don't blame P. Fleury if it doesn't work ;-)
  435. **************************************************************************/
  436. void uart_putbin_byte(const unsigned char b)
  437. {
  438. #if 0
  439.     char buffer[sizeof(int)*8+1];
  440.    
  441.     uart_puts( itoa(b, buffer, 2) );
  442. #else
  443.     signed char i;
  444.     for (i=7;i>=0;i--) {
  445.         if (b & (1<<i)) {
  446.             uart_putc('1');
  447.         }
  448.         else {
  449.             uart_putc('0');
  450.         }
  451.     }
  452. #endif
  453. } /* uart_putbin_byte */
  454.