以前に投稿したATtiny85版をPIC16F1454に移殖してみた。
ATtiny85版で対応したセンサー(LMT01, LM35, LM60, LM61)がどれもあまり芳しくなかったため今回はAliexpressで500円程度で購入可能なSONOFFのDS18B20温度センサーとAM2301(DHT21)温湿度センサーに対応してみた。DS18B20は初めて使ってみたが校正精度や安定性は他のセンサーとは比べ物にならないほど優秀だ。それに比べるとAM2301は校正精度や安定性で若干劣るようだ。
ついでにPIC16F1454のUSB機能を利用し仮想COMポート(CDC-ACM)経由でPC側から温度を取得できるようにしたり、USBの電源制御、PWM機能を追加したりした結果、ほぼコード領域一杯という前回の投稿に引き続きお腹一杯プロジェクト第二弾になってしまった。(笑)
ちなみにセンサー用の電源電圧は5V。他社の安い模造センサーも出回っているが3.3V仕様のものもあるので注意すべし。また、DS18B20直刺しとSONOFFセンサーの同時接続はできない。
回路図
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 |
/* * File: main.c * Author: Sasapea's Lab * * Created on 2018/12/21 */ #include <string.h> #include "system.h" #include "usb.h" #include "usb_device.h" #include "usb_device_cdc.h" #include "pwm.h" #include "tmr0.h" #define CMD_GET_SENSOR_DATA 0 #define CMD_SET_POWER_MODE 1 #define CMD_SET_PWM_MODE 2 #define PWM_PORT PWM_RC5 #define USB_DETACH_TIME TMR0_MS2TICK_L(5000) // ms // // from themo.c // extern int16_t temperature; extern int16_t humidity; extern uint8_t power_mode; extern void setup(); extern void loop(); static uint8_t ackbuf[32]; static uint8_t buffer[32]; static uint8_t count; #ifdef PWM_PORT static uint32_t pwmfreq = 1000; // Hz static uint8_t pwmduty = 100; // % void pwm_conf() { pwm_freq(pwmfreq); // pwm clock pwm_duty(PWM_PORT, pwmduty); // pwm duty cycle } #endif void ack(uint8_t len, uint8_t status) { ackbuf[2] = status; ackbuf[1] = buffer[1]; putUSBUSART(ackbuf, (ackbuf[0] = len) + 1); } void command() { count += getsUSBUSART(&buffer[count], sizeof(buffer) - count); if ((count > 0) && (count >= buffer[0] + 1)) { switch (buffer[1]) { case CMD_GET_SENSOR_DATA: *(int16_t *)&ackbuf[3] = temperature; *(int16_t *)&ackbuf[5] = humidity; ack(6, 0); break; case CMD_SET_POWER_MODE: power_mode = buffer[2]; ack(2, 0); break; #ifdef PWM_PORT case CMD_SET_PWM_MODE: pwmfreq = *(uint32_t *)&buffer[2]; pwmduty = buffer[6]; pwm_conf(); ack(2, 0); break; #endif default: ack(2, 0xFF); break; } if (count -= buffer[0] + 1) memcpy(buffer, &buffer[buffer[0] + 1], count); } } void main(void) { uint16_t usb_attach = 0; bool configured = false; // // System Initialize // SYSTEM_Initialize(SYSTEM_STATE_USB_START); // // Init USB // USBDeviceInit(); USBDeviceAttach(); // // Init PWM // #ifdef PWM_PORT pwm_init(PWM_PORT, 1); #endif // // Setup // setup(); // // Init PWM // #ifdef PWM_PORT pwm_conf(); #endif // // メイン・ループ // while(1) { // // Main // loop(); // // USB Task // if ((USBGetDeviceState() == CONFIGURED_STATE) && !USBIsDeviceSuspended()) { configured = true; command(); CDCTxService(); } else if (configured) { configured = false; usb_attach = TMR0_READ_L(); USBDeviceDetach(); } else if (usb_attach) { if (TIMEUP16(TMR0_READ_L(), usb_attach, USB_DETACH_TIME)) { usb_attach = 0; USBDeviceAttach(); } } // // Reset WDT // CLRWDT(); } } |
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 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 |
/////////////////////////////////////////////////////////////////////////////////////// // // // Tiny Thermo Switch Controller // // // // Author : Sasapea's Lab. // // Release: 2018-12-21. Version 1.00 // // // // power-on button operations (first LED on (3sec) operation) // // // // [+] and [-] ... setting reset. // // [+] ... select thermo switch mode. (0=normally open ) // // [-] ... select thermo switch mode. (1=normally close) // // // // normal button oerations // // // // [+] and [-] ... select sensor. (not used) // // [+] ... *1 ++threshold. // // [-] ... *1 --threshold. // // [+] ... *2 ++calibrate. // // [-] ... *2 --calibrate. // // *1 short time press. < 3sec // // *2 long time press. >=3sec (repeated) // // // /////////////////////////////////////////////////////////////////////////////////////// #include "tmr0.h" #include "pin_edge.h" #include "blink_code.h" #include "dstsensor.h" #include "dhtsensor.h" #include "HEFlash.h" // // gpio pin assign // #define CONCAT(r, p) r##p #define GPIO_THERMO_SW(r) CONCAT(r, C5) #define GPIO_BOARD_LED(r) CONCAT(r, C4) // // power mode // #define POWER_OFF 0 #define POWER_ON 1 #define POWER_AUTO 2 // // sensor type // #define NO_SENSOR 0 #define DSTSENSOR 1 #define DHTSENSOR 2 // // limit define // #define THRESHOLD_MAX +80 #define THRESHOLD_MIN -30 #define CALIBRATE_MAX +5 #define CALIBRATE_MIN -5 // // setting mode // #define SETTING_NONE 0 #define SETTING_SENSOR 1 // // timer setting // #define THERMO_CTRL_INTERVAL TMR0_MS2TICK_L(10000) // ms #define OPTIONS_SETTING_TIME TMR0_MS2TICK_L( 3000) // ms #define OPTIONS_SETTING_DISP 4 // // EEPROM values // #define FLASH_ROWADDR 3 #define OFFSETOF(t, f) ((int)&((t *)0)->f) typedef unsigned size_t; typedef struct { uint8_t size; int8_t threshold; int8_t calibrate; int8_t switch_1b; } options_t; // // option variables // options_t options = {sizeof(options_t), 30, 0, 0}; // // working variables // int16_t temperature; int16_t humidity; uint8_t power_mode = POWER_AUTO; static uint16_t thermo_ctrl; static uint16_t setting_start; static uint8_t setting_mode; static uint8_t setting_disp; static int8_t setting_value; static uint8_t sensor_type = NO_SENSOR; static uint8_t eeprom_readByte(uint8_t off) { return (uint8_t)HEFLASH_readByte(FLASH_ROWADDR, off); } static void eeprom_read() { HEFLASH_readBlock((char *)&options, FLASH_ROWADDR, sizeof(options)); } static void eeprom_write() { HEFLASH_writeBlock(FLASH_ROWADDR, (char *)&options, sizeof(options)); } void setup() { // // init gpio mode // OPTION_REGbits.nWPUEN = 0; // pull-up enable GPIO_THERMO_SW(LAT) = 1; GPIO_THERMO_SW(TRIS) = 1; GPIO_BOARD_LED(LAT) = 0; GPIO_BOARD_LED(TRIS) = 0; // // Init TMR0 // tmr0_init(); // // init temperature sensor // dst_init(); dht_init(DHTSENSOR_AM2301); // // init gpio edge state // pin_init(); // // power-up button control // setting_start = TMR0_READ_L(); do { // // read pin // pin_detect(GPIO_UP_BTN); pin_detect(GPIO_DW_BTN); // // reset WDT // CLRWDT(); } while (!TIMEUP16(TMR0_READ_L(), setting_start, OPTIONS_SETTING_TIME)); GPIO_BOARD_LED(LAT) = 1; // // reset eeprom values (press DW and UP button to reset) // if (!pin_state(GPIO_UP_BTN) && !pin_state(GPIO_DW_BTN)) { eeprom_write(); for (uint8_t i = 0; i < 10; ++i) { GPIO_BOARD_LED(LAT) = 0; tmr0_delay(TMR0_MS2TICK(50)); GPIO_BOARD_LED(LAT) = 1; tmr0_delay(TMR0_MS2TICK(50)); } } else { // // init eeprom values // if (eeprom_readByte(OFFSETOF(options_t, size)) != options.size) eeprom_write(); // // read eeprom values // else eeprom_read(); // // setting output mode // if (!pin_state(GPIO_UP_BTN)) { setting_value = (options.switch_1b = 0); setting_disp = OPTIONS_SETTING_DISP; eeprom_write(); } // // setting display mode // else if (!pin_state(GPIO_DW_BTN)) { setting_value = (options.switch_1b = 1); setting_disp = OPTIONS_SETTING_DISP; eeprom_write(); } } // // reset gpio edge state // pin_reset(GPIO_UP_BTN, HIGH); pin_reset(GPIO_DW_BTN, HIGH); // // init timer's // thermo_ctrl = TMR0_READ_L() - THERMO_CTRL_INTERVAL; // // display start // blink_start(); } void loop() { uint16_t now = TMR0_READ_L(); int16_t temp; // // read temperature // switch (sensor_type) { default: if (dst_handle()) sensor_type = DSTSENSOR; else if (dht_handle()) sensor_type = DHTSENSOR; else { temperature = 0; humidity = 0; } break; case DSTSENSOR: switch (dst_handle()) { case DSTSENSOR_NO_DEVICE: sensor_type = NO_SENSOR; break; case DSTSENSOR_READY: temperature = dst_temperature(); humidity = 0; break; } break; case DHTSENSOR: switch (dht_handle()) { case DHTSENSOR_NO_DEVICE: sensor_type = NO_SENSOR; break; case DHTSENSOR_READY: temperature = dht_temperature(); humidity = dht_humidity (); break; } break; } temp = (sensor_type == NO_SENSOR ? 0 : (temperature >> 4) + options.calibrate); // // power control // switch (power_mode) { case POWER_OFF: GPIO_THERMO_SW(TRIS) = 1; break; case POWER_ON: GPIO_THERMO_SW(TRIS) = 0; break; default: power_mode = POWER_AUTO; break; } if (TIMEUP16(now, thermo_ctrl, THERMO_CTRL_INTERVAL)) { thermo_ctrl += THERMO_CTRL_INTERVAL; if (power_mode == POWER_AUTO) GPIO_THERMO_SW(TRIS) = (temp < options.threshold ? !options.switch_1b : options.switch_1b); } // // -- threshold (short time press) // switch (pin_detect(GPIO_DW_BTN)) { case LOW: setting_start = now; setting_disp = 0; break; case HIGH: if (!setting_disp) { if (options.threshold > THRESHOLD_MIN) --options.threshold; setting_value = options.threshold; setting_disp = OPTIONS_SETTING_DISP; eeprom_write(); } break; } // // ++ threshold (short time press) // switch (pin_detect(GPIO_UP_BTN)) { case LOW: setting_start = now; setting_disp = 0; break; case HIGH: if (!setting_disp) { if (options.threshold < THRESHOLD_MAX) ++options.threshold; setting_value = options.threshold; setting_disp = OPTIONS_SETTING_DISP; eeprom_write(); } break; } // // option settings // if (!pin_state(GPIO_UP_BTN) || !pin_state(GPIO_DW_BTN)) { uint16_t t = now - setting_start; // // display stop // blink_stop(); // // sensor type setting (simultaneously press DW and UP button) // if (!pin_state(GPIO_UP_BTN) && !pin_state(GPIO_DW_BTN)) setting_mode = SETTING_SENSOR; // // option setting notify blink // GPIO_BOARD_LED(LAT) = !((t >= OPTIONS_SETTING_TIME - TMR0_MS2TICK_L(100)) && (t < OPTIONS_SETTING_TIME)); // // option settings // if (t >= OPTIONS_SETTING_TIME) { setting_start += OPTIONS_SETTING_TIME; // // change of sensor type // if (setting_mode == SETTING_SENSOR) { // not used. } // // ++ calibrate (long time press) // else if (!pin_state(GPIO_UP_BTN)) { if (options.calibrate < CALIBRATE_MAX) ++options.calibrate; setting_value = options.calibrate; setting_disp = OPTIONS_SETTING_DISP; eeprom_write(); } // // -- calibrate (long time press) // else if (!pin_state(GPIO_DW_BTN)) { if (options.calibrate > CALIBRATE_MIN) --options.calibrate; setting_value = options.calibrate; setting_disp = OPTIONS_SETTING_DISP; eeprom_write(); } } } else { // // reset setting mode // setting_mode = SETTING_NONE; // // display start // if (setting_disp == OPTIONS_SETTING_DISP) { --setting_disp; blink_start(); } } // // blink code display // if (blink_next()) { if (setting_disp) { --setting_disp; blink_print(setting_value); } else blink_print(temp); } GPIO_BOARD_LED(LAT) = !blink_handle(); } |
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 |
/* * File: tmr0.h * Author: Sasapea's Lab * * Created on 2018/12/21 */ #ifndef TMR0_H #define TMR0_H #include <xc.h> // include processor files - each processor file is guarded. #include <stdint.h> #ifndef _XTAL_FREQ #define _XTAL_FREQ 48000000 // 48MHz #endif ///////////////////////////////////////////// // Prescaler Setting's (_XTAL_FREQ=48MHz) // // max time(s) period(us) irq-cycle(us)// ///////////////////////////////////////////// // 0: 357.913, 0.083, 21.333 // // 1: 715.827, 0.166, 42.666 // // 2: 431.655, 0.333, 85.333 // // 3: 2863.311, 0.666, 170.666 // // 4: 5726.623, 1.333, 341.333 // // 5: 11453.246, 2.666, 682.666 // // 6: 22906.492, 5.333, 1365.333 // // 7: 45812.984, 10.666, 2730.666 // // 8: 91625.968, 21.333, 5461.333 // ///////////////////////////////////////////// #ifndef TMR0_PS #define TMR0_PS 8 // 0=1/1, 1=1/2, 2=1/4,...8=1/256 #endif #define TMR0_MS2TICK(t) ((t) * (uint32_t)(_XTAL_FREQ / 4 / 1000) / (1 << TMR0_PS)) #define TMR0_US2TICK(t) ((t) * (uint32_t)(_XTAL_FREQ / 4 / 1000000) / (1 << TMR0_PS)) #define TIMEUP8(n, s, d) ((uint8_t )((n) - (s)) >= (d)) #define TIMEUP16(n, s, d) ((uint16_t)((n) - (s)) >= (d)) #define TIMEUP32(n, s, d) ((uint32_t)((n) - (s)) >= (d)) #define TMR0_READ_L() (tmr0_read() >> 8) #define TMR0_MS2TICK_L(t) (TMR0_MS2TICK(t) >> 8) #define TMR0_ISR() do { \ if (INTCONbits.TMR0IF) \ { \ tmr0_isr(); \ INTCONbits.TMR0IF = 0; \ } \ } while (0) #ifdef __cplusplus extern "C" { #endif void tmr0_isr(); void tmr0_init(); uint32_t tmr0_read(); void tmr0_delay(uint32_t millis); #ifdef __cplusplus } #endif #endif // TMR0_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 |
/* * File: tmr0.c * Author: Sasapea's Lab * * Created on 2018/12/21 */ #include "tmr0.h" static volatile uint32_t _counter; void tmr0_isr() { _counter += 0x0100; } void tmr0_init() { OPTION_REGbits.TMR0CS = 0; OPTION_REGbits.PSA = !TMR0_PS; OPTION_REGbits.PS = TMR0_PS - 1; TMR0 = 0; INTCONbits.TMR0IF = 0; INTCONbits.TMR0IE = 1; } uint32_t tmr0_read() { uint32_t c; uint8_t t; do { t = TMR0; c = _counter; } while (t > TMR0); return c | t; } void tmr0_delay(uint32_t tick) { uint32_t t = tmr0_read(); while (!TIMEUP32(tmr0_read(), t, tick)) continue; } |
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 |
/* * File: pwm.h * Author: Sasapea's Lab * * Created on 2018/12/21 */ #ifndef PWM_H #define PWM_H #include <xc.h> // include processor files - each processor file is guarded. #include <stdint.h> #include <stdbool.h> #if defined(_16F1454) || defined(_16F1455) #define PWM_RC5 0 //#define PWM_RC3 1 //#define PWM_RA5 2 #elif defined(_16F1459) #define PWM_RC5 0 #define PWM_RC6 1 #endif #ifdef __cplusplus extern "C" { #endif bool pwm_init(uint8_t ch, uint8_t op); bool pwm_duty(uint8_t ch, uint8_t dc); bool pwm_freq(uint32_t freq); #ifdef __cplusplus } #endif #endif /* PWM_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 |
/* * File: pwm.c * Author: Sasapea's Lab * * Created on 2018/12/21 */ #include "pwm.h" #include "tmr0.h" #if defined(_16F1454) || defined(_16F1455) #if defined(PWM_RC5) #define PWM_P1 #elif defined(PWM_RC3) #define PWM_P2 #elif defined(PWM_RA5) #define PWM_P3 #endif #elif defined(_16F1459) #if defined(PWM_RC5) #define PWM_P1 #elif defined(PWM_RC6) #define PWM_P2 #endif #endif bool pwm_init(uint8_t ch, uint8_t op) { switch (ch) { #if defined(PWM_P3) case 2: if (!APFCONbits.P2SEL && PWM2CONbits.PWM2OE) TRISCbits.TRISC3 = 1; TRISAbits.TRISA5 = 1; APFCONbits.P2SEL = 1; PWM2CON = 0; PWM2DCH = 0; PWM2DCL = 0; PWM2CONbits.PWM2POL = op; PWM2CONbits.PWM2OE = 1; PWM2CONbits.PWM2EN = 1; TRISAbits.TRISA5 = 0; return true; #endif #if defined(PWM_P2) #if defined(_16F1454) || defined(_16F1455) case 1: if (APFCONbits.P2SEL && PWM2CONbits.PWM2OE) TRISAbits.TRISA5 = 1; TRISCbits.TRISC3 = 1; APFCONbits.P2SEL = 0; PWM2CON = 0; PWM2DCH = 0; PWM2DCL = 0; PWM2CONbits.PWM2POL = op; PWM2CONbits.PWM2OE = 1; PWM2CONbits.PWM2EN = 1; TRISCbits.TRISC3 = 0; return true; #elif defined(_16F1459) case 1: TRISCbits.TRISC6 = 1; PWM2CON = 0; PWM2DCH = 0; PWM2DCL = 0; PWM2CONbits.PWM2POL = op; PWM2CONbits.PWM2OE = 1; PWM2CONbits.PWM2EN = 1; TRISCbits.TRISC6 = 0; return true; #endif #endif #if defined(PWM_P1) case 0: TRISCbits.TRISC5 = 1; PWM1CON = 0; PWM1DCH = 0; PWM1DCL = 0; PWM1CONbits.PWM1POL = op; PWM1CONbits.PWM1OE = 1; PWM1CONbits.PWM1EN = 1; TRISCbits.TRISC5 = 0; return true; #endif } return false; } bool pwm_duty(uint8_t ch, uint8_t dc) { uint16_t c; if (dc <= 100) { switch (ch) { #if defined(PWM_P3) case 2: #endif #if defined(PWM_P2) case 1: #endif #if defined(PWM_P2) || defined(PWM_P3) c = ((((uint32_t)PR2 + 1) << _PWM2DCL_PWM2DCL_SIZE) * dc + 50) / 100; PWM2DCHbits.PWM2DCH = c >> _PWM2DCL_PWM2DCL_SIZE; PWM2DCLbits.PWM2DCL = c; return true; #endif #if defined(PWM_P1) case 0: c = ((((uint32_t)PR2 + 1) << _PWM1DCL_PWM1DCL_SIZE) * dc + 50) / 100; PWM1DCHbits.PWM1DCH = c >> _PWM1DCL_PWM1DCL_SIZE; PWM1DCLbits.PWM1DCL = c; return true; #endif } } return false; } bool pwm_freq(uint32_t freq) { uint32_t pr = freq ? ((_XTAL_FREQ * 10 / 4) / freq + 5) / 10 : 0; uint8_t ps; for (ps = 0; pr > 0x0100; ++ps) pr >>= _T2CON_T2CKPS_SIZE; if (pr && (ps < (1 << _T2CON_T2CKPS_SIZE))) { T2CONbits.TMR2ON = 0; PIE1bits.TMR2IE = 0; PIR1bits.TMR2IF = 0; T2CON = 0; TMR2 = 0; PR2 = pr - 1; T2CONbits.T2CKPS = ps; T2CONbits.TMR2ON = 1; return true; } return false; } |
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 |
/* * File: pin_edge.h * Author: Sasapea's Lab * * Created on 2018/12/21 */ #ifndef PINEDGE_H #define PINEDGE_H #include <xc.h> // include processor files - each processor file is guarded. #include <stdint.h> #include <stdbool.h> #define GPIO_DW_BTN 0x01, RA5 #define GPIO_UP_BTN 0x02, RA4 #define LOW 0 #define HIGH 1 #define UNCHANGED 0xFF #ifdef __cplusplus extern "C" { #endif void pin_init(); void pin_reset(uint8_t mask, uint8_t data, uint8_t inival); uint8_t pin_state(uint8_t mask, uint8_t data); uint8_t pin_detect(uint8_t mask, uint8_t data); #ifdef __cplusplus } #endif #endif /* PINEDGE_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 |
/* * File: pin_edge.c * Author: Sasapea's Lab * * Created on 2018/12/21 */ #include <string.h> #include "tmr0.h" #include "pin_edge.h" #define CHATTERING TMR0_MS2TICK(20) static uint8_t _flags; static uint8_t _state; static uint8_t _check; static uint16_t _start; void pin_init() { ANSELA = 0; TRISA4 = 1; TRISA5 = 1; WPUA4 = 1; WPUA5 = 1; pin_reset(GPIO_UP_BTN, UNCHANGED); pin_reset(GPIO_DW_BTN, UNCHANGED); } void pin_reset(uint8_t mask, uint8_t data, uint8_t inival) { _check &= ~mask; if (data) { _flags |= mask; _state |= mask; } else { _flags &= ~mask; _state &= ~mask; } if (inival == HIGH) _state |= mask; else if (inival == LOW) _state &= ~mask; } uint8_t pin_state(uint8_t mask, uint8_t data) { return _state & mask ? HIGH : LOW; } uint8_t pin_detect(uint8_t mask, uint8_t data) { uint16_t now = tmr0_read(); if ((_flags ^ (data ? mask : 0)) & mask) { _flags ^= mask; _check |= mask; _start = now; } else if ((_check & mask) && (TIMEUP16(now, _start, CHATTERING))) { _check &= ~mask; if ((_state ^ _flags) & mask) return (_state ^= mask) & mask ? HIGH : LOW; } return UNCHANGED; } |
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 |
/* * File: one_wire.h * Author: Sasapea's Lab * * Created on 2018/12/21 */ #ifndef ONEWIRE_H #define ONEWIRE_H #include <xc.h> // include processor files - each processor file is guarded. #include <stdint.h> #include <stdbool.h> #define PARASITE_POWER 0 #ifdef __cplusplus extern "C" { #endif bool ow_reset(); void ow_write_bit(uint8_t b); uint8_t ow_read_bit(); void ow_write(uint8_t b, bool parasite); void ow_write_bytes(const uint8_t *buf, uint8_t len, bool parasite); uint8_t ow_read(); void ow_read_bytes(uint8_t *buf, uint8_t len); void ow_skip(); uint8_t ow_crc8(const uint8_t *buf, uint8_t len); #ifdef __cplusplus } #endif #endif /* ONEWIRE_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 |
/* * File: one_wire.c * Author: Sasapea's Lab * * Created on 2018/12/21 */ #include "tmr0.h" #include "one_wire.h" #define CONCAT(r, p) r##p #define ONEWIRE(r) CONCAT(r, C2) bool ow_reset() { uint8_t r, retries = 125; ONEWIRE(ANS) = 0; // DIGITAL ONEWIRE(TRIS) = 1; // INPUT // wait until the wire is high... just in case while (!ONEWIRE(R)) { if (--retries == 0) return false; __delay_us(2); } ONEWIRE(LAT) = 0; // LOW ONEWIRE(TRIS) = 0; // OUTPUT __delay_us(480); di(); ONEWIRE(TRIS) = 1; // INPUT __delay_us(70); r = ONEWIRE(R); // READ ei(); __delay_us(410); return r ^ ONEWIRE(R); } void ow_write_bit(uint8_t b) { #if PARASITE_POWER ONEWIRE(LAT) = 0; // LOW #endif di(); ONEWIRE(TRIS) = 0; // OUTPUT if (b) { __delay_us(10); #if PARASITE_POWER ONEWIRE(LAT) = 1; // HIGH #else ONEWIRE(TRIS) = 1; // INPUT #endif ei(); __delay_us(55); } else { __delay_us(65); #if PARASITE_POWER ONEWIRE(LAT) = 1; // HIGH #else ONEWIRE(TRIS) = 1; // INPUT #endif ei(); __delay_us(5); } } uint8_t ow_read_bit() { uint8_t r; #if PARASITE_POWER ONEWIRE(LAT) = 0; // LOW #endif di(); ONEWIRE(TRIS) = 0; // OUTPUT __delay_us(3); ONEWIRE(TRIS) = 1; // INPUT __delay_us(10); r = ONEWIRE(R); // READ ei(); __delay_us(53); return r; } void ow_write(uint8_t b, bool parasite) { uint8_t bitMask; for (bitMask = 0x01; bitMask; bitMask <<= 1) ow_write_bit(b & bitMask); #if PARASITE_POWER if (!parasite) ONEWIRE(TRIS) = 1; // INPUT #endif } void ow_write_bytes(const uint8_t *buf, uint8_t len, bool parasite) { while (len--) ow_write(*buf++, true); #if PARASITE_POWER if (!parasite) ONEWIRE(TRIS) = 1; // INPUT #endif } uint8_t ow_read() { uint8_t bitMask; uint8_t r = 0; for (bitMask = 0x01; bitMask; bitMask <<= 1) { if (ow_read_bit()) r |= bitMask; } return r; } void ow_read_bytes(uint8_t *buf, uint8_t len) { while (len--) *buf++ = ow_read(); } void ow_skip() { ow_write(0xCC, false); } static const uint8_t CRC_L[] = { 0x00, 0x5E, 0xBC, 0xE2, 0x61, 0x3F, 0xDD, 0x83, 0xC2, 0x9C, 0x7E, 0x20, 0xA3, 0xFD, 0x1F, 0x41, }; static const uint8_t CRC_H[] = { 0x00, 0x9D, 0x23, 0xBE, 0x46, 0xDB, 0x65, 0xF8, 0x8C, 0x11, 0xAF, 0x32, 0xCA, 0x57, 0xE9, 0x74 }; uint8_t ow_crc8(const uint8_t *buf, uint8_t len) { uint8_t crc = 0; while (len--) { crc ^= *buf++; crc = CRC_L[crc & 0x0F] ^ CRC_H[(crc >> 4) & 0x0F]; } return crc; } |
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 |
/* * File: dstsensor.h * Author: Sasapea's Lab * * Created on 2018/12/21 */ #ifndef DSTSENSOR_H #define DSTSENSOR_H #include <xc.h> // include processor files - each processor file is guarded. #include <stdint.h> #include <stdbool.h> #include "one_wire.h" // Status #define DSTSENSOR_NO_DEVICE 0 #define DSTSENSOR_BUSY 1 #define DSTSENSOR_READY 2 typedef struct { int8_t th_reg_or_ub1; int8_t tl_reg_or_ub2; int8_t configuration; } DSTempConfig; #ifdef __cplusplus extern "C" { #endif void dst_init(); bool dst_get_config(DSTempConfig *config); bool dst_set_config(DSTempConfig *config, bool update); int16_t dst_temperature(); uint8_t dst_handle(); #ifdef __cplusplus } #endif #endif /* DSTSENSOR_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 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 |
/* * File: dstsensor.c * Author: Sasapea's Lab * * Created on 2018/12/21 */ #include <string.h> #include "dstsensor.h" #include "tmr0.h" #define CONVERSION_RESPONSE 0 // Device resolution #define DSTSENSOR_9BIT 0x00 #define DSTSENSOR_10BIT 0x20 #define DSTSENSOR_11BIT 0x40 #define DSTSENSOR_12BIT 0x60 // Model IDs #define DSTSENSOR_DS18S20 0x10 // also DS1820 #define DSTSENSOR_DS18B20 0x28 #define DSTSENSOR_DS1822 0x22 #define DSTSENSOR_DS1825 0x3B #define DSTSENSOR_DS28EA00 0x42 // OneWire commands #define DSTSENSOR_READROM 0x33 #define DSTSENSOR_STARTCONV 0x44 #define DSTSENSOR_WRITESCRATCH 0x4E #define DSTSENSOR_READSCRATCH 0xBE #define DSTSENSOR_COPYSCRATCH 0x48 #define DSTSENSOR_READPOWERSUPPLY 0xB4 #define DSTSENSOR_SAMPLING_PERIOD TMR0_MS2TICK_L(2000) typedef struct { uint8_t family_code; uint8_t searial[6]; uint8_t crc; } DSTempRomAddress; typedef struct { uint8_t temp_lsb; uint8_t temp_msb; uint8_t th_reg_or_ub1; uint8_t tl_reg_or_ub2; uint8_t configuration; uint8_t internal_byte; uint8_t count_remain; uint8_t count_per_c; uint8_t crc; } DSTempScratchPad; DSTempRomAddress _romAddress; static DSTempScratchPad _scratchPad; static uint8_t _status; static bool _parasite; static int16_t _temperature; static uint16_t _convertTime; static uint16_t _cvStartTime; static uint16_t _cvDelayTime; static uint16_t _nextSampling; static bool isDS18S20() { return (_romAddress.family_code == DSTSENSOR_DS18S20); } static int8_t getResolution() { return (isDS18S20() ? DSTSENSOR_12BIT : _scratchPad.configuration); } static void setup() { switch (getResolution() & DSTSENSOR_12BIT) { case DSTSENSOR_9BIT: _convertTime = TMR0_MS2TICK(94); break; case DSTSENSOR_10BIT: _convertTime = TMR0_MS2TICK(188); break; case DSTSENSOR_11BIT: _convertTime = TMR0_MS2TICK(375); break; case DSTSENSOR_12BIT: default: _convertTime = TMR0_MS2TICK(750); break; } } static bool readRomAddress() { if (ow_reset()) { ow_write(DSTSENSOR_READROM, false); ow_read_bytes((uint8_t *)&_romAddress, sizeof(_romAddress)); if (ow_crc8((uint8_t *)&_romAddress, sizeof(_romAddress) - sizeof(_romAddress.crc)) == _romAddress.crc) { if ( (_romAddress.family_code == DSTSENSOR_DS18S20 ) || (_romAddress.family_code == DSTSENSOR_DS18B20 ) || (_romAddress.family_code == DSTSENSOR_DS1822 ) || (_romAddress.family_code == DSTSENSOR_DS1825 ) || (_romAddress.family_code == DSTSENSOR_DS28EA00)) return true; } } return false; } static bool readPowerSupply() { if (ow_reset()) { ow_skip(); ow_write(DSTSENSOR_READPOWERSUPPLY, false); _parasite = (ow_read_bit() == 0); #if PARASITE_POWER return true; #else return !_parasite; #endif } return false; } static bool readScratchPad() { if (ow_reset()) { ow_skip(); ow_write(DSTSENSOR_READSCRATCH, false); ow_read_bytes((uint8_t *)&_scratchPad, sizeof(_scratchPad)); if (ow_crc8((uint8_t *)&_scratchPad, sizeof(_scratchPad) - sizeof(_scratchPad.crc)) == _scratchPad.crc) { setup(); return true; } } return false; } static bool writeScratchPad() { if (ow_reset()) { ow_skip(); ow_write(DSTSENSOR_WRITESCRATCH, false); ow_write(_scratchPad.th_reg_or_ub1, false); ow_write(_scratchPad.tl_reg_or_ub2, false); if (!isDS18S20()) ow_write(_scratchPad.configuration, false); setup(); return true; } return false; } static bool copyScratchPad() { if (ow_reset()) { ow_skip(); ow_write(DSTSENSOR_COPYSCRATCH, _parasite); if (_parasite) tmr0_delay(TMR0_MS2TICK(10)); } return false; } static bool startConversion() { if (ow_reset()) { ow_skip(); ow_write(DSTSENSOR_STARTCONV, _parasite); return true; } return false; } #if CONVERSION_RESPONSE static bool isConversionComplete() { return _parasite ? false : ow_read_bit(); } #endif static bool connect() { if (_status == DSTSENSOR_NO_DEVICE) { if (!readRomAddress()) return false; if (!readPowerSupply()) return false; if (!readScratchPad()) return false; _status = DSTSENSOR_BUSY; _cvDelayTime = 0; } return true; } void dst_init() { _status = DSTSENSOR_NO_DEVICE; _nextSampling = TMR0_READ_L(); } bool dst_get_config(DSTempConfig *config) { if (connect()) { config->th_reg_or_ub1 = _scratchPad.th_reg_or_ub1; config->tl_reg_or_ub2 = _scratchPad.tl_reg_or_ub2; config->configuration = getResolution(); return true; } return false; } bool dst_set_config(DSTempConfig *config, bool update) { DSTempConfig _save; if (dst_get_config(&_save)) { if (isDS18S20()) { if (config->configuration != DSTSENSOR_12BIT) return false; } else { if ((config->configuration < DSTSENSOR_9BIT) || (config->configuration > DSTSENSOR_12BIT)) return false; } if (memcmp(&config, &_save, sizeof(_save)) == 0) return true; _scratchPad.th_reg_or_ub1 = config->th_reg_or_ub1; _scratchPad.tl_reg_or_ub2 = config->tl_reg_or_ub2; _scratchPad.configuration = config->configuration | (_scratchPad.configuration & ~DSTSENSOR_12BIT); if (writeScratchPad()) return (update ? copyScratchPad() : true); _scratchPad.th_reg_or_ub1 = _save.th_reg_or_ub1; _scratchPad.tl_reg_or_ub2 = _save.tl_reg_or_ub2; _scratchPad.configuration = _save.configuration; } return false; } int16_t dst_temperature() { return _temperature; } uint8_t dst_handle() { if ((_status == DSTSENSOR_BUSY) && _cvDelayTime) { if (_cvDelayTime) { #if CONVERSION_RESPONSE if (TIMEUP16(tmr0_read(), _cvStartTime, _cvDelayTime) || isConversionComplete()) #else if (TIMEUP16(tmr0_read(), _cvStartTime, _cvDelayTime)) #endif { _cvDelayTime = 0; if (!readScratchPad()) return _status = DSTSENSOR_NO_DEVICE; _temperature = ((int16_t)_scratchPad.temp_msb << 8) | _scratchPad.temp_lsb; if (isDS18S20()) _temperature = ((_temperature & 0xFFFE) << 3) - 2 + ((_scratchPad.count_per_c - _scratchPad.count_remain) << 4) / _scratchPad.count_per_c; _status = DSTSENSOR_READY; } } } else if (TIMEUP16(TMR0_READ_L(), _nextSampling, DSTSENSOR_SAMPLING_PERIOD)) { _nextSampling += DSTSENSOR_SAMPLING_PERIOD; if (connect()) { if (!startConversion()) return _status = DSTSENSOR_NO_DEVICE; _cvDelayTime = _convertTime; _cvStartTime = tmr0_read(); _status = DSTSENSOR_BUSY; } } else if (_status == DSTSENSOR_READY) _status = DSTSENSOR_BUSY; return _status; } |
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 |
/* * File: dhtsensor.h * Author: Sasapea's Lab * * Created on 2018/12/21 */ #ifndef DHTSENSOR_H #define DHTSENSOR_H #include <xc.h> // include processor files - each processor file is guarded. #include <stdint.h> #include <stdbool.h> // // Status // #define DHTSENSOR_NO_DEVICE 0 #define DHTSENSOR_BUSY 1 #define DHTSENSOR_READY 2 // // Sensor Type // #define DHTSENSOR_DHT11 0 #define DHTSENSOR_DHT21 1 #define DHTSENSOR_DHT22 2 #define DHTSENSOR_AM2301 DHTSENSOR_DHT21 #define DHTSENSOR_AM2302 DHTSENSOR_DHT22 #ifdef __cplusplus extern "C" { #endif void dht_init(uint8_t type); int16_t dht_temperature(); int16_t dht_humidity(); uint8_t dht_handle(); #ifdef __cplusplus } #endif #endif /* DHTSENSOR_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 |
/* * File: dhtsensor.c * Author: Sasapea's Lab * * Created on 2018/12/21 */ #include "dhtsensor.h" #include "tmr0.h" #define CONCAT(r, p) r##p #define DHTSENSOR(r) CONCAT(r, C2) #define LOW 0 #define HIGH 1 #define DHTSENSOR_SAMPLING_PERIOD TMR0_MS2TICK_L(2000) static uint8_t _type; static uint8_t _status; static uint16_t _humidity; static uint16_t _temperature; static uint16_t _nextSempling; static uint8_t _data[5]; static uint8_t waitSignal(uint8_t state) { for (uint8_t i = 0; i < 255; ++i) { if (DHTSENSOR(R) == state) return i; } return 0xFF; } static bool readResponse() { uint8_t lo; if (waitSignal(LOW) == 0xFF) return false; ei(); di(); if (waitSignal(HIGH) == 0xFF) return false; if ((lo = waitSignal(LOW)) == 0xFF) return false; lo = (lo >> 1) + (lo >> 3); // // Recieve bit data // for (uint8_t i = 0; i < sizeof(_data) << 3; ++i) { uint8_t hi, off; ei(); di(); if (waitSignal(HIGH) == 0xFF) return false; if ((hi = waitSignal(LOW)) == 0xFF) return false; off = i >> 3; _data[off] <<= 1; if (lo < hi) _data[off] |= 1; } return true; } static bool read() { bool rv; // // Start signal // DHTSENSOR(LAT) = 0; // LOW DHTSENSOR(TRIS) = 0; // OUTPUT __delay_ms(1); // // Read response // di(); DHTSENSOR(TRIS) = 1; // INPUT rv = readResponse(); ei(); // // Check SUM // if (!rv || ((uint8_t)(_data[0] + _data[1] + _data[2] + _data[3]) != _data[4])) return false; // // Temperature (x16) and Humidity (x16) // switch (_type) { case DHTSENSOR_DHT11: _humidity = (uint16_t)_data[0] << 4; _temperature = (uint16_t)_data[2] << 4; break; case DHTSENSOR_DHT22: case DHTSENSOR_DHT21: _humidity = ((((uint16_t) _data[0] << 8) | _data[1]) << 4) / 10; _temperature = ((((uint16_t)(_data[2] & 0x7F) << 8) | _data[3]) << 4) / 10; if (_data[2] & 0x80) _temperature = - _temperature; break; } return true; } void dht_init(uint8_t type) { DHTSENSOR(ANS) = 0; // DIGITAL DHTSENSOR(TRIS) = 1; // INPUT _type = type; _status = DHTSENSOR_NO_DEVICE; _nextSempling = TMR0_READ_L(); } int16_t dht_temperature() { return _temperature; } int16_t dht_humidity() { return _humidity; } uint8_t dht_handle() { if (TIMEUP16(TMR0_READ_L(), _nextSempling, DHTSENSOR_SAMPLING_PERIOD)) { _nextSempling += DHTSENSOR_SAMPLING_PERIOD; _status = read() ? DHTSENSOR_READY : DHTSENSOR_NO_DEVICE; } else if (_status == DHTSENSOR_READY) _status = DHTSENSOR_BUSY; return _status; } |
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 |
/* * File: blink_code.h * Author: Sasapea's Lab * * Created on 2018/12/21 */ #ifndef BLINKCODE_H #define BLINKCODE_H #include <xc.h> // include processor files - each processor file is guarded. #include <stdint.h> #include <stdbool.h> #ifdef __cplusplus extern "C" { #endif void blink_init(); void blink_print(int8_t value); void blink_start(); void blink_stop(); bool blink_next(); bool blink_handle(); #ifdef __cplusplus } #endif #endif /* BLINKCODE_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 |
/* * File: blink_code.c * Author: Sasapea's Lab * * Created on 2018/12/21 */ #include "tmr0.h" #include "blink_code.h" #define DOT TMR0_MS2TICK_L(220) static uint16_t _start; static uint16_t _nspan; static uint16_t _elaps; static bool _ncall; static bool _output; static int8_t _state; static int8_t _data; void blink_init() { _nspan = 0; blink_start(); } void blink_print(int8_t value) { if ((_state == 0) || (_state == 3)) { _state = 0; _data = value; } } void blink_start() { _ncall = false; _output = false; _state = 3; } void blink_stop() { if (_state != -1) { if ((_state != 0) && (_state != 3)) _nspan = DOT * 7; _state = -1; _output = false; } } bool blink_next() { uint16_t now = TMR0_READ_L(); _ncall = true; if ((_elaps = now - _start) >= _nspan) { if (_nspan) _start += _nspan; else _start = now; return (_state == 0) || (_state == 3); } return false; } bool blink_handle() { if (!_ncall) blink_next(); _ncall = false; if (_elaps >= _nspan) { if (!_output) { switch (_state) { case 0: if (_data <= 0) { _output = true; _state = 2; _data = -_data; _nspan = DOT >> 2; break; } case 1: if (_data < 10) { _data -= 1; _nspan = DOT; } else { _data -= 10; _nspan = DOT * 3; } case 2: _output = true; _state = 1; break; case 3: _nspan = 0; break; } } else { _output = false; if (_state == 1) { if (_data) _nspan = DOT; else { _state = 3; _nspan = DOT * 7; } } } } return _output; } |
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 |
/******************************************************************************* Copyright 2016 Microchip Technology Inc. (www.microchip.com) Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. To request to license the code under the MLA license (www.microchip.com/mla_license), please contact mla_licensing@microchip.com *******************************************************************************/ #include "system.h" #include "usb.h" #include "tmr0.h" /** CONFIGURATION Bits **********************************************/ // PIC16F1459 configuration bit settings: #if defined (USE_INTERNAL_OSC) // Define this in system.h if using the HFINTOSC for USB operation // CONFIG1 #pragma config FOSC = INTOSC // Oscillator Selection Bits (INTOSC oscillator: I/O function on CLKIN pin) #pragma config WDTE = ON // Watchdog Timer Enable (WDT disabled) #pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled) #pragma config MCLRE = OFF // MCLR Pin Function Select (MCLR/VPP pin function is digital input) #pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled) #pragma config BOREN = ON // Brown-out Reset Enable (Brown-out Reset enabled) #pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin) #pragma config IESO = OFF // Internal/External Switchover Mode (Internal/External Switchover Mode is disabled) #pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is disabled) // CONFIG2 #pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off) #pragma config CPUDIV = NOCLKDIV// CPU System Clock Selection Bit (NO CPU system divide) #pragma config USBLSCLK = 48MHz // USB Low SPeed Clock Selection bit (System clock expects 48 MHz, FS/LS USB CLKENs divide-by is set to 8.) #pragma config PLLMULT = 3x // PLL Multipler Selection Bit (3x Output Frequency Selected) #pragma config PLLEN = ENABLED // PLL Enable Bit (3x or 4x PLL Enabled) #pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset) #pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.) #pragma config LPBOR = OFF // Low-Power Brown Out Reset (Low-Power BOR is disabled) #pragma config LVP = OFF // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming) #else // CONFIG1 #pragma config FOSC = HS // Oscillator Selection Bits (HS Oscillator, High-speed crystal/resonator connected between OSC1 and OSC2 pins) #pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled) #pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled) #pragma config MCLRE = OFF // MCLR Pin Function Select (MCLR/VPP pin function is digital input) #pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled) #pragma config BOREN = ON // Brown-out Reset Enable (Brown-out Reset enabled) #pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin) #pragma config IESO = OFF // Internal/External Switchover Mode (Internal/External Switchover Mode is disabled) #pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is disabled) // CONFIG2 #pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off) #pragma config CPUDIV = NOCLKDIV// CPU System Clock Selection Bit (NO CPU system divide) #pragma config USBLSCLK = 48MHz // USB Low SPeed Clock Selection bit (System clock expects 48 MHz, FS/LS USB CLKENs divide-by is set to 8.) #pragma config PLLMULT = 4x // PLL Multipler Selection Bit (4x Output Frequency Selected) #pragma config PLLEN = ENABLED // PLL Enable Bit (3x or 4x PLL Enabled) #pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset) #pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.) #pragma config LPBOR = OFF // Low-Power Brown Out Reset (Low-Power BOR is disabled) #pragma config LVP = OFF // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming) #endif /********************************************************************* * Function: void SYSTEM_Initialize( SYSTEM_STATE state ) * * Overview: Initializes the system. * * PreCondition: None * * Input: SYSTEM_STATE - the state to initialize the system into * * Output: None * ********************************************************************/ void SYSTEM_Initialize( SYSTEM_STATE state ) { switch(state) { case SYSTEM_STATE_USB_START: #if defined(USE_INTERNAL_OSC) //Make sure to turn on active clock tuning for USB full speed //operation from the INTOSC OSCCON = 0xFC; //HFINTOSC @ 16MHz, 3X PLL, PLL enabled ACTCON = 0x90; //Active clock tuning enabled for USB #endif break; case SYSTEM_STATE_USB_SUSPEND: break; case SYSTEM_STATE_USB_RESUME: break; } } void interrupt SYS_InterruptHigh(void) { #if defined(USB_INTERRUPT) USBDeviceTasks(); #endif #if defined(TMR0_ISR) TMR0_ISR(); #endif } |
その他、[Microchip:mla][USB Device – CDC – Basic]に含まれる下記ソースが必要。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
system.h fixed_address_memory.h usb.h usb_ch9.h usb_common.h usb_config.h usb_descriptors.c usb_device.h usb_device.c usb_device_cdc.h usb_device_cdc.c usb_device_local.h usb_events.c usb_hal.h usb_hal_pic16f1.h |
下記ソースも必要。
1 2 3 4 |
HEFFlash.h HEFFlash.c Flash.h Flash.c |
コード領域の最後の1ページをeeprom代わりに使用しているためブロジェクトのプロパティページにて次の設定が必要。
PC側で動作するコマンドライン・ツールのサンプルコード。windowsはmingw、linuxはgccでコンパイルする。参考まで。
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 |
/** * Command Utility for ThemoSW-PIC * * 2018 Writen by Sasapea's Lab. * / * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__) #define __WINDOWS__ #endif #ifdef __WINDOWS__ #include <windows.h> #include <fcntl.h> #define O_NOCTTY 0 #else #include <termios.h> #include <sys/time.h> #include <sys/types.h> #include <unistd.h> #endif #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <stdint.h> #include <string.h> #include <errno.h> #include <fcntl.h> // // Device Command // #define buff_GET_SENSOR_DATA 0 #define buff_SET_POWER_MODE 1 #define buff_SET_PWM_MODE 2 // // Power Mode // #define POWER_OFF 0 #define POWER_ON 1 #define POWER_AUTO 2 int main(int argc, char **argv) { int exitcode = 1; int help = false; int fd, rv, i, len; char buff[256] = {1, buff_GET_SENSOR_DATA}; char port[256] = ""; for (i = 1; i < argc; ) { char *p = argv[i++]; if (*p == '-') { ++p; if (strcmp(p, "power") == 0) { if (i >= argc) help = true; else { buff[0] = 2; buff[1] = buff_SET_POWER_MODE; p = argv[i++]; if (strcmp(p, "off") == 0) buff[2] = POWER_OFF; else if (strcmp(p, "on") == 0) buff[2] = POWER_ON; else if (strcmp(p, "auto") == 0) buff[2] = POWER_AUTO; else help = true; } } else if (strcmp(p, "pwm") == 0) { if (i + 1 >= argc) help = true; else { buff[0] = 6; buff[1] = buff_SET_PWM_MODE; *(int32_t *)&buff[2] = atoi(argv[i++]); buff[6] = atoi(argv[i++]); } } else help = true; } else if (!port[0]) #ifdef __WINDOWS__ sprintf(port, "\\\\.\\%s", p); #else sprintf(port, "/dev/%s", p); #endif else help = true; } if (help || !port[0]) { printf("Command Utility for ThemoSW-PIC, Version 1.0\n"); printf("2018 Writen by Sasapea's Lab.\n"); printf("\n"); printf("Usage: themosw port-name [options]\n"); printf("\n"); printf("options: -power {off|on|auto} ... set power mode\n"); printf(" -pwm freq duty ... set pwm mode (freq=Hz, duty=0-100%%)\n"); return exitcode; } if ((fd = open(port, O_RDWR | O_NOCTTY)) == -1) printf("[ERROR] open(\"%s\"): %s\n", port, strerror(errno)); else { #ifdef __WINDOWS__ COMMTIMEOUTS timeout; memset(&timeout, 0, sizeof(timeout)); timeout.ReadTotalTimeoutConstant = 1000; timeout.WriteTotalTimeoutConstant = 1000; SetCommTimeouts((HANDLE)_get_osfhandle(fd), &timeout); #else struct termios tios, save; tcgetattr(fd, &tios); save = tios; cfmakeraw(&tios); tcsetattr(fd, TCSANOW, &tios); tcflush(fd, TCIOFLUSH); #endif if ((rv = write(fd, buff, buff[0] + 1)) == -1) printf("[ERROR] write(): %s\n", strerror(errno)); else if (rv != buff[0] + 1) printf("[ERROR] write size (%d) < (%d)\n", rv, buff[0] + 1); else { for (len = buff[0] = 0; len < (unsigned char)buff[0] + 1; ++len) { #ifndef __WINDOWS__ fd_set readfds; struct timeval timeout; timeout.tv_sec = 1; timeout.tv_usec = 0; FD_ZERO(&readfds); FD_SET(fd, &readfds); if ((rv = select(fd + 1, &readfds, NULL, NULL, &timeout)) < 0) printf("[ERROR] select(): %s\n", strerror(errno)); else if (rv == 0) printf("[ERROR] timeout\n"); else #endif if ((rv = read(fd, buff + len, 1)) == -1) { printf("[ERROR] read(): %s\n", strerror(errno)); break; } else if (rv != 1) { printf("[ERROR] read size (%d) < (1)\n", rv); break; } } if (rv <= 0) ; else if ((len < 3) || (len != buff[0] + 1)) printf("[ERROR] invalid response\n"); else if (buff[2]) printf("[ERROR] device return code: (%d)\n", buff[2]); else { if (buff[1] == buff_GET_SENSOR_DATA) { if (*(short *)&buff[5]) printf("%.2f C, %.2f %%\n", *(short *)&buff[3] / 16.0, *(short *)&buff[5] / 16.0); else printf("%.2f C\n", *(short *)&buff[3] / 16.0); } exitcode = 0; } } #ifndef __WINDOWS__ tcsetattr(fd, TCSANOW, &save); #endif close(fd); } return exitcode; } |