瀏覽代碼

🍻 Preliminary fix for Max31865 SPI (#22682)

Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
Jin 3 年之前
父節點
當前提交
27220f0944
No account linked to committer's email address

+ 12
- 3
Marlin/src/HAL/shared/Delay.h 查看文件

@@ -92,6 +92,12 @@ void calibrate_delay_loop();
92 92
 
93 93
   #define DELAY_CYCLES(X) do { SmartDelay<IS_CONSTEXPR(X), IS_CONSTEXPR(X) ? X : 0> _smrtdly_X(X); } while(0)
94 94
 
95
+  #if GCC_VERSION <= 70000
96
+    #define DELAY_CYCLES_VAR(X) DelayCycleFnc(X)
97
+  #else
98
+    #define DELAY_CYCLES_VAR DELAY_CYCLES
99
+  #endif
100
+
95 101
   // For delay in microseconds, no smart delay selection is required, directly call the delay function
96 102
   // Teensy compiler is too old and does not accept smart delay compile-time / run-time selection correctly
97 103
   #define DELAY_US(x) DelayCycleFnc((x) * ((F_CPU) / 1000000UL))
@@ -200,9 +206,12 @@ void calibrate_delay_loop();
200 206
 #endif
201 207
 
202 208
 #if ENABLED(DELAY_NS_ROUND_DOWN)
203
-  #define DELAY_NS(x) DELAY_CYCLES((x) * ((F_CPU) / 1000000UL) / 1000UL)          // floor
209
+  #define _NS_TO_CYCLES(x) ( (x) * ((F_CPU) / 1000000UL)        / 1000UL) // floor
204 210
 #elif ENABLED(DELAY_NS_ROUND_CLOSEST)
205
-  #define DELAY_NS(x) DELAY_CYCLES(((x) * ((F_CPU) / 1000000UL) + 500) / 1000UL)  // round
211
+  #define _NS_TO_CYCLES(x) (((x) * ((F_CPU) / 1000000UL) + 500) / 1000UL) // round
206 212
 #else
207
-  #define DELAY_NS(x) DELAY_CYCLES(((x) * ((F_CPU) / 1000000UL) + 999) / 1000UL)  // "ceil"
213
+  #define _NS_TO_CYCLES(x) (((x) * ((F_CPU) / 1000000UL) + 999) / 1000UL) // "ceil"
208 214
 #endif
215
+
216
+#define DELAY_NS(x)         DELAY_CYCLES(_NS_TO_CYCLES(x))
217
+#define DELAY_NS_VAR(x) DELAY_CYCLES_VAR(_NS_TO_CYCLES(x))

+ 1
- 1
Marlin/src/HAL/shared/Marduino.h 查看文件

@@ -39,7 +39,7 @@
39 39
 #define DISABLED(V...) DO(DIS,&&,V)
40 40
 
41 41
 #undef _BV
42
-#define _BV(b) (1UL << (b))
42
+#define _BV(b) (1 << (b))
43 43
 #ifndef SBI
44 44
   #define SBI(A,B) (A |= _BV(B))
45 45
 #endif

+ 62
- 63
Marlin/src/libs/MAX31865.cpp 查看文件

@@ -48,20 +48,17 @@
48 48
 
49 49
 #if HAS_MAX31865 && !USE_ADAFRUIT_MAX31865
50 50
 
51
-//#include <SoftwareSPI.h> // TODO: switch to SPIclass/SoftSPI
52 51
 #include "MAX31865.h"
53 52
 
53
+#ifdef TARGET_LPC1768
54
+  #include <SoftwareSPI.h>
55
+#endif
56
+
54 57
 // The maximum speed the MAX31865 can do is 5 MHz
55 58
 SPISettings MAX31865::spiConfig = SPISettings(
56
-  #if defined(TARGET_LPC1768)
57
-    SPI_QUARTER_SPEED
58
-  #elif defined(ARDUINO_ARCH_STM32)
59
-    SPI_CLOCK_DIV4
60
-  #else
61
-    500000
62
-  #endif
63
-  , MSBFIRST
64
-  , SPI_MODE_1 // CPOL0 CPHA1
59
+  TERN(TARGET_LPC1768, SPI_QUARTER_SPEED, TERN(ARDUINO_ARCH_STM32, SPI_CLOCK_DIV4, 500000)),
60
+  MSBFIRST,
61
+  SPI_MODE1 // CPOL0 CPHA1
65 62
 );
66 63
 
67 64
 #ifndef LARGE_PINMAP
@@ -93,7 +90,7 @@ SPISettings MAX31865::spiConfig = SPISettings(
93 90
     _sclk = _miso = _mosi = -1;
94 91
   }
95 92
 
96
-#else
93
+#else // LARGE_PINMAP
97 94
 
98 95
   /**
99 96
    * Create the interface object using software (bitbang) SPI for PIN values
@@ -106,9 +103,7 @@ SPISettings MAX31865::spiConfig = SPISettings(
106 103
    * @param spi_clk      the SPI clock pin to use
107 104
    * @param pin_mapping  set to 1 for positive pin values
108 105
    */
109
-  MAX31865::MAX31865(uint32_t spi_cs, uint32_t spi_mosi,
110
-                     uint32_t spi_miso, uint32_t spi_clk,
111
-                     uint8_t pin_mapping) {
106
+  MAX31865::MAX31865(uint32_t spi_cs, uint32_t spi_mosi, uint32_t spi_miso, uint32_t spi_clk, uint8_t pin_mapping) {
112 107
     _cs = spi_cs;
113 108
     _mosi = spi_mosi;
114 109
     _miso = spi_miso;
@@ -130,14 +125,12 @@ SPISettings MAX31865::spiConfig = SPISettings(
130 125
 
131 126
 #endif // LARGE_PINMAP
132 127
 
133
-
134 128
 /**
135 129
  *
136 130
  * Instance & Class methods
137 131
  *
138 132
  */
139 133
 
140
-
141 134
 /**
142 135
  * Initialize the SPI interface and set the number of RTD wires used
143 136
  *
@@ -152,22 +145,13 @@ void MAX31865::begin(max31865_numwires_t wires, float zero, float ref) {
152 145
   OUT_WRITE(_cs, HIGH);
153 146
 
154 147
   if (_sclk != TERN(LARGE_PINMAP, -1UL, -1)) {
155
-    // Define pin modes for Software SPI
156
-    #ifdef MAX31865_DEBUG
157
-      SERIAL_ECHOLN("Initializing MAX31865 Software SPI");
158
-    #endif
159
-
160
-    OUT_WRITE(_sclk, LOW);
161
-    SET_OUTPUT(_mosi);
162
-    SET_INPUT(_miso);
148
+    softSpiBegin(SPI_QUARTER_SPEED); // Define pin modes for Software SPI
163 149
   }
164 150
   else {
165
-    // Start and configure hardware SPI
166 151
     #ifdef MAX31865_DEBUG
167
-      SERIAL_ECHOLN("Initializing MAX31865 Hardware SPI");
152
+      SERIAL_ECHOLNPGM("Initializing MAX31865 Hardware SPI");
168 153
     #endif
169
-
170
-    SPI.begin();
154
+    SPI.begin();    // Start and configure hardware SPI
171 155
   }
172 156
 
173 157
   setWires(wires);
@@ -176,25 +160,15 @@ void MAX31865::begin(max31865_numwires_t wires, float zero, float ref) {
176 160
   clearFault();
177 161
 
178 162
   #ifdef MAX31865_DEBUG_SPI
179
-    #ifndef LARGE_PINMAP
180
-      SERIAL_ECHOLNPGM(
181
-        "Regular begin call with _cs: ", _cs,
182
-        " _miso: ", _miso,
183
-        " _sclk: ", _sclk,
184
-        " _mosi: ", _mosi
185
-      );
186
-    #else
187
-      SERIAL_ECHOLNPGM(
188
-        "LARGE_PINMAP begin call with _cs: ", _cs,
189
-        " _miso: ", _miso,
190
-        " _sclk: ", _sclk,
191
-        " _mosi: ", _mosi
192
-      );
193
-    #endif // LARGE_PINMAP
194
-
195
-    SERIAL_ECHOLNPGM("config: ", readRegister8(MAX31856_CONFIG_REG));
196
-    SERIAL_EOL();
197
-  #endif // MAX31865_DEBUG_SPI
163
+    SERIAL_ECHOLNPGM(
164
+      TERN(LARGE_PINMAP, "LARGE_PINMAP", "Regular")
165
+      " begin call with _cs: ", _cs,
166
+      " _miso: ", _miso,
167
+      " _sclk: ", _sclk,
168
+      " _mosi: ", _mosi,
169
+      " config: ", readRegister8(MAX31856_CONFIG_REG)
170
+    );
171
+  #endif
198 172
 }
199 173
 
200 174
 /**
@@ -371,7 +345,6 @@ float MAX31865::temperature(float Rrtd) {
371 345
 // private:
372 346
 //
373 347
 
374
-
375 348
 /**
376 349
  * Set a value in the configuration register.
377 350
  *
@@ -432,10 +405,15 @@ void MAX31865::readRegisterN(uint8_t addr, uint8_t buffer[], uint8_t n) {
432 405
     WRITE(_sclk, LOW);
433 406
 
434 407
   WRITE(_cs, LOW);
435
-  spixfer(addr);
408
+
409
+  #ifdef TARGET_LPC1768
410
+    DELAY_CYCLES(_spi_speed);
411
+  #endif
412
+
413
+  spiTransfer(addr);
436 414
 
437 415
   while (n--) {
438
-    buffer[0] = spixfer(0xFF);
416
+    buffer[0] = spiTransfer(0xFF);
439 417
     #ifdef MAX31865_DEBUG_SPI
440 418
       SERIAL_ECHOLNPGM("buffer read ", n, " data: ", buffer[0]);
441 419
     #endif
@@ -462,8 +440,12 @@ void MAX31865::writeRegister8(uint8_t addr, uint8_t data) {
462 440
 
463 441
   WRITE(_cs, LOW);
464 442
 
465
-  spixfer(addr | 0x80); // make sure top bit is set
466
-  spixfer(data);
443
+  #ifdef TARGET_LPC1768
444
+    DELAY_CYCLES(_spi_speed);
445
+  #endif
446
+
447
+  spiTransfer(addr | 0x80); // make sure top bit is set
448
+  spiTransfer(data);
467 449
 
468 450
   if (_sclk == TERN(LARGE_PINMAP, -1UL, -1))
469 451
     SPI.endTransaction();
@@ -480,21 +462,38 @@ void MAX31865::writeRegister8(uint8_t addr, uint8_t data) {
480 462
  * @param  x  an 8-bit chunk of data to write
481 463
  * @return    the 8-bit response
482 464
  */
483
-uint8_t MAX31865::spixfer(uint8_t x) {
465
+uint8_t MAX31865::spiTransfer(uint8_t x) {
484 466
   if (_sclk == TERN(LARGE_PINMAP, -1UL, -1))
485 467
     return SPI.transfer(x);
486 468
 
487
-  uint8_t reply = 0;
488
-  for (int i = 7; i >= 0; i--) {
489
-    reply <<= 1;
490
-    WRITE(_sclk, HIGH);
491
-    WRITE(_mosi, x & (1 << i));
492
-    WRITE(_sclk, LOW);
493
-    if (READ(_miso))
494
-      reply |= 1;
495
-  }
469
+  #ifdef TARGET_LPC1768
470
+    return swSpiTransfer(x, _spi_speed, _sclk, _miso, _mosi);
471
+  #else
472
+    uint8_t reply = 0;
473
+    for (int i = 7; i >= 0; i--) {
474
+      WRITE(_sclk, HIGH);           DELAY_NS_VAR(_spi_delay);
475
+      reply <<= 1;
476
+      WRITE(_mosi, x & _BV(i));     DELAY_NS_VAR(_spi_delay);
477
+      if (READ(_miso)) reply |= 1;
478
+      WRITE(_sclk, LOW);            DELAY_NS_VAR(_spi_delay);
479
+    }
480
+    return reply;
481
+  #endif
482
+}
496 483
 
497
-  return reply;
484
+void MAX31865::softSpiBegin(const uint8_t spi_speed) {
485
+  #ifdef MAX31865_DEBUG
486
+    SERIAL_ECHOLNPGM("Initializing MAX31865 Software SPI");
487
+  #endif
488
+  #ifdef TARGET_LPC1768
489
+    swSpiBegin(_sclk, _miso, _mosi);
490
+    _spi_speed = swSpiInit(spi_speed, _sclk, _mosi);
491
+  #else
492
+    _spi_delay = (100UL << spi_speed) / 3; // Calculate delay in ns. Top speed is ~10MHz, or 100ns delay between bits.
493
+    OUT_WRITE(_sclk, LOW);
494
+    SET_OUTPUT(_mosi);
495
+    SET_INPUT(_miso);
496
+  #endif
498 497
 }
499 498
 
500 499
 #endif // HAS_MAX31865 && !USE_ADAFRUIT_MAX31865

+ 10
- 1
Marlin/src/libs/MAX31865.h 查看文件

@@ -90,6 +90,13 @@ private:
90 90
   static SPISettings spiConfig;
91 91
 
92 92
   TERN(LARGE_PINMAP, uint32_t, uint8_t) _sclk, _miso, _mosi, _cs;
93
+
94
+  #ifdef TARGET_LPC1768
95
+    uint8_t _spi_speed;
96
+  #else
97
+    uint16_t _spi_delay;
98
+  #endif
99
+
93 100
   float Rzero, Rref;
94 101
 
95 102
   void setConfig(uint8_t config, bool enable);
@@ -99,7 +106,9 @@ private:
99 106
   uint16_t readRegister16(uint8_t addr);
100 107
 
101 108
   void writeRegister8(uint8_t addr, uint8_t reg);
102
-  uint8_t spixfer(uint8_t addr);
109
+  uint8_t spiTransfer(uint8_t addr);
110
+
111
+  void softSpiBegin(const uint8_t spi_speed);
103 112
 
104 113
 public:
105 114
   #ifdef LARGE_PINMAP

+ 2
- 1
buildroot/tests/LPC1769 查看文件

@@ -14,11 +14,12 @@ exec_test $1 $2 "Azteeg X5GT Example Configuration" "$3"
14 14
 
15 15
 restore_configs
16 16
 opt_set MOTHERBOARD BOARD_SMOOTHIEBOARD \
17
-        EXTRUDERS 2 TEMP_SENSOR_1 -1 TEMP_SENSOR_BED 5 \
17
+        EXTRUDERS 2 TEMP_SENSOR_0 -5 TEMP_SENSOR_1 -1 TEMP_SENSOR_BED 5 TEMP_0_CS_PIN P1_29 \
18 18
         GRID_MAX_POINTS_X 16 \
19 19
         NOZZLE_CLEAN_START_POINT "{ {  10, 10, 3 }, {  10, 10, 3 } }" \
20 20
         NOZZLE_CLEAN_END_POINT "{ {  10, 20, 3 }, {  10, 20, 3 } }"
21 21
 opt_enable TFTGLCD_PANEL_SPI SDSUPPORT ADAPTIVE_FAN_SLOWING NO_FAN_SLOWING_IN_PID_TUNING \
22
+           MAX31865_SENSOR_OHMS_0 MAX31865_CALIBRATION_OHMS_0 \
22 23
            FIX_MOUNTED_PROBE AUTO_BED_LEVELING_BILINEAR G29_RETRY_AND_RECOVER Z_MIN_PROBE_REPEATABILITY_TEST DEBUG_LEVELING_FEATURE \
23 24
            BABYSTEPPING BABYSTEP_XY BABYSTEP_ZPROBE_OFFSET LEVEL_CORNERS_USE_PROBE LEVEL_CORNERS_VERIFY_RAISED \
24 25
            PRINTCOUNTER NOZZLE_PARK_FEATURE NOZZLE_CLEAN_FEATURE SLOW_PWM_HEATERS PIDTEMPBED EEPROM_SETTINGS INCH_MODE_SUPPORT TEMPERATURE_UNITS_SUPPORT \

+ 3
- 2
buildroot/tests/teensy41 查看文件

@@ -15,12 +15,13 @@ exec_test $1 $2 "Teensy4.1 with default config" "$3"
15 15
 #
16 16
 restore_configs
17 17
 opt_set MOTHERBOARD BOARD_TEENSY41 \
18
-        EXTRUDERS 2 TEMP_SENSOR_0 1 TEMP_SENSOR_1 5 TEMP_SENSOR_BED 1 \
18
+        EXTRUDERS 2 TEMP_SENSOR_0 -5 TEMP_SENSOR_1 5 TEMP_SENSOR_BED 1 TEMP_0_CS_PIN 23 \
19 19
         I2C_SLAVE_ADDRESS 63 \
20 20
         GRID_MAX_POINTS_X 16 \
21 21
         NOZZLE_CLEAN_START_POINT "{ {  10, 10, 3 }, {  10, 10, 3 } }" \
22 22
         NOZZLE_CLEAN_END_POINT "{ {  10, 20, 3 }, {  10, 20, 3 } }"
23
-opt_enable EXTENSIBLE_UI LCD_INFO_MENU SDSUPPORT SDCARD_SORT_ALPHA \
23
+opt_enable MAX31865_SENSOR_OHMS_0 MAX31865_CALIBRATION_OHMS_0 \
24
+           EXTENSIBLE_UI LCD_INFO_MENU SDSUPPORT SDCARD_SORT_ALPHA \
24 25
            FILAMENT_LCD_DISPLAY CALIBRATION_GCODE BAUD_RATE_GCODE \
25 26
            FIX_MOUNTED_PROBE Z_SAFE_HOMING AUTO_BED_LEVELING_BILINEAR Z_MIN_PROBE_REPEATABILITY_TEST DEBUG_LEVELING_FEATURE \
26 27
            BABYSTEPPING BABYSTEP_XY BABYSTEP_ZPROBE_OFFSET \

Loading…
取消
儲存