マイコンの実験がうまくいかない

更新サボりがちなのは大目に見て

実験内容

秋月電子のAKI-H8/3664Fキット(URL)を使ってなんか作れというもの。うちの班は秒カウンタ、もし出来ればストップウォッチや時計などを作れたらいいなーなんて話し合ってた。

甘 か っ た

基本的にうまくいかない

断線

初っ端のアクシデントは断線。ジャンパワイヤの特定の色が全部断線。で、新しくもらった1セットも赤いジャンパワイヤが全て断線していたという強運っぷり。なんでや。

謎故障

3日ほど放置しておいたマイコンが、プログラム書き込み時に応答なしになる。検証したところマイコンがオシャカになっていることが発覚。

ポート死んでる

故障したので、新しいマイコンをもらったが、あるポートが使えない。死んでいる。回路とプログラム書き直し。大した痛手じゃなかったけれどもへこむ。

書いたとおりにすら

「プログラムは思ったとおりには動かない。書いたとおりに動く」という名言があるが、なんべんやっても書いたとおりにすら動いてないんじゃないか?という状況。締め切りはもうすぐ。


何をどんな感じでやっているのか

2桁の7セグメントLEDをダイナミック点灯制御でカウントアップ。その後はタイマAによる割り込みで1秒毎に表示を更新。起動時からの秒数カウンタ(00秒から99秒まで)が完成した後に随時機能追加。

行き詰まっていることろ

基本的に動作が不安定である

突然CPUからの応答がなくなったり、点灯しなくなったりする。

割り込みができない

なんでだーーまったくわからんーーーーー

どこから持ってきたのかわからないヘッダファイル

マジどこから持ってきたし……先生が書いたのかも?
ネット上で使われているのは大抵がGCC Developer Lite(URL)内の3664f.hなのだが、この実験で提供される3664f.hはなんというか提供している機能は同じだが文法が大きく違う。最大の違いはGCC Developer Liteのヘッダファイルには構造体が使われているという点。よってネット上のサンプルコードはヘッダファイルを読み比べ、書きなおさなければいけない……っていうかGCC Developer Lite使っちゃいけないのかな?

現時点でのソースコード

バックアップ代わりに。もしかしたら優しい伊達直人が間違いを指摘してくれるかもという希望を抱いて。

/*
 *H8/3664F 7セグメントLEDのダイナミック点灯制御実験
 */

#include "3664.h"

/* P11をLEDに接続、P52をSWに接続 */
#define	P1OUT	0x2	/* P11:0000,0010 */
#define	P5IN	0x4	/* P52:0000,0100 */

//7セグメントLEDの各数字表示
#define	ZERO	0x80	//10000000	//0
#define	ONE	0xF1	//11110001	//1
#define	TWO	0x44	//01001000	//2
#define	THREE	0x60	//01100000	//3
#define	FOUR	0x31	//00110001	//4
#define	FIVE	0x22	//00100010	//5
#define	SIX	0x2	//00000010	//6
#define	SEVEN	0xB0	//10110000	//7
#define	EIGHT	0x0	//00000000	//8
#define	NINE	0x20	//00100000	//9

//7セグメントLEDの格桁に対応するポート
#define DIGIT0	0x1
#define DIGIT1	0x2
#define DIGIT2	0x4
#define DIGIT3	0x8
#define DIGIT4	0x10
#define DIGIT5	0x20
#define DIGIT6	0x40

//タイマAの割り込み要求フラグが立っている状況
#define IRRTA 0x70

//タイマAの割り込み要求を許可するflug
#define IENTA 0x40

int count = 0;

/*入力された数値に対応する7セグメントLEDを
 *負論理で点灯させるポート出力用の数値を返す
 */
int LightNumber( int num )
{
    int led[10] = { 	ZERO , 
		ONE , 
		TWO , 
		THREE , 
		FOUR , 
		FIVE , 
		SIX , 
		SEVEN , 
		EIGHT , 
		NINE ,
		};
    
    return led[num];
}


/*入力された数値に対応する桁をトランジスタのスイッチングによって
 *点灯させるようにポートをセットする
 */
int LightDigit( int num )
{
    int dig[] = {	DIGIT0 , 
		DIGIT1 , 
		DIGIT2 , 
		DIGIT3 , 
		DIGIT4 , 
		DIGIT5 , 
		DIGIT6 ,
		};
    
    return dig[num];
}

/*2桁でカウント
 *00から始まって99まで進む……すすめたらいいな
 */
void Count( void )
{
    int disp[2] = { 0 , 0 };
    int i;
    int j;
    int k;
    int wait;
    
    for( ;; )
    {
        for( j = 0; j < 100; j++ )
        {
            //1桁目の点灯
            PDR5 = LightDigit( 0 );
            PDR8 = LightNumber( disp[0] );
            
            //僅かな時間点灯させる
            for( wait = 0; wait < 10000; wait++ )
            {
                NOP();
            }
            
            //2桁目の点灯
            PDR5 = LightDigit( 1 );
            PDR8 = LightNumber( disp[1] );
            
            //僅かな時間点灯させる
            for( wait = 0; wait < 10000; wait++ )
            {
                NOP();
            }
            
        }
        
        //桁制御
        disp[0]++;
        if( disp[0] > 9 )
        {
            disp[0] = 0;
            disp[1]++;
            
            if( disp[1] > 9 )
            {
                disp[0] = 0;
                disp[1] = 0;
            }
        }
    }
}

/*タイマーAを使用して1秒毎に割り込みを行う関数
 *これにより1秒毎にカウントアップができるようになる気がする
 *できてほしい
 *まだよくわかってない
 *帰りたい
 */
#pragma interrupt
void int_timera( void )
{
    IRR1 &= ~IRRTA;		/*タイマAの割り込み要求をクリア*/
    count++;
}

/*7セグメントLEDを0から9の順に点灯させるプログラム*/
int main()
{
    int wait;
    //CLI();	//初期化操作のため割り込みを禁止
    
    //ポート1は7セグメントLEDの数値表示に用いる
    //ポート1は接触不良のため使用不可
    //PMR1 = 0x00;    /*汎用入出力ポートに設定*/
    //PCR1 = 0xff;	     /*ポート1を全ビット出力用に使用*/
    //PDR1 = 0x00;    /*ポート1をクリア*/
    
    //ポート5はどの7セグメントLEDを点灯させるかのトランジスタでのスイッチングに用いる
    PMR5 = 0x00;	    /*汎用入出力ポートに設定*/
    PCR5 = 0xff;	    /*全ビット出力用に設定*/
    PDR5 = 0x00;	    /*ポート5をクリア*/
	
    //ポート8は7セグメントLEDの数値表示に用いる
    //PMR8 = 0x00;   /*ポートBは出力専用なのか?*/
    PCR8 = 0xff;        /*ポートBを全ビット出力用に使用*/
    PDR8 = 0x00;      /*ポートBをクリア*/
	
    //この下の4行はコメントを外すと動かないことから怪しいがこれがないと割り込みできない
    //TMA = 0x8;           //タイマーAを低速時計用クロック、速度は1秒間隔に設定
    //STI();                     //初期化操作終了とともに割り込みを許可
    //IENR1 |= IENTA;    //タイマAの割り込みを許可
    //IRR1 &= ~IRRTA;  //タイマAの割り込み要求をクリア
    
    //この関数ならカウントアップ可能
    //Count();
    
    //このへんから割り込みなど行いたいがうんともすんとも。
    while( 1 )
    {
        if( count > 9 )
        {
            count = 0;
        }
        
        PDR5 = LightDigit( 0 );
        PDR8 = LightNumber( count );
        //僅かな時間点灯させる
        for( wait = 0; wait < 10000; wait++ )
        {
            NOP();
        }
    }
}