Skip to content

Commit a100b73

Browse files
committed
completely revised
1 parent 52ff135 commit a100b73

File tree

2 files changed

+94
-107
lines changed

2 files changed

+94
-107
lines changed

src/TJA1020.cpp

Lines changed: 78 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44
// Copyright mestrode <[email protected]>
55
// Original Source: "https://github.com/mestrode/Lin-Transceiver-Library"
66
//
7-
// Requires class Lin_Interface: https://github.com/mestrode/Lin-Interface-Library
8-
//
9-
// Tested with ESP32
7+
// Datasheet TJA1020: https://www.nxp.com/docs/en/data-sheet/TJA1020.pdf
108

119
#include "TJA1020.hpp"
1210

@@ -18,23 +16,30 @@
1816
#include <Arduino.h>
1917
#endif
2018

21-
constexpr auto BAUD_DEFAULT = 19200;
22-
23-
//-----------------------------------------------------------------------------
24-
// constructor
25-
26-
/// Provides HW UART via TJA1020 Chip
27-
Lin_TJA1020::Lin_TJA1020(const int _uart_nr, const uint32_t _baud, const int8_t _rxPin, const int8_t _txPin, const int8_t _nslpPin) :
19+
/// @brief Provides HAL for UART via TJA1020 Chip
20+
/// @param _uart_nr uart for LIN
21+
/// @param _baud max 20k. default 19.200 baud
22+
/// @param _rxPin GPIO
23+
/// @param _txPin GPIO
24+
/// @param _nslpPin GPIO
25+
/// @param _mode initial mode of statemachine within TJA
26+
Lin_TJA1020::Lin_TJA1020(const int _uart_nr, const uint32_t _baud, const int8_t _rxPin, const int8_t _txPin, const int8_t _nslpPin, const Mode _mode) :
2827
HardwareSerial(_uart_nr),
28+
rxPin(_rxPin),
2929
txPin(_txPin),
3030
nslpPin(_nslpPin)
3131
{
32-
// use default baud rate, if not specified
33-
// TODO: HardwareSerial::baudRate = _baud ? _baud : BAUD_DEFAULT;
34-
HardwareSerial::setPins(_rxPin, _txPin);
35-
}
32+
pinMode(nslpPin, OUTPUT);
33+
digitalWrite(nslpPin, LOW);
34+
35+
pinMode(rxPin, INPUT_PULLUP);
36+
pinMode(txPin, OUTPUT);
37+
HardwareSerial::setPins(rxPin, txPin);
3638

37-
//-----------------------------------------------------------------------------
39+
HardwareSerial::updateBaudRate(_baud);
40+
41+
setMode(_mode);
42+
}
3843

3944
/// does control sequences to switch from one to another operational mode of the chip
4045
/// NormalSlope, LowSlope for writing operation;
@@ -49,112 +54,105 @@ void Lin_TJA1020::setMode(const Mode mode)
4954
return;
5055
}
5156

52-
pinMode(txPin, OUTPUT); // TX Signal to LIN Tranceiver
53-
pinMode(nslpPin, OUTPUT); // /SLP Signal to LIN Tranceiver
54-
5557
// Statemachine des TJA1020 von [SLEEP] nach [NORMAL SLOPE MODE] ändern
56-
switch (mode)
57-
{
58-
case Mode::NormalSlope:
58+
if (mode == Mode::NormalSlope) {
5959
if (_currentMode == Mode::LowSlope)
6060
{
6161
// no direct step from LowSlope to NormalSlope
62+
// TODO: no valid transission, go over SLEEP may cut power
6263
setMode(Mode::Sleep);
6364
}
6465

6566
// rising edge on /SLP while TXD = 1
6667
digitalWrite(txPin, HIGH);
67-
delayMicroseconds(10); // ensure signal to settle
68+
delayMicroseconds(T_SETTLE);
6869

69-
// create rising edge
7070
digitalWrite(nslpPin, LOW);
71-
delayMicroseconds(15); // ensure t_gotosleep (min. 10us)
71+
delayMicroseconds(T_SETTLE);
7272
digitalWrite(nslpPin, HIGH);
73-
delayMicroseconds(15); // ensure t_gotonorm (min. 10us)
73+
delayMicroseconds(T_GOTONORM);
7474

7575
// [Normal Slope Mode] reached
7676
_currentMode = Mode::NormalSlope;
77-
break;
77+
return;
78+
}
7879

79-
case Mode::LowSlope:
80+
if (mode == Mode::LowSlope) {
8081
if (_currentMode == Mode::NormalSlope)
8182
{
8283
// no direct step from NormalSlope to LowSlope
84+
// TODO: no valid transission, go over SLEEP may cut power
8385
setMode(Mode::Sleep);
8486
}
8587

8688
// rising edge on /SLP while TXD = 0
8789
digitalWrite(txPin, LOW);
88-
delayMicroseconds(10); // ensure signal to settle
90+
delayMicroseconds(T_SETTLE);
8991

90-
// create rising edge
9192
digitalWrite(nslpPin, LOW);
92-
delayMicroseconds(15); // ensure t_gotosleep (min. 10us)
93+
delayMicroseconds(T_SETTLE);
9394
digitalWrite(nslpPin, HIGH);
94-
delayMicroseconds(15); // ensure t_gotonorm (min. 10us)
95+
delayMicroseconds(T_GOTONORM);
9596

96-
// release tx pin, to avoid occupation of Lin Bus
97-
digitalWrite(txPin, HIGH);
97+
// release tx pin (active Low), to avoid occupation of Lin Bus
98+
digitalWrite(txPin, LOW);
9899

99100
// [Low Slope Mode] reached
100101
_currentMode = Mode::LowSlope;
101-
break;
102+
return;
103+
}
102104

103-
default: // = Sleep
104-
// no direct step from Standby to Sleep, but we don't know if we're in
105-
// we're going over _writingSlope
106-
setMode(Mode::NormalSlope);
105+
// default: mode == Mode::Sleep or Mode::Standby
107106

108-
// rising edge on /SLP while TXD = 1
109-
digitalWrite(txPin, HIGH);
110-
delayMicroseconds(10); // ensure signal to settle
107+
// no direct step from Standby to Sleep
108+
if (_currentMode == Mode::Standby) {
109+
// we're going over LowSlope
110+
setMode(Mode::LowSlope);
111+
}
111112

112-
// create falling edge
113-
digitalWrite(nslpPin, HIGH);
114-
delayMicroseconds(15); // ensure t_gotosleep (min. 10us)
115-
digitalWrite(nslpPin, LOW);
116-
delayMicroseconds(15); // ensure t_gotonorm (min. 10us)
117-
// INH will be shut down by constant low, chip will go into sleep mode
113+
// rising edge on /SLP while TXD = 1
114+
digitalWrite(txPin, HIGH);
115+
delayMicroseconds(T_SETTLE);
118116

119-
// ensure pin level while sleeping
120-
#ifdef ESP32
121-
pinMode(txPin, INPUT_PULLDOWN); // ensure Low level while in sleep mode (since TJA1020 has internally a fixed pulldown)
122-
pinMode(nslpPin, INPUT_PULLDOWN); // ensure Low level while in sleep mode
123-
#else
124-
pinMode(txPin, INPUT); // ensure Low level while in sleep mode (since TJA1020 has internally a fixed pulldown)
125-
pinMode(nslpPin, INPUT); // ensure Low level while in sleep mode
126-
#endif
117+
digitalWrite(nslpPin, HIGH);
118+
delayMicroseconds(T_SETTLE);
127119

128-
// [Sleep] reached
129-
_currentMode = Mode::Sleep;
130-
break;
131-
}
132-
} // void Lin_TJA1020::setMode(TJA1020_Mode newMode)
120+
digitalWrite(nslpPin, LOW);
121+
//! avoid another sleep, cause chip will go into sleep mode soon
122+
//! --> INH will float = this may cause power cut off
123+
//! delayMicroseconds(T_GOTOSLEEP);
124+
125+
//! since TJA1020 has internally a fixed pulldown ensure Low level while in sleep mode
126+
//! digitalWrite(txPin, LOW);
127+
128+
_currentMode = Mode::Sleep;
129+
}
133130

134131
Lin_TJA1020::Mode Lin_TJA1020::getMode()
135132
{
136-
if (_currentMode == Mode::Sleep) {
133+
return _currentMode;
134+
}
137135

138-
// test MCU PullUp against TJA Pulldown
139-
pinMode(txPin, INPUT);
140-
delayMicroseconds(1); // settle time
141-
bool hasWeakPullDn = !digitalRead(txPin);
136+
/// @brief returns Wakeup Reason, this only possible after wakeup, before setMode() (standby mode will be detected)
137+
/// @return wake-up reason
138+
Lin_TJA1020::WakeUpSource Lin_TJA1020::getWakeupReason()
139+
{
140+
// only in standby mode TXD pull-down can be tested
142141

143-
pinMode(txPin, INPUT_PULLUP);
144-
delayMicroseconds(1); // settle time
145-
bool hasStrongPullDn = !digitalRead(txPin);
142+
// in Standby mode: /SLP must be low AND RXD must be low
143+
// --> equal to: /SLP is high OR RXD is high
144+
if (digitalRead(nslpPin) || digitalRead(rxPin)) {
145+
return WakeUpSource::unknown;
146+
}
147+
_currentMode == Mode::Standby;
146148

147-
// revert setting
148-
pinMode(txPin, INPUT);
149+
// test MCU pullup vs. TJA (weak) pull-down
150+
pinMode(txPin, INPUT_PULLUP);
151+
delayMicroseconds(T_SETTLE);
152+
bool hasTxWeakPullDn = digitalRead(txPin);
153+
// revert setting
154+
pinMode(txPin, OUTPUT);
149155

150-
if (hasWeakPullDn && !hasStrongPullDn)
151-
{
152-
// TXD has weak pull-down on remote wake-up
153-
_currentMode = Mode::StandbyWakeupRemote;
154-
} else {
155-
// TXD has strong pull-down on local wake-up (caused by /WAKE pin)
156-
_currentMode = Mode::StandbyWakeupLocal;
157-
}
158-
}
159-
return _currentMode;
156+
// TXD has weak pull-down on remote wake-up
157+
return hasTxWeakPullDn ? WakeUpSource::remote: WakeUpSource::local;
160158
}

src/TJA1020.hpp

Lines changed: 16 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
// Copyright mestrode <[email protected]>
55
// Original Source: "https://github.com/mestrode/Lin-Transceiver-Library"
66
//
7-
// Requires class Lin_Interface: https://github.com/mestrode/Lin-Interface-Library
8-
//
97
// Datasheet TJA1020: https://www.nxp.com/docs/en/data-sheet/TJA1020.pdf
108

119
#pragma once
@@ -21,45 +19,36 @@
2119
class Lin_TJA1020 : public HardwareSerial
2220
{
2321
public:
22+
static constexpr auto BAUD_DEFAULT = 19200;
23+
2424
enum class Mode
2525
{
2626
Sleep,
27-
// after Power on or setMode(Sleep)
28-
// NSLP TXD (OUTPUT) RXD INH TRANSMITTER REMARKS
29-
// 0 weak pull-down floating floating off no wake-up request detected
30-
// TERM = high-ohmic
31-
3227
NormalSlope,
33-
// NSLP TXD (OUTPUT) RXD INH TRANSMITTER
34-
// 1 weak pull-down active HIGH normal slope TERM = 30k
35-
3628
LowSlope,
37-
// NSLP TXD (OUTPUT) RXD INH TRANSMITTER
38-
// 1 weak pull-down active HIGH low slope TERM = 30k
29+
Standby
30+
};
3931

40-
StandbyWakeupRemote,
41-
StandbyWakeupLocal
42-
// NSLP TXD (OUTPUT) RXD INH TRANSMITTER REMARKS
43-
// 0 weak pull-down if remote wake-up; LOW HIGH off wake-up request detected;
44-
// strong pull-down if local wake-up; in this mode the microcontroller
45-
// note 2 can read the wake-up source:
46-
// remote or local wake-up
47-
// TERM = 30k
32+
enum class WakeUpSource
33+
{
34+
unknown,
35+
local,
36+
remote
4837
};
4938

50-
/// provides HW-Lin Interface via TJA1020 Chip
51-
/// @param uart_nr Index of HW UART to be used (0..2)
52-
/// @param baud Baud rate for RX/TX (0 = default 19200 baud)
53-
/// @param nslpPin /SLP Pin to control TJA1020
54-
Lin_TJA1020(const int _uart_nr, const uint32_t _baud, const int8_t _rxPin, const int8_t _txPin, const int8_t _nslpPin);
39+
Lin_TJA1020(const int _uart_nr, const uint32_t _baud, const int8_t _rxPin, const int8_t _txPin, const int8_t _nslpPin, const Mode _mode = Mode::NormalSlope);
5540

56-
/// switches the operational mode of TJA1020 chip
57-
/// @param mode target mode
5841
void setMode(const Mode mode);
5942
Mode getMode();
43+
WakeUpSource getWakeupReason();
6044

6145
private:
46+
static constexpr int T_SETTLE = 10;
47+
static constexpr int T_GOTOSLEEP = 10; // Spec: typ 5 us, max 10 us required by chip
48+
static constexpr int T_GOTONORM = 10; // Spec: typ 5 us, max 10 us required by chip
49+
6250
Mode _currentMode = Mode::Sleep; // after power on
51+
int8_t rxPin;
6352
int8_t txPin;
6453
int8_t nslpPin;
6554
};

0 commit comments

Comments
 (0)