裏目小僧の部屋に
(戻る)
4ビットマイコンのテクニック 主に東芝TLCS47(TMP47) 2000/1月着工 現在工事中

一般的アルゴリズムについて
チャタリング
10〜30m秒間隔でサンプリングした信号を前回と比較し、前回と同じビット
だけを使います。この判断を論理演算だけでする方法です。
;	Accに、入力データを
;	HLにP_OLDのアドレスを入れる。(P_OLD/P_BUF/P_MSKは同じアドレスに)
;	
;	P_OLD:RES  x	;このルーチンを呼んだ前回のビット状態が、
;	P_BUF:RES  x	;2回同じ状態に安定した場合だけ取り込まれる。
;	P_MSK:RES  x	;P_BUFが0->1になった時だけ1になる状態でret
CHAT_SUB:
	XCH	A,@HL  ;(P_OLD)
	XOR	A,@HL  ;(P_OLD)
	SUBR	A,#15  ;(CPL A)=NOT 処理 で、前回と同じビットだけ1になる
	ADD	L,#NLL  (P_MSK-P_OLD)
	ST	A,@HL  ;(P_MSK)
	ADD	L,#NLL  (P_OLD-P_MSK)
	LD	A,@HL  ;(P_OLD)	;今回のBIT	
	ADD	L,#NLL  (P_BUF-P_OLD)
	XOR	A,@HL  ;(P_BUF)	;今回とバッファで違うビットが1
	ADD	L,#NLL  (P_MSK-P_BUF)
	AND	A,@HL  ;(P_MSK)
	ADD	L,#NLL  (P_BUF-P_MSK)
	XCH	A,@HL  ;(P_BUF) ;直前のメモリには前回迄の安定状態が
	XOR	A,@HL  ;(P_BUF) ;  2回同じ状態でかつ異なるビットだけ反転
	XCH	A,@HL  ;(P_BUF)	;
	AND	A,@HL  ;(P_BUF) ;0->1のエッジだけみる
	ADD	L,#NLL  (P_MSK-P_BUF)
	ST	A,@HL  ;(P_MSK) ;エッジ発見フラグに1
	RET
スイッチ
入力
  CPUの入力ポートにスイッチ/リレー/リミットスイッチなんかを接続する時に
  使う回路です。

                   /
   ◎---------+----+ +5V
  SW        |
             ===C1
              |
   ◎---R1----+--------R2------○ CPU 双方向入力ポート
   C1=0.1uF  R1=330Ω R2=10K

    C1に貯えられた電荷がスイッチがONした瞬間R1を通して接点に流れ、
    接点のクリーニング動作をします。

  この回路だけみるとプルダウン抵抗を忘れていると思う人も居るでしょう。
   CPU側は普段 少しLパルスを出しては読み出すという動作をします。
    -->この動作により R2を通してプルダウンされる事になります。
   R2が0と判断すればそのパルス幅を広げます。
    -->これにより一種のシュミット動作をする事になり、チャタリング取り
       をする事になります。

   またR1,C1のCR回路で外来ノイズを軽減し、R2により高電圧から保護する
   保護回路としての役目も期待出来ます。

  接点に十分にクリーニング電流を流せ、かつ普段は低消費電力となります。
   電流を消費するのは接点ON時に R2を通して流すパルス電流です。

   プログラム例: R4の下3ビットが連続するスイッチ入力ポートとして
  1     OUT       #1000B,%04H
  2     NOP
  3     NOP
  4     NOP
  5     OUT       #1111B,%04H
  6     NOP
  7     NOP
  8     IN        %04H,A
  9     OR        A,#1000B
 10     OUT       A,%04H
 11     RET
  注意すべき事は このルーチンが呼ばれる周期と 1〜4ステップの出力パルス
   の比です。その比だけ C1*R2の時定数時間が延長されます。たとえば周期
   が2mSでパルスが10uSであれば200倍に延長される事になります。
   C1*R1時定数が0.3mS程度でしたら60mS程度です。この時間を調整すれば
   チャタリング取りに利用出来ます。
XCH
  Accとメモリを1命令で交換する命令です。この命令は非常に強力で便利な命
  令です。 TMP47では2マシンサイクルで実行されるので実行時間短縮にも有効
  に使えます。
  例えば、TMP47に用意されているシリアル送信を外部同期で使用したい場合、
  SIO割込みでの応答は出来るだけ短くしたいのです。というのは、この時間が
  クロック最少幅を決めてしまうからです。内部のSIOの能力ではクロック4MHz
  の時,100KBPSが可能な筈ですが,それを実現するには割込み中で %0FHポート
  への出力命令が割込み要求から 16MC程度でなされる事.また,割込み処理全
  体が20MC以内で終わる必要があります.
     割込み処理を
  V_SIO:
          XCH        A,(SIOSV_A)        ;1)
          OUT        A,%0FH                ;2)シリアル出力
          ...                        ;  次ぎの送信データをAccに用意
          XCH        A,(SIOSV_A)        ;3)
          RETI                        ;4)
  のようにします。1),3)でAccを保存すると同時に、次に出力すべきデータを
  準備しています。
    次ぎの送信データをAccに用意する処理も
          XCH        HL,(SIO_HL)
          LD        A,@HL
          INC        L
          XCH        HL,(SIO_HL)
   とXCHを使えば簡単に表現出来ます。
割込
との通信

   例えば、割込みがあった事をメインループに知らせ、メインがそれを
   受け取るような場合、1命令でread/writeの両方の働きをする命令を
   使うのが便利です。例えば割込みで
   V_TIMER1:
           ADD        (INTFLAG),#1
           RETI
   とコーデングされている時、この割込みがあるのをメインで
   WAIT_INT:                           1)
           LD        A,(INTFLAG)       2)
           BE        A,#0,WAIT_INT     3)
           DEC       A                 4)
           ST        A,(INTFLAG)       5)
   このようにすると、もし2),3)の行を実行している間に割込みがあった
   場合にミスカウントしてしまいます。
   WAIT_INT:                           1)
           EI
           NOP                        ;割込みがかかるようNOPを入れる
           DI
           LD        A,(INTFLAG)       2)
           BE        A,#0,WAIT_INT     3)
           DEC       A                 4)
           ST        A,(INTFLAG)       5)
           EI
   と結構面倒です。
   EI,DIを使わなくとも
   4),5)行をADD        (INTFLAG),#16-1で置き替えれば解決します。
sin
  例1:1度程度の精度で良い
      2バイトで角度を表現  H,L
         DEG=(H*256+L)*360/1024 
        テーブルとして、HL=0〜255(0〜90°)迄の表を用意
        HについてはMOD 4を実行する
         IF H=0(00B) THEN +TBL[Z    ]
         IF H=1(01B) THEN +TBL[256-Z]
         IF H=2(10B) THEN -TBL[Z    ]
         IF H=3(11B) THEN -TBL[256-Z]

    角度が1度精度なら、TBLも8ビットあれば十分

 例2:1/100°程度の精度が必要
         2バイトで角度を表現      DEG=(HL*360)/65546
           H=ssdddddd L=ddrrrrrr
         計算する方法は2ビットシフトして例1の方法で8ビット間隔
     で求め、その間を補間して残り6ビット精度を出すか、以下の
     ように3角公式を使って計算する
             x=X+R X:下位6BIT=0  R:残り精度
      sin(x)=SIN(X+R)=SIN(X)*COS(R)+COS(X)*SIN(R)
     つまり    SIN(X),COS(X) と SIN(R),COS(R)のテーブルを
      用意しておけば良い。
          SIX(X)はアドレス8ビットで用意しCOS(X)と共用する。
          SIN(R) は6ビット=64個なので別個に用意しても簡単。
       実際にテーブルを作れば解るが、非常に単調な表なので1次近
     似でも1/100°程度ならば良い。例 SIN(R)≒6.28*R

         COS(R)はこの精度でこの区間ならば1と見なしても良い。
          -->最も小さな値はR=63の時でCOS(R)=0.9999817だから
             求める精度が16bitなら再下位1BITに影響する程度

       テーブルについては 16bit用意し、2^16=65536になるようにする
    ssの2ビットで符号は判っているので、符号フラグは別WORDに取
    る。まずss=00 の時 T=X/64として 
     sin(x)=SIN(X+R)=SIN(T)*COS(R)+COS(T)*SIN(R)
                       =SIN(T)+(SIN(256-T)*R*201)/32/65536

         R*201は8ビット以下なので掛算命令を内臓しているマイコンな
    ら比較的実装が容易と思われる。

        それ以上の精度が必要な場合は、当然真面目に計算するしかない
赤外リモコン送受
これはメシのタネなのであまり詳しくは書けません
オーダで送信部、受信部共、廉く作りますからよろしくお願いします。
あ、これらの情報はメーカ資料等の公開ではありません。独自に解析したものです

 赤外コードの変調周波数は38KHz〜42KHzが良く使われます
 [ヘッダ][データ部][連続無信号]で構成されます
 データ部は 変調:無信号の時間割合で0:1を区別します。
 変調を @ 無信号を_とすると
  Nタイプ 0:@_  1:@___   無信号時間が 1:3 全体の時間比が1:4(多い)
  Sタイプ 0:@_  1:@@_    信号時間が   1:2 全体の時間比が1:3 (SONY)
  この2つが殆どです。Nタイプが多いですね。
  ヘッダは H:@@@@@@@@________
  とデータに比べて長い変調部と無信号期間で構成されます
  これは各社微妙に違います。

 データ部は普通機種部データ部と別れています。
 Nタイプの多くは機種部とデータ部がそれぞれ反転したデータつく事が多いです
 これは、チェックの意味と、変調信号の長さを同じにする目的の2つの為ですね。
 Sタイプ(ソニー)では、信号そのものでチェックサムを取らず、代わりに短い
 周期で送出して2度同じコードだったら受信するという方式を取っいます。
 Nタイプでも、この反転信号を付加しないものもあります。
  Nタイプのコードについては、トラ技とかにタマに掲載されるのでそちらを
  参考して下さい。
 
 SONYの場合、独自のコード体系とした為に、機種コードで他社と区別する必要が
 無い為か非常に短いコードとなっています。 LSB先出しです。
  12bit 20bit 他に業務用では15bitなどのコードがあります
  
機種部 の例 
    VTR1        H---- ---  0100 0
    VTR2        H---- ---  1110 0
    VTR3        H---- ---  1101 0
    VTR4        H---- ---  1001 1101 00100
    VTR5        H---- ---  1001 1101 00110
    VTR6        H---- ---  1001 1101 00101
    DVD         H---- ---  0101 1100 10010
    TV          H---- ---  1000 0
    LD          H---- ---  0110 0
    CD          H---- ---  1000 1
コード部 の例
        CH-UP   H0000 100  ---- -
        CH-DOWN H1000 100  ---- -
        VR-UP   H0100 100  ---- -
        VR-DOWN H1100 100  ---- -
        POWER   H1010 100  ---- -
        EJECT   H0110 100  ---- -
        STOP    H0001 100  ---- -
        PAUSE   H1001 100  ---- -
        PLAY    H0101 100  ---- -
        REW     H1101 100  ---- -
        FF      H0011 100  ---- -
        REC     H1011 100  ---- -

自分用47P443レジュメ