stm32使用arduino encoder库的改造草案
改装以前的简单项目,升级一下开发板,arduino nano 328p 换到STM32F103。
原项目用到中断监测编码器的库Encoder Library
https://www.pjrc.com/teensy/td_libs_Encoder.html
官方似乎没有说明如何移植到STM32的方法。
来做个实验。
示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | /* Encoder Library - Basic Example * http://www.pjrc.com/teensy/td_libs_Encoder.html * * This example code is in the public domain. */ #include <Encoder.h> // Change these two numbers to the pins connected to your encoder. // Best Performance: both pins have interrupt capability // Good Performance: only the first pin has interrupt capability // Low Performance: neither pin has interrupt capability Encoder myEnc(2,3); // avoid using pins with LEDs attached void setup() { Serial.begin(9600); Serial.println("Basic Encoder Test:"); } long oldPosition = -999; void loop() { long newPosition = myEnc.read(); if (newPosition != oldPosition) { oldPosition = newPosition; Serial.println(newPosition); } } |
nano板编译下载运行都很漂亮。
但是 选择 Generic STM32F103C series开发板时编译都不过。报错如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | D:\Program Files\arduino-1.8.9\arduino-builder -dump-prefs -logger=machine -hardware D:\Program Files\arduino-1.8.9\hardware -hardware C:\Users\Administrator\AppData\Local\Arduino15\packages -tools D:\Program Files\arduino-1.8.9\tools-builder -tools D:\Program Files\arduino-1.8.9\hardware\tools\avr -tools C:\Users\Administrator\AppData\Local\Arduino15\packages -built-in-libraries D:\Program Files\arduino-1.8.9\libraries -libraries C:\Users\Administrator\Documents\Arduino\libraries -fqbn=Arduino_STM32-master:STM32F1:genericSTM32F103C:device_variant=STM32F103C8,upload_method=serialMethod,cpu_speed=speed_72mhz,opt=osstd -vid-pid=10C4_EA60 -ide-version=10809 -build-path C:\Users\ADMINI~1\AppData\Local\Temp\arduino_build_683750 -warnings=none -build-cache C:\Users\ADMINI~1\AppData\Local\Temp\arduino_cache_499795 -prefs=build.warn_data_percentage=75 -verbose C:\Users\Administrator\Documents\Arduino\libraries\Encoder\examples\Basic\Basic.pde D:\Program Files\arduino-1.8.9\arduino-builder -compile -logger=machine -hardware D:\Program Files\arduino-1.8.9\hardware -hardware C:\Users\Administrator\AppData\Local\Arduino15\packages -tools D:\Program Files\arduino-1.8.9\tools-builder -tools D:\Program Files\arduino-1.8.9\hardware\tools\avr -tools C:\Users\Administrator\AppData\Local\Arduino15\packages -built-in-libraries D:\Program Files\arduino-1.8.9\libraries -libraries C:\Users\Administrator\Documents\Arduino\libraries -fqbn=Arduino_STM32-master:STM32F1:genericSTM32F103C:device_variant=STM32F103C8,upload_method=serialMethod,cpu_speed=speed_72mhz,opt=osstd -vid-pid=10C4_EA60 -ide-version=10809 -build-path C:\Users\ADMINI~1\AppData\Local\Temp\arduino_build_683750 -warnings=none -build-cache C:\Users\ADMINI~1\AppData\Local\Temp\arduino_cache_499795 -prefs=build.warn_data_percentage=75 -verbose C:\Users\Administrator\Documents\Arduino\libraries\Encoder\examples\Basic\Basic.pde Using board 'genericSTM32F103C' from platform in folder: D:\Program Files\arduino-1.8.9\hardware\Arduino_STM32-master\STM32F1 Using core 'maple' from platform in folder: D:\Program Files\arduino-1.8.9\hardware\Arduino_STM32-master\STM32F1 Detecting libraries used... "C:\\Users\\Administrator\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\arm-none-eabi-gcc\\4.8.3-2014q1/bin/arm-none-eabi-g++" -c -g -Os -w -DDEBUG_LEVEL=DEBUG_NONE -std=gnu++11 -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -DBOARD_generic_stm32f103c -DVECT_TAB_ADDR=0x8000000 -DERROR_LED_PORT=GPIOC -DERROR_LED_PIN=13 -w -x c++ -E -CC -mcpu=cortex-m3 -DF_CPU=72000000L -DARDUINO=10809 -DARDUINO_GENERIC_STM32F103C -DARDUINO_ARCH_STM32F1 -DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG -DMCU_STM32F103C8 -mthumb -march=armv7-m -D__STM32F1__ -DARDUINO_ARCH_STM32 -DMCU_STM32F103C8 -mthumb -march=armv7-m -D__STM32F1__ -DARDUINO_ARCH_STM32 "-ID:\\Program Files\\arduino-1.8.9\\hardware\\Arduino_STM32-master\\STM32F1\\system/libmaple" "-ID:\\Program Files\\arduino-1.8.9\\hardware\\Arduino_STM32-master\\STM32F1\\system/libmaple/include" "-ID:\\Program Files\\arduino-1.8.9\\hardware\\Arduino_STM32-master\\STM32F1\\system/libmaple/stm32f1/include" "-ID:\\Program Files\\arduino-1.8.9\\hardware\\Arduino_STM32-master\\STM32F1\\system/libmaple/usb/stm32f1" "-ID:\\Program Files\\arduino-1.8.9\\hardware\\Arduino_STM32-master\\STM32F1\\system/libmaple/usb/usb_lib" "-ID:\\Program Files\\arduino-1.8.9\\hardware\\Arduino_STM32-master\\STM32F1\\cores\\maple" "-ID:\\Program Files\\arduino-1.8.9\\hardware\\Arduino_STM32-master\\STM32F1\\variants\\generic_stm32f103c" "C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\arduino_build_683750\\sketch\\Basic.pde.cpp" -o nul "C:\\Users\\Administrator\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\arm-none-eabi-gcc\\4.8.3-2014q1/bin/arm-none-eabi-g++" -c -g -Os -w -DDEBUG_LEVEL=DEBUG_NONE -std=gnu++11 -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -DBOARD_generic_stm32f103c -DVECT_TAB_ADDR=0x8000000 -DERROR_LED_PORT=GPIOC -DERROR_LED_PIN=13 -w -x c++ -E -CC -mcpu=cortex-m3 -DF_CPU=72000000L -DARDUINO=10809 -DARDUINO_GENERIC_STM32F103C -DARDUINO_ARCH_STM32F1 -DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG -DMCU_STM32F103C8 -mthumb -march=armv7-m -D__STM32F1__ -DARDUINO_ARCH_STM32 -DMCU_STM32F103C8 -mthumb -march=armv7-m -D__STM32F1__ -DARDUINO_ARCH_STM32 "-ID:\\Program Files\\arduino-1.8.9\\hardware\\Arduino_STM32-master\\STM32F1\\system/libmaple" "-ID:\\Program Files\\arduino-1.8.9\\hardware\\Arduino_STM32-master\\STM32F1\\system/libmaple/include" "-ID:\\Program Files\\arduino-1.8.9\\hardware\\Arduino_STM32-master\\STM32F1\\system/libmaple/stm32f1/include" "-ID:\\Program Files\\arduino-1.8.9\\hardware\\Arduino_STM32-master\\STM32F1\\system/libmaple/usb/stm32f1" "-ID:\\Program Files\\arduino-1.8.9\\hardware\\Arduino_STM32-master\\STM32F1\\system/libmaple/usb/usb_lib" "-ID:\\Program Files\\arduino-1.8.9\\hardware\\Arduino_STM32-master\\STM32F1\\cores\\maple" "-ID:\\Program Files\\arduino-1.8.9\\hardware\\Arduino_STM32-master\\STM32F1\\variants\\generic_stm32f103c" "-IC:\\Users\\Administrator\\Documents\\Arduino\\libraries\\Encoder" "C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\arduino_build_683750\\sketch\\Basic.pde.cpp" -o nul Error while detecting libraries included by C:\Users\ADMINI~1\AppData\Local\Temp\arduino_build_683750\sketch\Basic.pde.cpp "C:\\Users\\Administrator\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\arm-none-eabi-gcc\\4.8.3-2014q1/bin/arm-none-eabi-g++" -c -g -Os -w -DDEBUG_LEVEL=DEBUG_NONE -std=gnu++11 -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -DBOARD_generic_stm32f103c -DVECT_TAB_ADDR=0x8000000 -DERROR_LED_PORT=GPIOC -DERROR_LED_PIN=13 -w -x c++ -E -CC -mcpu=cortex-m3 -DF_CPU=72000000L -DARDUINO=10809 -DARDUINO_GENERIC_STM32F103C -DARDUINO_ARCH_STM32F1 -DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG -DMCU_STM32F103C8 -mthumb -march=armv7-m -D__STM32F1__ -DARDUINO_ARCH_STM32 -DMCU_STM32F103C8 -mthumb -march=armv7-m -D__STM32F1__ -DARDUINO_ARCH_STM32 "-ID:\\Program Files\\arduino-1.8.9\\hardware\\Arduino_STM32-master\\STM32F1\\system/libmaple" "-ID:\\Program Files\\arduino-1.8.9\\hardware\\Arduino_STM32-master\\STM32F1\\system/libmaple/include" "-ID:\\Program Files\\arduino-1.8.9\\hardware\\Arduino_STM32-master\\STM32F1\\system/libmaple/stm32f1/include" "-ID:\\Program Files\\arduino-1.8.9\\hardware\\Arduino_STM32-master\\STM32F1\\system/libmaple/usb/stm32f1" "-ID:\\Program Files\\arduino-1.8.9\\hardware\\Arduino_STM32-master\\STM32F1\\system/libmaple/usb/usb_lib" "-ID:\\Program Files\\arduino-1.8.9\\hardware\\Arduino_STM32-master\\STM32F1\\cores\\maple" "-ID:\\Program Files\\arduino-1.8.9\\hardware\\Arduino_STM32-master\\STM32F1\\variants\\generic_stm32f103c" "-IC:\\Users\\Administrator\\Documents\\Arduino\\libraries\\Encoder" "-IC:\\Users\\Administrator\\Documents\\Arduino\\libraries\\Encoder\\utility" "C:\\Users\\Administrator\\Documents\\Arduino\\libraries\\Encoder\\Encoder.cpp" -o nul Error while detecting libraries included by C:\Users\Administrator\Documents\Arduino\libraries\Encoder\Encoder.cpp Generating function prototypes... "C:\\Users\\Administrator\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\arm-none-eabi-gcc\\4.8.3-2014q1/bin/arm-none-eabi-g++" -c -g -Os -w -DDEBUG_LEVEL=DEBUG_NONE -std=gnu++11 -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -DBOARD_generic_stm32f103c -DVECT_TAB_ADDR=0x8000000 -DERROR_LED_PORT=GPIOC -DERROR_LED_PIN=13 -w -x c++ -E -CC -mcpu=cortex-m3 -DF_CPU=72000000L -DARDUINO=10809 -DARDUINO_GENERIC_STM32F103C -DARDUINO_ARCH_STM32F1 -DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG -DMCU_STM32F103C8 -mthumb -march=armv7-m -D__STM32F1__ -DARDUINO_ARCH_STM32 -DMCU_STM32F103C8 -mthumb -march=armv7-m -D__STM32F1__ -DARDUINO_ARCH_STM32 "-ID:\\Program Files\\arduino-1.8.9\\hardware\\Arduino_STM32-master\\STM32F1\\system/libmaple" "-ID:\\Program Files\\arduino-1.8.9\\hardware\\Arduino_STM32-master\\STM32F1\\system/libmaple/include" "-ID:\\Program Files\\arduino-1.8.9\\hardware\\Arduino_STM32-master\\STM32F1\\system/libmaple/stm32f1/include" "-ID:\\Program Files\\arduino-1.8.9\\hardware\\Arduino_STM32-master\\STM32F1\\system/libmaple/usb/stm32f1" "-ID:\\Program Files\\arduino-1.8.9\\hardware\\Arduino_STM32-master\\STM32F1\\system/libmaple/usb/usb_lib" "-ID:\\Program Files\\arduino-1.8.9\\hardware\\Arduino_STM32-master\\STM32F1\\cores\\maple" "-ID:\\Program Files\\arduino-1.8.9\\hardware\\Arduino_STM32-master\\STM32F1\\variants\\generic_stm32f103c" "-IC:\\Users\\Administrator\\Documents\\Arduino\\libraries\\Encoder" "C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\arduino_build_683750\\sketch\\Basic.pde.cpp" -o "C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\arduino_build_683750\\preproc\\ctags_target_for_gcc_minus_e.cpp" In file included from C:\Users\Administrator\Documents\Arduino\libraries\Encoder/Encoder.h:46:0, from C:\Users\Administrator\Documents\Arduino\libraries\Encoder\examples\Basic\Basic.pde:7: C:\Users\Administrator\Documents\Arduino\libraries\Encoder/utility/interrupt_pins.h:150:2: error: #error "Interrupts are unknown for this board, please add to this code" #error "Interrupts are unknown for this board, please add to this code" ^ C:\Users\Administrator\Documents\Arduino\libraries\Encoder/utility/interrupt_pins.h:153:2: error: #error "Encoder requires interrupt pins, but this board does not have any :(" #error "Encoder requires interrupt pins, but this board does not have any :(" ^ C:\Users\Administrator\Documents\Arduino\libraries\Encoder/utility/interrupt_pins.h:154:2: error: #error "You could try defining ENCODER_DO_NOT_USE_INTERRUPTS as a kludge." #error "You could try defining ENCODER_DO_NOT_USE_INTERRUPTS as a kludge." ^ 使用库 Encoder 在文件夹: C:\Users\Administrator\Documents\Arduino\libraries\Encoder (legacy) exit status 1 为开发板 Generic STM32F103C series 编译时出错。 |
Error while detecting libraries included by C:\Users\Administrator\Documents\Arduino\libraries\Encoder\Encoder.cpp,
没有细究,可能编译时与头文件引用顺序有关??,发现Encoder.cpp内部只有两行代码,直接拿到主文件就好了。
再经过穿针引线读了一番库的源码,示例文件做了相关改进
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | /* Encoder Library - Basic Example * http://www.pjrc.com/teensy/td_libs_Encoder.html * * This example code is in the public domain. */ //STM32F103C8 使用 Encoder Library //设置使用外部中断 #define ENCODER_USE_INTERRUPTS //设置核心中断数,这个数并不是个数,实际上是设置interruptArgs数组的长度 #define CORE_NUM_INTERRUPT 50// //外部中断引脚号,interruptArgs数组索引相关,CORE_NUM_INTERRUPT要大于等于使用最大的引脚号 #define CORE_INT28_PIN PB12 //28 #define CORE_INT29_PIN PB13 //29 //stm32 set direct_pin_read_h_ #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) //*/ #include <Encoder.h> //lib file Encoder.cpp 编译err,注释cpp的代码,write them here。 Encoder_internal_state_t * Encoder::interruptArgs[]; //interruptArgs的长度就是CORE_NUM_INTERRUPT,中断与引脚号相关联。 //假设CORE_INT100_PIN=100,interruptArgs会有100个指针,不管是否使用100个中断,所以有点浪费。 // Change these two numbers to the pins connected to your encoder. // Best Performance: both pins have interrupt capability // Good Performance: only the first pin has interrupt capability // Low Performance: neither pin has interrupt capability Encoder myEnc(PB12, PB13); // avoid using pins with LEDs attached void setup() { Serial.begin(9600); Serial.println("Basic Encoder Test:"); } long oldPosition = -999; void loop() { long newPosition = myEnc.read(); if (newPosition != oldPosition) { oldPosition = newPosition; Serial.println(newPosition); } } |
这样虽然能用,但想想CORE_NUM_INTERRUPT、 Encoder::interruptArgs[];总有些纠结。
当然这是库的优势能适应各种不同的开发板。浪费几个字节也是值得的。
下面开刀改库,为了找回这几个字节,并稍微改动了原来的架构,并没有多考虑可移植的问题。
ZEncoder.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 | // _______ _______ // Pin1 ______| |_______| |______ Pin1 // negative <--- _______ _______ __ --> positive // Pin2 __| |_______| |_______| Pin2 // new new old old // pin2 pin1 pin2 pin1 Result // ---- ---- ---- ---- ------ // 0 0 0 0 no movement // 0 0 0 1 +1 // 0 0 1 0 -1 // 0 0 1 1 +2 (assume pin1 edges only) // 0 1 0 0 -1 // 0 1 0 1 no movement // 0 1 1 0 -2 (assume pin1 edges only) // 0 1 1 1 +1 // 1 0 0 0 +1 // 1 0 0 1 -2 (assume pin1 edges only) // 1 0 1 0 no movement // 1 0 1 1 -1 // 1 1 0 0 +2 (assume pin1 edges only) // 1 1 0 1 -1 // 1 1 1 0 +1 // 1 1 1 1 no movement /* // Simple, easy-to-read "documentation" version :-) // void update(void) { uint8_t s = state & 3; if (digitalRead(pin1)) s |= 4; if (digitalRead(pin2)) s |= 8; switch (s) { case 0: case 5: case 10: case 15: break; case 1: case 7: case 8: case 14: position++; break; case 2: case 4: case 11: case 13: position--; break; case 3: case 12: position += 2; break; default: position -= 2; break; } state = (s >> 2); } */ #ifndef ZEncoder_h_ #define ZEncoder_h_ #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) // All the data needed by interrupts is consolidated into this ugly struct // to facilitate assembly language optimizing of the speed critical update. // The assembly code uses auto-incrementing addressing modes, so the struct // must remain in exactly this order. typedef struct { uint8_t pin1; uint8_t pin2; volatile IO_REG_TYPE * pin1_register; volatile IO_REG_TYPE * pin2_register; IO_REG_TYPE pin1_bitmask; IO_REG_TYPE pin2_bitmask; uint8_t state; int32_t position; } Encoder_internal_state_t; typedef void (*funcptr)(void); class ZEncoder { public: Encoder_internal_state_t encoder; uint8_t encoder_id; ZEncoder(uint8_t pin1, uint8_t pin2) { #ifdef INPUT_PULLUP pinMode(pin1, INPUT_PULLUP); pinMode(pin2, INPUT_PULLUP); #else pinMode(pin1, INPUT); digitalWrite(pin1, HIGH); pinMode(pin2, INPUT); digitalWrite(pin2, HIGH); #endif encoder.pin1 = pin1; encoder.pin2 = pin2; encoder.pin1_register = PIN_TO_BASEREG(pin1); encoder.pin1_bitmask = PIN_TO_BITMASK(pin1); encoder.pin2_register = PIN_TO_BASEREG(pin2); encoder.pin2_bitmask = PIN_TO_BITMASK(pin2); encoder.position = 0; // allow time for a passive R-C filter to charge // through the pullup resistors, before reading // the initial state delayMicroseconds(2000); uint8_t s = 0; if (DIRECT_PIN_READ(encoder.pin1_register, encoder.pin1_bitmask)) s |= 1; if (DIRECT_PIN_READ(encoder.pin2_register, encoder.pin2_bitmask)) s |= 2; encoder.state = s; interrupts_in_use = 0; //interrupts_in_use = attach_interrupt(pin1, &encoder); //interrupts_in_use += attach_interrupt2(pin2, &encoder); //update_finishup(); // to force linker to include the code (does not work) //interruptArgs[0]=&encoder; //interruptArgs[1]=&encoder; encoder_id = ZEncoder_id; interruptArgs[encoder_id] = &encoder; ZEncoder_id++; } inline int32_t read() { noInterrupts(); if (interrupts_in_use < 2) { update(&encoder); } int32_t ret = encoder.position; interrupts(); return ret; } inline void write(int32_t p) { noInterrupts(); encoder.position = p; interrupts(); } uint8_t interrupts_in_use; private: public: uint8_t ZEncoder_id = 0; static Encoder_internal_state_t * interruptArgs[2]; static void update1(Encoder_internal_state_t *arg) { uint8_t state = arg->state & 3; if (digitalRead(arg->pin1)) state |= 4; if (digitalRead(arg->pin2)) state |= 8; arg->state = (state >> 2); switch (state) { case 1: case 7: case 8: case 14: arg->position++; return; case 2: case 4: case 11: case 13: arg->position--; return; case 3: case 12: arg->position += 2; return; case 6: case 9: arg->position -= 2; return; } } static void update(Encoder_internal_state_t *arg) { uint8_t p1val = DIRECT_PIN_READ(arg->pin1_register, arg->pin1_bitmask); uint8_t p2val = DIRECT_PIN_READ(arg->pin2_register, arg->pin2_bitmask); uint8_t state = arg->state & 3; if (p1val) state |= 4; if (p2val) state |= 8; arg->state = (state >> 2); switch (state) { case 1: case 7: case 8: case 14: arg->position++; return; case 2: case 4: case 11: case 13: arg->position--; return; case 3: case 12: arg->position += 2; return; case 6: case 9: arg->position -= 2; return; } } //static void myEnc0_isr_pin1(void) { update(interruptArgs[0]); } //static void myEnc0_isr_pin2(void) { update(interruptArgs[0]); } uint8_t attach_interrupt_pin1(uint8_t interruptArgs_id, void (*FuncPtr)(void)) { Encoder_internal_state_t * e = interruptArgs[interruptArgs_id] ; attachInterrupt(e->pin1, FuncPtr, CHANGE); interrupts_in_use++; return 1; } uint8_t attach_interrupt_pin2(uint8_t interruptArgs_id, void (*FuncPtr)(void)) { Encoder_internal_state_t * e = interruptArgs[interruptArgs_id] ; attachInterrupt(e->pin2, FuncPtr, CHANGE); interrupts_in_use++; return 1; } /* static void isr0(void) { update(interruptArgs[0]); } static void isr1(void) { update(interruptArgs[1]); } uint8_t attach_interrupt(uint8_t pin, Encoder_internal_state_t *state) { interruptArgs[0] = state; attachInterrupt(pin, isr0,CHANGE); return 1; } uint8_t attach_interrupt2(uint8_t pin, Encoder_internal_state_t *state) { interruptArgs[1] = state; attachInterrupt(pin, isr1,CHANGE); return 1; } //*/ }; #endif |
不考虑兼容性代码简洁了很多。
使用方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #define ENCODER_USE_INTERRUPTS #define ENCODER_ARGLIST_SIZE 2 #include "ZEncoder.h" Encoder_internal_state_t * ZEncoder::interruptArgs[]; ZEncoder myEnc0(PB12, PB13); void myEnc0_isr_pin1(void) { ZEncoder::update(ZEncoder::interruptArgs[0]);} void myEnc0_isr_pin2(void) { ZEncoder::update(ZEncoder::interruptArgs[0]);} void setup() { myEnc0.attach_interrupt_pin1(0, myEnc0_isr_pin1); myEnc0.attach_interrupt_pin2(0, myEnc0_isr_pin2); Serial.begin(9600); Serial.println("Basic Encoder Test:"); Serial.println(ZEncoder::interruptArgs[0]->pin1); Serial.println(ZEncoder::interruptArgs[0]->pin2); Serial.println(myEnc0.interrupts_in_use); } long oldPosition = -999; void loop() { long newPosition = myEnc0.read(); if (newPosition != oldPosition) { oldPosition = newPosition; Serial.println(newPosition); } } |
虽然不优雅,但心里舒坦了。