6: 2009-11-18 (水) 03:59:54 takaboo ソース 現: 2013-10-07 (月) 19:00:15 eid7gud ソース
Line 1: Line 1:
 +TITLE:ATmega32 Sample Code
 +#norelated
 +#contents
*ダウンロード[#l493db9b] *ダウンロード[#l493db9b]
-#ref(http://www.besttechnology.co.jp/dow​nload/ATMEGA32SMPL1.5.ZIP)+#ref(http://www.besttechnology.co.jp/dow​nload/ATMEGA32SMPL1.6.ZIP) 
 +|CENTER:BGCOLOR(red): :idea:|最新のGCCにおいてATmega32Aをターゲットとした場合のDDRのビット定義名が変わってしまったためソース互換性が保てなくなりました。そのため、PORT・DDR・PINの各レジスタのビット定義名は、PORT7~PORT0・DD7~DD0・PIN7~PIN0に変更しました。|
*一覧 [#j8c69fab] *一覧 [#j8c69fab]
Line 13: Line 17:
 // 通常の使用においては数バイト程度で十分です。またバッファはグローバル変数としてください。  // 通常の使用においては数バイト程度で十分です。またバッファはグローバル変数としてください。
 static char txb[10], rxb[10];  static char txb[10], rxb[10];
 + 
 // 通信ポートを初期化 ボーレートは115200[bps]  // 通信ポートを初期化 ボーレートは115200[bps]
 rs_init (br115200, txb, sizeof(txb), rxb, sizeof(rxb));  rs_init (br115200, txb, sizeof(txb), rxb, sizeof(rxb));
Line 24: Line 28:
 ・文字列送信  ・文字列送信
  void  rs_puts (char *);   void  rs_puts (char *);
- ・バイナリ列送信+ ・指定サイズのバイナリバイト列送信
  void  rs_putb (char *, short);   void  rs_putb (char *, short);
 ・受信バッファデータサイズ取得  ・受信バッファデータサイズ取得
Line 30: Line 34:
 ・受信バッファクリア  ・受信バッファクリア
  void  rs_rx_purge (void);   void  rs_rx_purge (void);
- ・1文字受信+ ・1文字受信(受信されるまで待つ)
  char rs_getc (void);   char rs_getc (void);
- ・文字列受信+ ・文字列受信(入力時のエコーバックあり,CRで入力完了)
  short rs_gets (char *, short);   short rs_gets (char *, short);
 ・簡易書式化文字列送信  ・簡易書式化文字列送信
Line 53: Line 57:
 #include <avr/io.h>  #include <avr/io.h>
PC4を出力ポートに設定するにはDDRCの4ビット目を1に設定する。 PC4を出力ポートに設定するにはDDRCの4ビット目を1に設定する。
- DDRC |= _BV(DDC4);    // PC4を出力に+ DDRC |= _BV(DD4);    // PC4を出力に
PC4へ1を書くとLEDは点灯、0を書くと消灯する。ちなみに、_BV() は引数で指定した数値をビットに変換するavr-libcで提供されるマクロである。~ PC4へ1を書くとLEDは点灯、0を書くと消灯する。ちなみに、_BV() は引数で指定した数値をビットに変換するavr-libcで提供されるマクロである。~
- PORTC &= ~_BV(PC4); // 消灯 + PORTC &= ~_BV(PORT4); // 消灯 
- PORTC |= _BV(PC4);  // 点灯+ PORTC |= _BV(PORT4);  // 点灯
点滅の周期は util/delay.h で宣言される _delay_ms 関数を使用し、ミリ秒単位で設定している。 点滅の周期は util/delay.h で宣言される _delay_ms 関数を使用し、ミリ秒単位で設定している。
 _delay_ms (500);    // 500ms待つ  _delay_ms (500);    // 500ms待つ
Line 64: Line 68:
出力端子の初期化は以下の通り。 出力端子の初期化は以下の通り。
- DDRC |= _BV(DDC4) | _BV(DDC5) | _BV(DDC6) | _BV(DDC7);  // PC4..7を出力に+ DDRC |= _BV(DD4) | _BV(DD5) | _BV(DD6) | _BV(DD7);  // PC4..7を出力に
点灯させるビットが増えると一つ一つビットを指定するのが面倒なので、4ビットまとめて点灯ないし消灯させる関数を用意している。 点灯させるビットが増えると一つ一つビットを指定するのが面倒なので、4ビットまとめて点灯ないし消灯させる関数を用意している。
 void LED (int d) {  void LED (int d) {
Line 75: Line 79:
入力端子の初期化は以下の通り。 入力端子の初期化は以下の通り。
 // DIP1(PC2,3)を構成  // DIP1(PC2,3)を構成
- DDRC &= ~(_BV(DDC2) | _BV(DDC3)); // PC2,3を入力に + DDRC &= ~(_BV(DD2) | _BV(DD3)); // PC2,3を入力に 
- PORTC |= (_BV(PC2) | _BV(PC3));  // PC2,3の内蔵プルアップ抵抗をON + PORTC |= (_BV(PORT2) | _BV(PORT3));  // PC2,3の内蔵プルアップ抵抗をON 
 + 
 // PB1~PB2(PD2,3)を構成  // PB1~PB2(PD2,3)を構成
- DDRD &= ~(_BV(DDD2) | _BV(DDD3)); // PD2,3を入力に + DDRD &= ~(_BV(DD2) | _BV(DD3)); // PD2,3を入力に 
- PORTD |= (_BV(PD2) | _BV(PD3));  // PD2,3の内蔵プルアップ抵抗をON+ PORTD |= (_BV(PORT2) | _BV(PORT3));  // PD2,3の内蔵プルアップ抵抗をON
DIPスイッチは2ビットまとめて数値として取り込む関数を用意している。 DIPスイッチは2ビットまとめて数値として取り込む関数を用意している。
 // DIP1(ディップスイッチ)の状態取り込み  // DIP1(ディップスイッチ)の状態取り込み
Line 89: Line 93:
 // プッシュボタン1の状態取り込み  // プッシュボタン1の状態取り込み
 unsigned char PB1_STAT (void) {  unsigned char PB1_STAT (void) {
-   return bit_is_clear (PIND, PIND2);+   return bit_is_clear (PIND, PIN2);
 }  }
 + 
 // プッシュボタン2の状態取り込み  // プッシュボタン2の状態取り込み
 unsigned char PB2_STAT (void) {  unsigned char PB2_STAT (void) {
-   return bit_is_clear (PIND, PIND3);+   return bit_is_clear (PIND, PIN3);
 }  }
Line 104: Line 108:
 MCUCR |= _BV(ISC11) | _BV(ISC01);    // ISC11とISC01を1に  MCUCR |= _BV(ISC11) | _BV(ISC01);    // ISC11とISC01を1に
 MCUCR &= ~(_BV(ISC10) | _BV(ISC00));  // ISC10とISC00を0に  MCUCR &= ~(_BV(ISC10) | _BV(ISC00));  // ISC10とISC00を0に
 + 
 // INT0/1割り込みを許可  // INT0/1割り込みを許可
 GICR |= _BV(INT1) | _BV (INT0);  GICR |= _BV(INT1) | _BV (INT0);
 + 
 // 全割り込み許可  // 全割り込み許可
 sei ();  sei ();
Line 117: Line 121:
 while (1) {  while (1) {
   sleep_mode ();    sleep_mode ();
-   PORTC ^= _BV(PC7);  // 起きる度にLED4をブリンク+   PORTC ^= _BV(PORT7);  // 起きる度にLED4をブリンク
 }  }
INT0に対応した割り込みルーチン名は INT0_vect としてavr-libcにて決められているので、その様に記述。処理はcnt変数の値をインクリメントし、その値をLED1~3に表示する。 INT0に対応した割り込みルーチン名は INT0_vect としてavr-libcにて決められているので、その様に記述。処理はcnt変数の値をインクリメントし、その値をLED1~3に表示する。
Line 167: Line 171:
   if (cnt++ > 31) { // 約0.5秒毎にLEDを反転    if (cnt++ > 31) { // 約0.5秒毎にLEDを反転
     cnt = 0;      cnt = 0;
-     rbi (PORTC, PORTC4);+     rbi (PORTC, PORT4);
   }    }
 }  }
Line 181: Line 185:
LED1が接続されたPC4とPWM信号を出力するPD4とPD5を出力に設定する。 LED1が接続されたPC4とPWM信号を出力するPD4とPD5を出力に設定する。
 // LED1(PC4)を構成  // LED1(PC4)を構成
- DDRC |= _BV(DDC4);    // PC4を出力に + DDRC |= _BV(DD4);    // PC4を出力に 
- PORTC &= ~_BV(PC4);    // LEDをOFF PC4=0 + PORTC &= ~_BV(PORT4);    // LEDをOFF PC4=0 
 + 
 // PWM出力端子を構成  // PWM出力端子を構成
- DDRD |= _BV(DDB4) | _BV(DDB5);  // PD5,PD4を出力に+ DDRD |= _BV(DD4) | _BV(DD5);  // PD5,PD4を出力に
タイマ/カウンタ1を高速PWMモードに設定する。ICR1がPWMの周期、OCR1AがPD5(OC1A)のデューティー、OCR1BがPD4(OC1B)のデューティーとなり、ここでは周期を8ms(=125Hz=CLK/256 /500)としたので以下の通りに設定する。 タイマ/カウンタ1を高速PWMモードに設定する。ICR1がPWMの周期、OCR1AがPD5(OC1A)のデューティー、OCR1BがPD4(OC1B)のデューティーとなり、ここでは周期を8ms(=125Hz=CLK/256 /500)としたので以下の通りに設定する。
 // タイマ/カウンタ1を高速PWMモードに設定 (ICR1でTOP)  // タイマ/カウンタ1を高速PWMモードに設定 (ICR1でTOP)
Line 200: Line 204:
 ISR (TIMER1_COMPA_vect) {  ISR (TIMER1_COMPA_vect) {
   int i;    int i;
 + 
   // 1周期毎に比較レジスタ更新    // 1周期毎に比較レジスタ更新
   for (i = 0; i < 2; i++) if (cnt[i]++ > 500) cnt[i] = 0;    for (i = 0; i < 2; i++) if (cnt[i]++ > 500) cnt[i] = 0;
   OCR1A = cnt[0];    OCR1A = cnt[0];
   OCR1B = cnt[1];    OCR1B = cnt[1];
- +  
-   rbi (PORTC, PINC4); // LEDビット反転+   rbi (PORTC, PORT4); // LEDビット反転
 }  }
Line 229: Line 233:
 const char gyao[27000] PROGMEM = {0,0,0,0,0,0,};  const char gyao[27000] PROGMEM = {0,0,0,0,0,0,};
**BUZZER.c [#e8471f5c] **BUZZER.c [#e8471f5c]
-指定周波数で圧電ブザーを鳴らす。+PD7(OC2)端子に接続されたトランジスタを介して他励式のブザーを駆動する。 
 +#ref(bz.png) 
 +この回路ではPD7端子がHIGHになるとトランジスタがONしてブザーの+/-両端に電圧が加わる。LOWになるとトランジスタがOFFしてブザーの-端子がオープンになる。これをゆっくり繰り返すとブザーがプチプチとなるだけだが、数百~数kHzの周期で繰り返すとぴ~ぷ~といった音として聞こえる様になる。 
 + 
 +周波数はPA7(ADC7)端子に接続したポテンショメータで分圧された電圧を計測する事で設定するものとしている。 
 +#ref(vr.png) 
 + 
 +PD7はカウンタタイマ2のOC2端子が接続されており、コンペアマッチでトグル動作する様に設定すればOCR2に設定できる範囲の値で周波数が設定出来る。また同時にPD7を出力端子に設定する必要もある。 
 + void ToneOn (int tone) { 
 +   OCR2 = UD_ToneTable[tone]; 
 +   TCCR2 = _BV(WGM21) | _BV(COM20) | _BV(CS22) | _BV(CS20); 
 +   // PD7(OC2)を出力に 
 +   DDRD |= _BV(DD7); 
 + } 
 +大抵ブザーの類は常時一定の電圧を加えておく事は推奨されていないので、音を出さないときはOFFしておく事で劣化を防ぎつつ無駄に電力を消費する事もなくなる。 
 + void ToneOff (void) { 
 +   // PD7(OC2)を入力(外部のプルダウン抵抗でLOWに) 
 +   DDRD &= ~_BV(DD7); 
 +   TCCR2 = 0; 
 + }
**SPI_BRIDGE.c [#j47c03d0] **SPI_BRIDGE.c [#j47c03d0]
SPIバスで接続されたATA6831(3ch ハーフブリッジドライバ)と通信を行い、任意のパターンで各チャネルのトランジスタをON/OFFさせる。 SPIバスで接続されたATA6831(3ch ハーフブリッジドライバ)と通信を行い、任意のパターンで各チャネルのトランジスタをON/OFFさせる。
 +#ref(spi.png)
 +SPIは簡単に言えばクロック同期式の双方向シリアル通信で、MISO・MOSI・SCKとチップセレクトの4本の信号でコミュニケーションする。対象によってタイミング等細かい違いはあるが、AVRの場合は大抵のデバイスとと接続する事ができる。
 +
 +ATA6831は3chのハーフブリッジを内蔵した主にリレーやランプを駆動するドライバICである。ここのうちハーフブリッジを2つ使えばモータの正/逆転を行うのに十分なHブリッジが構成できるので、小型モータの駆動程度であれば十分に使える。~
 +また3chのハーフブリッジに対してモータをうまくつなげば、動作モードの制限はあるものの2台を個別に駆動する事ができない事も無い。
**RCSERVO.c [#l9555243] **RCSERVO.c [#l9555243]


トップ   差分 リロード印刷に適した表示   全ページ一覧 単語検索 最新ページの一覧   最新ページのRSS 1.0 最新ページのRSS 2.0 最新ページのRSS Atom