├── .gitattributes ├── .github └── workflows │ └── tg-send.yml ├── LICENSE ├── README.md ├── README_EN.md ├── examples ├── parseTest │ └── parseTest.ino └── printTest │ └── printTest.ino ├── keywords.txt ├── library.properties └── src ├── GyverUART.cpp └── GyverUART.h /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/workflows/tg-send.yml: -------------------------------------------------------------------------------- 1 | 2 | name: Telegram Message 3 | on: 4 | release: 5 | types: [published] 6 | jobs: 7 | build: 8 | name: Send Message 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: send telegram message on push 12 | uses: appleboy/telegram-action@master 13 | with: 14 | to: ${{ secrets.TELEGRAM_TO }} 15 | token: ${{ secrets.TELEGRAM_TOKEN }} 16 | disable_web_page_preview: true 17 | message: | 18 | ${{ github.event.repository.name }} v${{ github.event.release.tag_name }} 19 | ${{ github.event.release.body }} 20 | https://github.com/${{ github.repository }} 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 AlexGyver 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![latest](https://img.shields.io/github/v/release/GyverLibs/GyverUART.svg?color=brightgreen)](https://github.com/GyverLibs/GyverUART/releases/latest/download/GyverUART.zip) 2 | [![PIO](https://badges.registry.platformio.org/packages/gyverlibs/library/GyverUART.svg)](https://registry.platformio.org/libraries/gyverlibs/GyverUART) 3 | [![Foo](https://img.shields.io/badge/Website-AlexGyver.ru-blue.svg?style=flat-square)](https://alexgyver.ru/) 4 | [![Foo](https://img.shields.io/badge/%E2%82%BD%24%E2%82%AC%20%D0%9F%D0%BE%D0%B4%D0%B4%D0%B5%D1%80%D0%B6%D0%B0%D1%82%D1%8C-%D0%B0%D0%B2%D1%82%D0%BE%D1%80%D0%B0-orange.svg?style=flat-square)](https://alexgyver.ru/support_alex/) 5 | [![Foo](https://img.shields.io/badge/README-ENGLISH-blueviolet.svg?style=flat-square)](https://github-com.translate.goog/GyverLibs/GyverUART?_x_tr_sl=ru&_x_tr_tl=en) 6 | 7 | [![Foo](https://img.shields.io/badge/ПОДПИСАТЬСЯ-НА%20ОБНОВЛЕНИЯ-brightgreen.svg?style=social&logo=telegram&color=blue)](https://t.me/GyverLibs) 8 | 9 | # GyverUART 10 | Лёгкая библиотека для работы с последовательным портом 11 | - Практически полный аналог Serial, но гораздо легче 12 | 13 | ### Совместимость 14 | ATmega328 и прочие из этого поколения 15 | 16 | ## Содержание 17 | - [Установка](#install) 18 | - [Инициализация](#init) 19 | - [Использование](#usage) 20 | - [Пример](#example) 21 | - [Версии](#versions) 22 | - [Баги и обратная связь](#feedback) 23 | 24 | 25 | ## Установка 26 | - Библиотеку можно найти по названию **GyverUART** и установить через менеджер библиотек в: 27 | - Arduino IDE 28 | - Arduino IDE v2 29 | - PlatformIO 30 | - [Скачать библиотеку](https://github.com/GyverLibs/GyverUART/archive/refs/heads/main.zip) .zip архивом для ручной установки: 31 | - Распаковать и положить в *C:\Program Files (x86)\Arduino\libraries* (Windows x64) 32 | - Распаковать и положить в *C:\Program Files\Arduino\libraries* (Windows x32) 33 | - Распаковать и положить в *Документы/Arduino/libraries/* 34 | - (Arduino IDE) автоматическая установка из .zip: *Скетч/Подключить библиотеку/Добавить .ZIP библиотеку…* и указать скачанный архив 35 | - Читай более подробную инструкцию по установке библиотек [здесь](https://alexgyver.ru/arduino-first/#%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%B1%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA) 36 | ### Обновление 37 | - Рекомендую всегда обновлять библиотеку: в новых версиях исправляются ошибки и баги, а также проводится оптимизация и добавляются новые фичи 38 | - Через менеджер библиотек IDE: найти библиотеку как при установке и нажать "Обновить" 39 | - Вручную: **удалить папку со старой версией**, а затем положить на её место новую. "Замену" делать нельзя: иногда в новых версиях удаляются файлы, которые останутся при замене и могут привести к ошибкам! 40 | 41 | 42 | 43 | ## Инициализация 44 | Нет 45 | 46 | 47 | ## Использование 48 | Как у Serial 49 | 50 | 51 | ## Пример 52 | Остальные примеры смотри в **examples**! 53 | ```cpp 54 | #include 55 | 56 | char data0 = 'b'; 57 | int8_t data1 = -50; 58 | uint8_t data2 = 125; 59 | int16_t data3 = -2000; 60 | uint16_t data4 = 30000; 61 | int32_t data5 = -70000; 62 | uint32_t data6 = 4194967295; 63 | float data7 = 3681.65424; 64 | float data8 = -4375.12353; 65 | String data9 = "LOL LOL"; 66 | 67 | const char *data10[] = { 68 | "LOL", 69 | "KEK", 70 | "CHEBUREK", 71 | }; 72 | 73 | byte data11 = 0b11101011; 74 | uint32_t data12 = 0xFAB666; 75 | 76 | void setup() { 77 | uart.begin(); 78 | uart.println(data0); 79 | uart.println(data1); 80 | uart.println(data2); 81 | uart.println(data3); 82 | uart.println(data4); 83 | uart.println(data5); 84 | uart.println(data6); 85 | uart.println(data7); 86 | uart.println(data8, 3); 87 | uart.println(data9); 88 | uart.println("KEK KEK"); 89 | uart.println(F("KEK KEK MACRO")); 90 | uart.println(data10[2]); 91 | uart.println(data11, BIN); 92 | uart.println(data12, HEX); 93 | } 94 | 95 | void loop() { 96 | } 97 | ``` 98 | 99 | 100 | ## Версии 101 | - v1.2 - добавлен циклический буфер 102 | - v1.3 - поправлен вывод float и добавлен вывод с базисом 103 | - v1.4 - либа собрана в класс, добавлена readStringUntil 104 | - v1.5 - добавлен буфер на отправку и flush 105 | - v1.6 - ускорена запись и чтение 106 | - v1.7 - чуть оптимизирован код 107 | - v1.8 - пофикшен write (спасибо eugenebartosh) 108 | - v1.9 - пофикшен write + оптимизация + поддержка USART0 atmega2560 (by Siliverst) 109 | - v1.10 - вывод переведён на Print.h. Размер стал чуть больше, но будет меньше при работе с другими либами на Print.h 110 | 111 | 112 | ## Баги и обратная связь 113 | При нахождении багов создавайте **Issue**, а лучше сразу пишите на почту [alex@alexgyver.ru](mailto:alex@alexgyver.ru) 114 | Библиотека открыта для доработки и ваших **Pull Request**'ов! 115 | 116 | 117 | При сообщении о багах или некорректной работе библиотеки нужно обязательно указывать: 118 | - Версия библиотеки 119 | - Какой используется МК 120 | - Версия SDK (для ESP) 121 | - Версия Arduino IDE 122 | - Корректно ли работают ли встроенные примеры, в которых используются функции и конструкции, приводящие к багу в вашем коде 123 | - Какой код загружался, какая работа от него ожидалась и как он работает в реальности 124 | - В идеале приложить минимальный код, в котором наблюдается баг. Не полотно из тысячи строк, а минимальный код 125 | -------------------------------------------------------------------------------- /README_EN.md: -------------------------------------------------------------------------------- 1 | This is an automatic translation, may be incorrect in some places. See sources and examples! 2 | 3 | # Gyveruart 4 | Light library for working with a sequential port 5 | - almost a complete analogue of Serial, but much easier 6 | 7 | ## compatibility 8 | Atmega328 and other from this generation 9 | 10 | ## Content 11 | - [installation] (# Install) 12 | - [initialization] (#init) 13 | - [use] (#usage) 14 | - [Example] (# Example) 15 | - [versions] (#varsions) 16 | - [bugs and feedback] (#fedback) 17 | 18 | 19 | ## Installation 20 | - The library can be found by the name ** gyveruart ** and installed through the library manager in: 21 | - Arduino ide 22 | - Arduino ide v2 23 | - Platformio 24 | - [download the library] (https://github.com/gyverlibs/gyvert/archive/refs/heads/main.zip). Zip archive for manual installation: 25 | - unpack and put in * C: \ Program Files (X86) \ Arduino \ Libraries * (Windows X64) 26 | - unpack and put in * C: \ Program Files \ Arduino \ Libraries * (Windows X32) 27 | - unpack and put in *documents/arduino/libraries/ * 28 | - (Arduino id) Automatic installation from. Zip: * sketch/connect the library/add .Zip library ... * and specify downloaded archive 29 | - Read more detailed instructions for installing libraries [here] (https://alexgyver.ru/arduino-first/#%D0%A3%D1%81%D1%82%D0%B0%BD%D0%BE%BE%BE%BED0%B2%D0%BA%D0%B0_%D0%B1%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA) 30 | ### Update 31 | - I recommend always updating the library: errors and bugs are corrected in the new versions, as well as optimization and new features are added 32 | - through the IDE library manager: find the library how to install and click "update" 33 | - Manually: ** remove the folder with the old version **, and then put a new one in its place.“Replacement” cannot be done: sometimes in new versions, files that remain when replacing are deleted and can lead to errors! 34 | 35 | 36 | 37 | ## initialization 38 | No 39 | 40 | 41 | ## Usage 42 | Like Serial 43 | 44 | 45 | ## Example 46 | The rest of the examples look at ** Examples **! 47 | `` `CPP 48 | #incLude 49 | 50 | char data0 = 'b'; 51 | int8_t data1 = -50; 52 | Uint8_t Data2 = 125; 53 | Int16_t Data3 = -2000; 54 | Uint16_t Data4 = 30000; 55 | Int32_T DATA5 = -70000; 56 | Uint32_T DATA6 = 4194967295; 57 | Float Data7 = 3681.65424; 58 | Float Data8 = -4375.12353; 59 | String Data9 = "Lol Lol"; 60 | 61 | const char *DATA10 [] = {{ 62 | "Lol", 63 | "Kek", 64 | "Cheburek", 65 | }; 66 | 67 | Byte data11 = 0b11101011; 68 | Uint32_T DATA12 = 0XFAB666; 69 | 70 | VOID setup () { 71 | uart.begin (); 72 | UART.PRINTLN (DATA0); 73 | urt.println (Data1); 74 | urt.println (Data2); 75 | UART.PRINTLN (DATA3); 76 | urt.println (Data4); 77 | urt.println (Data5); 78 | urt.println (Data6); 79 | urt.println (Data7); 80 | urt.println (Data8, 3); 81 | UART.PRINTLN (DATA9); 82 | urt.println ("Kek Kek"); 83 | uart.println (F ("Kek Kek Macro")); 84 | urt.println (Data10 [2]); 85 | urt.println (Data11, Bin); 86 | urt.println (Data12, Hex); 87 | } 88 | 89 | VOID loop () { 90 | } 91 | `` ` 92 | 93 | 94 | ## versions 95 | - V1.2 - Added cyclic buffer 96 | - V1.3 - The conclusion of Float is corrected and the conclusion with the basis has been added 97 | - V1.4 - Liba is assembled to class, added by ReadStringuntil 98 | - v1.5 - added a buffer for sending and Flush 99 | - V1.6 - Record and reading accelerated 100 | - V1.7 - The code is slightly optimized 101 | - V1.8 - Found Write (thanks to Eugenebartosh) 102 | - V1.9 - Found Write + Optimization + Support USART0 Atmega2560 (By Siliverst) 103 | - V1.10 - The conclusion was transferred to Print.h.The size has become a little larger, but it will be smaller when working with Dcranberries on Print.h 104 | 105 | 106 | ## bugs and feedback 107 | Create ** Issue ** when you find the bugs, and better immediately write to the mail [alex@alexgyver.ru] (mailto: alex@alexgyver.ru) 108 | The library is open for refinement and your ** pull Request ** 'ow! 109 | 110 | 111 | When reporting about bugs or incorrect work of the library, it is necessary to indicate: 112 | - The version of the library 113 | - What is MK used 114 | - SDK version (for ESP) 115 | - version of Arduino ide 116 | - whether the built -in examples work correctly, in which the functions and designs are used, leading to a bug in your code 117 | - what code has been loaded, what work was expected from it and how it works in reality 118 | - Ideally, attach the minimum code in which the bug is observed.Not a canvas of a thousand lines, but a minimum code -------------------------------------------------------------------------------- /examples/parseTest/parseTest.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int dataArray[8]; 4 | 5 | void setup() { 6 | uart.begin(); // открыть на 9600 7 | } 8 | 9 | void loop() { 10 | // $10 21 458 63 8 45 875 215; 11 | if (uart.parsePacket((int*)dataArray)) { 12 | for (byte i = 0; i < 8; i++) { 13 | uart.print(dataArray[i]); 14 | uart.print(" "); 15 | } 16 | uart.println(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/printTest/printTest.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | char data0 = 'b'; 4 | int8_t data1 = -50; 5 | uint8_t data2 = 125; 6 | int16_t data3 = -2000; 7 | uint16_t data4 = 30000; 8 | int32_t data5 = -70000; 9 | uint32_t data6 = 4194967295; 10 | float data7 = 3681.65424; 11 | float data8 = -4375.12353; 12 | String data9 = "LOL LOL"; 13 | 14 | const char *data10[] = { 15 | "LOL", 16 | "KEK", 17 | "CHEBUREK", 18 | }; 19 | 20 | byte data11 = 0b11101011; 21 | uint32_t data12 = 0xFAB666; 22 | 23 | void setup() { 24 | uart.begin(); 25 | uart.println(data0); 26 | uart.println(data1); 27 | uart.println(data2); 28 | uart.println(data3); 29 | uart.println(data4); 30 | uart.println(data5); 31 | uart.println(data6); 32 | uart.println(data7); 33 | uart.println(data8, 3); 34 | uart.println(data9); 35 | uart.println("KEK KEK"); 36 | uart.println(F("KEK KEK MACRO")); 37 | uart.println(data10[2]); 38 | uart.println(data11, BIN); 39 | uart.println(data12, HEX); 40 | } 41 | 42 | void loop() { 43 | 44 | } 45 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For GyverUART 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | GyverUART KEYWORD1 9 | uart KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | begin KEYWORD2 16 | end KEYWORD2 17 | peek KEYWORD2 18 | flush KEYWORD2 19 | clear KEYWORD2 20 | read KEYWORD2 21 | write KEYWORD2 22 | print KEYWORD2 23 | println KEYWORD2 24 | available KEYWORD2 25 | setTimeout KEYWORD2 26 | parseInt KEYWORD2 27 | readString KEYWORD2 28 | parseFloat KEYWORD2 29 | parsePacket KEYWORD2 30 | 31 | 32 | ####################################### 33 | # Constants (LITERAL1) 34 | ####################################### 35 | 36 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=GyverUART 2 | version=1.10.1 3 | author=AlexGyver 4 | maintainer=AlexGyver 5 | sentence=Light and fast Serial library 6 | paragraph=Light and fast Serial library 7 | category=Communication 8 | url=https://github.com/GyverLibs/GyverUART 9 | architectures=avr -------------------------------------------------------------------------------- /src/GyverUART.cpp: -------------------------------------------------------------------------------- 1 | #include "GyverUART.h" 2 | 3 | #define UART_RX_BUFFER_SIZE 64 4 | static volatile char _UART_RX_BUFFER[UART_RX_BUFFER_SIZE]; 5 | static volatile uint8_t _UART_RX_BUFFER_HEAD; 6 | static volatile uint8_t _UART_RX_BUFFER_TAIL; 7 | uint32_t _UART_TIMEOUT = 100; 8 | 9 | #define UART_TX_BUFFER_SIZE 32 10 | static volatile char _UART_TX_BUFFER[UART_TX_BUFFER_SIZE]; 11 | static volatile uint8_t _UART_TX_BUFFER_HEAD; 12 | static volatile uint8_t _UART_TX_BUFFER_TAIL; 13 | 14 | #if defined(__AVR_ATmega2560__) 15 | #define USARTx_RX_vect USART0_RX_vect 16 | #define USARTx_UDRE_vect USART0_UDRE_vect 17 | #else 18 | #define USARTx_RX_vect USART_RX_vect 19 | #define USARTx_UDRE_vect USART_UDRE_vect 20 | #endif 21 | 22 | // =========================== INIT ======================== 23 | void GyverUart::begin(uint32_t baudrate) { 24 | uint16_t speed = (F_CPU / (8L * baudrate)) - 1; 25 | UBRR0H = highByte(speed); 26 | UBRR0L = lowByte(speed); 27 | UCSR0A = (1 << U2X0); 28 | UCSR0B = ((1 << TXEN0) | (1 << RXEN0) | (1 << RXCIE0)); 29 | UCSR0C = ((1 << UCSZ01) | (1 << UCSZ00)); 30 | _UART_RX_BUFFER_HEAD = _UART_RX_BUFFER_TAIL = 0; 31 | _UART_TX_BUFFER_HEAD = _UART_TX_BUFFER_TAIL = 0; 32 | } 33 | 34 | void GyverUart::end() { 35 | UCSR0B = 0; 36 | } 37 | 38 | // =========================== READ ============================ 39 | ISR(USARTx_RX_vect) { 40 | uint8_t c, i; 41 | if (UCSR0A & (1 << UPE0)) { 42 | c = UDR0; 43 | } // Не сохранять новые данные если parity error 44 | else { 45 | c = UDR0; 46 | if (_UART_RX_BUFFER_HEAD + 1 == UART_RX_BUFFER_SIZE) { 47 | i = 0; 48 | } else { 49 | i = _UART_RX_BUFFER_HEAD + 1; 50 | } 51 | // Не сохранять новые данные если нет места 52 | if (i != _UART_RX_BUFFER_TAIL) { 53 | _UART_RX_BUFFER[_UART_RX_BUFFER_HEAD] = c; 54 | _UART_RX_BUFFER_HEAD = i; 55 | } 56 | } 57 | } 58 | 59 | char GyverUart::read() { 60 | if (_UART_RX_BUFFER_HEAD == _UART_RX_BUFFER_TAIL) { 61 | return -1; 62 | } 63 | uint8_t c = _UART_RX_BUFFER[_UART_RX_BUFFER_TAIL]; 64 | if (++_UART_RX_BUFFER_TAIL >= UART_RX_BUFFER_SIZE) { 65 | _UART_RX_BUFFER_TAIL = 0; 66 | } // хвост двигаем 67 | return c; 68 | } 69 | 70 | char GyverUart::peek() { 71 | return _UART_RX_BUFFER_HEAD != _UART_RX_BUFFER_TAIL ? _UART_RX_BUFFER[_UART_RX_BUFFER_TAIL] : -1; 72 | } 73 | 74 | void GyverUart::flush() { 75 | while (_UART_TX_BUFFER_HEAD != _UART_TX_BUFFER_TAIL); 76 | } 77 | 78 | uint8_t GyverUart::available() { 79 | return ((uint16_t)(UART_RX_BUFFER_SIZE + _UART_RX_BUFFER_HEAD - _UART_RX_BUFFER_TAIL) % UART_RX_BUFFER_SIZE); 80 | } 81 | 82 | void GyverUart::clear() { 83 | _UART_RX_BUFFER_HEAD = _UART_RX_BUFFER_TAIL = 0; 84 | } 85 | 86 | void GyverUart::setTimeout(int timeout) { 87 | _UART_TIMEOUT = timeout; 88 | } 89 | 90 | int32_t GyverUart::parseInt() { 91 | uint32_t timeoutTime = millis(); 92 | uint32_t value = 0; 93 | boolean negative = false; 94 | 95 | while (millis() - timeoutTime < _UART_TIMEOUT) { 96 | if (available()) { 97 | timeoutTime = millis(); 98 | char newByte = read(); 99 | if (newByte == '-') { 100 | negative = true; 101 | } else { 102 | value += (newByte - '0'); 103 | value *= 10L; 104 | } 105 | } 106 | } 107 | value /= 10L; 108 | return (!negative) ? value : -value; 109 | } 110 | 111 | boolean GyverUart::parsePacket(int *intArray) { 112 | if (available()) { 113 | uint32_t timeoutTime = millis(); 114 | int value = 0; 115 | byte index = 0; 116 | boolean parseStart = 0; 117 | 118 | while (millis() - timeoutTime < 100) { 119 | if (available()) { 120 | timeoutTime = millis(); 121 | if (peek() == '$') { 122 | parseStart = true; 123 | read(); 124 | continue; 125 | } 126 | if (parseStart) { 127 | if (peek() == ' ') { 128 | intArray[index] = value / 10; 129 | value = 0; 130 | index++; 131 | read(); 132 | continue; 133 | } 134 | if (peek() == ';') { 135 | intArray[index] = value / 10; 136 | read(); 137 | return true; 138 | } 139 | value += read() - '0'; 140 | value *= 10; 141 | } else { 142 | clear(); 143 | } 144 | } 145 | } 146 | } 147 | return false; 148 | } 149 | 150 | float GyverUart::parseFloat() { 151 | uint32_t timeoutTime = millis(); 152 | float whole = 0.0; 153 | float fract = 0.0; 154 | boolean negative = false; 155 | boolean decimal = false; 156 | byte fractSize = 0; 157 | 158 | while (millis() - timeoutTime < 100) { 159 | if (available()) { 160 | timeoutTime = millis(); 161 | char newByte = read(); 162 | if (newByte == '-') { 163 | negative = true; 164 | continue; 165 | } 166 | if (newByte == '.') { 167 | decimal = true; 168 | continue; 169 | } 170 | if (!decimal) { 171 | whole += (newByte - '0'); 172 | whole *= 10L; 173 | } else { 174 | fract += (newByte - '0'); 175 | fract *= 10L; 176 | fractSize++; 177 | } 178 | } 179 | } 180 | whole /= 10L; 181 | for (byte i = 0; i <= fractSize; i++) { 182 | fract /= 10; 183 | } 184 | whole += fract; 185 | return (!negative) ? whole : -whole; 186 | } 187 | 188 | String GyverUart::readString() { 189 | uint32_t timeoutTime = millis(); 190 | String buf = ""; 191 | while (millis() - timeoutTime < _UART_TIMEOUT) { 192 | if (available()) { 193 | timeoutTime = millis(); 194 | buf += read(); 195 | } 196 | } 197 | return buf; 198 | } 199 | 200 | String GyverUart::readStringUntil(char terminator) { 201 | uint32_t timeoutTime = millis(); 202 | String buf = ""; 203 | while (millis() - timeoutTime < _UART_TIMEOUT) { 204 | if (available()) { 205 | if (peek() == terminator) { 206 | clear(); 207 | return buf; 208 | } 209 | timeoutTime = millis(); 210 | buf += read(); 211 | } 212 | } 213 | return buf; 214 | } 215 | 216 | // ====================== WRITE =========================== 217 | 218 | /* 219 | // прямая запись без буфера 220 | void GyverUart::writeBuffer(byte data){ 221 | while (!(UCSR0A & (1<= UART_TX_BUFFER_SIZE) { 246 | _UART_TX_BUFFER_TAIL = 0; 247 | } // хвост двигаем 248 | if (_UART_TX_BUFFER_HEAD == _UART_TX_BUFFER_TAIL) { 249 | UCSR0B &= ~(1 << UDRIE0); 250 | } 251 | } 252 | 253 | #ifdef USE_PRINT_H 254 | size_t GyverUart::write(uint8_t data) { 255 | writeBuffer(data); 256 | return 1; 257 | } 258 | 259 | #else 260 | 261 | boolean GyverUart::availableForWrite() { return 1; } 262 | 263 | void GyverUart::println(void) { 264 | writeBuffer('\r'); 265 | writeBuffer('\n'); 266 | } 267 | 268 | void GyverUart::print(char data) { 269 | writeBuffer(data); 270 | } 271 | void GyverUart::println(char data) { 272 | print(data); 273 | println(); 274 | } 275 | 276 | void GyverUart::print(int8_t data, byte base) { printHelper((int32_t)data, base); } 277 | void GyverUart::print(uint8_t data, byte base) { printHelper((uint32_t)data, base); } 278 | void GyverUart::print(int16_t data, byte base) { printHelper((int32_t)data, base); } 279 | void GyverUart::print(uint16_t data, byte base) { printHelper((uint32_t)data, base); } 280 | void GyverUart::print(int32_t data, byte base) { printHelper((int32_t)data, base); } 281 | void GyverUart::print(uint32_t data, byte base) { printHelper((uint32_t)data, base); } 282 | 283 | void GyverUart::println(int8_t data, byte base) { 284 | printHelper((int32_t)data, base); 285 | println(); 286 | } 287 | void GyverUart::println(uint8_t data, byte base) { 288 | printHelper((uint32_t)data, base); 289 | println(); 290 | } 291 | void GyverUart::println(int16_t data, byte base) { 292 | printHelper((int32_t)data, base); 293 | println(); 294 | } 295 | void GyverUart::println(uint16_t data, byte base) { 296 | printHelper((uint32_t)data, base); 297 | println(); 298 | } 299 | void GyverUart::println(int32_t data, byte base) { 300 | printHelper((int32_t)data, base); 301 | println(); 302 | } 303 | void GyverUart::println(uint32_t data, byte base) { 304 | printHelper((uint32_t)data, base); 305 | println(); 306 | } 307 | 308 | void GyverUart::printHelper(int32_t data, byte base) { 309 | if (data < 0) { 310 | writeBuffer(45); 311 | data = -data; 312 | } 313 | printHelper((uint32_t)data, base); 314 | } 315 | void GyverUart::printHelper(uint32_t data, byte base) { 316 | if (base == 10) { 317 | printBytes(data); 318 | } else { 319 | char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte. 320 | char *str = &buf[sizeof(buf) - 1]; 321 | *str = '\0'; 322 | if (base < 2) base = 10; 323 | do { 324 | char c = data % base; 325 | data /= base; 326 | *--str = c < 10 ? c + '0' : c + 'A' - 10; 327 | } while (data); 328 | print(str); 329 | } 330 | } 331 | 332 | void GyverUart::printBytes(uint32_t data) { 333 | byte bytes[10]; 334 | byte amount; 335 | for (byte i = 0; i < 10; i++) { 336 | bytes[i] = data % 10; 337 | data /= 10; 338 | if (data == 0) { 339 | amount = i; 340 | break; 341 | } 342 | } 343 | for (int8_t i = amount; i >= 0; i--) { 344 | writeBuffer(bytes[i] + '0'); 345 | } 346 | } 347 | 348 | void GyverUart::print(double data, byte decimals) { 349 | if (data < 0) { 350 | writeBuffer(45); 351 | data = -data; 352 | } 353 | uint32_t integer = data; 354 | printBytes(integer); 355 | writeBuffer(46); // точка 356 | data -= integer; 357 | for (byte i = 0; i < decimals; i++) { 358 | data *= 10.0; 359 | print((byte)data); 360 | data -= (byte)data; 361 | } 362 | } 363 | 364 | void GyverUart::println(double data, byte decimals) { 365 | print(data, decimals); 366 | println(); 367 | } 368 | 369 | void GyverUart::print(String data) { 370 | byte stringSize = data.length(); 371 | for (byte i = 0; i < stringSize; i++) { 372 | print(data[i]); 373 | } 374 | } 375 | void GyverUart::println(String data) { 376 | print(data); 377 | println(); 378 | } 379 | 380 | void GyverUart::print(const char data[]) { 381 | byte i = 0; 382 | while (data[i] != '\0') { 383 | print(data[i]); 384 | i++; 385 | } 386 | } 387 | void GyverUart::println(const char data[]) { 388 | print(data); 389 | println(); 390 | } 391 | #endif 392 | -------------------------------------------------------------------------------- /src/GyverUART.h: -------------------------------------------------------------------------------- 1 | /* 2 | Лёгкая библиотека для работы с последовательным портом 3 | Документация: https://alexgyver.ru/gyveruart/ 4 | GitHub: https://github.com/GyverLibs/GyverUART 5 | Возможности: 6 | - Практически полный аналог Serial, но гораздо легче 7 | - Данная версия встроена в ядро GyverCore! 8 | 9 | AlexGyver & Egor 'Nich1con' Zaharov, alex@alexgyver.ru 10 | https://alexgyver.ru/ 11 | MIT License 12 | 13 | Версии: 14 | v1.2 - добавлен циклический буфер 15 | v1.3 - поправлен вывод float и добавлен вывод с базисом 16 | v1.4 - либа собрана в класс, добавлена readStringUntil 17 | v1.5 - добавлен буфер на отправку и flush 18 | v1.6 - ускорена запись и чтение 19 | v1.7 - чуть оптимизирован код 20 | v1.8 - пофикшен write (спасибо eugenebartosh) 21 | v1.9 - пофикшен write + оптимизация + поддержка USART0 atmega2560 (by Siliverst) 22 | v1.10 - вывод переведён на Print.h. Размер стал чуть больше, но будет меньше при работе с другими либами на Print.h 23 | */ 24 | 25 | #define USE_PRINT_H // закомментируй, чтобы использовать gyver-вывод 26 | 27 | #ifndef GyverUART_h 28 | #define GyverUART_h 29 | #include 30 | 31 | #include "Arduino.h" 32 | 33 | #ifdef USE_PRINT_H 34 | #include "Print.h" 35 | class GyverUart : public Print { 36 | #else 37 | 38 | #define DEC 10 39 | #define HEX 16 40 | #define OCT 8 41 | #define BIN 2 42 | 43 | class GyverUart { 44 | #endif 45 | public: 46 | void begin(uint32_t baudrate = 9600); 47 | void end(); 48 | 49 | uint8_t available(); 50 | char read(); 51 | char peek(); 52 | void clear(); 53 | void flush(); 54 | 55 | void setTimeout(int timeout); 56 | int32_t parseInt(); 57 | float parseFloat(); 58 | String readString(); 59 | String readStringUntil(char terminator); 60 | boolean parsePacket(int *intArray); 61 | 62 | #ifdef USE_PRINT_H 63 | virtual size_t write(uint8_t); 64 | #else 65 | boolean availableForWrite(); 66 | void write(byte data); 67 | void println(); 68 | 69 | void print(char data); 70 | void print(int8_t data, byte base = DEC); 71 | void print(uint8_t data, byte base = DEC); 72 | void print(int16_t data, byte base = DEC); 73 | void print(uint16_t data, byte base = DEC); 74 | void print(int32_t data, byte base = DEC); 75 | void print(uint32_t data, byte base = DEC); 76 | void print(double data, byte decimals = 2); 77 | void print(String data); 78 | void print(const char data[]); 79 | 80 | void println(char data); 81 | void println(int8_t data, byte base = DEC); 82 | void println(uint8_t data, byte base = DEC); 83 | void println(int16_t data, byte base = DEC); 84 | void println(uint16_t data, byte base = DEC); 85 | void println(int32_t data, byte base = DEC); 86 | void println(uint32_t data, byte base = DEC); 87 | void println(double data, byte decimals = 2); 88 | void println(String data); 89 | void println(const char data[]); 90 | #endif 91 | private: 92 | void writeBuffer(byte data); 93 | #ifndef USE_PRINT_H 94 | void printHelper(int32_t data, byte base); 95 | void printHelper(uint32_t data, byte base); 96 | void printBytes(uint32_t data); 97 | #endif 98 | }; 99 | 100 | extern GyverUart uart; 101 | #endif --------------------------------------------------------------------------------