当我尝试构建 teeny 4.1 编码器>speedTest.ino 示例时,出现类型转换错误,从 volatile uint32_t* 到 volatile unsigned char*

When I try to build the teeny 4.1 encoder>speedTest.ino example I get a type conversion error, from volatile uint32_t* to volatile unsigned char*

当我尝试构建 teeny 4.1 编码器>speedTest.ino 示例时,出现以下错误:

错误:无法在初始化中将'volatile uint32_t {aka volatile long unsigned int}'转换为'volatile unsigned char*' #define portOutputRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg + 0))**

有关以下错误的更多详细信息。

硬件和软件 木板 青少年 4.1

Arduino IDE 版本 1.8.19

Teensyduino 版本 1.56,适用于 windows 7 及更高版本(今天 3/22/2022 从 teensyduino 网站下载)

板子是 Teensy 4.1

我的操作系统是Windows10 pro

Arduino 草图

使用包含的编码器>speedtest.ino 最新版本,从 https://github.com/PaulStoffregen/Encoder 下载。 Teensyduino 1.56 附带的版本也会出现同样的错误。

    /* Encoder Library - SpeedTest - for measuring maximum Encoder speed
     * http://www.pjrc.com/teensy/td_libs_Encoder.html
     *
     * This example code is in the public domain.
     */
    
    
    // This SpeedTest example provides a simple way to verify how much
    // CPU time Encoder is consuming.  Connect a DC voltmeter to the
    // output pin and measure the voltage while the encoder is stopped
    // or running at a very slow speed.  Even though the pin is rapidly
    // pulsing, a DC voltmeter will show the average voltage.  Due to
    // software timing, it will read a number much less than a steady
    // logic high, but this number will give you a baseline reading
    // for output with minimal interrupt overhead.  Then increase the
    // encoder speed.  The voltage will decrease as the processor spends
    // more time in Encoder's interrupt routines counting the pulses
    // and less time pulsing the output pin.  When the voltage is
    // close to zero and will not decrease any farther, you have reached
    // the absolute speed limit.  Or, if using a mechanical system where
    // you reach a speed limit imposed by your motors or other hardware,
    // the amount this voltage has decreased, compared to the baseline,
    // should give you a good approximation of the portion of available
    // CPU time Encoder is consuming at your maximum speed.
    
    // Encoder requires low latency interrupt response.  Available CPU
    // time does NOT necessarily prove or guarantee correct performance.
    // If another library, like NewSoftSerial, is disabling interrupts
    // for lengthy periods of time, Encoder can be prevented from
    // properly counting the intput signals while interrupt are disabled.
    
    
    // This optional setting causes Encoder to use more optimized code,
    // but the downside is a conflict if any other part of your sketch
    // or any other library you're using requires attachInterrupt().
    // It must be defined before Encoder.h is included.
    //#define ENCODER_OPTIMIZE_INTERRUPTS
    
    #include <Encoder.h>
    #include "pins_arduino.h"
    
    // Change these two numbers to the pins connected to your encoder
    // or shift register circuit which emulates a quadrature encoder
    //  case 1: both pins are interrupts
    //  case 2: only first pin used as interrupt
    Encoder myEnc(5, 6);
    
    // Connect a DC voltmeter to this pin.
    const int outputPin = 12;
    
    /* This simple circuit, using a Dual Flip-Flop chip, can emulate
       quadrature encoder signals.  The clock can come from a fancy
       function generator or a cheap 555 timer chip.  The clock
       frequency can be measured with another board running FreqCount
       http://www.pjrc.com/teensy/td_libs_FreqCount.html
    
                            +5V
                             |        Quadrature Encoder Signal Emulator
     Clock                   |
     Input o----*--------------------------      ---------------------------o Output1
                |            |14           |    |
                |     _______|_______      |    |     _______________ 
                |    |    CD4013     |     |    |    |    CD4013     |
                |  5 |               | 1   |    |  9 |               | 13
            ---------|  D         Q  |-----|----*----|  D         Q  |------o Output2
           |    |    |               |     |         |               |
           |    |  3 |               |     |      11 |               |
           |     ----|> Clk          |      ---------|> Clk          |
           |         |               |               |               |
           |       6 |               |             8 |               |
           |     ----|  S            |           ----|  S            |
           |    |    |               |          |    |               |
           |    |  4 |            _  | 2        | 10 |            _  | 12
           |    *----|  R         Q  |---       *----|  R         Q  |----
           |    |    |               |          |    |               |    |
           |    |    |_______________|          |    |_______________|    |
           |    |            |                  |                         |
           |    |            | 7                |                         |
           |    |            |                  |                         |
            --------------------------------------------------------------
                |            |                  |
                |            |                  |
              -----        -----              -----
               ---          ---                ---
                -            -                  -
    */
    
    
    void setup() {
      pinMode(outputPin, OUTPUT);
    }
    
    #if defined(__AVR__) || defined(TEENSYDUINO)
    #define REGTYPE unsigned char
    #else
    #define REGTYPE unsigned long
    #endif
    
    void loop() {
      volatile int count = 0;
      volatile REGTYPE *reg = portOutputRegister(digitalPinToPort(outputPin));
      REGTYPE mask = digitalPinToBitMask(outputPin);
    
      while (1) {
        myEnc.read();   // Read the encoder while interrupts are enabled.
        noInterrupts();
        *reg |= mask;   // Pulse the pin high, while interrupts are disabled.
        count = count + 1;
        *reg &= ~mask;
        interrupts();
      }
    }

完整错误读数

Arduino: 1.8.19 Hourly Build 2019/02/04 10:33 (Windows 10), TD: 1.56, Board: "Teensy 4.1, Serial, 600 MHz, Faster, US English"

In file included from C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/core_pins.h:33:0,

                 from C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/wiring.h:39,

                 from C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/WProgram.h:45,

                 from C:\Users\name\AppData\Local\Temp\arduino_build_426018\pch\Arduino.h:6:

SpeedTest: In function 'void loop()':

C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/pins_arduino.h:149:75: error: cannot convert 'volatile uint32_t* {aka volatile long unsigned int*}' to 'volatile unsigned char*' in initialization

 #define portOutputRegister(pin)  ((digital_pin_to_info_PGM[(pin)].reg + 0))

                                                                           ^

C:\Users\name~1\AppData\Local\Temp\arduino_modified_sketch_275677\SpeedTest.ino:101:27: note: in expansion of macro 'portOutputRegister'

   volatile REGTYPE *reg = portOutputRegister(digitalPinToPort(outputPin));

                           ^

C:\Users\name~1\AppData\Local\Temp\arduino_modified_sketch_275677\SpeedTest.pde: At global scope:

SpeedTest:46: error: redefinition of 'Encoder myEnc'

 Encoder myEnc(5, 6);

              ^

C:\Users\name~1\AppData\Local\Temp\arduino_modified_sketch_275677\SpeedTest.ino:46:9: note: 'Encoder myEnc' previously declared here

 Encoder myEnc(5, 6);

         ^

SpeedTest:49: error: redefinition of 'const int outputPin'

 const int outputPin = 12;

           ^

C:\Users\name~1\AppData\Local\Temp\arduino_modified_sketch_275677\SpeedTest.ino:49:11: note: 'const int outputPin' previously defined here

 const int outputPin = 12;

           ^

SpeedTest: In function 'void setup()':

SpeedTest:89: error: redefinition of 'void setup()'

 void setup() {

      ^

C:\Users\name~1\AppData\Local\Temp\arduino_modified_sketch_275677\SpeedTest.ino:89:6: note: 'void setup()' previously defined here

 void setup() {

      ^

SpeedTest: In function 'void loop()':

SpeedTest:99: error: redefinition of 'void loop()'

 void loop() {

      ^

C:\Users\name~1\AppData\Local\Temp\arduino_modified_sketch_275677\SpeedTest.ino:99:6: note: 'void loop()' previously defined here

 void loop() {

      ^

In file included from C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/core_pins.h:33:0,

                 from C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/wiring.h:39,

                 from C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/WProgram.h:45,

                 from C:\Users\name~1\AppData\Local\Temp\arduino_build_426018\pch\Arduino.h:6:

C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4/pins_arduino.h:149:75: error: cannot convert 'volatile uint32_t* {aka volatile long unsigned int*}' to 'volatile unsigned char*' in initialization

 #define portOutputRegister(pin)  ((digital_pin_to_info_PGM[(pin)].reg + 0))

                                                                           ^

C:\Users\name~1\AppData\Local\Temp\arduino_modified_sketch_275677\SpeedTest.pde:101:27: note: in expansion of macro 'portOutputRegister'

   volatile REGTYPE *reg = portOutputRegister(digitalPinToPort(outputPin));

                           ^

redefinition of 'Encoder myEnc'



This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

我进行了搜索,但无法在任何地方找到答案。我在 Github here 上发现了类似的问题,但版本不同:

https://github.com/PaulStoffregen/Encoder/issues/44

但是没有“direct_pin_red.h”,这就是答案所说的添加代码的内容。

他说要将以下代码添加到该文件

#if defined(__IMXRT1062__)
#define IO_REG_TYPE             uint32_t
#define PIN_TO_BASEREG(pin)             (portInputRegister(digitalPinToPort(pin)))
#define PIN_TO_BITMASK(pin)             (digitalPinToBitMask(pin))
#define DIRECT_PIN_READ(base, mask)     (((*(base)) & (mask)) ? 1 : 0)

我在 Arduino\hardware\teensy\avr\libraries\Encoder\utility\direct_pin_read.h

中找到了一个具有类似代码的文件
#define IO_REG_TYPE         uint32_t
#define PIN_TO_BASEREG(pin)             (portOutputRegister(pin))
#define PIN_TO_BITMASK(pin)             (digitalPinToBitMask(pin))
#define DIRECT_PIN_READ(base, mask)     (((*(base)) & (mask)) ? 1 : 0)

唯一的区别是 git 答案中的 PIN_TO_BASEREG 定义是

#define PIN_TO_BASEREG(引脚)(端口输出寄存器(引脚))

#define PIN_TO_BASEREG(pin) (portInputRegister(digitalPinToPort(pin)))

所以我尝试更改它以匹配给定的解决方案,但我得到了同样的错误。

我不确定为什么将此称为 volatile uint32_t* 到 volatile unsigned char* 之间的转换错误,或者我需要更改定义的地方。

宏定义明显错误。看起来它是为旧的 AVR Teensies 完成的,并没有针对 32 位 ARM 板进行调整。对于 T4.x,您只需将其替换为

// #if defined(__AVR__) || defined(TEENSYDUINO)
// #define REGTYPE unsigned char
// #else
// #define REGTYPE unsigned long
// #endif

using REGTYPE = uint32_t;

编译。您也可以替换完整的寄存器内容并简单地使用

#include <Encoder.h>
#include "pins_arduino.h"

// Change these two numbers to the pins connected to your encoder
// or shift register circuit which emulates a quadrature encoder
//  case 1: both pins are interrupts
//  case 2: only first pin used as interrupt
Encoder myEnc(5, 6);

// Connect a DC voltmeter to this pin.
const int outputPin = 12;


void setup() {
  pinMode(outputPin, OUTPUT);
}


void loop() {
  volatile int count = 0;

  while (1) {
    myEnc.read();   // Read the encoder while interrupts are enabled.

    noInterrupts();
    digitalWriteFast(outputPin, HIGH);
    count = count + 1;
    digitalWriteFast(outputPin, LOW);
    interrupts();
  }
}

但是,我不确定测量对于 600MHz T4 是否有意义。 outputPin 将仅高几纳秒...