78k0sで38k発振テスト

 2011-02-26
LIRCではエアコンの赤外線を扱えなかったので、とりあえず78k0sでやれないかテストするという記事なのさ

LIRCでエアコンの信号も学習できれば…こんなことせんでも良かったのになぁ。
 
リモコンの信号は赤外線でやりとりしているわけですが、赤外線なんて日常にありふれているので馬鹿正直に赤外線を受信しているとノイズが多い。そこで一般的な家電では38kHzのキャリア波を用いている。らしい。38kHz付近「以外」の赤外線をフィルタして無視することでノイズの影響を低減しているのです。
そして38kHzで明滅する赤外線がある時間に観測される/されないを情報の1/0としているというワケ。

そんなわけでまず第一歩として78k0sから38kHzの信号を出力するテストを行います。最終工程ではこの38kHzを出したり止めたりして信号を発振するので、まずは38kを出せないとお話になりません。



78k0sはCPUクロックに内蔵高速リング発振の8MHzを使います。つまりロジックは8MHz動作です。この時、104クロック毎に外部端子の0/1を反転させると、約38kHzの出力が得られます。(8MHz ÷ 208分周 = 38.46kHz)

…とまあ、それをCPU命令で行うのも良いのですが、、、少々問題があります。出力を反転させるということは、一度「現在の値」を取得しなくてはなりませんし、その動作の分だけクロックを使うことになるです。if文で分岐しても結局は同じです。さらに割り込み処理等もあるとまたそこでクロックの調整が必要です。嗚呼、面倒臭い。

なので今回は8bitタイマ H1を使います。これは上記の動作をCPU命令無しで行うハードウェアです。最初にいくつか設定を流し込んでやるだけで動きます。わあ、便利。


タイマを発振させるところ↓
#define	TM_TM00_CLOCK	0x0
#define TM_TMH1_SQUAREWIDTH 0x68

TMHMD1 |= ( TM_TMH1_CLOCK << 4 ); /* set count clock */

/* TMH1 square wave output */
SetIORBit(TMHMD1, 0x1); /* enable output */
ClrIORBit(P4, 0x04);
ClrIORBit(PM4, 0x04); /* P42/TOH1 */
ClrIORBit(TMHMD1, 0x2);
CMP01 = TM_TMH1_SQUAREWIDTH;

上はApplilet君が吐いてくれたお便利コードの部分。
TM_TM00_CLOCKを0x0でdefineしてTMHMD1レジスタの6-4bit目に収めます。TMHMD1レジスタの6-4bitはクロックセレクタとなっており、いくつか選べますが今回はCPU動作クロックをそのまま使います。ということで8MHzです。
つづいてTM_TMH1_SQUAREWIDTHに0x68をdefineしてCMP01レジスタに転送します。これはコンペアレジスタであり、8MHzをカウントしていって0x68になると出力端子の値を反転させます。0x68は十進数で104ですね。104クロック数えたところで出力が反転します。(=208分周)
その他の行はお決まりの設定なので魔法の呪文だと思って下さい。

あとはmain関数の上の方で上記のコードが実行されるようにしておけばオッケー。最初に一回だけ実行すればあとはタイマーH1がずーっと動いてくれます。



DSC_0074.jpg DSC_0075.jpg
秋月のマルチテスタの周波数測定で見てみると、38.08kHzとなり問題なし!
8MHzの208分周は38.46kHzですが、リング8MHz自体や測定器の誤差もあるので今回は不問とする。40kHzのキャリアでも赤外送信できたという記載もWebにあったのであんまり精度は必要ない。

デューティー比測定もあったのでついでに確認。方形波出力させているので約50%となりました。オッケー!


78k0sでの38kHz発振テスト: 問題なし



おまけ: 疑似waitを実装し、CPU命令で5Hzを発振
#define WAIT_MS 197
void wait_ms(unsigned int);

void main( void ){
P4.1=0x1;
while(1){
wait_ms(100);
P4.1 = ~P4.1;
}
}

void wait_ms(unsigned int wait){
unsigned char count;
for(;wait>0;wait--){
for(count=WAIT_MS;count>0;count--){
;
}
}
return;
}
関係ない箇所は省略しています。

P4.1ってのが外部出力レジスタで、whileの無限ループで反転させているだけのコード。
ここのキモはWAIT_MSのdefine数。この数字の分だけ空っぽのforを回してCPU命令を無駄遣いさせている。1ms分だけwaitできる数になっているのが望ましい。

今回はwait_ms(100);しているので100ms毎に出力がトグルします。つまり周期は200msとなり、5Hzです。

DSC_0076.jpg
適当に5Hzを確認。

 
コメント












管理者にだけ表示を許可する
トラックバック
トラックバックURL:
http://wbbwbb.blog83.fc2.com/tb.php/38-f5ce4b7f
≪ トップページへこのページの先頭へ  ≫