Digispark 16.5MHzの謎に迫る [Arduino]
Digispark は V-USBのとき、16MHzではなく16.5MHzと気持ち(3%ほど)速めの設定になっています。
USBの処理のために3%ほど速くしてくれているのだと思います。(たぶん)
そもそもATtiny85は、外部クリスタルなしでは8MHzなのですが、そこからいろいろあって16MHzや16.5MHzを作りだしているようです。
そのあたりを調べてみました。
まずfuse。
工場出荷時と異なるのは、、
・Fuse Extended Byte
Self-programming enabledが、1→0で自己プログラミング機能が許可されています。
USBから書き込めるということでこれは当然。
・Fuse Low Byte
7ビット目のCKDIV8と、3~0ビット目のCKSEL3~CKSEL0が変更されています。
CKDIV8 は、0→1となり、システムクロックの8分周はしないということでこれも当然。
CKSEL3~CKSEL0 を CKSEL[3:0] 0001 に設定することで、
Clock source setting を High Frequency PLL Clock として、divided by four として、16MHz にしているようです。
つづいてRegister。
クロックに関係しそうなのは、CLKPR, PLLCSR, OSCCALです。
手持ちのDigisparkに以下のスケッチを書き込み、LEDの点灯時間を目視で確認することでこれらのレジスタの値を調べました。
・0x26 CLKPR (Clock Prescale Register)
CLKPS[3:0] Clock Division Factor のところで16MHz, 16.5MHz時は、分周なし(1分周), 8MHz時は2分周, 1MHz時は16分周となっていました。
・0x27 PLLCSR (PLL Control and Status Register)
Bit 7 – LSM: Low Speed Mode(32MHz) はそのまま 0 で高速モード(64MHz)。
Bit 2 – PCKE: PCK Enable もそのまま 0で、はタイマ/カウンタ1のクロック元はシステムクロック。
Bit 1 – PLLE: PLL Enable は1に変更されていますが、システムクロック元としてPLLが選択されているので当然。
Bit 0 – PLOCK: PLL Lock Detector も1に変更で、PLLが基準クロックに固定化されている、と。
・0x31 OSCCAL (Oscillator Calibration Register)
あらかじめ工場で設定された値が自動的に入るようにできているようです。
手持ちのDigisparkでは、
16/8/1MHz時は、0x91(10進で145) (おそらく工場での設定値のまま)
16.5MHz時は、0x99(10進で153)
となっていました。
このレジスタで3%のclock upをしていたようです。
USBの処理のために3%ほど速くしてくれているのだと思います。(たぶん)
そもそもATtiny85は、外部クリスタルなしでは8MHzなのですが、そこからいろいろあって16MHzや16.5MHzを作りだしているようです。
そのあたりを調べてみました。
まずfuse。
工場出荷時と異なるのは、、
・Fuse Extended Byte
Self-programming enabledが、1→0で自己プログラミング機能が許可されています。
USBから書き込めるということでこれは当然。
・Fuse Low Byte
7ビット目のCKDIV8と、3~0ビット目のCKSEL3~CKSEL0が変更されています。
CKDIV8 は、0→1となり、システムクロックの8分周はしないということでこれも当然。
CKSEL3~CKSEL0 を CKSEL[3:0] 0001 に設定することで、
Clock source setting を High Frequency PLL Clock として、divided by four として、16MHz にしているようです。
つづいてRegister。
クロックに関係しそうなのは、CLKPR, PLLCSR, OSCCALです。
手持ちのDigisparkに以下のスケッチを書き込み、LEDの点灯時間を目視で確認することでこれらのレジスタの値を調べました。
#define isBitSet(byte, bit) ((byte) & (1 << (bit)))
void setup() {
pinMode( 0, INPUT_PULLUP ); // tactile switch
pinMode( 1, OUTPUT ); // builtin LED
}
void loop() {
uint8_t i;
while( digitalRead(0) );
delay(1000);
//0x31 OSCCAL
for(i=0; i<8; i++) {
digitalWrite( 1, HIGH);
delay( isBitSet( OSCCAL, 7-i) ? 500: 100 );
digitalWrite( 1, LOW );
delay(500);
}
delay(2000);
// 0x27 PLLCSR
for(i=0; i<8; i++) {
digitalWrite( 1, HIGH);
delay( isBitSet( PLLCSR, 7-i) ? 500: 100 );
digitalWrite( 1, LOW );
delay(500);
}
delay(2000);
// 0x26 CLKPR
for(i=0; i<8; i++) {
digitalWrite( 1, HIGH);
delay( isBitSet( CLKPR, 7-i) ? 500: 100 );
digitalWrite( 1, LOW );
delay(500);
}
}
・0x26 CLKPR (Clock Prescale Register)
CLKPS[3:0] Clock Division Factor のところで16MHz, 16.5MHz時は、分周なし(1分周), 8MHz時は2分周, 1MHz時は16分周となっていました。
・0x27 PLLCSR (PLL Control and Status Register)
Bit 7 – LSM: Low Speed Mode(32MHz) はそのまま 0 で高速モード(64MHz)。
Bit 2 – PCKE: PCK Enable もそのまま 0で、はタイマ/カウンタ1のクロック元はシステムクロック。
Bit 1 – PLLE: PLL Enable は1に変更されていますが、システムクロック元としてPLLが選択されているので当然。
Bit 0 – PLOCK: PLL Lock Detector も1に変更で、PLLが基準クロックに固定化されている、と。
・0x31 OSCCAL (Oscillator Calibration Register)
あらかじめ工場で設定された値が自動的に入るようにできているようです。
手持ちのDigisparkでは、
16/8/1MHz時は、0x91(10進で145) (おそらく工場での設定値のまま)
16.5MHz時は、0x99(10進で153)
となっていました。
このレジスタで3%のclock upをしていたようです。
タグ:Digispark
2022-06-05 02:28
nice!(0)
コメント(0)
コメント 0