aitendoで買ったSTCmicroのSTC12C2052でプログラミングできるようになったので、8Queen問題を解くプログラムを走らせてみた。
以前作った8031SBC用に書いたソースを変更した。 (8Queen2011/09/15)
8031(8051のROM無し)は内臓RAMが128byteしかないので、スタックを消費する再帰プログラムは厳しい。
↓オプション --idata_loc 0x0000 --idata_size 128(8031用)でコンパイルするとスタックは98byteとれた。
-- 8031; ---
Internal RAM layout:
0 1 2 3 4 5 6 7 8 9 A B C D E F
0x00:|0|0|0|0|0|0|0|0|a|b|b|c|d|e|e| |
0x10:| | | | | | | | | | | | | | | | |
0x20:|T|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x30:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x40:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x50:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x60:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x70:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x80:| | | | | | | | | | | | | | | | |
0x90:| | | | | | | | | | | | | | | | |
0xa0:| | | | | | | | | | | | | | | | |
0xb0:| | | | | | | | | | | | | | | | |
0xc0:| | | | | | | | | | | | | | | | |
0xd0:| | | | | | | | | | | | | | | | |
0xe0:| | | | | | | | | | | | | | | | |
0xf0:| | | | | | | | | | | | | | | | |
0-3:Reg Banks, T:Bit regs, a-z:Data, B:Bits, Q:Overlay, I:iData, S:Stack, A:Absolute
STC12C2052は256byteの内臓RAMが載っているので、オプション --idata_size 240でコンパイルするとスタックは192byte確保できている。(なぜ--idata_size 256ではないかは後で)
-- STC12C2052 ---
Internal RAM layout:
0 1 2 3 4 5 6 7 8 9 A B C D E F
0x00:|0|0|0|0|0|0|0|0|a|a|a|a|a|a|a|a|
0x10:|a|b|b|b|b|b|b|b|b|b|b|b|b|b|b|b|
0x20:|b|b|b|b|b|b|b|b|b|c|d|d|e|Q|Q|Q|
0x30:|Q|Q|Q|Q|Q|S|S|S|S|S|S|S|S|S|S|S|
0x40:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x50:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x60:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x70:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x80:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0x90:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0xa0:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0xb0:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0xc0:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0xd0:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0xe0:|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|S|
0xf0:| | | | | | | | | | | | | | | | |
0-3:Reg Banks, T:Bit regs, a-z:Data, B:Bits, Q:Overlay, I:iData, S:Stack, A:Absolute
プログラム用のメモリが2kbyteしかないので、printf()は使えない。
↓実行結果
ところで、内蔵のR/C発振器でUARTを使おうとしたら、一発では動かない。ソースはそのままで動くと思っていた。
通信速度の設定はTH1、TL1に設定する値で決まる。
TH1 = TL1 = 256 - (クロック周波数 / 12 / 32 / 通信速度)
SDCCのライブラリに autobaud()という関数がある。この関数を呼んでRxDにCR(0Dh)を送ると1byte(8bit)分の時間を測ってTH1、TL1レジスタを自動的に設定してくれるという便利な関数だ。
この関数を使ってみると、4,800bpsでは文字化けが多い、4,800bpsで動いていも次の日には文字化けが多くて使い物にならなくなる。確実に動かすには1,200bpsまで下げなければならない。
TH1、TL1レジスタにセットされている値を表示させてみると大きい。 (TH1,TL1=FDh @4,800bps)
この値が大きいとズレが大きくなる。または正確なクロック周波数の発振器が必要だ。
データーシートではクロック周波数は18.234MHzと書いてあることが多いので、R/C発振器の周波数も18.234MHzかと思っていた。 よく読むとそんなことは書いてない。
データーシートに「R/C発振器の周波数を知る方法」が載っている。
電源ON直後、内蔵RAMのF8h~FBh、FCh~FFhを読むことで分かるのだそうだ。F8h~FBhに直前の設定値、FCh~FFhに工場出荷時の設定値が書かれている。この領域はRAMとして普通に使えるので当然データを書いたり読んだりできる。
確認してみようと、この領域を読みだすと全て 00hだ。 (?_?
SDCCはstart_up時にIDATA領域をクリアする。 (SDCC/lib/src/mcs51/crtclean.asm) つまり、IDATA領域の末尾の部分(F8h~FFh)も00hでクリアされているようだ。
SDCCは --idata_loc と --idata_size オプションでIDATAのサイズと位置を指定できる。そこで、内蔵RAM(IDATA)は256byteあるけど --idata_size 240 とすると、F8h~FFhがクリアされなくなる。
読んでみた。
工場出荷時の設定値は 5,619776MHz、電源投入時の設定値は5,669,485MHzのようだ。
よく見たら、stcgal.pyのメッセージで表示される値だ。
【最近の投稿】【最近のCPUボード】【8031/8052 SBC】【2016の投稿】【2015の投稿】
最近のコメント