フォト
無料ブログはココログ

8031/8052 SBC

2017年10月 8日 (日)

STC12C2052(2) <8Queen問題>

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()は使えない。
↓実行結果

Stc12c2052_8q

 ところで、内蔵の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がクリアされなくなる。

 読んでみた。
Stc12c2052_freq  

 工場出荷時の設定値は 5,619776MHz、電源投入時の設定値は5,669,485MHzのようだ。

 よく見たら、stcgal.pyのメッセージで表示される値だ。



最近の投稿】【最近のCPUボード】【8031/8052 SBC】【2016の投稿】【2015の投稿

2012年11月11日 (日)

8052BASIC(6)

プログラムがEEPROMにセーブできない原因を調べていた。

 配線を調べたが間違っていないようなので、EEPROM書き込みタイミングの問題かと思いEEPROMをSRAMに変えてみたが症状は変わらない。
 ロジアナを持ち出して調べてみたところ、EEPROMの#WE、#OE、#CE、R/#Bは問題ないようだ。
良く見るとデータが全て00Hである??。

 EEPROMをダンププログラムでダンプするとちゃんと読めている。問題はEEPROMではないのではと思いEEPROMを取り外してROMのアドレスをダンプすると全て00hである。
Dump8000h
あれれ、EEPROMを取り外したので、全てFFHが読み出されるはずだ。
誰かがデータ・バスをLにドライブしている?ともう一度配線をチェックすると
Pullup
データバスをプルアップしている集合抵抗の左端はVccに接続しなければならないのだが、よく見るとGNDに接続されていてプルダウンされているではないか!!更に、この集合抵抗は7素子でAD7には何も接続されていない。お粗末>自分

 原因がわかったところで、集合抵抗を8素子の物に変えて、本当にプルアップしたら
Dump8000h_ff
全てFFHが読み出されるようになった。

 EEPROMを戻して、プログラムがセーブすると
Fprog1

エラー無く書き込まれた。EEPROMのアドレス8000hをダンプすると、ちゃんと書き込まれているようだ。

 ROMにセーブされたプログラムの一覧を表示するプログラムを書こうかと思ったら、ここにあった。
Romdir
プログラム番号、先頭アドレス、サイズ、先頭のREMを表示してくれる。

2012年11月 3日 (土)

8052BASIC(5)

EEPROMにプログラムが保存できない問題があるが、何はともあれメモリダンププログラム
Hexdump
データメモリをダンプしてみた

 久しぶりにBASICでプログラムを書くと違和感がある。
LISTを表示したときのこのインデントはなじめないなあ。


100    REM


110    REM ###############################
120    REM dump memory
130    REM ###############################
140    STRING 11,5 :  DIM ASCI(16)
150    REM INPUT "address: ",ADR
160    INPUT "length: ",L
170    REM == dump ==
180    FOR I=ADR TO (ADR+L-1)
190    IF (I.AND.0FH)=0 THEN  GOSUB 4000
200   C=XBY(I)
210   HH=C :  GOSUB 2000
215    PRINT " ",
220   ASCI(I.AND.0FH)=C
230    IF C<20H.OR.7EH<C THEN ASCI(I.AND.0FH)=ASC(.)
240    NEXT I
320    GOSUB 3000
325    PRINT
330    INPUT "next:1 end:0 ?",ANS
340    IF ANS<>1 THEN  STOP
350   ADR=ADR+L
360    FOR II=0 TO 15
370   ASCI(II)=0
380    NEXT II
390    GOTO 180
900    STOP
990    REM ===================================
1000   REM print 16bit data / HHHH:print data
1010  HH=INT(HHHH/256) :  GOSUB 2000
1020  HH=HHHH-HH*256 :  GOSUB 2000
1030   PRINT ": ",
1040   RETURN
2000   REM print 8bit data / HH: print data
2010  BB=INT(HH/16)
2020   PRINT CHR(30H+(BB>9)/65535*7+BB),
2030  BB=HH-BB*16
2040   PRINT CHR(30H+(BB>9)/65535*7+BB),
2050   RETURN
2990   REM ===================================
3000   REM print ascii data
3020   FOR II=0 TO 15
3030   PRINT CHR(ASCI(II)),
3040   NEXT II
3050   PRINT
3060   RETURN
4000   REM
4010  HHHH=I :  GOSUB 3000 :  GOTO 1000

行番号2020、2040nの PRINT CHR(30H+(BB>9)/65535*7+BB), をC風に書くと
putchar('0' + (BB>9)? BB+7: BB);
のような感じだ。丁寧に書くと
if (BB>9)
      
putchar('A'+(BB-10));
else putchar('0'+BB);

BASIC-52のtrueは65535(FFFFh)ということを知った。

 お約束の8Queen問題

8queenb52

 BASIC-52はNEXTをGOTOやRETURNで飛び越してはいけないらしい。(ちょっとハマった。)
それにしても遅い!!インタプリタだからね。

 プログラムはPC上のviで書いてターミナル(Traterm)を使って送信する。スクリーンエディタ無しでは生きていけないヘタレになってしまった。
8queenb52_load

 1行入力後処理時間を取らないと文字を落としてしまうのでディレイを入れる。特に長い文は時間がかかるようだ。
8queenb52_load_delay

1      REM ################################


2      REM 8Queen
3      REM Sep. 2012 / Yoshi
4      REM ################################
10     REM init
20    TRUE=(0=0)
30    FALSE=(0=1)
40    N=0 : rem pattern
50    D=0 : rem debug level
60     FOR Y=1 TO 8
70    A(Y)=0       : REM init array
80     NEXT Y
100    REM
110    REM main routine
120    REM
130   S=1
140    FOR Y=1 TO 8
150    FOR X=S TO 8
160   YY=Y : XX=X :  GOSUB 1000 :  REM check
170    IF CHK=FALSE THEN  GOTO 220 :  REM end if
180   A(Y)=X
190   X=8
200   S=1
210    REM gosub 2000
220    REM end if
230    NEXT X
240    IF CHK=TRUE THEN  GOTO 330 :  REM end if
250   S=A(Y-1)+1
260   A(Y-1)=0
270   Y=Y-2
280    IF S<9 THEN  GOTO 320 :  REM end if
290   S=A(Y)+1
300   A(Y)=0
310   Y=Y-1
320    REM end if
330    REM end if
340    IF D>=1 THEN  GOSUB 2000
350    NEXT Y
360    N=N+1
370    GOSUB 2000
390    REM
900    STOP
990    REM =====================================
1000   REM check : pos(x,y)
1010   IF D>=2 THEN  PRINT "(",X,",",Y,")"
1020  CHK=TRUE
1030   IF Y=1 THEN  GOTO 1100 :  REM end if
1040   FOR YY=1 TO Y-1
1050   IF A(Y-YY)=X THEN CHK=FALSE
1060   IF A(Y-YY)=X+YY THEN CHK=FALSE
1070   IF A(Y-YY)=X-YY THEN CHK=FALSE
1080   IF CHK=FALSE THEN YY=Y
1090   NEXT YY
1100   REM endif
1110   RETURN
1120   REM
1990   REM ======================================
2000   REM print array
2010   PRINT "--",N,"--"
2020   IF D>=2 THEN  PRINT "(",X,",",Y,")","S:",S
2030   FOR YY=1 TO 8
2040   FOR XX=1 TO 8
2050   IF A(YY)=XX THEN  PRINT "|X", ELSE  PRINT "| ",
2060   NEXT XX
2070   PRINT "|"
2080   NEXT YY
2090   RETURN
2100   REM

 行番号1と2の間の改行はわざと入れてある。
 NEW実行後、最初に行番号付きでプログラムを入力すると処理に時間がかかるので、行番号1と行番号2の間に改行を入れておくと、ターミナルからプログラムをDLしたときに、ちゃんと入力されるようになる。

2012年10月18日 (木)

8052BASIC(4)

BASIC-52のマニュアルを読んでいて気がついた。
ポート0(AD0-AD7)はオープン・ドレインなのでプルアップしてね。10Kでプルアップするとうまく動いたよ。という注意書きがある。なるほど、それで参考にした回路図は皆プルアップしていたのか!
ということで、とってつけたようなプルアップ抵抗
8052basic_sbc6

プルアップ抵抗追加回路図
8052basic_sbc_12

ところがプログラムをEEPROMに保存しようとするとEEPROMに書けない。
Error_programming

もう一度配線チェックしてみよう。

2012年10月12日 (金)

8052BASIC(3)

74HCT08を買ってきて残りを配線した
8052basic_sbc4

シリアルを繋いで電源を投入し、スペースを入力すると、シリアルの速度が自動認識されて

*MCS-51(tm) BASIC V1.1*   
READY
>

が表示される。
九九の表を表示してみた。

Basic529x9

とりあえず動いたようなのでBASIC-52のマニュアルをじっくり読んでみよう。

2012年10月 6日 (土)

8052BASIC(2)

配線した。
8052basic_sbc_2
HCT08の手持ちが無かったのでここまで。
8052の下に実装しようとするとソケットが使えないので、配線は現物を買ってきてからだ。

裏面、中ほどにシール基板が見える。
8052basic_sbc1

8052basic_sbc2
2階建て部分。奥にあるのは74BC574で手前にHCT08を実装し、その上に8052AH-BASICが載る予定。

アドレスラッチはHCT573を使う予定だったのだが、日米でレール\350のTD74BC573を見つけたのでこれを使うことにした。
Td74bc573
店先に大特価のレールが置いてあると、ついつい漁ってしまう。日米は型番が書いてあるので非常に良い。

2012年9月30日 (日)

8052BASIC

最近ARMやArduinoで遊んでいたので、久しぶりに古いCPUで遊んでみようと思い,
以前に買った8052AH-BASICを使ったSBCを作り始めた。

回路図はマニュアルどおり
8052basic_sbc_11

PassでサンハヤトのICB-293Uに置いてみた
8052basic_sbc3
HCT573とHCT08は8052の下に置くと配線が楽になる。

更に配線作業を減らすために↓これを使う
Icb055
これをRAMとEEPROMの間に使うと大幅に配線.作業が減る。
このシール基板(ICB-055)は半分が600mil×5 でもう半分が300mil×8だ、今回は600milの部分2個分を切って使おう。(64k DRAM×8 の配線に使うと、とても楽そうだ)

 このシール基板販売完了品なので見つけたらまた買っておくかな。ちょっと高いんだよな。


いしかわきょうすけさんも偶然(12/09/16)に 8052AH-BASICについて書いておられる。

2011年10月 6日 (木)

8052AH-BASIC

8052AH-BASIC をとうとう見つけた.

マルツの特価半導体を眺めていたら特価現品限りで8052AHが出ていた.
画像はマーキングが消してあったので,8052AH-BASICかどうかわからなかったけど
まあ1つ買ってみるかと注文したら8052AH-BASICだった。

8052basic

マーキング部分拡大
8052basic_marking
1991の11週か

2011年9月15日 (木)

8Queen

 8Queen問題のプログラムを書いてみた.
 8Queen問題といえば,再帰プログラムということで再帰で書いたのだが8051/31は内臓RAMが少ないので関数のネストが深くなる再帰プログラムには厳しい.

DATAとSTACKをXRAMに移したのだがスタックが足りない.ようだ


--- 8queen.mem --
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|c|c|c|c|c|c|
0x10:|c|c|d|e|e| | | | | | | | | | | |
0x20:|B|T|I|I|I|I|I|I|I|I|I|I|I|I|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

 よく見てみると,使った覚えはないiDataやBitsが使われている.(20h-2Dh)
 調べたところ,ライブラリで使われているようで,printf_small()をprintf()に変えると95byte使えるようになった.
 できたバイナリはかなり大きいが,CODEにSTACKは代えられない.

-- 8queen.c ---
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


ようやく通った
8queen

再帰呼び出しする関数は次のとおりである. が...

char place(char x, char y) __reentrant {
    static char n = 1;

    if (check(x,y)) {
        table[y] = x;
        if (y==7) {
            printtb(n++);
            return FALSE;
        } else {
            if (place(0, y+1)) {
                return TRUE;
            } else {
                table[y] = 0xff;
                if (x==7)
                        return FALSE;
                else    return place(x+1,y);
                }
            }
    } else {
        if (x==7)
                return FALSE;
        else    return place(x+1, y);
    }
}

ほんとうはこうしたいのだが, 再帰レベルが増えるのでスタックが足りなくなる.

char place(char x, char y) __reentrant {
    static char n = 1;

    if (7<=y) {  /* 解 */
        printtb(n++);
        return FALSE;
    }
    if (7<=x) {  /* 見つからない */
        return FALSE;
    }

    if (check(x,y)) {         table[y] = x;
        place(0, y+1);         table[y] = (u_char)-1;     }
    return place(x+1, y); }

2011年9月 6日 (火)

sdcc

SDCCでテストプログラムを書いてみる.
まずは Hello World


/*
 * hello world
 * Sep.2011 / Yoshi
 */
#include <stdio.h>
#include <mcs51>

#include "io.h"
#define printf printf_fast

void main(void) {
        printf("Hello world!\n");
        exit(0);
}

io.c


#include <stdio.h>
#include <mcs51/8051.h>
#include "e;paulmon2.h"e
#include "io.h"

char getchar(void) {
        return pm2_cin();
}

void putchar(char c) {
        if (c=='\n') pm2_cout('\r');
        pm2_cout(c);
}

void exit(char c) __naked {
        c;
        __asm
        ljmp 0x0000
        __endasm;
}

pm2_cin(),pm2_cout()はPaulmon2への入出力サブルーチンへのインタフェースが記述されたpaulmon2.cで定義されている.
paulmon2.c, paulmon2.h は親切な人が公開しているのでぐぐると見つかる

コンパイル

#sdcc -mmcs51 --model-small --code-loc 0x8000 hello.c io.rel paulmon2.rel

実行結果

Helloworld

九九の表

9x9

printf_fast() は %3d のように出力幅を指定できるが %02x のように0で埋めることができない. printf_small() はその逆らしい.「帯に短したすきに長し」

 EZ-USBで遊んでいたころにsdccを使っていた.    EZ-USBはCODE領域が2kしかないので,printf_tiny()しか使えずソースコードに手を入れて %02x がちゃんと出力されるようにして使っていた.
8031SBCはcode領域が32kとれるのでとっても楽である.

より以前の記事一覧