はじめに
前回に引き続きATtiny13でタイマーを作成していこうと思うのですが、意外と情報量が多そうで、申し訳ないのですがソフトとハードで記事を分けたいと思います。
今回はソフト編について書こうと思います。実装する機能については前回の構想編を参照いただければと思います。タイマーカウントとタクトスイッチでの機能切り替えのみの単純な構成です。
では、早速どうぞ。
プログラム
早速ですが、今回使用するプログラムのコードです。
ATtiny13のちっこい容量を有効活用するためにArduino関数は一切使用していません。また、ダラダラ関数を描いているので見にくいコードになっていますがご容赦ください。
心配だったプログラム容量は736バイトでそこそこ余裕ありました。空きピンに関しても1ピン(+reset)あるので何かしら追加で機能を実装できそうです。
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 |
#include <avr/wdt.h> #include <avr/interrupt.h> //読み取り専用 const uint8_t MODE= 0b00000001;//5桁7セグメント const uint8_t DSET1= 0b01000000;//固定アドレス const uint8_t DSET2= 0b01000000;//移動アドレス const uint8_t ADRS= 0b11000000;//アドレス00H const uint8_t DISP= 0b10001001;//表示設定:2/16 const uint8_t PIN=1,DIO=0,CLK=2,STB=3; //読み取り/書き込み bool sw1,flag1; bool sw2,flag2; bool sw_stop; uint8_t d[10]={0b01111110,0b00001100,0b10110110,0b10011110,0b11001100,0b11011011,0b11111010,0b01001110,0b11111110,0b11011110}; volatile uint16_t num; volatile uint8_t state1,state2; ISR(INT0_vect){ state1 = 1;//リセットフラグ state2 = 1;//一時停止フラグ } //0.0998sec位で割り込み@システムクロック1.2MHz ISR(TIM0_COMPA_vect){ static uint8_t i; if(i>=10){ num++; i=0; } i++;//カウントアップ } //state1のチャタリング防止回路 void sw1_update(){ static uint8_t cnt;//0~4294967295 switch(state1){ case 0: break; case 1: cnt=255;//長押し時間 state1=2; break; case 2: cnt--; if(cnt==0){ sw1 =~(PINB>>1)&1;//sw1状態抽出 flag1=1; state1=0; } break; } } //state2のチャタリング防止回路 void sw2_update(){ static uint8_t cnt2;//0~4294967295 switch(state2){ case 0: break; case 1: cnt2=10; state2=2; break; case 2: cnt2--; if(cnt2==0){ sw2=~(PINB>>1)&1;//sw1状態抽出 flag2=1; state2=0; } } } void setup() { DDRB |= (1<<DIO)|(1<<CLK)|(1<<STB);//STB:3, DIO:0, CLK:2 PORTB |= (1<<3)|(1<<PIN);//3をHIGH,PINをPULLUP //Timer0設定 TCCR0A = 0b00000010;//CTC TCCR0B = 0b00000101;//1024分周 OCR0A = 117;//0.0998sec TIMSK0 |= 0b00000100;//比較A割り込み //外部割込みINT0設定 MCUCR |= 0b00000001;//論理変化 GIMSK |= (1<<6);//INT0割り込み許可 } //shiftOutの下位ビットfirst機能限定 void shiftLSB(uint8_t sh){ bool buff=0; for(int i=0;i<8;i++){ buff = (sh>>i) & 1;//下位ビットからbit取り出し PORTB |= (buff<<DIO);//1bitデータ送信 PORTB |= (1<<CLK);//クロックパルス PORTB &= ~(0b00000001<<0); PORTB &= ~(0b00000001<<2); } } void TM1630(uint16_t math){ PORTB &= ~(1<<STB); shiftLSB(MODE); PORTB |= (1<<STB); PORTB &= ~(1<<STB); shiftLSB(DSET1); PORTB |= (1<<STB); //一桁目 PORTB &= ~(1<<STB); shiftLSB(ADRS); shiftLSB(d[math/1000]); PORTB |= (1<<STB); //二桁目 PORTB &= ~(1<<STB); shiftLSB(ADRS|2); shiftLSB(d[(math%1000)/100]); PORTB |= (1<<STB); //三桁目 PORTB &= ~(1<<STB); shiftLSB(ADRS|4); shiftLSB(d[((num%1000)%100)/10]); PORTB |= (1<<STB); //四桁目 PORTB &= ~(1<<STB); shiftLSB(ADRS|6); shiftLSB(d[((math%1000)%100)%10]); PORTB |= (1<<STB); PORTB &= ~(1<<STB); shiftLSB(DISP); PORTB |= (1<<STB); } void loop() { wdt_reset(); //リセット条件 sw1_update(); if(flag1){ flag1=0; switch(sw1){ case 0: break; case 1: num=0; break; } } //一時停止条件 sw2_update(); if(flag2){ flag2=0; switch(sw2){ case 0: break; case 1: sw_stop=!sw_stop; break; } } if(sw_stop){ TIMSK0 &= ~0b00000100; }else if(sw_stop==0){ TIMSK0 |= 0b00000100; } TM1630(num); } |
コード解説(LED制御)
LED制御は中華ICのTM1630を使用しています。このICはデータとクロック、チップセレクトの3線で通信を行ないます。通信方式はチップセレクトをセットした後にデータを送信しクロックで確認を行ないます。Arduino標準関数である【shiftOut】を使用すれば簡単に通信できますが、容量削減のために【shiftLSB】関数を作ってshiftOutを再現しています。shiftLSBの機能は標準関数のshiftOutの下位ビットからの送信のみに機能を限定して書いてあります。
コード解説(タクトスイッチ機能切り替え)
このコードではタクトスイッチの機能として【タイマーの一時停止】【タイマーリセット】を設けています。タクトスイッチは一個しか実装しない予定なので、押下時間によって機能を切り替えるようにしています。具体的には外部割込み(論理変化)を使用して個別フラグを2個立てます。このフラグに対してスイッチ状態変化関数【update_sw1】【update_sw2】を作って、この中のチャタリング防止のカウンタの時間を変えております。なお、一時停止については後述するタイマー割り込みを一旦禁止しています。再度、タクトスイッチを押されたときにタイマー割り込みを許可する感じです。
コード解説(秒数カウント制御)
タイマーの本質の秒数カウントは正確に行ないたいので、タイマー割り込みで秒数をカウントします。
タイマー割り込みは自分でタイマーのTOPを指定できるCTC(Clear Timer on Compare Match)モードを使用します。なおATtiny13にはTimer0(8bit)のみの実装である為に、1秒カウントのタイマーを使用する為にはカウントなどを使用するなどして工夫する必要があります。本コードではメインクロックを1.2MHzとして、分周比1024としています。そしてTOP値の設定は117としています。なので、タイマー割り込みとしては0.00998secとなるので10回タイマー割り込みが発生したら1秒としています。
おわりに
今回はATtiny13タイマーのプログラムについて纏めました。このコードで実装してみようかと思いますが、動かしてみておかしかったら改定していきたいと思います。また、修整した方がいい所がありましたらご助言いただけるとありがたいです。
次回はハード編で実際に実装していきたいと思います。
では、良いお年を!
コメント