2020年7月23日 (木)

ZK-80で足し算

20200723

 ZK-80で足し算をやってみました。
Aレジスタに0x16を入れておいて,そこに0x24を加えます。んで,答(Aレジスタの内容)は8010番地に書き込みましょう。

電子ブロック工房さんの JavaScript Z80 tiny assembler を使うと便利です。

8000: LD A,16          3E 16
8002: ADD A,24        C6 24
8004: LD (8010),A    32 10 80
8007: RET                C9 

 下の動画のように,パチパチ入力してRUNすると,8010番地に答の0x3Aが書き込まれてるのが確認できます。そうか,42年前に僕の友人はこういうことをやって遊んでたのか。
なんとなく活動記録。さんのところからリンクされてる 8080の命令セットの説明書をちゃんと読んで勉強してみようかな。

| | | コメント (0)

2020年7月21日 (火)

TK-80互換機 ZK-80のキット

20200721-zk80

 1976年に発売されて大ヒットしたマイコンTK-80の互換機ZK-80のキットをaitendoで買って組み立ててみました。
TK-80は工学部電気電子系へ進学した友人の間では流行ってましたが,僕は全然関心がありませんでした。で,まったくニーモニックや機械語に触れることもなく大学時代を過ごし,就職後に初めて買ったコンピュータ(FM-8)で覚えた言語はBASICでした。
 定年退職後ヒマだし,aitendoの「ミニ版ZK-80組立てキット」は2,500円というリーズナブルなお値段なので,つい手が出てしまったというわけです。

 キットとしては部品点数も少ないし,あっという間にでき上がったのでネットで拾ったプログラムをパチパチ入力してるときに「あれ?4桁LEDのアドレス表示部とデータ表示部が逆だぞ」と気づきました。
回路を設計したピコソフト(株)のWebサイトのFAQを見てみたらその答えがありました。
「4桁LEDは二つ使用していますが,片方はアノードコモン,他方はカソードコモンで別物です。説明書にあるように,アドレス表示部にはアノードコモンのLED,データ表示部にはカソードコモンのLEDを付けてください。」

「うわ,そうだったのか! 気づかなかったー!」
逆に取り付ける確率は50%ですが,やらかしました。さあここからが大変。ハンダ吸取線や吸取器を使って悪戦苦闘すること30分。やっと取り外しに成功して正しい位置に付け直しました。
 しかし,電源を入れてみると7セグLEDのセグメントのひとつが点灯しません。取り外すときに基板のパターンを剥がしてしまったようです。回路図を見ながらテスターで調べ,切れてるっぽい箇所を見つけて配線。7セグLEDも無事点灯して,やっと完成です。
さっきのプログラムを入力してRUNすると,ちゃんと動いてるみたいです。やれやれ。

 ところが,また不具合発見。一番右上のRESETボタンが効かないのです。基板の表を見ても裏を見ても,このスイッチはどこにもつながってません。aitendoのキットの基板はこういうミスがよくあるんだよなあ。
回路図を見て,このスイッチはマイコンの1番ピン(MCLR)とGNDにつなぐことを確認して配線しました。この写真をごらんください ↓
20200721

 手間取りましたが,RESETボタンも効くようになってやっと完成! ↓ こんなサンプルプログラムがあらかじめ入ってました。

 

| | | コメント (0)

2015年6月 2日 (火)

PICのお勉強(37) C言語編 12F683でA/D変換

20150602 8ピンPICの定番,12F683でA/D変換をやってみました。
PICのお勉強(29)で16F88を使ってやったことを12f683に移植しただけですな。
10kΩVRを使って,12f683のGP4/AN3に0~3Vの電圧を入力,これを10bitのデジタル値に変換して,GP0に接続したLEDの点滅周期を変えています。

HI-TECH Cで書いたソースとhexファイルはコレ↓です。
「lesson37.c」をダウンロード
「lesson37.hex」をダウンロード

12f683_ad 16F88との違いは,ANSELレジスタやTRISIOレジスタの設定くらいでしょうか。詳細はこちらで確認して下さい。
最初,4ピンのGP3がAN3だと勘違いしていて,GP3にアナログ電圧を入力し,「プログラムは間違ってないはずなのに,全然動かないじゃないかー」としばらく悩みました(笑) この失敗は誰もがやるんじゃないかしらん。僕だけ?

ソースも貼っておきますね。

/**************************************
12F683 HI-TECH C v.9.83
GP4/AN3の入力をA/D変換,GP0のLED点滅周期変える
**************************************/

#include <htc.h>
__CONFIG(FOSC_INTOSCIO & WDTE_OFF & PWRTE_ON & BOREN_ON & MCLRE_OFF & CP_OFF & IESO_OFF & FCMEN_OFF);
#define _XTAL_FREQ 1000000 // PICのクロックは1MHz

unsigned int adconv();
unsigned int tmp;
unsigned int i;

void main(void)
{
OSCCON = 0b1000000; // 内蔵OSC 1MHz
ANSEL = 0b00001000; // GP4/AN3がアナログ入力,他はデジタル
CMCON0 = 0b00000111; // コンパレータを使わない
TRISIO = 0b00001000; // GP4/AN3は入力,その他は出力

while (1)
{
tmp = adconv();
GP0 = 1;
for(i = 0; i __delay_ms(2);
}
GP0 = 0;
for(i = 0; i __delay_ms(2);
}
}
}

unsigned int adconv()
{
ADCON0 = 0b10001101; //右詰,基準電圧はVdd,GP4/AN3の入力をA/D変換
__delay_us(25);
GO=1;
while(GO);
return (ADRESH<<8)+ADRESL;
}

| | | コメント (0) | トラックバック (0)

2015年5月15日 (金)

UVレジンでLEDイルミネーション (2)

20150515 UVレジンで作ったLEDイルミをPIC12F683で点滅させてみました。
話の流れでいくとIchigoJamで光らせることになるところですが,LEDイルミを5個も作っちゃったので,久しぶりにPICでLチカです。
 これまで「PICのお勉強」では,16F84Aと16F88を使ってきましたが,定番の8ピンPIC,12F683を初めて使ってみました。小さくて安価なPICですが,これはこれでなかなか魅力的なやつです。単3電池2本で動くのもいいですね。

12f683_led_5 回路図はごく平凡なもので,GP0,GP1,GP2,GP4,GP5の5つにLEDをつなぎます。GP3は入力専用だから使えないんですね。
 今後のお勉強用に,12F683のテストボードを作って他に流用できるようにしてあります。PICkitを直接つないで書き込めるようにピンヘッダも取り付けてみました。
ソースはこんな↓具合です。GPIOに,LEDの点灯・消灯パターンを送って点滅させています。

/**************************************
12F683 HI-TECH C v.9.83
GP0~GP2,GP4,GP5のLED順次点灯
**************************************/

#include <htc.h>
__CONFIG(FOSC_INTOSCIO & WDTE_OFF & PWRTE_ON & BOREN_ON & MCLRE_OFF & CP_OFF & IESO_OFF & FCMEN_OFF);
#define _XTAL_FREQ 1000000 // PICのクロックは1MHz

void main(void)
{
OSCCON = 1000000; // 内蔵OSC 1MHz
ANSEL = 0b00000000; // デジタル
CMCON0 = 0b00000111; //コンパレータを使わない
TRISIO = 0b00001000; //GP3は入力,その他は出力

while (1)
{
GPIO = 0b00000001; //GP0点灯,他は消灯
__delay_ms(300);
GPIO = 0b00000010; //GP1点灯,他は消灯
__delay_ms(300);
GPIO = 0b00000100; //GP2点灯,他は消灯
__delay_ms(300);
GPIO = 0b00010000; //GP4点灯,他は消灯
__delay_ms(300);
GPIO = 0b00100000; //GP5点灯,他は消灯
__delay_ms(300);
}
}

HI-TECH Cで書いたソースとhexファイルはこちら↓
「lesson36.c」をダウンロード
「lesson36.hex」をダウンロード

 

| | | コメント (0) | トラックバック (0)

2014年10月 5日 (日)

PICのお勉強(35) C言語編 PWMでサーボモータを動かす

Pic16f88 16F88のPWM機能を使ってサーボモーターを動かしてみました。
まだ分からないことがたくさんあるのですが、なんとか動いてるようなのでソースを公開します→ lesson35.c
 モーターは秋月で買ったコレですが、まあ何でも大丈夫でしょう。電流をたくさん喰うので、マイコン用とは別に5V電源を用意します。

 サーボモータを動かすためにPWM周期を20ms程度に設定します。(このサイトで勉強しました)
内蔵クロックを1MHz,PR2 を 255,TMR2 プリスケーラ を16 とすると、


命令サイクル:(1s/1MHz)×4クロック = 4μs
PWM周期:4μs×(255+1)×16 = 16,384μs (= 16.384ms)
PWM周期16.4msだとちょっと短いかなあと思いましたが、これで大丈夫みたい。

あとはパルス幅を決めるCCPR1Lの値を指定してやればいいんだけど、これは試行錯誤で10,25,40という値にたどり着きました。これでサーボはだいたい-90度、0度、+90度になりました。
パルス幅を計算してみると、
CCPR1L=10 のとき、4×16×10 = 640μs (=0.64ms)
CCPR1L=25 のとき、4×16×25 = 1,600μs (=1.60ms)
CCPR1L=40のとき、 4×16×40 = 2,560μs (=2.56ms)
となるんだけど、これで計算は合ってるのかなあ。
PICの解説本やWebサイトを見てみると「パルス幅を1.0ms、1.5ms、2.0msにする」なんて書いてあるんだけどね。

/**************************************
16F88 HI-TECH C v.9.83
PWM でサーボモータを動かす
**************************************/

#define _LEGACY_HEADERS
#include

__CONFIG(CCPRB3 & DEBUGDIS & LVPDIS & BOREN & MCLRDIS & PWRTEN & WDTDIS & INTIO);

#define _XTAL_FREQ 1000000 // PICのクロックを1MHz

void main(void)
{
OSCCON = 1000000; // 内蔵OSC 1MHz
ANSEL = 0b00000000; // デジタル
TRISA = 0b11111111; // すべて入力
TRISB = 0b11110111; // BR3は出力
PORTA = 0b00000000;
PORTB = 0b00000000;

CCP1CON = 0b00001100; // PWMモードにする
T2CON = 0b00000111; // プリスケール16
PR2 = 255; // PWM周期
CCPR1L=25; // 中央

while (1)
{
CCPR1L=10;
__delay_ms(1000);
CCPR1L=25;
__delay_ms(1000);
CCPR1L=40;
__delay_ms(1000);
CCPR1L=25;
__delay_ms(1000);
}
}


| | | コメント (0) | トラックバック (0)

2014年4月 6日 (日)

秋月電子/新居浜高専PICマイコン学習キット Ver.2

Akizuki_pic_2 秋月電子から3月に発売になったばかりの新居浜高専PICマイコン学習キット Ver.2 を作ってみました。
Ver.1は,PIC16F84Aでしたが,このVer.2は16F886にアップグレード。より多くの機能を使えるようになりました。
PICkit3を接続できるソケットがあり、新たに作ったソフトを書き込む事が容易に出来ますし,すでに16種類の機能がプログラム済みですから,組み立てればすぐに遊べます。
サンプルプログラムは,
・デジタル時計
・2進数のカウント
・Wave
・電子ピアノ
・タッチアラーム
・電子すず虫
・イリュージョンライト
・キャンドルライト
・もぐらたたき
・ミニテルミン
・目覚まし鳥
・電子サイコロ
・音スイッチ
・A/Dコンバータ
・RCサーボコントロール
・タイマー
の16種類。これは楽しめます。

| | | コメント (0) | トラックバック (0)

2012年11月 3日 (土)

PICのお勉強(34) C言語編 デジットで買った10桁7セグLCD

7lcd 先日デジットで買ったジャンクの10桁7segLCD(200円)がとりあえず使えるようになりました。
A/D変換で簡易な電圧計(単位はmV)にしただけですが,ちょっとした表示用にこのLCDは使えますね。1個200円という,お手頃価格もうれしいですな。
Disit7segldc ピン配置くらいしか書かれてない簡単なデータシートしかありませんでしたから,ネットで検索してみるとこんなページを見つけたので,ソースを頂戴して,HI-TECH C用に書き換えてみました。
ソースはこれ→ lesson34.c
 lcd7seg_outという文字列表示関数がうまく動かなかったので,使い慣れないポインタを使って,なんとか切り抜けました。まだまだ勉強が足りないなー。

| | | コメント (0) | トラックバック (0)

2012年8月20日 (月)

PIC16F84Aでブレークアウト・ゲーム

Breakoutgame 昨日,PICマイコン16F84Aたった1個でできているブレークアウト・ゲーム(ブロック崩し)を作ってみました。
 もちろん僕のオリジナル作品ではなく(^^:)エレキジャックNo.2の「PICでテレビ・ゲームを作ってみよう!」の回路とプログラムをそのまま使っただけですが,1個250円のPICマイコンでTVゲームを作れるなんてすごいですねー。
 ただ,ココにあるBREAKOUT.HEXだと,ハイスコアが記録されません。ASMファイルをちょっと書き換えてビルドし直したコレならバッチリです。この方の記事を参考にしました。感謝。


液晶テレビだからなのか,残像が気になります。ブラウン管のテレビ,もううちにないしなー(^^;)

| | | コメント (0) | トラックバック (0)

2012年7月22日 (日)

PICのお勉強(33) C言語編 LM35DZの出力をオペアンプで5倍にしてみる

Lm358n PIC16F88+温度センサLM35DZの温度計の話の続きです。
 気温が28.6℃だとLM35DZの出力が286mVなのですが,AD変換の分解能が約5mVですから,温度の分解能も0.5℃になってしまいます。これではつまらないので,0.1℃単位で温度表示できるように,温度センサの出力をオペアンプで5倍に増幅してやりました。
Lm358 LM358Nという1個20円のオペアンプを使いました。ソースは,前回のやつの
tmp=adconv()*4.53; ってとこを
tmp=adconv(); と変えただけです。
10kVRで,表示温度の微調整ができます。これは結構実用的なものができたかも(^-^)

| | | コメント (0) | トラックバック (0)

2012年7月21日 (土)

PICのお勉強(32) C言語編 LM35DZで測った温度を7セグLEDに表示する

Lm35dz7seg 温度センサLM35DZの出力をPIC16F88でAD変換して,3桁の7セグLEDに表示してみました。
この7セグLEDは,ダイナミックドライブ用に内部で配線されてて11ピンのものです。こりゃ便利ですね。
ソースはこれ→lesson32.c

 7セグLEDへの表示は,TMR0割り込みで実行していますが,小数点をつけるのに少々苦労しました。
結局,小数点つきの0~9の表示用数字データを作って配列に入れておき,これを使うことにしました。PORTB=p[tmp1+10]なんてあたりに苦労のあとが忍ばれますなあ(笑)
7seg3 気温が28.5℃だと,AD変換の結果,tmpという変数に285という値が入りますから,これを100で割ってから,さらに10で割ったときの余りを求めて「2」という数字を得て,tmpを10で割ってからさらに10で割ったときの余りを求めて「8」という数字を得ます。最後にtmpを10で割ったときの余りを求めて「5」という数字を得ます。これで3桁ぶんの数字が得られるのです。LCDの場合と違ってめんどくさいですねー。

/**************************************
16F88 HI-TECH C v.9.83
温度計 LM35DZをRA0(AN0)に接続 7segLED表示
**************************************/

#define _LEGACY_HEADERS
#include "pic.h"
#include "stdlib.h"
#define _XTAL_FREQ 8000000
__CONFIG(DEBUGDIS & LVPDIS & BORDIS & MCLRDIS & PWRTEN & WDTDIS & INTIO);
__CONFIG(FCMDIS & IESODIS);

unsigned int adconv(),tmp,tmp0,tmp1,tmp2;
unsigned char i=0;
unsigned int p[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F, //0,1,2,3,4,5,6,7,8,9
0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0xa7,0xff,0xef}; //0.,1.,2.,3.,4.,5.,6.,7.,8.,9.

static void interrupt warikomi(void)//割り込み処理で7セグLED表示
{
TMR0IF = 0; //TMR0割り込み禁止
i++;
if(i==3){
i=0;
}

switch(i){
case 0:
PORTA=0b00011000;
PORTB=p[tmp0];
break;
case 1:
PORTA=0b00010100;
PORTB=p[tmp1+10];
break;
case 2:
PORTA=0b00001100;
PORTB=p[tmp2];
break;
}
}

void main()
{
OSCCON = 0b0111000; // 内蔵OSC 8MHz
ADCS2 = 0; //AD変換クロック値設定
ADCS1 = 0;
ADCS0 = 1;
ADFM = 1; // AD変換結果は右詰めで格納
VCFG1 = 0; // 基準電圧はVddとVss
VCFG0 = 0;
ANSEL = 0b00000001; // RA0(AN0)はアナログ
TRISA = 0b00000001; // RA0(AN0)入力
TRISB = 0b00000000; // すべて出力
PORTA = 0b00011100;
PORTB = 0b00000000;

OPTION = 0x00;
TMR0 = 0x00; //TMR0は0からスタート
TMR0IE = 1; //TMR0割り込み許可
GIE = 1; //すべての割り込み許可

while (1)
{
tmp=adconv()*4.53;
tmp2=(tmp/100)%10;
tmp1=(tmp/10)%10;
tmp0=tmp%10;
__delay_ms(100); //100msの時間待ち
}
}

unsigned int adconv()
{
CHS2 = 0; //AD変換ポート設定 RA0(AN0)
CHS1 = 0;
CHS0 = 0;
ADON = 1; //AD変換ON
__delay_us(20); //アクィジション時間 20us
GODONE = 1; //AD変換開始
while(GODONE); //変換完了待ち
return (ADRESH<<8) + ADRESL;
}


 

| | | コメント (0) | トラックバック (0)

より以前の記事一覧