You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

182 lines
5.6 KiB

  1. /* UART Example for Teensy USB Development Board
  2. * http://www.pjrc.com/teensy/
  3. * Copyright (c) 2009 PJRC.COM, LLC
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a copy
  6. * of this software and associated documentation files (the "Software"), to deal
  7. * in the Software without restriction, including without limitation the rights
  8. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. * copies of the Software, and to permit persons to whom the Software is
  10. * furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be included in
  13. * all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. * THE SOFTWARE.
  22. */
  23. // Version 1.0: Initial Release
  24. // Version 1.1: Add support for Teensy 2.0, minor optimizations
  25. #include <avr/io.h>
  26. #include <avr/interrupt.h>
  27. #include "uart.h"
  28. #if defined(__AVR_AT90USB162__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__)
  29. # define UDRn UDR1
  30. # define UBRRnL UBRR1L
  31. # define UCSRnA UCSR1A
  32. # define UCSRnB UCSR1B
  33. # define UCSRnC UCSR1C
  34. # define U2Xn U2X1
  35. # define RXENn RXEN1
  36. # define TXENn TXEN1
  37. # define RXCIEn RXCIE1
  38. # define UCSZn1 UCSZ11
  39. # define UCSZn0 UCSZ10
  40. # define UDRIEn UDRIE1
  41. # define USARTn_UDRE_vect USART1_UDRE_vect
  42. # define USARTn_RX_vect USART1_RX_vect
  43. #elif defined(__AVR_ATmega32A__)
  44. # define UDRn UDR
  45. # define UBRRnL UBRRL
  46. # define UCSRnA UCSRA
  47. # define UCSRnB UCSRB
  48. # define UCSRnC UCSRC
  49. # define U2Xn U2X
  50. # define RXENn RXEN
  51. # define TXENn TXEN
  52. # define RXCIEn RXCIE
  53. # define UCSZn1 UCSZ1
  54. # define UCSZn0 UCSZ0
  55. # define UDRIEn UDRIE
  56. # define USARTn_UDRE_vect USART_UDRE_vect
  57. # define USARTn_RX_vect USART_RX_vect
  58. #elif defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__)
  59. # define UDRn UDR0
  60. # define UBRRnL UBRR0L
  61. # define UCSRnA UCSR0A
  62. # define UCSRnB UCSR0B
  63. # define UCSRnC UCSR0C
  64. # define U2Xn U2X0
  65. # define RXENn RXEN0
  66. # define TXENn TXEN0
  67. # define RXCIEn RXCIE0
  68. # define UCSZn1 UCSZ01
  69. # define UCSZn0 UCSZ00
  70. # define UDRIEn UDRIE0
  71. # define USARTn_UDRE_vect USART_UDRE_vect
  72. # define USARTn_RX_vect USART_RX_vect
  73. #endif
  74. // These buffers may be any size from 2 to 256 bytes.
  75. #define RX_BUFFER_SIZE 64
  76. #define TX_BUFFER_SIZE 256
  77. static volatile uint8_t tx_buffer[TX_BUFFER_SIZE];
  78. static volatile uint8_t tx_buffer_head;
  79. static volatile uint8_t tx_buffer_tail;
  80. static volatile uint8_t rx_buffer[RX_BUFFER_SIZE];
  81. static volatile uint8_t rx_buffer_head;
  82. static volatile uint8_t rx_buffer_tail;
  83. // Initialize the UART
  84. void uart_init(uint32_t baud) {
  85. cli();
  86. UBRRnL = (F_CPU / 4 / baud - 1) / 2;
  87. UCSRnA = (1 << U2Xn);
  88. UCSRnB = (1 << RXENn) | (1 << TXENn) | (1 << RXCIEn);
  89. UCSRnC = (1 << UCSZn1) | (1 << UCSZn0);
  90. tx_buffer_head = tx_buffer_tail = 0;
  91. rx_buffer_head = rx_buffer_tail = 0;
  92. sei();
  93. }
  94. // Transmit a byte
  95. void uart_write(uint8_t data) {
  96. uint8_t i;
  97. i = tx_buffer_head + 1;
  98. if (i >= TX_BUFFER_SIZE) i = 0;
  99. // return immediately to avoid deadlock when interrupt is disabled(called from ISR)
  100. if (tx_buffer_tail == i && (SREG & (1 << SREG_I)) == 0) return;
  101. while (tx_buffer_tail == i)
  102. ; // wait until space in buffer
  103. // cli();
  104. tx_buffer[i] = data;
  105. tx_buffer_head = i;
  106. UCSRnB = (1 << RXENn) | (1 << TXENn) | (1 << RXCIEn) | (1 << UDRIEn);
  107. // sei();
  108. }
  109. // Receive a byte
  110. uint8_t uart_read(void) {
  111. uint8_t data, i;
  112. while (rx_buffer_head == rx_buffer_tail)
  113. ; // wait for character
  114. i = rx_buffer_tail + 1;
  115. if (i >= RX_BUFFER_SIZE) i = 0;
  116. data = rx_buffer[i];
  117. rx_buffer_tail = i;
  118. return data;
  119. }
  120. void uart_transmit(const uint8_t *data, uint16_t length) {
  121. for (uint16_t i = 0; i < length; i++) {
  122. uart_write(data[i]);
  123. }
  124. }
  125. void uart_receive(uint8_t *data, uint16_t length) {
  126. for (uint16_t i = 0; i < length; i++) {
  127. data[i] = uart_read();
  128. }
  129. }
  130. // Return whether the number of bytes waiting in the receive buffer is nonzero.
  131. // Call this before uart_read() to check if it will need
  132. // to wait for a byte to arrive.
  133. bool uart_available(void) {
  134. uint8_t head, tail;
  135. head = rx_buffer_head;
  136. tail = rx_buffer_tail;
  137. if (head >= tail) return (head - tail) > 0;
  138. return (RX_BUFFER_SIZE + head - tail) > 0;
  139. }
  140. // Transmit Interrupt
  141. ISR(USARTn_UDRE_vect) {
  142. uint8_t i;
  143. if (tx_buffer_head == tx_buffer_tail) {
  144. // buffer is empty, disable transmit interrupt
  145. UCSRnB = (1 << RXENn) | (1 << TXENn) | (1 << RXCIEn);
  146. } else {
  147. i = tx_buffer_tail + 1;
  148. if (i >= TX_BUFFER_SIZE) i = 0;
  149. UDRn = tx_buffer[i];
  150. tx_buffer_tail = i;
  151. }
  152. }
  153. // Receive Interrupt
  154. ISR(USARTn_RX_vect) {
  155. uint8_t c, i;
  156. c = UDRn;
  157. i = rx_buffer_head + 1;
  158. if (i >= RX_BUFFER_SIZE) i = 0;
  159. if (i != rx_buffer_tail) {
  160. rx_buffer[i] = c;
  161. rx_buffer_head = i;
  162. }
  163. }