連載
» 2010年03月26日 00時00分 公開

イチから作って丸ごと学ぶ! H8マイコン道(12):シリアル通信でオリジナルprintf関数を作ろう (3/3)

[横田一弘 埼玉県立新座総合技術高等学校 教諭,@IT MONOist]
前のページへ 1|2|3       

マイコンのプログラムをパソコンでデバッグする

――晴子さんは、簡単に「printf関数を作って!」というけれど、実際、プログラムをROMに書き込んで実行・デバッグするのはとても手間が掛かります。そこで、C言語の利点を生かして、パソコンでデバッグしてはいかかでしょうか?

 シリアル通信の応用として、オリジナルprintf関数を作ってみましょう。

 いままでのプログラムでは、H8Tiny-USBにプログラムをダウンロードして、すなわち、実機で動作を確認してきました。しかし、そのやり方では手間が掛かりますし、マイコンのフラッシュメモリの寿命を浪費しかねません。

 そこで今回は、パソコン上でプログラムを完成させ、最後にマイコンで動作を確認する方法を取ります。


 今回、晴子さんは以下の「mprintf関数」を作りました(ソースコード2)。

/*==============================================================================
 +
 + 書式付きターミナル出力
 +
 +============================================================================*/
#include <stdarg.h>
/*#define H8TINY_USB*/
 
#ifdef H8TINY_USB
# include "sci.h"
# define output(ch)    sci_putc(ch)
#else
# include <stdio.h>
# define output(ch)    putchar(ch)
#endif
 
#define C_MAX 12    /* ロングデータを8進数で表示するときの最大けた数 */
 
static void outs(char *, short);
static void outc(char, short);
static void outn(char, unsigned long, short);
 
void mprintf(char *fmt, ...);
 
/*------------------------------------------------------------------------------
 + 書式付きターミナル出力
 +----------------------------------------------------------------------------*/
void mprintf(char *fmt, ...)
{
    va_list args;
    char *p;
    unsigned long v;
    short c;
 
    va_start(args, fmt);
    for (p = fmt; *p != '\0'; p++) {
        if (*p == '%') {
            p++;
            if ((*p >= '1') && (*p <= '9')) {
                c = *p++ - '0';
                while ((*p >= '0') && (*p <= '9')) c = c * 10 + (*p++ - '0');
            }
            else
                c = -1;
 
            v = (unsigned long)va_arg(args, long);
 
            switch (*p) {
            case 's':
                outs((char*)v, c);
                break;
            case 'c':
                outc((char)v, c);
                break;
            case 'd': case 'o': case 'x':
                outn(*p, v, c);
            }
            if (*p == '\0') goto fin;
        }
        else if (*p == '\n') {
#ifdef H8TINY_USB
            output('\r');
#endif
            output('\n');
        }
        else
            output(*p);
    }
fin:
    va_end(args);
}
 
/*------------------------------------------------------------------------------
 + 文字列を出力する
 +----------------------------------------------------------------------------*/
static void outs(char *s, short c)
{
    char *p;
    for (p = s; *p != '\0'; p++) {
        if (c-- == 0) return;
        output(*p);
    }
    while (c-- > 0) output(' ');
}
 
/*------------------------------------------------------------------------------
 + 文字を出力する
 +----------------------------------------------------------------------------*/
static void outc(char ch, short c)
{
    output(ch);
    while (--c > 0) output(' ');
}
 
/*------------------------------------------------------------------------------
 + 整数を出力する
 +----------------------------------------------------------------------------*/
static void outn(char fm, unsigned long v, short c)
{
    char s[C_MAX], *p, z;
    unsigned short b;
 
    switch (fm) {
    case 'd':
        b = 10; z = ' '; break;
    case 'o':
        b = 8; z = '0'; break;
    case 'x':
        b = 16; z = '0'; break;
    default:
        return;
    }
    p = s;
    do {
        c--;
        *p++ = "0123456789abcdef"[v % b];
        v /= b;
    } while (v != 0);
 
    for (; c > 0; c--) output(z);
 
    while (p > s) output(*--p);
} 
ソースコード2 晴子さんが作った「mprintf関数」

 このモジュールをmain関数で呼び出すと、図9のようにパソコンのgccで動かすことができます(ここから「print.lzh」をダウンロード)。

パソコンでmprintf関数をデバッグ 図9 パソコンでmprintf関数をデバッグ

 パソコンでの動作が確認できたところで、今度はH8Tiny-USBで動作させます(ここから「hello2.lzh」をダウンロード)。

mprintf関数の実行 図10 mprintf関数の実行

 いかがでしょうか? C言語プログラムは機種に関係なく動作させることができるので、以上のようなデバッグの方法が可能です。

 それでは、晴子さんオリジナルのprintfモジュールを詳しく調べてみましょう。

 晴子さんのプログラムでは、機種依存となる1文字出力をうまく切り替えています。

/*#define H8TINY_USB*/
 
#ifdef H8TINY_USB
# include "sci.h"
# define output(ch)    sci_putc(ch)
#else
# include <stdio.h>
# define output(ch)    putchar(ch)
#endif 

の記述がそれで、

/*#define H8TINY_USB*/ 

のコメントを消して、「H8TINY_USB」を定義すると、1文字出力関数にH8Tiny_USBのシリアルポートが使われます。

 コメントアウトした状態では、標準入出力のputchar関数が使われるので、同じプログラムがパソコンで動きました。


photo

すごーい。晴子さん!


さすが!!


photo

C言語でプログラムを作っているんだから、それを生かさない手はないわね。


photo

ところで晴子さん、卒業後はどうするんですか?


photo

組み込みソフトウェア開発の企業から内定をもらったの。


ワタシ、忙しくなるからしばらく健一君にも会えないわね(涙)。


photo

グスン……(涙)。


photo

もう!! 健一君まで泣かないの!


健一君ももっとマイコン勉強して、ワタシを追いかけてきてね。


photo

はい! もっと勉強して晴子さんに似合うオトコになります!


そ、そうすれば、デ、デートも……。


photo

そうね。楽しみにしてるわ。


ウフフッ。





 今回は、視点を変えてマイコンのソフトウェア開発環境について触れました。マイコンのソフトウェア開発の特徴的な点として“ROM化”があります。プログラムもシステムに組み込まなければなりません。ですから、ソフトウェア開発環境が何をしているのかを分かっていた方が、断然、有利なのです。

 さて、ハードウェアの製作からプログラミングまでを一貫してお届けしてきた連載「イチから作って丸ごと学ぶ! H8マイコン道」もこれで終わりです。

 健一君、そして、読者の皆さま、1年間お疲れさまでした。思い返すと、健一君はいつも晴子さんにやり込められてばかりでしたね。そして、健一君を指導してくれた二三夫さん、晴子さんも本当にありがとうございました。本連載が組み込み開発に携わる、そしてこれから組み込みの世界に飛び込もうとしている方々のお役に立てば幸いです。それでは皆さん、またどこかでお会いしましょう! さようなら。 (連載完)


前のページへ 1|2|3       

Copyright © ITmedia, Inc. All Rights Reserved.