「ATtiny13を使用したプログラマブル・ディバイダ」の版間の差分
提供:泣かないでゆり子
ナビゲーションに移動検索に移動 (+初めてのCコンパイラ) |
(新バージョンのコード、ヒューズ設定) |
||
5行目: | 5行目: | ||
PLL ICの4046で周波数シンセサイザを作ろうと思って、その前フリとしてATtiny13内蔵のカウンタでプログラマブル・ディバイダ('''1/N'''ディバイダ)を作ってみた♡ DIPスイッチで分周比'''N'''を設定できちゃう~♪ | PLL ICの4046で周波数シンセサイザを作ろうと思って、その前フリとしてATtiny13内蔵のカウンタでプログラマブル・ディバイダ('''1/N'''ディバイダ)を作ってみた♡ DIPスイッチで分周比'''N'''を設定できちゃう~♪ | ||
+ | |||
+ | マイコンのI/Oポート数が少ないせいで、4bitDIPスイッチのうち3bit(0~7)しか読めない・・・RESETピンをI/Oポートにすれば4bit読めるけどISP書き込みができなくなる・・・ | ||
==C言語コード== | ==C言語コード== | ||
今まで([[キッチンタイマーもどき]]など)はアセンブラでAVRマイコンの開発を行っていたが、今回は初めてCコンパイラを用いて開発してみた。アセンブラに比べてとっても簡単☆ コンパイラ様様です。 | 今まで([[キッチンタイマーもどき]]など)はアセンブラでAVRマイコンの開発を行っていたが、今回は初めてCコンパイラを用いて開発してみた。アセンブラに比べてとっても簡単☆ コンパイラ様様です。 | ||
+ | ===ヒューズビット設定=== | ||
+ | :HIGH: 0xFD LOW: 0x7A | ||
+ | :SPIEN * | ||
+ | :BODLEVEL 1V8 | ||
+ | :SUT_CKSEL INTRCOSC_9MHZ6_14CK_64MS | ||
+ | |||
+ | T0ピンパルス入力はエッジ検出回路を通りカウンタへ入力される。が、エッジ検出回路は'''ClkI/O'''(I/Oクロック、'''ClkCPU'''と同じ)で駆動されているためサンプリング定理より('''ClkI/O''')/2 [Hz]が最高入力周波数となる。データシートによれば('''ClkI/O''')/2.5 [Hz]以下を推奨とのこと。消費電力が増えるが最高入力周波数を上げるため、内蔵9.6MHz発振器を'''ClkCPU'''、'''ClkI/O'''とした。 | ||
+ | |||
+ | ===コード=== | ||
<pre> | <pre> | ||
/* | /* | ||
27行目: | 38行目: | ||
--PIN Connection-- | --PIN Connection-- | ||
1 RESET: N/C | 1 RESET: N/C | ||
− | 2 PB3: DIP SW bit | + | 2 PB3: DIP SW bit 2 |
− | 3 PB4: DIP SW bit | + | 3 PB4: DIP SW bit 4 |
4 GND: GND | 4 GND: GND | ||
5 OC0A: Divider signal out | 5 OC0A: Divider signal out | ||
39行目: | 50行目: | ||
char readDIPsw(); | char readDIPsw(); | ||
+ | unsigned char calcOCR0AfromN(unsigned int n); | ||
int main(void) | int main(void) | ||
48行目: | 60行目: | ||
OCR0A = (unsigned int) 0; //init Counter Compare Register | OCR0A = (unsigned int) 0; //init Counter Compare Register | ||
TCCR0A = (1 << COM0A0) + (1 << WGM01); //OC0A pin Toggle, CTC counter mode. | TCCR0A = (1 << COM0A0) + (1 << WGM01); //OC0A pin Toggle, CTC counter mode. | ||
− | TCCR0B = (1 << CS01) + (1 << CS02); //Counter clock source T0 pin (external). | + | TCCR0B = (1 << CS01) + (1 << CS02); //Counter clock source T0 pin falling edge (external). |
while(1) | while(1) | ||
{ | { | ||
− | OCR0A = | + | OCR0A = calcOCR0AfromN( 10 * readDIPsw()); //Read DIP SW and set it to Compare Register. |
} | } | ||
} | } | ||
63行目: | 75行目: | ||
return (bit2 << 2) | (bit1 << 1) | bit0; //Joining bits. | return (bit2 << 2) | (bit1 << 1) | bit0; //Joining bits. | ||
+ | } | ||
+ | |||
+ | // If you want set 10 to divider N, then OCR0A needs set 4. | ||
+ | // If N is 20, then OCR0A needs 9. | ||
+ | // This function calcurate OCR0A from N automatically. | ||
+ | unsigned char calcOCR0AfromN(unsigned int n) { | ||
+ | unsigned char ocrna = (n/2) -1; | ||
+ | |||
+ | if (ocrna < 0 || n == 0) { | ||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | return ocrna; | ||
}</pre> | }</pre> |
2016年2月23日 (火) 22:38時点における版
PLL ICの4046で周波数シンセサイザを作ろうと思って、その前フリとしてATtiny13内蔵のカウンタでプログラマブル・ディバイダ(1/Nディバイダ)を作ってみた♡ DIPスイッチで分周比Nを設定できちゃう~♪
マイコンのI/Oポート数が少ないせいで、4bitDIPスイッチのうち3bit(0~7)しか読めない・・・RESETピンをI/Oポートにすれば4bit読めるけどISP書き込みができなくなる・・・
C言語コード
今まで(キッチンタイマーもどきなど)はアセンブラでAVRマイコンの開発を行っていたが、今回は初めてCコンパイラを用いて開発してみた。アセンブラに比べてとっても簡単☆ コンパイラ様様です。
ヒューズビット設定
- HIGH: 0xFD LOW: 0x7A
- SPIEN *
- BODLEVEL 1V8
- SUT_CKSEL INTRCOSC_9MHZ6_14CK_64MS
T0ピンパルス入力はエッジ検出回路を通りカウンタへ入力される。が、エッジ検出回路はClkI/O(I/Oクロック、ClkCPUと同じ)で駆動されているためサンプリング定理より(ClkI/O)/2 [Hz]が最高入力周波数となる。データシートによれば(ClkI/O)/2.5 [Hz]以下を推奨とのこと。消費電力が増えるが最高入力周波数を上げるため、内蔵9.6MHz発振器をClkCPU、ClkI/Oとした。
コード
/* * DeviderCounter.c * * Created: 2016/02/11 1:00:41 * Author: 市川ゆり子 */ /* Programmable Divider by tiny13 + DIP SW --Fuses-- HIGH: 0xFD LOW:0x7A SPIEN * BODLEVEL 1V8 SUT_CKSEL INTRCOSC_9MHZ6_14CK_64MS --PIN Connection-- 1 RESET: N/C 2 PB3: DIP SW bit 2 3 PB4: DIP SW bit 4 4 GND: GND 5 OC0A: Divider signal out 6 PB1: DIP SW bit 1 7 T0: Divider signal in 8 Vcc: +5V */ #include <avr/io.h> char readDIPsw(); unsigned char calcOCR0AfromN(unsigned int n); int main(void) { //Peripheral initialize. DDRB = 0b00100001; //DDRB0,5 is out. other is in. PORTB = 0b00011010; //PORTB1,3.4 pull up. OCR0A = (unsigned int) 0; //init Counter Compare Register TCCR0A = (1 << COM0A0) + (1 << WGM01); //OC0A pin Toggle, CTC counter mode. TCCR0B = (1 << CS01) + (1 << CS02); //Counter clock source T0 pin falling edge (external). while(1) { OCR0A = calcOCR0AfromN( 10 * readDIPsw()); //Read DIP SW and set it to Compare Register. } } //Read DIP SW state and return it. char readDIPsw() { char bit0 = ~(PINB >> PINB1) & 0x01; //Read PINB1 state. char bit1 = ~(PINB >> PINB3) & 0x01; //Read PINB3 char bit2 = ~(PINB >> PINB4) & 0x01; //Read PINB4 return (bit2 << 2) | (bit1 << 1) | bit0; //Joining bits. } // If you want set 10 to divider N, then OCR0A needs set 4. // If N is 20, then OCR0A needs 9. // This function calcurate OCR0A from N automatically. unsigned char calcOCR0AfromN(unsigned int n) { unsigned char ocrna = (n/2) -1; if (ocrna < 0 || n == 0) { return 0; } return ocrna; }