自作PCのUSB電源が常にオン状態であるためUSB機器との電源連動ができなくて困っていた。市販のPC電源連動型ハブも試して見たが駄目。しょうがないので自作してみた。
aitendoのUSB2.0-HUBチップFE1.1S(100円)と秋月電子のPIC16F1454(130円)を使い、FE1.1Sの4ポートあるうちの一つをPIC16F1454に直結、1ポートを未使用、残りの2ポートを外部機器用とするバスパワー動作の2ポートハブ構成としてみた。
外部機器側のUSB電源はPC電源ON後のBIOS或いはOS起動中にONになりシャットダウン中にオフになる。
PIC16F1454はCDC-ACMとして構成されておりWindows/Linuxの標準デバイスドライバーのみで動作する。そのUSBステータスを判断することにより電源制御している。実装はしてないがPCとの通信が仮想COMポート経由で可能なことからPCアプリからUSBの電源制御を行うことも可能だ。以外に便利かもしれない...
回路はこんな感じ。
プログラムはMicrochipのPIC16F145X用の[USB Device – CDC – Basic]サンプルコードから今回の目的には必要のないbuttons.c/h, leds.c/hを削除したうえで使用。
2018-06-29
system.cにタイマー割り込み処理を追加しないといけないのに公開するのを忘れてたので今更ながら公開。最初の#include “tmr0.h”と、最後のTMR0_ISR()だけ追加すれば良い。
ついでに改良版も投稿したのでどうぞ!
Microchip PIC16F1454 PC電源連動型USB-HUBを改良してみた。
2018-05-18
UEFI起動のPCの場合、USBデバイスは、UEFI起動中に一旦接続&切断され、その後のOS起動時に再度接続されるのだが正常に接続されない場合があった。USBデバイスの状態が不正になってるようなので、USBデバイス側から非アクティブになったときにUSBを切断&一定時間後に再接続するようにしてみた。
暫く様子を見ていたが問題ないようなので変更後のソースを公開。
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 |
/******************************************************************************* 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 *******************************************************************************/ /** INCLUDES *******************************************************/ #include "system.h" #include "tmr0.h" #include "usb.h" #include "usb_device.h" #include "usb_device_cdc.h" /******************************************************************** * Function: void main(void) * * PreCondition: None * * Input: None * * Output: None * * Side Effects: None * * Overview: Main program entry point. * * Note: None *******************************************************************/ #define PORTBIT(r, f, x, n) r##x##bits.##f##x##n #define BOARD_LED(r) PORTBIT(r, r, C, 3) #define POWER_OUT(r) PORTBIT(r, r, A, 5) MAIN_RETURN main(void) { uint32_t led, usb = 0; bool power = false; SYSTEM_Initialize(SYSTEM_STATE_USB_START); USBDeviceInit(); USBDeviceAttach(); BOARD_LED(TRIS) = 0; // LED OUTPUT POWER_OUT(TRIS) = 1; // PWR OUTPUT POWER_OUT(LAT) = 0; // tmr0_init(); led = tmr0_read(); while(1) { // // Read TMR0 // uint32_t now = tmr0_read(); // // Check USB State // bool active = !USBIsDeviceSuspended() && (USBGetDeviceState() == CONFIGURED_STATE); if (power != active) { power = active; // // Power Control // POWER_OUT(TRIS) = !power; // // Detach USB // if (!power) { usb = now; USBDeviceDetach(); } } // // Attach USB // else if (usb) { if (now - usb >= TMR0_MS2TICK(5000)) { usb = 0; USBDeviceAttach(); } } // // Blink LED // if (now - led >= TMR0_MS2TICK(1000)) { led += TMR0_MS2TICK(1000); if(active) BOARD_LED(LAT) ^= 1; } else if (!active) { BOARD_LED(LAT) = (now - led >= TMR0_MS2TICK(10)); } SYSTEM_Tasks(); #if defined(USB_POLLING) // Interrupt or polling method. If using polling, must call // this function periodically. This function will take care // of processing and responding to SETUP transactions // (such as during the enumeration process when you first // plug in). USB hosts require that USB devices should accept // and process SETUP packets in a timely fashion. Therefore, // when using polling, this function should be called // regularly (such as once every 1.8ms or faster** [see // inline code comments in usb_device.c for explanation when // "or faster" applies]) In most cases, the USBDeviceTasks() // function does not take very long to execute (ex: <100 // instruction cycles) before it returns. USBDeviceTasks(); #endif }//end while }//end main /******************************************************************************* End of File */ |
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 |
/******************************************************************************* 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 = 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 = 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 // // TIMER0 // TMR0_ISR(); } |