覚え書きTOP

AVR TOP

小手調べ

1本目
まずはアセンブラで書いてみた。

 使ったCPUはTiny2313.
 ブレッドボードに電源とLEDを載せただけ・・・ICE と as6 を試すだけだからこれで十分だよね。

  /*
* AssemblerApplication1.asm
*
* Created: ?? 24/5/16 14:21:30
* Author: oj3
*/

.INCLUDE <tn2313def.inc>

        RJMP reset

;ポートBを全ビット出力に設定
reset:
        LDI R18, 1<<4       ;LEDポート(PD4)のみ出力ポートに設定
        OUT DDRD, R18

        SBI PORTD, 4 ;LED1 ON
        CBI PORTD, 4 ;LED1 OFF

main: RJMP main

 こりゃすごいね。
 CPUの初期設定も何も要らずに動いちまう。
 ルネサスのSHなんかを動かそうと思ったら初期設定だけで気が狂いそうなのに、AVRはなんもせんでもまず動いてしまう。素晴らしいっす。
 良く見ればコメントがC形式だ(^^;
 なんか良い感じ〜
 ちゅうことで1本目は終わり。


2本目
次はCで書いてみた。

 ハードは同じ物。
 せっかくだから内蔵のクロックやらWDTやらを試してみた(WDTの実例はここにもあり)。

  //---------------------------------------------------------------------------------------------
//
// ■I/Oφの分周比変更と動作確認
//
// ■WDTの動作確認
//
// Atmel studio 6 & AVRDragon & ATtiny2313
//
//---------------------------------------------------------------------------------------------
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <util/delay.h>

#define nop() __asm__ __volatile__ ("nop")

volatile uint32_t _timer;

//---------------------------------------------------------------------------------------------
// I/Oクロック・プリスケーラ変更方法 2012/05/25 oj3
// http://awawa.hariko.com/chira-ura/atmega168-chapter8-jp.html#chapter8-12-2
// CKDIV8ヒューズがプログラムされていない場合、CLKPSビットは"0000"にリセットされます。
// CKDIV8がプログラムされている場合、CLKPSビットは"0011"にリセットされ、スタートアップ時の
// 分周比は8=1MHzになります。
//
// ・CKDIV8ヒューズに「レ」が入ってるとI/Oクロックは1Mになる。外すと8Mになる。
//  「レ」が入ってても以下の方法でI/Oクロックを自由に変更可能だけど、まず使わないな。
//
//---------------------------------------------------------------------------------------------
void ioclk_test(void)
{
    // φ確認用のTIMER0の設定
    TIMSK = (1<<TOIE0); // タイマ0のオーバーフロー割り込み許可
    TCCR0B = 0x4; // 8M動作時 0x4=256 分周だと実測で約8ms周期(timer=131で1秒)
    sei();

    // 分周無し(=8MHz動作)でTimer動作時間を見る
    CLKPR = 0b10000000; // クロック・プリスケーラ変更許可ビットをセットしておいて
    CLKPR = 0b00000000; // プリスケーラ値を変える:0=分周無し、1=2分周、3=4分周...
    _timer = 1310L; // BP3 10秒待ち
    while (_timer);
    nop(); // BP4

    // 分周値1でTimer動作時間を見る
    CLKPR = 0b10000000; // クロック・プリスケーラ変更許可ビットをセットしておいて
    CLKPR = 0b00000001; // プリスケーラ値を変える:0=分周無し、1=2分周...8=256分周...
    _timer = 1310L; // BP1 20秒待ち
    while (_timer);
    nop(); // BP2
}
// TIMER0オーバーフロー割込みハンドラ
ISR(TIMER0_OVF_vect)
{
    if (_timer) --_timer; // I/Oφ8M時、_timer=131で約1秒待ちになる(8mS周期)
}
//---------------------------------------------------------------------------------------------
// WDTの動作チェック 2012/05/25 oj3
// http://cega.jp/avr-libc-jp/group__avr__watchdog.html
//
// ・FuseはデフォルトのままでOK(ベクタ割込を発生させる場合は変更の必要が有るようだ)。
// ・wdt_enableとするだけでWDTは使用可能であり、WDT発生時はmain()に戻ってくるのを確認した。
// ・WDT発生までの時間は以下のマクロで指定する(wdt.h内にある)
//
//#include <avr/wdt.h>
//#define wdt_reset() __asm__ __volatile__ ("wdr")
//#define wdt_enable(value)
//#define wdt_disable()
//#define WDTO_15MS 0
//#define WDTO_30MS 1
//#define WDTO_60MS 2
//#define WDTO_120MS 3
//#define WDTO_250MS 4
//#define WDTO_500MS 5
//#define WDTO_1S 6
//#define WDTO_2S 7
//#define WDTO_4S 8
//#define WDTO_8S 9
//---------------------------------------------------------------------------------------------
ISR(WDT_OVERFLOW_vect) // ベクタ割込みはテストしてない
{
    if (_timer) --_timer;
}
void WDT_off(void)
{
    cli();
    wdt_reset(); // ウォッチドッグ タイマ リセット
    MCUSR &= ~(1<<WDRF); // ウォッチドッグ リセット フラグ(WDRF)解除
    WDTCSR |= (1<<WDCE)|(1<<WDE); // WDCEとWDEに論理1書き込み
    WDTCSR = 0x00; // ウォッチドッグ禁止
    sei();
}
void wdt_test(void)
{
    volatile long i;
    PORTD = 0xff;
    DDRD = 0xff;
    for (i = 100000L; i > 0L; i--) wdt_reset();

    sei();
    wdt_enable(WDTO_1S); // 約0.12sでタイマアウトする
    nop();
    while (1) {
        PIND |= _BV(PD6);
        for (i = 1000L; i > 0L; i--);// wdt_reset();
        nop();
    }
}
//---------------------------------------------------------------------------------------------
// Tiny2313動作テスト用
//---------------------------------------------------------------------------------------------
void test2313(void)
{
    volatile long i;
    PORTD = 0xff;
    DDRD = 0xff;
    while(1) {
        PIND |= _BV(PD6);
        for (i = 100000L; i > 0L; i--) nop();
        nop();
    }
}
//---------------------------------------------------------------------------------------------
//
//---------------------------------------------------------------------------------------------
int main (void)
{
    nop();
    WDT_off();
    wdt_disable();

    // LED点灯で基礎動作チェック
    test2313();

    // I/Oクロックの分周比のテスト
    //ioclk_test();

    // WDTのテスト(テスト終了後はmain先頭でWDTを止めること)
    nop(); // ここにBPをセッとして実行させるとWDTの発生を見られる
    wdt_test();
}


 良いね〜
 ステップ実行もブレークも綺麗にかかる。
 調子が悪いときはライターでFlashをクリアするとか、ISPの通信速度を125Kにしたりリセットしたりして回復させる。
 ISPケーブルの接触不良やハンダの外れかけとかで調子を崩したらCPUを交換しちまうのが手っ取り早い。100円だし(笑)

 この時点で徹底的にいじっておかないと、怖くて先に進めないよ。
 ICEが100%とは言わなくても90%は確実に動く事、Flash上でプログラムが間違いなく安定して動くこと、WDTが効くこととか調べておかないと組み込みには使えないもん。


2012/08/02
3本目
 tiny2313で色々作ってたんだけど、ちょいI/Oとメモリが不足してきた(tiny2313は浮動小数点とか使うとメモリが足りなくなるよ・・・当たり前だ)。
 で、一回り大きいmega328pをメインに使うことにした。確か150円だったかな?
 足の数が28本とちょっと多いけど、メモリ量やI/O点数からしてやっぱ便利そうなんだもん・・・これ以上の能力が必要だとR8やSH2を使うかも。

 まずはXtalを外付けしただ。
 高速通信やPWMを使うとなると、やっぱり安定した周波数が欲しい。

  16MのXtalの足を無理矢理曲げて9Pと10Pに突っ込んだ・・・16Mにした理由は特になし。
両方の足に22pFのコンデンサを挿して実験じゃ。 回路図

メインクロックがまともに動いてるか調べるのに一番簡単なのはUARTか?
ざっとプログラムを組んでターミナルと通信できるか調べてみようっと。
    Xtalを繋いだだけじゃダメよ。その程度の事はオラでも分かる(^^;
Fuseを書き換えるのだ。
あまり深く考えずにデータシートを斜め読みして安全パイそうなやつを設定。 

ここに詳しい説明有り。
    ちなみにFuseビットはこんな感じ。
  #include "_common.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <avr/wdt.h>
#include <avr/sleep.h>
#include <avr/sfr_defs.h>
#include <string.h>
#include <stdlib.h>

#define F_CPU  16000000
#define BAUD 9600
#define MYUBRR (F_CPU/16/BAUD)-1

// 初期化
void uart_init(void)
{
    // ボーレート設定
    unsigned short tmp = MYUBRR;
    UBRR0H = (tmp >> 8) & 0xff;
    UBRR0L = tmp & 0xff;
    // 受信完了割込み、送信機能、受信機能を利用する
    UCSR0B = (1 << RXCIE0) | (1 << RXEN0) | (1 << TXEN0) ;
    UCSR0C = (3 << UCSZ00) ; // データ長8bit
}

// 受信完了割込み
ISR(USART_RX_vect)
{
    volatile unsigned char ch ;
    ch = UDR0 ;
    UDR0 = ch;
}
 
エコーバックするプログラムはこんな。
受信は割込みで取ってる。
そのうち本気で使うときにリングバッファ化すべ。

ちゅうことでXtal外付け成功じゃ。


AVR TOP

覚え書きTOP