4
4
// Copyright mestrode <[email protected] >
5
5
// Original Source: "https://github.com/mestrode/Lin-Transceiver-Library"
6
6
//
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
10
8
11
9
#include " TJA1020.hpp"
12
10
18
16
#include < Arduino.h>
19
17
#endif
20
18
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) :
28
27
HardwareSerial(_uart_nr),
28
+ rxPin(_rxPin),
29
29
txPin(_txPin),
30
30
nslpPin(_nslpPin)
31
31
{
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);
36
38
37
- // -----------------------------------------------------------------------------
39
+ HardwareSerial::updateBaudRate (_baud);
40
+
41
+ setMode (_mode);
42
+ }
38
43
39
44
// / does control sequences to switch from one to another operational mode of the chip
40
45
// / NormalSlope, LowSlope for writing operation;
@@ -49,112 +54,105 @@ void Lin_TJA1020::setMode(const Mode mode)
49
54
return ;
50
55
}
51
56
52
- pinMode (txPin, OUTPUT); // TX Signal to LIN Tranceiver
53
- pinMode (nslpPin, OUTPUT); // /SLP Signal to LIN Tranceiver
54
-
55
57
// Statemachine des TJA1020 von [SLEEP] nach [NORMAL SLOPE MODE] ändern
56
- switch (mode)
57
- {
58
- case Mode::NormalSlope:
58
+ if (mode == Mode::NormalSlope) {
59
59
if (_currentMode == Mode::LowSlope)
60
60
{
61
61
// no direct step from LowSlope to NormalSlope
62
+ // TODO: no valid transission, go over SLEEP may cut power
62
63
setMode (Mode::Sleep);
63
64
}
64
65
65
66
// rising edge on /SLP while TXD = 1
66
67
digitalWrite (txPin, HIGH);
67
- delayMicroseconds (10 ); // ensure signal to settle
68
+ delayMicroseconds (T_SETTLE);
68
69
69
- // create rising edge
70
70
digitalWrite (nslpPin, LOW);
71
- delayMicroseconds (15 ); // ensure t_gotosleep (min. 10us)
71
+ delayMicroseconds (T_SETTLE);
72
72
digitalWrite (nslpPin, HIGH);
73
- delayMicroseconds (15 ); // ensure t_gotonorm (min. 10us)
73
+ delayMicroseconds (T_GOTONORM);
74
74
75
75
// [Normal Slope Mode] reached
76
76
_currentMode = Mode::NormalSlope;
77
- break ;
77
+ return ;
78
+ }
78
79
79
- case Mode::LowSlope:
80
+ if (mode == Mode::LowSlope) {
80
81
if (_currentMode == Mode::NormalSlope)
81
82
{
82
83
// no direct step from NormalSlope to LowSlope
84
+ // TODO: no valid transission, go over SLEEP may cut power
83
85
setMode (Mode::Sleep);
84
86
}
85
87
86
88
// rising edge on /SLP while TXD = 0
87
89
digitalWrite (txPin, LOW);
88
- delayMicroseconds (10 ); // ensure signal to settle
90
+ delayMicroseconds (T_SETTLE);
89
91
90
- // create rising edge
91
92
digitalWrite (nslpPin, LOW);
92
- delayMicroseconds (15 ); // ensure t_gotosleep (min. 10us)
93
+ delayMicroseconds (T_SETTLE);
93
94
digitalWrite (nslpPin, HIGH);
94
- delayMicroseconds (15 ); // ensure t_gotonorm (min. 10us)
95
+ delayMicroseconds (T_GOTONORM);
95
96
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 );
98
99
99
100
// [Low Slope Mode] reached
100
101
_currentMode = Mode::LowSlope;
101
- break ;
102
+ return ;
103
+ }
102
104
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
107
106
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
+ }
111
112
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);
118
116
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);
127
119
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
+ }
133
130
134
131
Lin_TJA1020::Mode Lin_TJA1020::getMode ()
135
132
{
136
- if (_currentMode == Mode::Sleep) {
133
+ return _currentMode;
134
+ }
137
135
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
142
141
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;
146
148
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);
149
155
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;
160
158
}
0 commit comments