LIN_master_portable_Arduino 1.4
Arduino library for Local Interconnect Network master node emulation
Loading...
Searching...
No Matches
LIN_master_SoftwareSerial.cpp
Go to the documentation of this file.
1
9// assert platform which supports SoftwareSerial. Note: ARDUINO_ARCH_ESP32 requires library ESPSoftwareSerial
10#if defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
11
12// include files
14
15
22{
23 // if state is wrong, exit immediately
25 {
26 // print debug message
27 DEBUG_PRINT(1, "wrong state 0x%02X", this->state);
28
29 // set error state and return immediately
32 this->_disableTransmitter();
33 return this->state;
34 }
35
36 // optionally enable transmitter
37 this->_enableTransmitter();
38
39 // generate BREAK directly via GPIO (less overhead)
40 digitalWrite(this->pinTx, LOW);
41 delayMicroseconds(this->durationBreak);
42 digitalWrite(this->pinTx, HIGH);
43 delayMicroseconds(100); // stop bit + 1b delimiter
44
45 // progress state
47
48 // print debug message
49 DEBUG_PRINT(3, " ");
50
51 // return state
52 return this->state;
53
54} // LIN_Master_SoftwareSerial::_sendBreak()
55
56
57
64{
65 // if state is wrong, exit immediately
67 {
68 // print debug message
69 DEBUG_PRINT(1, "wrong state 0x%02X", this->state);
70
71 // set error state and return immediately
74 this->_disableTransmitter();
75 return this->state;
76 }
77
78 // restore nominal baudrate not required, use digitalWrite() for BREAK
79
80 // disable reception to skip LIN echo (disturbs SoftwareSerial)
81 this->SWSerial.stopListening();
82
83 // send rest of frame (request frame: SYNC+ID+DATA[]+CHK; response frame: SYNC+ID). Is blocking and receive is disabled!
84 this->SWSerial.write(this->bufTx+1, this->lenTx-1);
85
86 // optionally disable transmitter for slave response frames
88 this->_disableTransmitter();
89
90 // re-enable reception (above write is blocking)
91 this->SWSerial.listen();
92
93 // Emulate LIN echo for sent bytes
94 memcpy(this->bufRx, this->bufTx, this->lenTx);
95
96 // progress state
98
99 // print debug message
100 DEBUG_PRINT(2, " ");
101
102 // return state
103 return this->state;
104
105} // LIN_Master_SoftwareSerial::_sendFrame()
106
107
108
115{
116 // if state is wrong, exit immediately
118 {
119 // print debug message
120 DEBUG_PRINT(1, "wrong state 0x%02X", this->state);
121
122 // set error state and return immediately
125 this->_disableTransmitter();
126 return this->state;
127 }
128
129 // master request frame
131 {
132 // LIN echo already emulated in _sendFrame()
133
134 // check frame for errors
135 this->error = (LIN_Master_Base::error_t) ((int) this->error | (int) this->_checkFrame());
136
137 // optionally disable transmitter after frame is completed
138 this->_disableTransmitter();
139
140 // progress state
142
143 } // master request frame
144
145 // slave response frame
146 else
147 {
148 // slave response received (-lenTx because header already emulated in _sendFrame())
149 if (this->SWSerial.available() >= this->lenRx - this->lenTx)
150 {
151 // store bytes in Rx
152 this->SWSerial.readBytes(this->bufRx+3, this->lenRx - this->lenTx);
153
154 // check frame for errors
155 this->error = (LIN_Master_Base::error_t) ((int) this->error | (int) this->_checkFrame());
156
157 // progress state
159
160 } // frame body received
161
162 // frame body received not yet received
163 else
164 {
165 // check for timeout
166 if (micros() - this->timeStart > this->timeoutFrame)
167 {
168 // print debug message
169 DEBUG_PRINT(1, "Rx timeout");
170
171 // set error state and return immediately
174 this->_disableTransmitter();
175 return this->state;
176 }
177
178 } // not enough bytes received
179
180 } // slave response frame
181
182 // print debug message
183 DEBUG_PRINT(2, " ");
184
185 // return state
186 return this->state;
187
188} // LIN_Master_SoftwareSerial::_receiveFrame()
189
190
191
201LIN_Master_SoftwareSerial::LIN_Master_SoftwareSerial(uint8_t PinRx, uint8_t PinTx, bool InverseLogic, const char NameLIN[], const int8_t PinTxEN) :
202 LIN_Master_Base::LIN_Master_Base(NameLIN, PinTxEN), SWSerial(PinRx, PinTx, InverseLogic)
203{
204 // Debug serial initialized in begin() -> no debug output here
205
206 // store pins used for SW serial
207 this->pinRx = PinRx;
208 this->pinTx = PinTx;
209 this->inverseLogic = InverseLogic;
210
211 // must not open connection here, else (at least) ESP32 and ESP8266 fail
212
213 // cannot print debug message, as constructor is called before setup()
214
215} // LIN_Master_SoftwareSerial::LIN_Master_SoftwareSerial()
216
217
218
224void LIN_Master_SoftwareSerial::begin(uint16_t Baudrate)
225{
226 // call base class method
227 LIN_Master_Base::begin(Baudrate);
228
229 // open serial interface. Timeout not required here
230 this->SWSerial.end();
231 this->SWSerial.begin(this->baudrate);
232
233 // calculate duration of BREAK
234 this->durationBreak = this->timePerByte * 13 / 10;
235
236 // print debug message
237 DEBUG_PRINT(2, "ok");
238
239} // LIN_Master_SoftwareSerial::begin()
240
241
242
248{
249 // call base class method
251
252 // close serial interface
253 this->SWSerial.end();
254
255 // print debug message
256 DEBUG_PRINT(2, " ");
257
258} // LIN_Master_SoftwareSerial::end()
259
260
261#endif // ARDUINO_ARCH_AVR || ARDUINO_ARCH_ESP8266 || ARDUINO_ARCH_ESP32
262
263/*-----------------------------------------------------------------------------
264 END OF FILE
265-----------------------------------------------------------------------------*/
LIN master emulation library for SoftwareSerial.
LIN master node base class.
uint8_t lenRx
receive buffer length (max. 12)
virtual void begin(uint16_t Baudrate=19200)
Open serial interface.
uint16_t baudrate
communication baudrate [Baud]
@ MASTER_REQUEST
LIN master request frame.
@ SLAVE_RESPONSE
LIN slave response frame.
uint8_t bufTx[12]
send buffer incl. BREAK, SYNC, DATA and CHK (max. 12B)
LIN_Master_Base::error_t _checkFrame(void)
Check received LIN frame.
LIN_Master_Base::error_t error
error state. Is latched until cleared
void _enableTransmitter(void)
Enable RS485 transmitter (DE=high)
uint32_t timeStart
starting time [us] for frame timeout
uint8_t lenTx
send buffer length (max. 12)
LIN_Master_Base::state_t state
status of LIN state machine
void _disableTransmitter(void)
Disable RS485 transmitter (DE=low)
error_t
LIN error codes. Use bitmasks, as error is latched. Use same as LIN_slave_portable.
@ ERROR_STATE
error in LIN state machine
@ ERROR_TIMEOUT
frame timeout error
uint32_t timePerByte
time [us] per byte at specified baudrate
state_t
state of LIN master state machine. Use bitmasks for fast checking multiple states
@ STATE_BODY
rest of frame is being sent/received
@ STATE_BREAK
sync break is being transmitted
@ STATE_IDLE
no LIN transmission ongoing
@ STATE_DONE
frame completed
virtual void end(void)
Close serial interface.
uint8_t bufRx[12]
receive buffer incl. BREAK, SYNC, DATA and CHK (max. 12B)
LIN_Master_Base::frame_t type
LIN frame type.
uint32_t timeoutFrame
max. frame duration [us]
void begin(uint16_t Baudrate=19200)
Open serial interface.
LIN_Master_Base::state_t _sendBreak(void)
Send LIN break.
void end(void)
Close serial interface.
LIN_Master_SoftwareSerial(uint8_t PinRx, uint8_t PinTx, bool InverseLogic=false, const char NameLIN[]="Master", const int8_t PinTxEN=INT8_MIN)
Class constructor.
LIN_Master_Base::state_t _receiveFrame(void)
Read and check LIN frame.
LIN_Master_Base::state_t _sendFrame(void)
Send LIN bytes (request frame: SYNC+ID+DATA[]+CHK; response frame: SYNC+ID)