1
1
/*
2
2
Лёгкая реализация UART для ATmega328 и подобных из этого поколения
3
- Документация:
3
+ Документация:
4
4
GitHub: https://github.com/GyverLibs/MicroUART
5
5
Возможности:
6
6
- Полный аналог Serial
7
7
- Опционально работа с буфером/без
8
8
- Опционально наследует Print.h
9
9
- Опционально наследует Stream.h
10
-
10
+
11
11
12
12
https://alexgyver.ru/
13
13
MIT License
20
20
#define _MicroUART
21
21
22
22
#if defined(__AVR_ATmega2560__)
23
- #define USARTx_RX_vect USART0_RX_vect
24
- #define USARTx_UDRE_vect USART0_UDRE_vect
23
+ #define USARTx_RX_vect USART0_RX_vect
24
+ #define USARTx_UDRE_vect USART0_UDRE_vect
25
25
26
26
#elif defined(USART_RX_vect) && defined(USART_UDRE_vect)
27
- #define USARTx_RX_vect USART_RX_vect
28
- #define USARTx_UDRE_vect USART_UDRE_vect
27
+ #define USARTx_RX_vect USART_RX_vect
28
+ #define USARTx_UDRE_vect USART_UDRE_vect
29
29
#else
30
30
31
31
#error "AVR USART not defined"
@@ -55,27 +55,27 @@ void MU_serialEvent() __attribute__((weak));
55
55
class MicroUART
56
56
#ifdef MU_STREAM
57
57
#undef MU_PRINT
58
- : public Stream
58
+ : public Stream
59
59
#endif
60
60
#ifdef MU_PRINT
61
- : public Print
61
+ : public Print
62
62
#endif
63
63
{
64
- public:
64
+ public:
65
65
// ================= BEGIN ==================
66
66
void begin (const uint32_t baud) {
67
- UBRR0 = (F_CPU / (8ul * baud)) - 1 ; // скорость
68
- UCSR0A = (1 << U2X0); // скорость
69
- UCSR0B = (1 << TXEN0) | (1 << RXEN0) | (1 << RXCIE0); // подрубаем rx tx и rx isr
70
- UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); // 8 бит байт
71
- #if (MU_TX_BUF > 0)
67
+ UBRR0 = (F_CPU / (8ul * baud)) - 1 ; // скорость
68
+ UCSR0A = (1 << U2X0); // скорость
69
+ UCSR0B = (1 << TXEN0) | (1 << RXEN0) | (1 << RXCIE0); // подрубаем rx tx и rx isr
70
+ UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); // 8 бит байт
71
+ #if (MU_TX_BUF > 0)
72
72
_headTX = _tailTX = 0 ;
73
- #endif
74
- #if (MU_RX_BUF > 0)
73
+ #endif
74
+ #if (MU_RX_BUF > 0)
75
75
_headRX = _tailRX = 0 ;
76
- #endif
76
+ #endif
77
77
}
78
-
78
+
79
79
void end () {
80
80
UCSR0B = 0 ;
81
81
}
@@ -87,100 +87,107 @@ class MicroUART
87
87
void
88
88
#endif
89
89
write (uint8_t data) {
90
- #if (MU_TX_BUF > 0) // если есть буфер на отправку
91
- uint8_t i = (_headTX + 1 ) % MU_TX_BUF; // позиция нового байта в буфере
92
- while (i == _tailTX); // ждать освобождения места в буфере
93
- _bufTX[_headTX] = data; // пишем в буфер
94
- _headTX = i; // двигаем
95
- UCSR0B |= (1 << UDRIE0); // на отправку
96
- #else // нет буфера
97
- while (!(UCSR0A & (1 << UDRE0))); // ждём отправку
98
- UDR0 = data; // пишем
99
- #endif
90
+ #if (MU_TX_BUF > 0) // если есть буфер на отправку
91
+ uint8_t i = (_headTX + 1 ) % MU_TX_BUF; // позиция нового байта в буфере
92
+ while (i == _tailTX); // ждать освобождения места в буфере
93
+ _bufTX[_headTX] = data; // пишем в буфер
94
+ _headTX = i; // двигаем
95
+ UCSR0B |= (1 << UDRIE0); // на отправку
96
+ return 1 ;
97
+ #else // нет буфера
98
+ while (!(UCSR0A & (1 << UDRE0))); // ждём отправку
99
+ UDR0 = data; // пишем
100
+ #endif
100
101
}
101
-
102
+
103
+ size_t write (const uint8_t *buffer, size_t size) {
104
+ for (size_t i = 0 ; i < size; i++) write (buffer[i]);
105
+ return size;
106
+ }
107
+
108
+
102
109
// ================= AVAILABLE ==================
103
110
#if defined(MU_STREAM)
104
111
virtual int
105
112
#else
106
113
int
107
114
#endif
108
115
available () {
109
- #if (MU_RX_BUF > 0)
116
+ #if (MU_RX_BUF > 0)
110
117
return ((uint16_t )(MU_RX_BUF + _headRX - _tailRX) % MU_RX_BUF);
111
- #else
118
+ #else
112
119
return _availFlag;
113
- #endif
120
+ #endif
114
121
}
115
-
122
+
116
123
int availableForWrite () {
117
- #if (MU_TX_BUF > 0)
124
+ #if (MU_TX_BUF > 0)
118
125
if (_headTX >= _tailTX) return MU_TX_BUF - 1 - _headTX + _tailTX;
119
126
return _tailTX - _headTX - 1 ;
120
- #else
127
+ #else
121
128
return 1 ;
122
- #endif
129
+ #endif
123
130
}
124
-
131
+
125
132
// ================= READ ==================
126
133
#if defined(MU_STREAM)
127
134
virtual int
128
135
#else
129
136
uint8_t
130
137
#endif
131
138
read () {
132
- #if (MU_RX_BUF > 0)
133
- if (_headRX == _tailRX) return -1 ; // буфер пуст
139
+ #if (MU_RX_BUF > 0)
140
+ if (_headRX == _tailRX) return -1 ; // буфер пуст
134
141
uint8_t c = _bufRX[_tailRX];
135
142
_tailRX = (_tailRX + 1 ) % MU_RX_BUF; // хвост двигаем
136
143
return c;
137
- #else
144
+ #else
138
145
_availFlag = 0 ;
139
146
return _byteBufRX;
140
- #endif
147
+ #endif
141
148
}
142
-
149
+
143
150
#if defined(MU_STREAM)
144
151
virtual int
145
152
#else
146
153
uint8_t
147
154
#endif
148
155
peek () {
149
- #if (MU_RX_BUF > 0)
150
- return (_headRX != _tailRX) ? _bufRX[_tailRX]: -1 ;
151
- #else
156
+ #if (MU_RX_BUF > 0)
157
+ return (_headRX != _tailRX) ? _bufRX[_tailRX] : -1 ;
158
+ #else
152
159
return _byteBufRX;
153
- #endif
160
+ #endif
154
161
}
155
162
156
- private:
163
+ private:
157
164
};
158
165
159
166
// ================= ISR VECT ==================
160
167
// прерывание на приём
161
168
ISR (USARTx_RX_vect) {
162
169
uint8_t data = UDR0;
163
- if (!(UCSR0A & (1 << UPE0))) { // не parity error
164
- #if (MU_RX_BUF > 0)
170
+ if (!(UCSR0A & (1 << UPE0))) { // не parity error
171
+ #if (MU_RX_BUF > 0)
165
172
uint8_t i = (_headRX + 1 ) % MU_RX_BUF;
166
173
if (i != _tailRX) {
167
174
_bufRX[_headRX] = data;
168
175
_headRX = i;
169
176
}
170
- #else
177
+ #else
171
178
_byteBufRX = data;
172
- _availFlag = 1 ;
173
- #endif
179
+ _availFlag = 1 ;
180
+ #endif
174
181
}
175
182
MU_serialEvent ();
176
183
}
177
184
178
185
// прерывание на отправку
179
186
#if (MU_TX_BUF > 0)
180
- ISR (USARTx_UDRE_vect) {
187
+ ISR (USARTx_UDRE_vect) {
181
188
UDR0 = _bufTX[_tailTX];
182
189
_tailTX = (_tailTX + 1 ) % MU_TX_BUF;
183
- if (_headTX == _tailTX) UCSR0B &= ~(1 << UDRIE0);
190
+ if (_headTX == _tailTX) UCSR0B &= ~(1 << UDRIE0);
184
191
}
185
192
#endif
186
193
#endif
0 commit comments