Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

204 lines
4.7KB

  1. /* UART (hardware serial) for Teensy & Teensy++
  2. * http://www.pjrc.com/teensy/
  3. * Copyright (c) 2008 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. #include <avr/io.h>
  24. #include <avr/interrupt.h>
  25. #include "core_pins.h"
  26. #include "HardwareSerial.h"
  27. #define RX_BUFFER_SIZE 64
  28. static volatile uint8_t rx_buffer[RX_BUFFER_SIZE];
  29. static volatile uint8_t rx_buffer_head = 0;
  30. static volatile uint8_t rx_buffer_tail = 0;
  31. #define TX_BUFFER_SIZE 40
  32. static volatile uint8_t tx_buffer[TX_BUFFER_SIZE];
  33. static volatile uint8_t tx_buffer_head = 0;
  34. static volatile uint8_t tx_buffer_tail = 0;
  35. static volatile uint8_t transmitting = 0;
  36. static volatile uint8_t tx_enable_pin = 255;
  37. // Public Methods //////////////////////////////////////////////////////////////
  38. void HardwareSerial::_begin(uint16_t baud_count, uint8_t txen_pin)
  39. {
  40. tx_enable_pin = txen_pin;
  41. if (txen_pin < 255) {
  42. pinMode(txen_pin, OUTPUT);
  43. digitalWrite(txen_pin, LOW);
  44. }
  45. if ((baud_count & 1) && baud_count <= 4096) {
  46. UCSR1A = (1<<U2X1);
  47. UBRR1 = baud_count - 1;
  48. } else {
  49. UCSR1A = 0;
  50. UBRR1 = (baud_count >> 1) - 1;
  51. }
  52. if (!(UCSR1B & (1<<TXEN1))) {
  53. rx_buffer_head = 0;
  54. rx_buffer_tail = 0;
  55. tx_buffer_head = 0;
  56. tx_buffer_tail = 0;
  57. transmitting = 0;
  58. UCSR1C = (1<<UCSZ11) | (1<<UCSZ10);
  59. UCSR1B = (1<<RXEN1) | (1<<TXCIE1) | (1<<TXEN1) | (1<<RXCIE1);
  60. }
  61. }
  62. void HardwareSerial::end(void)
  63. {
  64. while (transmitting) ; // wait for buffered data to send
  65. UCSR1B = 0;
  66. rx_buffer_head = 0;
  67. rx_buffer_tail = 0;
  68. }
  69. void HardwareSerial::transmitterEnable(uint8_t pin)
  70. {
  71. while (transmitting) ;
  72. pinMode(pin, OUTPUT);
  73. digitalWrite(pin, LOW);
  74. tx_enable_pin = pin;
  75. }
  76. int HardwareSerial::available(void)
  77. {
  78. uint8_t head, tail;
  79. head = rx_buffer_head;
  80. tail = rx_buffer_tail;
  81. if (head >= tail) return head - tail;
  82. return RX_BUFFER_SIZE + head - tail;
  83. }
  84. int HardwareSerial::peek(void)
  85. {
  86. uint8_t head, tail;
  87. head = rx_buffer_head;
  88. tail = rx_buffer_tail;
  89. if (head == tail) return -1;
  90. if (++tail >= RX_BUFFER_SIZE) tail = 0;
  91. return rx_buffer[tail];
  92. }
  93. int HardwareSerial::read(void)
  94. {
  95. uint8_t c, i;
  96. if (rx_buffer_head == rx_buffer_tail) return -1;
  97. i = rx_buffer_tail + 1;
  98. if (i >= RX_BUFFER_SIZE) i = 0;
  99. c = rx_buffer[i];
  100. rx_buffer_tail = i;
  101. return c;
  102. }
  103. void HardwareSerial::flush()
  104. {
  105. #if ARDUINO >= 100
  106. while (transmitting) ; // wait for buffered data to send
  107. #else
  108. rx_buffer_head = rx_buffer_tail;
  109. #endif
  110. }
  111. void HardwareSerial::clear()
  112. {
  113. rx_buffer_head = rx_buffer_tail;
  114. }
  115. #if ARDUINO >= 100
  116. size_t HardwareSerial::write(uint8_t c)
  117. #else
  118. void HardwareSerial::write(uint8_t c)
  119. #endif
  120. {
  121. uint8_t i;
  122. if (!(UCSR1B & (1<<TXEN1))) {
  123. #if ARDUINO >= 100
  124. setWriteError();
  125. return 0;
  126. #else
  127. return;
  128. #endif
  129. }
  130. if (tx_enable_pin < 255 && !transmitting) {
  131. digitalWrite(tx_enable_pin, HIGH);
  132. }
  133. i = tx_buffer_head + 1;
  134. if (i >= TX_BUFFER_SIZE) i = 0;
  135. while (tx_buffer_tail == i) ; // wait until space in buffer
  136. tx_buffer[i] = c;
  137. transmitting = 1;
  138. tx_buffer_head = i;
  139. UCSR1B = (1<<RXEN1) | (1<<TXCIE1) | (1<<TXEN1) | (1<<RXCIE1) | (1<<UDRIE1);
  140. #if ARDUINO >= 100
  141. return 1;
  142. #endif
  143. }
  144. ISR(USART1_RX_vect)
  145. {
  146. uint8_t c, i;
  147. c = UDR1;
  148. i = rx_buffer_head + 1;
  149. if (i >= RX_BUFFER_SIZE) i = 0;
  150. if (i != rx_buffer_tail) {
  151. rx_buffer[i] = c;
  152. rx_buffer_head = i;
  153. }
  154. }
  155. ISR(USART1_UDRE_vect)
  156. {
  157. uint8_t i;
  158. if (tx_buffer_head == tx_buffer_tail) {
  159. // buffer is empty, disable transmit interrupt
  160. UCSR1B = (1<<RXEN1) | (1<<TXCIE1) | (1<<TXEN1) | (1<<RXCIE1);
  161. } else {
  162. i = tx_buffer_tail + 1;
  163. if (i >= TX_BUFFER_SIZE) i = 0;
  164. UDR1 = tx_buffer[i];
  165. tx_buffer_tail = i;
  166. }
  167. }
  168. ISR(USART1_TX_vect)
  169. {
  170. transmitting = 0;
  171. if (tx_enable_pin < 255) {
  172. digitalWrite(tx_enable_pin, LOW);
  173. }
  174. }
  175. // Preinstantiate Objects //////////////////////////////////////////////////////
  176. HardwareSerial Serial1;