X



トップページ電気・電子
146コメント53KB
H8
0122774ワット発電中さん
垢版 |
2019/04/24(水) 08:19:34.91ID:ZfM5v4b/
;一文字だけの16進変換
;extern char itox1(char)
; .export _itox1
_itox1:
and.b #15,R0L ;16進1文字の範囲でマスク
cmp.b #10,R0L ;数値判定
blt ?_itox1_num ;10以下の場合分岐
add.b #7,R0L ;英字の場合の処理

?_itox1_num:
add.b #48,R0L ;文字記号へ変換
rts
0123774ワット発電中さん
垢版 |
2019/04/24(水) 08:22:13.97ID:ZfM5v4b/
;itoa1;一文字の整数から文字への変換
;extern char itoa1(char)
; .export _itoa1
_itoa1:
cmp.b #9,R0L
bgt ?_itoa1_end ;整数が数値範囲外か判定
add.b #48,R0L
rts

?_itoa1_end:
mov.b #45,R0L ;数値以外は文字"-"で返す
rts
0124774ワット発電中さん
垢版 |
2019/04/24(水) 08:27:06.21ID:ZfM5v4b/
;ソフトシリアル出力(P80-81,P81は反転,bps速度はディレイで任意設定)
;extern void ser01(char)
; .export _ser01
PCR8 .equ H'00FFEB ;I/Oレジスタ定義
PDR8 .equ H'00FFDB ;3694は64K範囲のみ
_ser01:
push R1 ;作業用退避
mov.b R0L,R0H ;引数R0Lをコピー
mov.w #0,E0
mov.b #1,R0H ;stopbit作成
shll.w R0 ;下位ビットゼロクリアしてstartbit作成

mov.b #B'11,R1L ;ポート出力設定
mov.b R1L,@PCR8
mov.b #B'10,R1L ;データ出力
mov.b R1L,@PDR8
0125774ワット発電中さん
垢版 |
2019/04/24(水) 08:29:34.04ID:ZfM5v4b/
?_loop:
nop ;delay作成
nop
shlr.w R0 ;1bit取り出してCYへ
bst #0,@PDR8 ;CYからgpioへ通常出力
bist #1,@PDR8 ;反転シリアル出力

cmp #0,R0 ;比較
bne ?_loop ;送信データ空でない時ループ

pop R1 ;復帰
rts
0126774ワット発電中さん
垢版 |
2019/04/27(土) 16:38:14.22ID:5M9Yonpr
;TimerAの設定処理をアセンブラで書く ;extern void init_timer_a(void)
; .export _init_timer_a
TMA .equ H'00FFA6 ;TMAタイマー設定
IRR1 .equ H'00FFF6 ;TRR1割り込みフラグ
IENR1 .equ H'00FFF4 ;割り込み設定
_init_timer_a:
mov.b #B'00001000,R1L ;TimerA設定 φw(32khz),psc=1s
mov.b R1L,@TMA
bclr #6,@IRR1 ;TimerA割り込みフラグクリア
bset #6,@IENR1 ;割り込み有効
rts

これで時計用1秒TimerA割り込みが有効となる。割り込み期間中に毎回フラグクリアするため
bclr #6,@IRR1等ハンドラに書くこと。通常はINT_TimerA()内に IRR1.BIT.IRRTA=0 でよい
0127774ワット発電中さん
垢版 |
2019/04/27(土) 16:42:23.25ID:5M9Yonpr
;cpuclock速度変更ルーチン3664/3694(TimerA割り込みを動作させておく事)
;extern void _chgclk(void)
; .export _chgclk
IRR1 .equ H'00FFF6 ;TRR1割り込みフラグ
IENR1 .equ H'00FFF4 ;割り込み設定
SYSCR2 .equ H'00FFF1 ;
_chgclk:
jsr @_init_timer_a ;TimerA初期化
mov.b #B'00110100,R1L ;Clock設定 φ=20Mhz/16=1.25Mhz,DTON=1
mov.b R1L,@SYSCR2
bclr #7,@IRR1 ;直接遷移割り込みフラグクリア
bclr #7,@IENR1;直接遷移割り込みbit有効,0=有効/1=無効、(マニュアルは誤記あり)
sleep ;Sleep実行後TimerA割り込みでクロック切替再始動
rts
0128774ワット発電中さん
垢版 |
2020/03/09(月) 20:06:33.67ID:+ZhReQ9o
H8用クロサワ式乱数生成器32bit版を作ったので書いとく。乱数生成器としては非常に
優秀でアセンブラで書いているので高速なので広帯域のノイズ生成器として最適。
オーディオ用LCフィルタ,RFシグナルテストなど様々なノイズソースとして利用可能。
0129774ワット発電中さん
垢版 |
2020/03/09(月) 20:08:56.96ID:+ZhReQ9o
;クロサワ式 PN生成器(32bit改良版)H8/3664,3694用
;GPIOのP80に出力。Cからはextern void kuro32(void)で参照

.export _kuro32

_kuro32:
mov.l #65816,ER0 ;初期値設定
mov.l #h'4b18b4e7,ER1
mov.l #h'32a9cd56,ER2

mov.b #B'11,R1L ;ポートP8出力設定
mov.b R1L,@PCR8
mov.b #B'11,R1L ;P8データ出力
mov.b R1L,@PDR8

?_inspire_the_next:
xor.l ER1,ER0
sub.l ER2,ER0
rotl.l ER0
rotl.l ER0

mov.b R0L,R3L ;bit0の抽出
and.b #1,R3L
mov.b R3L,@PDR8 ;GPIO(P80)出力

jsr @_delay ;ディレイ(動作が速すぎるためI/O用遅延)

jmp @?_inspire_the_next
0130774ワット発電中さん
垢版 |
2020/04/18(土) 07:54:14.65ID:yJRHxjeg
通信用に必要なパリティ検出は簡単なので関数を書いてみる。
エラー検出用なので送信時にパリティを求めてデータと一緒に送信後、受信側でパリティを
求めて一致するかチェックする。一致しない場合はエラー処理再送などを要求する。

//パリティビットを返す
unsigned char parity(unsigned char i){
return(i & 1);
}

これをアセンブラで書くとこんな感じ
mov.b #123,R0L
and #1,R0L
単純なので関数化してもよい。
0131774ワット発電中さん
垢版 |
2020/04/19(日) 02:33:31.84ID:jRmTaX4f
続いてチェックサムを求める関数。引数は配列と要素数の二つ。戻り値は1byteで返す。
エラーチェックとしては古典的で処理も簡単。送信側で求めてフレームに追加して受信側で
データを計算して値が同じか異なるかでチェックする。Sレコードなどのチェックサムでも利用する。

char checksum(char dat[], int len){
int i;
unsigned int sum=0;
for(i=0; i<len; i++){
sum=sum+dat[i];
}
return(sum & 0xff);
}
0132774ワット発電中さん
垢版 |
2020/04/19(日) 02:41:36.64ID:jRmTaX4f
最後にCRC8を求める。char配列を渡すと8bitのCRC値(標準CRC8)が求まる。

char crc8_4(char data[],int len){
int i,j,crc;
for(j=0; j<len; j++){
crc=crc^data[j];
for(i=0; i<8; i++){crc=crc & 0x80 ? (crc<<1) ^0x7 : crc<<1;}
}
return(crc&0xff);
}

ここで得られた標準CRC値に0x55をXORするとCRC8/ITU仕様の結果となる。
0133774ワット発電中さん
垢版 |
2020/04/28(火) 21:10:45.41ID:a56Asx87
配列要素間のswapをアセンブラで書いてみる

.export _swap

;二箇所のbyte配列の中身を入れ替える。引数swap(char[], int a, int b)
;呼び出し側の引数はR0,E0,R1に割り当てられる。配列はスタックフレーム上にある
_swap:
push.l ER2 ;保存
push.l ER3

mov.w R0,R2 ;配列アドレス計算(a,ポインタとしてR2を使用)
add.w E0,R2
mov.w R2,E2 ;aのアドレス保存
mov.b @(R2),R3L ;データをtempとしてR3Lへ保存

mov.w R0,R2 ;配列アドレス計算(b)
add.w R1,R2
mov.w R2,E3 ;bのアドレス保存
mov.b @(R2),R3H ;bの内容を保存

mov.w E2,R2 ;aアドレス設定
mov.b R3H,@(R2) ;b->aへコピー
mov.w E3,R2 ;bアドレス設定
mov.b R3L,@(R2) ;temp->bへコピー

pop.l ER3
pop.l ER2 ;復帰
rts

Cから利用する場合は,extern void swap(char[], int, int);でプロトタイプし
配列と指定インデクス2つを引数に与える
0134774ワット発電中さん
垢版 |
2020/04/29(水) 20:12:16.11ID:cXGpdj8I
>>133のswap()を利用して選択ソートを実装する。

extern void swap(char[],int,int);

uchar a[]={9,8,7,6,1,2,3,4};
int i,j,len,min;
len=8;
for(j=0; j<len; j++){
min=j;
for(i=j; i<len; i++){ min=(a[i]<a[min])?i:min; }
swap(a,j,min);
}
0135774ワット発電中さん
垢版 |
2020/04/29(水) 20:41:29.91ID:cXGpdj8I
Byte配列の指定インデクスを一つだけ右に移動させる(ビット列のシフトではない)
インデクスは配列のポインタで指定

.export _rightsft

;引数の配列アドレスはR0に入る
;配列の添え字を指定して隣接する配列の一要素のみ一つだけ移動
_rightsft:
push R2 ;保存

mov.b @(-1:16,ER0),R2L ;隣と要素の入れ替え
mov.b R2L,@(ER0)

pop R2 ;復帰
rts
0136774ワット発電中さん
垢版 |
2020/04/29(水) 20:51:01.30ID:cXGpdj8I
>>135をCから利用する例。Byte配列の右移動(右ローテート)。配列の他に画像で使うと面白い

extern void rightsft(char[]);

uchar a[]={9,8,7,6,1,2,3,4};
int i,j;
j=a[7];
for(i=7; i; i--){ rightsft(a+i); }
a[0]=j;
0137774ワット発電中さん
垢版 |
2020/08/16(日) 20:22:51.84ID:UDcdAFvS
TimerWを用いた任意周波数発生器(矩形波)例。H8/3694版

周波数はTimerWのTGRAを用いて周期を設定。デューティは50%。タイマーを流用
した簡易機能のため高周波数になると分解能は低下する。利用例はAM用IFT調整用455khz
調整用マーカー発振。出力端子はP81/FTIOA。正確な455khz可能。
(おまけとしてP82/FTIOBは直交変換用に90度位相のIQ信号を出力する)

IO.PCR8=7;//Port8_0/8_1/8_2を出力端子に設定
// 周期計算式 f=20(Mhz)/psc/(2*(1+n))
// psc=メインクロック分周比(SYSCR2.MA),n=タイマーGRA値
TW.GRA=21;
TW.GRB=11;//P82_FTIOBは P81_FTIOAに対して位相が90度のIQ信号

TW.TIOR0.BIT.IOA=3;//出力端子設定,トグル設定
TW.TIOR0.BIT.IOB=3;
TW.TCRW.BIT.CCLR=1;//クリア条件設定
TW.TCRW.BIT.CKS=0;//クロック分周
MSTCR1.BYTE=123;//TimerW以外停止
TW.TMRW.BIT.CTS=1;//TimerWカウンタスタート
sleep();while(1);
0138774ワット発電中さん
垢版 |
2020/08/16(日) 20:30:41.07ID:UDcdAFvS
ハードウエアタイマーが足りない場合のソフトPWMを実装する。

通常のPWM機能と同等のマークスペース法のSoftPWM。H8内部のカウンタ・タイマーの
PWMと同等の機能を実現する。マークスペース法はサーボ制御用などに利用されている方式。
ソフト処理のためにPWM周期クロックは低くなる。ハードウエアタイマーに依存しないので
任意のGPIOポートで使用可能。(割り込みハンドラ内で実装する方法はループを工夫すること)

unsigned int d,cnt,m;
IO.PCR8=7;//H8のPort8_0/8_1/8_2を出力端子に設定,P8_0を使用
d=100;//初期値
cnt=1;

while(1){
while(cnt<1024){ //pwm分解能1024
if (cnt==d) IO.PDR8.BIT.B0=0; //もしpwm周期dが過ぎたらGPIO=Lとする
cnt++;
}
cnt=1; //ループ内初期化
IO.PDR8.BIT.B0=1;
}
0139774ワット発電中さん
垢版 |
2020/08/16(日) 20:34:53.65ID:UDcdAFvS
次の方法はマークスーペース法を若干修正したSoftPWM実装。マークスペース法は固定
周期のPWMクロックの為にノイズが強く出る。このSoftPWMはキャリア変調型PWM方式で
LED調光時のノイズ低減のためにアルゴリズムにデューティ可変時にPWMクロック周期を
約20%偏移させる方法を実装。周波数偏移により調光時のデューティサイクル可変時スペクト
ラム拡散と同等のEMC対策を期待できる。

unsigned int d,cnt,m;
IO.PCR8=7;//H8のPort8_0/8_1/8_2を出力端子に設定,P8_0を使用
d=100;//初期値
cnt=1;

while(1){
m=640-(d>>2);//d=0〜512までの分解能。ループ定数は512+(512>>2)=640
while( cnt<m ){
if(cnt==d) IO.PDR8.BIT.B0=0;
cnt++;
}
cnt=1;
IO.PDR8.BIT.B0=1;
}
0140774ワット発電中さん
垢版 |
2020/08/16(日) 20:43:02.69ID:UDcdAFvS
次は0/1のビットパターン列で出力制御するパルス列制御型のSoftPWM方式。
ビットパターンはメモリか変数にあらかじめ配置しておく。
PWMの出力を可変する場合は必要な数だけビットパターンを用意する。

unsigned int cnt;
unsigned char m;
unsigned long bp=0xAAAAAA00; //ビットパターン(32bit)

IO.PCR8=7;//Port8_0/8_1/8_2を出力端子に設定,P8_1を使用
while(1){
while(cnt<1024){
m=(bp >> (cnt % 32)) & 1; //ビットスライス処理
IO.PDR8.BIT.B1=m;//ポート出力
cnt++;
}
cnt=0;
}
0141774ワット発電中さん
垢版 |
2021/01/03(日) 09:25:18.28ID:9khtnhKY
>>124辺りでアセンブラによるソフトシリアル出力(ser_putcharと等価)を書いたので
今度はシリアル入力を書いてみる。

;シリアル受信 extern char ser_getchar(void)
;PCR8 .equ H'00FFEB ;I/Oレジスタ定義
;PDR8 .equ H'00FFDB ;3694は64K範囲のみ
_ser_getchar:
mov.w #0,R0 ;初期化
mov.w #0,R1
?_getchar_start:
mov.b @PDR8,R0H ;シリアルデータ入力(P80)
btst #0,R0H ;スタートビット(L)を検出,P80=0のときZ=1
bne ?_getchar_start ;スタートビット(L)検出するまでポーリング
;
bset #1,@PDR8 ;debug用serialパルス出力(P81端子をオシロ測定してbps推定する)
jsr @_delay ;スタートビット用bps速度調整ディレイ
bclr #1,@PDR8
;
;シリアルデータ読み取りルーチン開始
mov.b #8,R1L ;8bitデータ取得用カウンタ設定
?_getchar_get:
bld.b #0,@PDR8 ;ポートから1bitシリアル入力し指定ビットの状態をCYに得る
rotxr.b R0L ;シリアルのビット情報を保存しレジスタに並べる
;
bset #1,@PDR8 ;debug用serialパルス出力(P81)
jsr @_delay ;データビット用bps速度調整ディレイ
bclr #1,@PDR8
;
dec.b R1L ;シリアル受信用カウンタ-1
bne ?_getchar_get ;残りビットあればループ
rts
0142774ワット発電中さん
垢版 |
2021/01/03(日) 09:27:53.71ID:9khtnhKY
>>141の続き
;ループカウンタを用いたディレイ(ser_getchar用) クロック20Mhz,ループ定数46で約38.4kbps
_delay:
push R0 ;レジスタ退避
mov.w #0,R0 ;ループカウンタ定数初期化
_delay_loop:
inc.w #1,R0
cmp.w #46,R0 ;比較する
bne _delay_loop ;bccの時はロングジャンプではないのでラベルの@を記載しない
;
pop R0 ;復帰
rts
;
;kbhitの実装 extern char kbhit(void);
_kbhit:
mov.b @PDR8,R0H ;シリアルデータ入力(P80)
btst #0,R0H ;P80のスタートビット(L)を検出
bne ?_kbhit_end ;ポートがHかLか判定する
;ポートLのときにキー入力有り
?_kbhit_wait:
mov.b #1,R0L ;リターンコード=1
rts
;ポートH状態のときキー入力なしとして抜ける
?_kbhit_end:
mov.b #0,R0L ;リターンコード=0
rts
0143774ワット発電中さん
垢版 |
2021/01/03(日) 09:33:24.85ID:9khtnhKY
上記ソフトシリアル入力関数の利用例)

extern void ser_putchar(char); //ここは>>124のプロトタイプ変えただけ(要delay調整)
extern char ser_getchar(void);
extern char kbhit(void);
main(){
char rtn;
IO.PCR8=0x02; //Port8_0をRxD入力、8_1をdebug用出力端子に設定
while(1){
while(kbhit()); //キー入力待ちポーリング
rtn=ser_getchar();
/*何らかの処理*/
}
}
0144774ワット発電中さん
垢版 |
2021/01/06(水) 12:10:11.20ID:jIUrVjPR
次はH8/3694FのTimerWを制御してFMラジオから音を出すワイヤレス実験。
TimerWの出力端子P81/FTIOAに約2Mほどの電線アンテナを繋げてFMラジオに送信する

FMラジオで音が発生する仕組みはTimerW出力の矩形波成分833*100倍高調波と910*92倍
高調波がそれぞれ83.33Mhz,83.720Mhz近傍に発生し近い周波数で電波が生じる。
信号がFMラジオ占有帯域である約200-300khz帯域に入るので、833k,910kの高調波が適切な時間で
切り替えればシンプルな二値のFM変調動作となりFMラジオのFM検波回路で再生され音として
聞こえる。83Mhzに適切に同調したアンテナやLC回路がTimerW出力側にあると周辺帯域のノイズは
さらに小さくなる。音として確認することができ、FMラジオ経由のASKとしてシリアル
データを送信する事も可。
0145774ワット発電中さん
垢版 |
2021/01/06(水) 12:11:54.41ID:jIUrVjPR
//FMラジオ送信実験 H8/3694F 20Mhz
main(){
volatile unsigned int i,w;

IO.PCR8=7; //8_0/1/2を出力端子に設定
MSTCR1.BYTE=123; //スタンバイ設定,TimerW
TW.GRA=11;
TW.TIOR0.BIT.IOA=3; //出力端子設定,トグル設定
TW.TCRW.BIT.CCLR=1; //クリア条件設定
TW.TCRW.BIT.CKS=0; //クロック分周 内部クロック動作
TW.TMRW.BIT.CTS=1; //TimerWカウンタスタート

while(1){
//FM変調出力ループ(Freq1,Freq2のFSK切り替え) Freq1=833k ,Freq2=909k
for(i=0; i<10000; i++){
TW.TCNT=0; //レジスタGRA更新前にTWカウンタクリア
TW.GRA=11;
for(w=0; w<300; w++); //wait タイミング調整でFMラジオの音声周波数を変える

TW.TCNT=0;
TW.GRA=10;
for(w=0; w<300; w++); //wait
}
//数秒間停止
for(i=0; i<100; i++){ for(w=0; w<50000; w++);} //delay
}
}
レスを投稿する


ニューススポーツなんでも実況