Quantcast
Channel: JA1QVM
Viewing all 161 articles
Browse latest View live

古希から始めるPICマイコン・・・その3

$
0
0
・・・その2の続きです。
はやる気持を抑えて(どうやるの・・・どうやるの・・・まるで少年の様)先へ進みました。
まず PICkit-3を AE-PICKIT-ライトに繋ぎ、徐に PIC12F683をライトに差込ます。
次にPICkitに付随してきた赤色のケーブルでPCの USBに接続です。
下の様になりました。
イメージ 1
PICkitのランプ(LED)がアレコレ点灯して落ち着くのを待ちます。
・・・・・・・・・・
後はPC画面を見ながら英語で表示される云々を実行すればオシマイです・・・が、悲しいかな其の英語が解らない・・・ああ~
途中、最大の難所はパワーONの所かな?
つまり、セットしたPICに規定の電圧を加えなければ動作しません。
幾らやっても「PICに電気がこないよ~」状態になりまして、これは PICkitが壊れていると・・・
赤いケースのフタまで外し、電源ラインを直結にしようとしたところで我に返りました。
・・・ここで止まって良かったです。
幾らなんでもソレはないだろうと色々探したら、PC画面にボタンがありました。
結局プログラム書き込み成功です。
イメージ 2

う~ん嬉しいよ~~です。

遅くなりましたが得意分野の配線は下図です。
イメージ 3

凄く簡単ですね!
そして実際に 12F683をソケットに差し込んで・・・電源ONです。
イメージ 4

「わ~ついた~・・・ばんざ~い」大感激です。

40年ほど前、SSB無線機を作り自分の声の「もがもが」音を初めて聞いた時の感激に匹敵します。
思わずカミサンを呼んで見せたのですが・・・「ん~だから何?忙しい時に呼ばないで」・・・ったく。
「そうだよな~興味の無い人から見れば、どうしようもないアブナイ爺さん」に見えるのでしょう。
でもこれでグッスリ眠る事が出来ます。

今年は私にとってPIC元年のスタートです。
楽しい事が待っている予感・・・  by    JA1QVM

PICを使って見よう/エレキー・・・その1

$
0
0
いわゆるLチカで PIC元年を迎えたのですが、何時までも LEDの点滅を見ていたのでは情けないです。
でも具体的に、今の私の実力で何か作れますかね~。
その時ふと考えついたのが、LEDをリレーに置き換えて何かを動かして見ようと・・・
当然 LEDの点滅周期はプログラムで何とかなるはずです。
そこで現在使用中のエレキーに代わる物を考えます。

今のは FETを使ったマルチバイブレータ発振を利用しています。
かなり好い加減な定数で長短比・・・3:1を作り出していますが、実際にCWで活躍しています。
ですから失敗してもイイやと云う軽い気持で作ってみましょう。

目標を決めます。
1・・・現在使用中のモノより使いやすいこと。(当たり前だろ~)
2・・・原則、メモリキーは要らない。(嫌いです・キリッ)
3・・・出来る限りプログラムは自分で考える。(あくまでも出来る限りです)
4・・・スピードコントロールはツマミひとつでする。(今のもそうですが?)

以上ですが、4番の目標は A/D変換を使わざるを得ないので、今の私では無理です。
でも良い機会なのでソレナリに勉強しました。
原理は大変難しく、解った様な気がするだけで止めときます。
A/D変換実験中の1コマ・・・
イメージ 1
VRに付けたツマミを廻して、LEDの点滅周期が変化するのを確認しています。
この原理を利用してCW信号のスピードを連続可変させる心算ですが、これは紛れも無く A/D変換の賜物で、12F683を選んだ理由でもあります。
でも残念ながら 100%先人の知恵を「お借り」しました・・・(いわゆるパクリ)
何時の日か私もパクられて見たいものです。(無理だよ~)
おそらく動作するであろう配線図を下に・・・
イメージ 2

後は楽しい?プログラムを考えます。
by    JA1QVM

PICを使って見よう/エレキー・・・その2

$
0
0

独りよがりの怪しげなプログラムを書いて遊んでいます。
BASIC言語のプログラムは過去に多少勉強しました。
でも今回はC言語と云う事で、心新たにスタートです。
極力パクリを無くして(本当か?)下記のプログラムが出来ました。
実際に思い通りの「エレキー」として動作するので間違いは無いと思います。

 #include<pic.h>                 ・・・PICを使うと云う合図
 __CONFIG(FOSC_INTOSCIO&WDTE_OFF ・・・此の辺は初期設定?
 &PWRTE_ON&BOREN_ON&MCLRE_OFF
 &CP_OFF&IESO_OFF&FCMEN_OFF);
 #define _XTAL_FREQ 1000000・・・これを指定しないと__delay_msがダメ
 unsigned int adconv(),t0,t1,t2,i;  ・・・変数の範囲指定(+65025まで可)
 
 void main(){
 OSCCON=0b01000000;  ・・・この設定で内部クロックが 1MHzになる
 ANSEL  =0b01010010;   ・・・6ピンのアナログ設定+他難しい事
 CMCON0=0b00000111;   ・・・正直、良く解らない・・・
 TRISIO =0b00001011;   ・・・4,6,7ピンを入力ピンとして使う
 GPIO    =0b00000000;      ・・・初期設定で電源以外のピンをlowにする

 while(1){    ・・・ホイールと読むらしい・・・無限ループの始まり位置
 t0=adconv()/10;t1=t0*1;t2=t0*3;  ・・・各変数に具体的数値を代入
 if (GP0==1) GP2=0; ・・・もし入力ピンGP0が 1ならば出力ピンGP2は0
 else {GP2=1;        ・・・GP0が 1でないならGP2は 1で以下の操作をする
 for (i=0;i<t1;i++){  ・・・iが0からスタートして1ずつ加算してt1まで?
 __delay_ms(1); ・・・上記の条件に達するまでヒタスラ1ミリ秒の繰り返し
 }
 GP2=0;    ・・・上記の繰り返しが終ったらGP2を 0にする
 for (i=0;i<t1;i++){  ・・・又iを0を1ずつ加算してt1まで
 __delay_ms(1);    ・・・ヒタスラ1ミリ秒の繰り返し
 }   ・・・結局、同じ時間(i=0~t1)でGP2を 1と0で切り替えた訳で
 }   ・・・短点の発生です
 if (GP3==1) GP2=0;   ・・・今度は同じ原理で長点を作る
 else {GP2=1;
 for (i=0;i<t2;i++){   ・・・t2=t0*3  t1=t0*1に設定してあるので3倍
 __delay_ms(1);     ・・・つまり長点は短点の3倍時間GP2が1
 }
 GP2=0;
 for (i=0;i<t1;i++){  ・・・間隔は短点と同じ
 __delay_ms(1);
 }
 }
 }
 }      ・・・無限ループのオシマイ部分で、此処からwhile(1)に戻る 
 unsigned int adconv(){  ・・・此処から5行下の}まではA/DC部分です
 ADCON0=0b10000101;  ・・・A/DCの初期設定かと思いますが?
 __delay_us(20);GC=1;
 while(GC);  ・・・動作はGP1に入るアナログ電圧をVDD(5V)と比較して
 return(ADRESH*256+ADRESL);・・・その結果をadconv()に10bitで出力
 }   ・・・詳しい事は勉強中です
 
「・・・」より右側は私の独り言ですから「・・・」を含めてプログラムに入力すると当然動作しませんので、あしからず。

実際の完成基板は・・・
イメージ 1

配線図は前回のブログに上げて有りますから其方を見て下さい。

そして今まで活躍していた FETマルチバイブレータ部分を外して心臓部として収めた様子です。
イメージ 2

イメージ 3

可也汚らしいですが動作は完璧です。

この先どうなるか判りませんが PICについてはドンドン前に進みます。
宜しくお願いします。
by    JA1QVM

PIC12F683/低速PWM・・・その1

$
0
0

世の中に PWM と云うものが有ります。
聞き慣れない名ですがパルス幅変調と訳すのでしょうか?
パルス周期は変えずにデューティー比を変えるで宜しいかと。
何か御利益が有るのでしょうか。

例えば電球の明るさを変えたい場合・・・アナログ爺さん(私)は直に思いつくのは電流を変化させるです。
直列に可変抵抗を入れれば簡単ですね。
でも其れでは抵抗に電力を食われて凄く無駄です。
特にモータの様な物は電流を小さくすると、回転数も落ちますがトルクも落ちて結局回らなくなります。

そこで考え付くのが電流を変えずに流れている時間を変える・・・です。
つまりデューティー比を変える PWM方式に到達しました。
パルス周期に付いては制御するモノにより最適周期が有る様ですが、今回は直流モータに照準を合せました。
おそらく 100Hz前後になると思います・・・いわゆる低速 PWMです。

早速ネットで検索しましたが、本来 12F683に付随している高速 PWM?の使用例ばかりで、低速は少ない様です。
プログラムだけで PWM動作をさせるのは [if~~]命令?を多様せざるを得ないので敬遠されるのでしょう。
其の中で注意を引いたプログラムを発見しました。
基本動作は変数の範囲設定を逆手に取って、範囲を超えると「0」に戻ると云う理屈で [if]を一つ減らす事が出来ます。
私でも解る様に書き直したプログラムを下に・・・

 #include<pic.h>
 __CONFIG(FOSC_INTOSCIO&WDTE_OFF
 &PWRTE_ON&BOREN_ON&MCLRE_OFF
 &CP_OFF&IESO_OFF&FCMEN_OFF);
 #define _XTAL_FREQ 8000000 ・・・クロック周波数値を入れる
 unsigned char t2;・・・t2の範囲を最大 255に設定して、それを超えると 0
 unsigned int t1,adconv();

 void main(){
 OSCCON=0b01110000;  ・・・クロック周波数4MHzは0b01100000;
 ANSEL   =0b01010010;
 CMCON0=0b00000111;
 TRISIO  =0b00000010;
 GPIO     =0b00000000;

 while(1){
 if(t2==255) t1=adconv()/4;・・・t1の最大値はadconv()/4で 255
 if(t2<t1) GP2=1;
 else GP2=0;
 t2++;   ・・・t2に1を加算するが設定範囲を超えると0に戻る。
 }
 }
 unsigned int adconv(){   ・・・adconv()に入る数値は 10bitで最大 1023
 ADCON0=0b10000101;
 __delay_us(20);GO=1;
 while(GO);
 return(ADRESH*256+ADRESL);
 }

大半はパクリですが、非常に簡素な創りになっています。
このまま 8MHzのクロック周波数での PWM周期は 240Hz前後になりました。
後は実際のモータを繋げた時の状態で周期を可変します。
ちなみに4MHzにすると半分の 120Hzになりました(当たり前かな?)。
LED負荷の配線図を下に・・・
イメージ 1
実際のデューティー比の変化によると思われる? LEDの明るさは・・・
イメージ 2

イメージ 3

イメージ 4

イメージ 5

LEDでは上手く行った様です。
by    JA1QVM

冬桜の季節

$
0
0

毎年、この季節になると思いつく様な気がします。
そして今年も・・・群馬県側・桜山公園そして埼玉県側・城峯公園に冬桜を見に行って来ました。
地理的には神流湖を挟んだ2ヶ所です。

最初は桜山公園です。
イメージ 1

着いて分かったのですが、此処の桜祭はもう少し後の様です。
つまり来るのが早すぎた・・・余り良く咲いて無い・・・あらら!
でも園内を散策して結構咲いている木を見つけました。
イメージ 2

来た甲斐が有りましたかね?
それに引換え紅葉の見事なこと。
イメージ 3

イメージ 4

オマケに池には・・・
イメージ 5

凄いですね、餌をあげている人の所へ集中していました。

お次は神流湖・下久保ダムの上の道を通って城峯公園です。
イメージ 6

此方の桜は如何でしょうか?
イメージ 7

見頃ですかね~、もともと冬桜は春の華やいだ桜と違い、ひっそりと寂しげに咲きます。
私の性格?に合っているのでしょうか、PICマイコンで熱くなった頭を冷やすにはピッタリです。

そして定番の宿・・・
イメージ 8

今回もお世話になります。

夜にライトアップとイルミネーションが有ると云うので、夕食後いそいそと出掛けました。
イメージ 9

イメージ 10

満足そうな顔をした爺さんが写っていますが・・・
リタイヤした後の「黄金の15年」を思い切り楽しんでいます。
by    JA1QVM

PIC12F683/低速PWM・・・その2

$
0
0

その1で LEDは巧く明るさが変化して成功したようです。
でもモータをキチンと制御する為には、PWM動作を確認すべきです。
其処で LEDの電圧をオシロで観測しました。
イメージ 1
LEDが殆ど消えてます。
イメージ 2
波形の上側が少し延びたのが見えて、LDEも暗く点いています。
イメージ 3
此の辺でデユーティー 比が 50%でしょうか。
イメージ 4
もう少しVRを廻してみましょう。
イメージ 5
殆ど繋がりそうで 90%以上かな?

当然モータは LEDより電流を食いますので、スイッチング動作に成りますがトランジスタを奮発しました。
実用では逆回転もあるので、其れを考慮した配線図を下に・・・
イメージ 6

製作途中の写真を・・・
イメージ 7
一応、入力はトランスの別巻 10Vです。
イメージ 8
主要部分が出来ました。

そしてモータは此れです。
イメージ 9
小さなモータに減速ギアが付いていて(名称はギアドモータ)低回転でトルクも有ります。
おまけに軸径が 6mmで、廻す筈のバリコン・シャフト径と同じです。
実際に此の装置でアンテナの根元に付いている、ガンマー・マッチ用バリコンを回しますが、とても具合が良いです。

着々と実用レベルの PIC活用が進んでいて楽しいです。
by    JA1QVM

PIC12F683/電子オルゴール

$
0
0

低速 PWMがあれば当然高速 PWMがある訳で、今回は 12F683に付随している高速 PWM?にチャレンジします。
と云いつつ調べましたが・・・よく解りません。
結局 PWMのデューティー比を 50%のまま変化させず(それじゃ~PWMではナイだろう)周波数だけ変化させて遊ぶ事にします。

出力される波形は矩形波なので、お世辞にも良い音とは云えません。
でも PWMを勉強するスタートとしては良いかも?
下に努力した結果オーライのプログラムを・・・

 include<pic.h>

 __CONFIG(FOSC_INTOSCIO&WDTE_OFF
 &PWRTE_ON&BOREN_ON&MCLRE_OFF
 &CP_OFF&IESO_OFF&FCMEN_OFF);
 #define _XTAL_FREQ 1000000
 unsigned char h,i,t1,t2;

 void main(){
 OSCCON =0b01000000;  ・・・今回は都合により? 1MHzに設定
 ANSEL    =0b00000000;
 CMCON0 =0b00000111;
 TRISIO   =0b00000000;
 GPIO      =0b00000000;
 CCP1CON=0b00001100;  ・・・PWM機能を使うには設定するようです
 T2CON    =0b00000101;  ・・・同上
 INTCON  =0b10000000;  ・・・同上

 while(1){
 AKATONBO();   ・・・曲は「赤とんぼ」にしました・・・この命令で同名の
 }            ・・・関数(サブルーチン)へとびます
 }
 AKATONBO(){   ・・・此処へとんで来ます(関数間の行き来の得とく)
 S(3,212);S(3,158);S(9,158);S(3,141); ・・・ここは S( , )と云う関数に2個
 S(3,126);S(3,105);S(3,79);S(3,94);  ・・・の数値(音の長さ、音程)を
 S(6,105);S(3,94);S(3,158);S(6,158);  ・・・持ってとびます
 S(6,141);S(12,126);Z(6);S(3,126);  ・・・結局 S( , ) Z( )の関数を数値を
 S(3,94);S(9,105);S(3,94);S(3,79);  ・・・持って行き来して其の都度数値
 S(3,94);S(3,105);S(3,94);S(3,105);  ・・・で指定された音程と長さの
 S(3,126);S(3,105);S(3,126);S(3,158); ・・・低周波(矩形波)を PWMで
 S(3,126);S(3,141);S(3,158);S(12,158); ・・・発生させる訳です
 Z(6);Z(16);   ・・・Z( )は休みで長さだけです
 }

 S(t1,t2){  ・・・持って来た2個の数値を t1,t2に代入します
 PR2=t2;  ・・・ここから2行は PWMの周波数設定です
 CCPR1L=(t2+1)/2;  ・・・t2値で決まる周波数の矩形波を発生
 for(i=1;i<=t1;i++){  ・・・t1値で決まる音符の長さを設定
 __delay_ms(100);
 }
 CCPR1L=0;
 for(i=1;i<=t1;i++){  ・・・音符の「切れ」を良くする為に入れた休みです
 __delay_ms(25);   ・・・これを入れないと音が繋がってしまう
 }
 }   ・・・S(t1,t2)の関数はここで終わりとばした場所にもどります

 Z(t1){   ・・・t1値で決まる休み長さです
 CCPR1L=0;
 for(i=1;i<=t1;i++){
 __delay_ms(125);
 }
 }

実は関数間を数値を持って行き来するやりかたが解らず困っていました。
その時たまたま無線で交信した相手に話をしたら・・・「ソンナの簡単だよ」と教えて頂き感謝です。
OM有難うございました。

下に簡単な配線図を・・・
イメージ 1
PWMの出力は GP2(5ピン)に決まっている?様なので、そこに保護用の抵抗とコンデンサを入れて小さな SPを繋げました。
音は小さいですが実験用としては充分かと思います。

PICで色んな事をしていますが、だんだん仕組み?が解って来ました。
今回はC言語の関数間の行き来が少し解りました。
次回は PWMの真髄?に迫ります。 宜しく・・・

PIC12F683/高速PWM・・・その1

$
0
0

12F683に付随している PWMモードを、自分勝手に「高速」と決めているだけですので笑って下さい。
色々勉強して解ったのですが、決められたレジスタ?に数値を入れれば、後は勝手に其れに見合った周波数、デューティー比の矩形波が出力されると云う・・・簡単ジャン・・・らしいです。
ただ其の数値を決める計算式が、古希の爺さんには楽しかったかな?
下に基本となるプログラムと回路を乗っけて置きます。

#include <pic.h>

__CONFIG(FOSC_HS&WDTE_OFF  ・・・今回は外付Xtal使用
&PWRTE_ON&BOREN_ON&MCLRE_OFF
&CP_OFF&IESO_ON&FCMEN_ON);


#define _XTAL_FREQ 20000000  ・・・最高速の 20MHz
unsigned int adconv(),t0;

void main(){
ANSEL    =0b00100011;  ・・・これも 20MHzで使える最高値に設定
CMCON0 =0b00000111;
TRISIO   =0b00000011;
GPIO      =0b00000000;
CCP1CON=0b00001100;
T2CON    =0b00000100;
INTCON  =0b10000000;
PR2=255;   ・・・20MHz/10bitの最高値に設定

while(1){
t0=adconv();  ・・・A/DCで得られた 10bit数値を t0に代入
CCPR1L=t0>>2; ・・・CCPR1Lに t0の上位8bitの内容が入る
CCP1CON=((t0<<4)&48)|12; ・・・t0の下位 2bitの内容がCCP1CONの
}                    ・・・の上位4bitに入り、下位4bitに 12が入る
}

unsigned int adconv(){
ADCON0=0b11000001; ・・・A/DCの基準電圧は6pinの電圧とする
__delay_us(12);GO=1;  ・・・A/DC最速の 12usに設定
while(GO);
return((ADRESH<<8)+ADRESL); ・・・bitシフトで [*256]の演算を[<<8]で
}                       ・・・する(計算結果は同じ)

A/DC,PWM共に最大 10bitまでです。
今回は bit操作(シフト)にチャレンジしました。
イメージ 1

クロック用の 20MHzは手持ちの水晶発振子を使いました。
動作は・・・

1:入力 (7pin)のアナログ信号電圧を、基準電圧 (6pin)と比較した結果をデジタル信号として [adconv()]に 10bitで格納する。(A/D変換モード)

2:PWMモードの周波数は [PR2]レジスタで設定。 今回は PR2=255で周波数は計算上 19.531kHzになりました。

3:デューティー比は [CCPR1L]レジスタに adconv()の 10bitの内、上位 8bitを格納する。

4:残りの下位 2bitは [CCP1CON]レジスタの 4,5bit(右端から 5,6番目)に格納する。・・・この辺はヤヤコしいです。

実際の計算は複雑ですが、プログラムはエレキーより簡単かな?
VRを廻して 7pinの入力電圧を可変すると、当たり前の様に出力の 19kHz矩形波のデューティー比が変化します。
イメージ 2

イメージ 3

次回は此処に音声信号を入れてみます。  by    JA1QVM

PIC12F683/高速PWM・・・その2

$
0
0
その1でVRの中点から来ている 7pinに低周波信号を入力すれば、それで終りのはずです。
でも考えて見れば交流ですから、プラス・マイナス両方共に同じ様にしなくては・・・と気付きました。
これは 7pinに直流バイアスを掛けると云うことです。
つまり 6pinの基準電圧の半値を加えます。
そして、なるべく 10bit全てを利用したい訳で、何か細工をしないとマズイでしょう。
其処で入力電圧に比例して基準電圧も変化する、オートゲインコントロール (AGC)回路を付けました。
下に配線図を・・・
イメージ 1
5Vの電源接続を書き忘れました・・・上の横ラインです。
非常に怪しげな回路ですが巧く動作するようです。

原理は入力信号を整流した直流電圧で FET(2SK192)のソース電圧を変化させています。
其の先の Sid*3は、いわゆるゲタを履かして見かけ上の変化を大きくしています。

出来具合は・・・
イメージ 2
何時もの通り酷いです。

実際に低周波を入力した時の出力波形を・・・
1000Hz
イメージ 3
此の辺までは綺麗です。
2000Hz
イメージ 4
う~ん・・・
3000Hz
イメージ 5
何でこうなるの?
4000Hz
イメージ 6
周波数が高くなると振幅が小さくなるのは、出力側のローパスフィルタの影響かと思いますが、波形が何重にも重なって見えるのは如何してか?
オシロのシングルパルスで観測するとマトモです。
おそらく、A/Dコンバータの精度がいい加減で、其の都度変化しているのでしょう。
此の程度の PICでは音声信号の ADCまでは考えて無いと思います。

最後に女性ボーカルの曲を入力して聴いてみましたが、ソコソコ聞えるのでビックリしました。
そして AGC回路が巧く動作するので他に流用できるかもしれません。

途中のデジタル部分で何も細工が出来なかったのは、私の実力不足で残念です。
by    JA1QVM

W-DBM

$
0
0
題目の [W-DBM]とは特性の揃った2個のバランスド・モジュレータの意味です。

ひょんな事から 7MHzダイレクトPSN/SSBジェネレータの実験をやる羽目になりました。
当然ダイレクトですからキャリア周波数=運用周波数(今回は 7000-7200kHz)になります。
つまりバンド幅を持つ訳で、長い自作の経験でも初めてです。
実験と思いつつ、取りあえずバランスド・モジュレータ(BM)を2個組んでみます。
PSN式では後段に RFフィルタが在りませんから、キャリアサプレッションはBMの性能に支配されます。
そこで自分で一番自信のある、ダイオードDBMを2こ作った場面を自慢げに?公表します。
イメージ 1
トランスコアは定番のフェライトビーズ FB801を使います。
今回は扱う周波数が 7MHzですから巻数は 5回にして、線径は 0.15mmを使いました。
20cm/3本の線を・・・
イメージ 2
指先で軽くヨジリます。
イメージ 3
ビーズに通して(巻数が奇数ですから、ほぼ真ん中にビーズを持ってくる)爪楊枝で型を揃えます。
イメージ 10
5回巻いた結果が・・・
イメージ 4
後は線を短くして、各々のコイルの巻き始め・終りをテスターで確認して
イメージ 5
センタータップを作って、コイルは出来上がりです。
イメージ 6
予め一刀彫しておいた基板と、クワッド・ダイオード/487C-1です。
イメージ 7
先にダイオードを基板に半田付けします。
イメージ 8
そして最後に先程作ったトランスを乗っけてオシマイです。
イメージ 9
PSNですから和算(今回は引き算)用のトランス(BM用と同じ)も取り付けました。

実験用として軽い気持で作りましたが、果たして陽の目を見る日が来るのか興味津々で終ります。
by    JA1QVM

PIC12F683/Si5351制御

$
0
0
PICマイコンを始めた時に、何時の日か Si5351(クロックジェネレータ)制御が出来れば良いな~と漠然と考えていました。
色々、自分なりにプログラムを組めるようになり、そろそろ本腰を入れて「本丸」にアタックします。

Si5351:クロックジェネレータと云われるモノで PLL/分周器が内蔵されている高周波発振器と書いてあります。
アマチュア無線機の自作を趣味でやっている人は多分に興味があると思います。
5個ほど購入(@500)して現物を見ましたが・・・小さいです。

イメージ 1


プリ説によると・・・
1:2.5kHz~200MHzの出力が可能・・・「凄い」の一言

2:3チャンネルの出力がある・・・互いのアイソレーションは如何なの?

3:出力波形は矩形波・・・高調波が沢山出るのかな?

4:周波数は I2Cで設定する・・・何ですか[I2C]って?

以上ですが、2:については1信号だけを目的にすれば関係ないです。
3:は LPFを入れれば良いかな?特に DBMをドライブするには矩形波の方が良いとノタマウ人も居るくらいですから・・・
問題は4:です。
う~ん「I2C・I2C・I2C・・・・・」と連呼しても全く前に進みません。
そう云えば「使い方がよくわかる」に書いてあった様な・・・
早速、調べて見ました。
読み方は「アイツーシー」と云うらしい・・・フムフム。
I2Cインターフェース内蔵のデバイス(当に Si5351)間のシリアル通信?を行う為のもの・・・だそうです。
因みに Si5351と一緒に購入した「小型8文字*2行液晶」にも I2C接続と書いてあります。
つまり此処で I2Cを得とくすれば、液晶画面に周波数を表示させながら自在にロータリーエンコーダ等で Si5351の周波数制御が可能(そのプログラムが組めれば)な訳です。

此れはもう、やるっきゃないですね!(高価な DDSVFOを買う必要が無い)凄~い楽しみ・・・
by    JA1QVM

PIC12F683/I2C・・・その1

$
0
0
Si5351制御、液晶画面操作をしたいが為に I2Cを勉強しはじめたのですが、何の事は無い最初から I2Cモードを内部に格納してある PICが有るじゃないですか。
しかもデバイスの価格も変わらない位、安いです。
いっぺんにヤル気が失せました・・・

・・・・・・・・・・あ~あ、ヤダヤダ・・・・・・・・・・でも、愚痴っていてもしょうがないので一応 I2Cを 12F683で出来る様にしますが、お急ぎの人は I2C内蔵 PICを使う事をお勧めします。

I2Cでデータを送る仕組みは [SCL]と云うタイミングを計る連続パルス信号と、[SDA]と云う送りたいデータ信号の、決まりを持った絶妙な組み合わせで成り立っています。
そして同じバスライン上に複数の子機(スレーブ)が繋がっていて、そのスレーブアドレスを指定してデータを送れば、異なるアドレスのスレーブは全く感知せず、指定したスレーブだけにデータを送れると云うシステムです。
ですから今回の様に Si5351を制御しつつ、液晶画面(SCD)に周波数をほぼ同時に表示させる事が可能です。

完全に I2Cの仕組みを知りたい方は専門書をお読み下さい。
かなり読み応えが有ると思います。
私は前に買っておいた「8ピン PICマイコンの使い方がよくわかる本」を参考にしました。

下に関数として取り扱う I2Cの 8bitデータ出力プログラムを上げて置きます。
上から順に関数名で・・・

STA():スタート条件の出力
STP():ストップ条件の出力
OUT(data):1バイト・8bitデータ出力/確認信号 ACK受信
上3個の関数だけです。

 STA(){
 SDA=0;TRISSDA=0;
}

 STP(){
 SCL=0;__delay_us(1);
 SDA=0;TRISSDA=0;
 SCL=1;__delay_us(1);
 SDA=1;__delay_us(10);
}

 OUT(data){ ・・・此の関数で、スレーブに送る 8bit信号を書き込みます
 unsigned char BP,ACK,i;
 TRISSDA=0;BP=128;
 for(i=0;i<8;i++){ SCL=0;
 if((data&BP)!=0) SDA=1;
 else SDA=0;
 BP=BP>>1;SCL=1;  ・・・無事に 8bit信号を1個送りました。
}
 SCL=0;TRISSDA=1;__delay_us(2);
 SCL=1;__delay_us(2);
 ACK=SDA;return(ACK);  ・・・スレーブからの確認信号(ACK)チエック
}

以上で I2Cの基本はオシマイです。
後はスレーブの条件で色々な関数がぶら下がります。
当然ながら今回のプログラムは関数だけですから、此れだけでは動作しません。
次回から液晶画面を繋げて、実際の I2C動作の確認をしたいと思います。
尚、関数の内容プログラムは一度しか書きません。
それ以降は関数名だけの「サブルーチン」として扱います。
そうしないとプログラムが長すぎて、作った本人さえ解らなく成る・・・実際に良く起こりそう!

12F683で I2Cをやって見たい人に参考になれば幸いです。
お楽しみに・・・   by    JA1QVM

PIC12F683/I2C・・・その2

$
0
0
Si5351と一緒に購入した液晶画面(LCD)を下に・・・

イメージ 1

型式は AQM0802A-FLW-GBW バックライト付きで、小さいです。
でも一応 8*2 で周波数表示だけでしたら問題無く使えるでしょう。
プリ説を見ましたが、後は私が実際に使いこなせるか如何か・・・
単純に、繋げればソレだけで動作する訳ではなさそうで、此処でも「何タラ設定」と云うオマジナイが必要です。
その設定を最小限3個の関数プログラムにして下に貼って置きます。

FA():LCD初期化
LD(data):LCD1文字表示データ出力
LC(data):LCD1コマンド出力

 FA(){
 __delay_ms(100);
 LC(56);LC(57);LC(20);
 LC(120);LC(93);      ・・・コントラスト設定
 LC(106);__delay_ms(300);
 LC(56);LC(12);LC(1);
}

 LD(data){
 STA();OUT(124);       ・・・LCDスレーブアドレス+0
 OUT(64);OUT(data);
 STP();__delay_us(30);
}

 LC(cmd){
 STA();OUT(124);       ・・・LCDスレーブアドレス+0
 OUT(0);OUT(cmd);STP();
 if((cmd==1)||(cmd==2))
 __delay_ms(2);
 else __delay_us(30);
}

得意な配線分野は・・・

イメージ 2

解り辛いですかね~。

此れで前回のも含めて6個の関数プログラムが出来ました。
次回は其れを組み合わせて(サブルーチンとして使う) LCDに文字を表示させます。
お楽しみに・・・しかし、何でもっと簡単に出来ないの?<陰の声・・・
  by    JA1QVM

PS 素人の実験ですので、パクる人は自己責任でオヤリ下さい

PIC12F683/I2C・・・その3

$
0
0
その3でヤッと LCD画面に文字が表示されそうです。
取りあえず画面の上下に "A"文字を8個づつ並べました。

そのプログラムを下に・・・

 #include<pic.h>
 __CONFIG(FOSC_INTOSCIO&WDTE_OFF
 &PWRTE_ON&BOREN_ON&MCLRE_OFF
 &CP_OFF&IESO_OFF&FCMEN_OFF);

 #define _XTAL_FREQ 8000000
 #define SDA GP1
 #define SCL GP0
 #define TRISSDA TRISIO1

 unsigned char i,data,cmd;

 void main(){
 OSCCON=0b01110000;
 ANSEL  =0b00000000;
 CMCON0=0b00000111;
 TRISIO =0b00111100;
 GPIO    =0b00000000;

 FA();                     ・・・関数FA()にジャンプ
 LC(128);for(i=0;i<=7;i++) LD(65);   ・・・LC(128)は上段の左端
 LC(192);for(i=0;i<=7;i++) LD(65);   ・・・LC(192)は下段の左端
 while(1){ }
}           ・・・此処までがメインプログラムです

 FA(){ }      ・・・此処から下6個はサブルーチンとして使う関数
 LD(data){ }
 LC(cmd){ }
 STA(){ }
 STP(){ }
 OUT(data){ }  ・・・此処まで6個の関数は前回まで書いたプログラム

必ずメインプログラムの下に、今まで作った6個の関数プログラムを書いて下さい。

文字のデータは LCDを買った時について来る「文字データ」を参考にします。
因みに [LD(65)]を [LD(66)]にすると "B"になります。
表示位置については上段の左端が [LC(128)]になり、右に行くに従って[LC128-->LC129-->LC130・・・]になりますが、今回の様に連続して "A"を表示する場合は上記のプログラム方法でも良い様です。
下段は左端が [LC(192)]になります。

実際の LCD画面は・・・
イメージ 1

此の画面になった時、思わず「わ~写った!」と叫んでしまいました。
其れぐらい苦心した所です。

さて、此れで Si5351で発振させた周波数を表示出来そうです。(本当はソンナ簡単ではナイ)

其れでは次回から Si5351と格闘します。
宜しく。   by    JA1QVM

クロックジェネレータ/Si5351A・・・その1

$
0
0
PICマイコンに手を出した時、ただ漠然と此のデバイスを制御出来たら良いな~と思っていました。
PICの最終目標とは云いませんが・・・思わず遠くへ来たもんだ・・・の心境です。

現物はモジュールとして組み上がったモノです。

イメージ 1

仕様:
電源電圧: コア電圧(VDD)         2.5~3.3V・・・5V掛けると壊れる?
         出力部電圧(VDDO)  1.8~3.3V・・・上と同じ(ヤッテみたい)
消費電流(最大): コア消費電流     35mA
            出力部消費電流  5.6mA
出力周波数:     2.5kHz~200MHz
出力波形:    矩形波
デューティ比:  50%
I2Cスレーブアドレス    0b1100000(7bit) 固定
原発信      25MHz

レジスタ値の設定方法(決められたレジスタに I2Cで数値を代入)
・・・詳しくはAN619をご覧ください、と書いてある・・・読んでも解らず・・・

PLLの入力元: 水晶振動子のみ
PLL周波数(Fvco)の計算:
     Fvco=Fxtal*(a+(b/c))
     MSNxP1[17:0]=128*a+Floor(128*(b/c))   ・・・Floorって何?
     MSNxP2[19:0]=128*b-c*Floor(128*(b/c))
     MSNxP3[19:0]=c
出力分周器の設定:
  出力周波数 Fout=Fvco/(a+(b/c)) ・・・上記のa,b,cではナイ
     MSxQ1[17:0]=128*a+Floor(128*(b/c))
     MSxQ2[19:0]=128*b-c*Floor(128*(b/c))
     MSxQ3[19:0]=c
原文では分周器の方も P1,P2,P3と有りますが紛らわしいので、あえて Q1,Q2,Q3としました。

以上の計算結果 P1,P2,P3/Q1,Q2,Q3 値を I2C で然るべきレジスタに送れば、目的の周波数を得られる訳です。

以上プリ説を読みましたが・・・全く解りません(勉強します)・・・
思うに・・・此れを読んで直に解る、と云う人にお会いしたいです。

最後に I2C でVFOデータ(P1~Q3)を送るための関数プログラムを下に貼って置きます。

VD(regi,data){      ・・・VFO 1データ出力
 STA();OUT(192);OUT(regi);OUT(data);
 STP();__delay_us(30);
} 


此れで関数プログラムは計7個になりました。
いくつになるか楽しみ?です。  by    JA1QVM

クロックジェネレータ/Si5351A・・・その2

$
0
0
眺めてばかりいてもツマラナイのでデバイスに通電してみます。
電圧はコア、出力部・・・共に3.3Vです。
えっ、と云う事は I2Cで PICに繋がる SCL/SDAは当然、最大値が 3.3V以下でしょうか?
・・・考えて無かったよ~、如何しよう・・・
こう云う場合、私はデバイスの価格にも依りますが、躊躇なく 5Vを掛けるタイプの人間です。(安全率が有るだろう・・・)
結果的には全て 5Vで動作しました。(人には進めませんが)

下にはオトナシク 3.3V動作の写真を・・・
イメージ 1

SCL/SDAは抵抗分割 2.2k-6.8kohmでやってみたら上手くいきました。
ACK(確認信号)が如何して巧く伝わるのか解りませんが・・・

実験途中の PIC12F683の勇姿です。
イメージ 2


簡単に P1~Q3値を I2Cで送り込めばオシマイと思いきや、此処でも Si5351Aの基本設定が必要です。
其の関数プログラムを下に貼って置きます。


VFO(){            ・・・VFO基本設定
 VD(3,15);VD(16,128);VD(183,128);
 FK();FABC1();FABC2();  ・・・周波数設定
 VD(177,32);VD(16,76);VD(3,14);
}

 FABC1(){     ・・・VFO()の周波数設定用内関数
 VD(26,P3H);VD(27,P3L);     ・・・必ずアドレスが若い方を先にする
 VD(29,P1H);VD(30,P1L);
 VD(32,P2H);VD(33,P2L);
 VD(44,N<<4);     ・・・Nは最初[0]にします
 }

 FABC2(){     ・・・VFO()の周波数設定用内関数
 VD(43,Q3L);VD(45,Q1H);
}

出力分周器(FABC2)についてはスプリアスの問題が有ったので、綺麗な整数固定(50)にしました。

FK();は後で大変複雑な計算式が入りますが、最初は FK(){ }で空の関数で良いと思います。

では簡単?な周波数計算をしてみます。
取りあえず Fvcoを 400MHzにして、分周を 50に設定。
Fvco=Fxtal*(a+(b/c))・・・400MHz=25MHz*(a+(b/c))ですから
(a+(b/c))=16で良い訳です。
色々な数の組み合わせが可能ですが、此処はプリ説どおり
a=15:b=1:c=1でやってみます。

・・・15+(1/1)=16・・・
P1=128*a(15)+(128*(b(1)/c(1))-512=1536
P2=128*b(1)-c(1)*(128*(b(1)/c(1))=0
P3=c(1)=1

次は分周(50)の計算です。
a+(b/c)=50にすれば良い。

・・・a=50:b=0:c=1でOKです・・・
Q1=128*a(50)+(128*(b(0)/c(1))-512=5888
Q2=128*b(0)-c(1)*(128*(b(0)/c(1))=0
Q3=c(1)=1

以上の結果を周波数設定用内関数 FABC1/2に代入すればお終いですが、P1~Q3は基本的に 8bitづつしか入れられないので H(上位8bit)-L(下位bit)に分けて送ります。
実際に H/Lに分けてみましょう。

P1=1536=0b110,0000,0000  ・・・8bitに収まらない。
P1H=0b110=6     P1L=0b0000,0000=0
P2=0  P2H=0  P2L=0    ・・・下位の8bitに収まる。
P3=1  P3H=0  P3L=0b0001=1 ・・・下位の8bitに収まる。

Q1=5888=0b1,0111,0000,0000  ・・・8bitに収まらない。
Q1H=0b1,0111=23    Q1L=0b0000,0000=0
Q2=0  Q2H=0  Q2L=0   ・・・下位の8bitに収まる。
Q3=1  Q3H=0  Q3L=0b0001=1 ・・・下位の8bitに収まる。

私の計算方法では 8+8=16bitで済みましたが、もう少し大きな数も扱える様に、最大で 20bitの余裕が有ります。(モノによっては 18bitも有る)
此の辺の扱いはウンザリしました。

簡単な配線図を下に・・・
イメージ 3

さて、実際に出力分周器を [50]に固定して、PLL値を 16に設定してテストしました。
PLL周波数=25MHz(付随してるXtal)*16=400MHz
分周器は [50]ですから 出力周波数=400/50=8MHzになる筈?です。



・・・・・メデタク発振しました、しかも計算通りの 8MHzです・・・・・
私にとっては歴史的瞬間です。

次回は此の[8000000Hz]の数値を、先に組上げていた LCDに表示させるプログラムを考えます。
ご期待下さい。    by    JA1QVM

クロックジェネレータ/Si5351A・・・その3

$
0
0
前回で曲りなりにも 8MHzの高周波を出力できました。
まさに「バンザ~イ」状態であります。

さて、落ち着いて来ると色々欲張った事を考えます。
其の中に、発振器ですから其の周波数を表示させたい・・・当たり前ですね。
其の為に I2Cに8桁の LCDがぶら下っている訳で。
最初は簡単に表示できると思いました。
軽~い気持でプログラムを考えます。

F: 8桁に収まる発振周波数 [0~99.999999MHz]・・・(凄いです)

此の数値の各位の単独数値 (0~9)を拾って、LCDに送ればお終いです。(簡単じゃん)
確か BASICにはそんな命令が有った様な・・・現在使っている「C」言語は其れより高級?ですから当然有るでしょう。
探しました・・・本当は有るのでしょうが、私が使っている PIC用の「C」には見当たりません。(単なる探し方がヘタ)
う~ん、此れは「其れ位自分で考えろ!」と云う神の御告げでしょう(私は無神論者)。

此処から急に真面目に考えてみます。
各位の単独数値を拾う・・・とは如何云うことか?
例えば 8桁数 [12345678]の一の位[8]を如何すれば拾えるのか?
????????
世の中には四則計算(+、-、×、÷)が有ります・・・小学校で習った
其れに付随して剰余計算と云うのが有ります・・・割り算の結果「余り」だけを出す(習った覚えがないぞ)

其れを使って [12345678]を 10で割ります。
結果は 12345678÷10=1234567 余 [8]です。
C言語では 12345678 % 10 と書きます。
今求めたいのは結果の [8]ですから、其れを未知数 [h]として次の方程式が成り立ちます。

h=12345678 % 10・・・hに1の位の 8が入る

此れを 10でなく 100で割ると下2桁の [78]が余として出て来ます。
此の [78]を整数の割り算で 10で割ると 78÷10=7 余 [8]になります。
j=78÷10・・・整数限定で此の計算をすると [j]に10の位の [7]が入ります。
以上の事を踏まえ、メモリが少ない 12F683を考慮して下記の関数プログラムを考えました。


FC(){                           // 周波数カウンタ***
 unsigned int K1,K2;
 K1=F%10000;K2=F/10000;
 h1=(K1%100)%10;h2=(K1%100)/10;
 h3=(K1/100)%10;h4=(K1/100)/10;
 h5=(K2%100)%10;h6=(K2%100)/10;
 h7=(K2/100)%10;h8=(K2/100)/10;
}

[F]に8桁までの整数(~99999999Hz)を代入すると、各位の単独数値が [h1~h8]に表れます。
其の数値を LCDの各位置に表示する関数プログラムを下に・・・

LCN(){                       // 8桁の数字を表示***
 LC(12);LC(128);
 LD(48+h8);LD(48+h7);LD(48+h6);LD(48+h5);
 LD(48+h4);LD(48+h3);LD(48+h2);LD(48+h1);
}

結果的に上手く動作する様です。
[F]に勝手な数値 [15002576]を代入して LCDに表示させてみました。

イメージ 1

一時はどうなるか心配でしたが・・・
流石に70過ぎの爺さんの頭では此れが限界かと思います(疲れました)。

次回はロータリ・エンコーダを使って[F]値を自在に操る事を考えます。
ご期待下さい。 by    JA1QVM

クロックジェネレータ/Si5351A・・・その4

$
0
0
世の中にはロータリ・エンコーダと云う便利な物が有ります。
動作は多数の接点があるロータリ・スイッチの様な物?でしょうか。(違うだろ~)
私のお気に入りを下に貼って置きます。

イメージ 1

一見するとボリュウム(VR)です・・・メーカーもアルプス・・・
此れにソレナリのツマミを付けて廻すと、パルスを発生します。
一応、現物は1回転で 100パルスと書いてあります。
そして、右回転と左回転では異なるパルスが出て来ます。(意味が解らないぞ~)
つまり、回転方向の違いで扱う「数」を増減できます。(フムフム)

右へ静かに廻すと(時計方向)数が増える・・・周波数が高くなる・・・
左へ静かに廻すと数が減る・・・周波数が低くなる・・・

と云う使い方が出来ます。(お~ VFOのメインダイヤルにピッタシじゃん)
前振りが長く成りましたが、今回の Si5351A制御には欠かせない部品かと思います。

さて実際に使うとなると、其のパルスの出具合(右・左回転の違い)を認識させるプログラムを考えなければイケマセン。
当然、諸先輩が色々考えてネット上に沢山有るようですが、其れには目もクレズ・・・独りよがりの爺さんが考えてみます。(又かよ~)
同じ様なプログラムが有ったらゴメンナサイ。

さて、右・左回転のパルスの違いは何なのか?・・・此れが理解できないと話しになりません。(勉強しました・・・本当です)
私レベル(素人)で解った事は、廻した時に発生する2種類のパルスのスピードがA/Bで異なると云うことです。(必ず2種類のパルスが出力される)
廻すとA/Bのパルスの山どうしが重なるタイミングは必ず来る訳で、其の回数は此のエンコーダでは1回転で100回です。
つまり、廻して行くと山が重なった状態から徐々に外れて行き、完全に重なりが無くなり・・・次の重なり始める、絶妙なタイミングはどちらのパルスなのか?・・・を確認すれば回転状況が解るはずです。(難し過ぎて、此れを書いてる本人も解ってないな~)
素人の屁理屈は此の辺にしてプログラムを下に・・・

EN(){                         // エンコーダ***
 loop: ER=0;EL=0;
 if ((GP5==0)&&(GP4==0)){
 __delay_ms(2);if (GP5==1){
 ER=1;goto loap;
} if (GP4==1){ EL=1;goto loap;
}
}
 if ((GP2==0)||(GP3==0)){LCC();}  //ここはカーソルに続く
 goto loop;
 loap: F=F+(EL*J)-(ER*J);
}

C言語で [goto]を使うとイモだと云われそうですが、上手く動作します。
下に写真と配線図を・・・

イメージ 2

イメージ 3


此のプログラムを考えている時間は大変楽しかったです。
でも実際に使う段になると、エンコーダで可変できる「位」・・・(周波数で云えば1Hz--10--100--1kHz)を動かせないとダメだと気付きました。
つまり、カーソル表示と其の移動が必要です。

次回は周波数スパンも含めた其の方面を考えます。
先は長いですが宜しく。  by    JA1QVM

クロックジェネレータ/Si5351A・・・その5

$
0
0
当然・・・その4の続きです。
今回はロータリエンコーダで増減させる周波数の「位」を、前後に動かす事を考えます。
言葉で表すとメンドクサソウですが、何の事はないカーソルを移動させ、其の位置に有る数字を増減するだけです。

取りあえずカーソルを表示するプログラム関数を下に・・・

 CC(){                         // カーソル表示***
 LC(JJ);LC(14);
}

何ですかね~、拍子抜けするほど簡単です。
そして次に[JJ]に値を入れて、表示位置を決めるプログラム関数を・・・

LCC(){                       // カーソル操作***
 if (GP2==0) LC(JJ=JJ-1);
 else LC(JJ=JJ+1);
 if (JJ<=129) JJ=135;
 if (JJ>=136) JJ=130;
 CC();
 if (JJ==135) J=1;
 if (JJ==134) J=10;
 if (JJ==133) J=100;
 if (JJ==132) J=1000;
 if (JJ==131) J=10000;
 if (JJ==130) J=100000;
 __delay_ms(300);
}

前回の・・・その4でエンコーダ・プログラムの後半に有った GP2/GP3=0の場合(タクトスイッチON)で飛んで来たのが、この [LCC]です。
押されたのがどちらのスイッチか?を判断して、カーソルを左右に一つ移動させます。
そしてカーソルの在る位置によって、増減させる周波数の「位」を [J]に代入します。
J=1:1Hz・・・J=100:100Hz・・・J=100000:100kHz・・・まで可能にしました。

この辺はモット巧いプログラムが組めそうですが、取りあえず此の程度で・・・笑って下さい。
タクトSWは GP2/GP3に繋ぎます。
下に配線図を・・・

イメージ 1

GP2が ICの 5ピンで GP3が ICの 4ピンです。
紛らわしくて、間違えそうですね。
実際の姿は下の様になります。

イメージ 2

画面では 10MHzを表示しており、カーソルの位置は其の 100kHzの所に有りますから、この状態でエンコーダを廻すと 100kHzステップで数字が変化します。

さて残るは、此の LCDに表示させている数値で現実に発振させることが可能か?・・・
次回は周波数スパンも含めた、其の Si5351A制御の真髄に迫ろうと思います。
お楽しみに。  by    JA1QVM

クロックジェネレータ/Si5351A・・・その6

$
0
0
「・・・その6」でやっと細かな周波数設定に辿り着きました、と云う事に成っていますが、実際の時系列は違います。
本当はかなり前の時期に1Hzステップのプログラムは完成しています。
Si5351Aにのめり込むキッカケが当にそれで、自分で其のプログラムを「考える」からスタートしました。

今考えても良く解らない(作った本人でも)プログラム関数を下に・・・

FK(){                         // 発振周波数計算 P/Q***
 unsigned int SS;
 SS=1536+(B1*128/499989);
 P1L=SS&255;P1H=(SS>>8)&255; 
 SS=(B1-((B1*128/499989)*499989/128));
 P2L=SS&255;P2H=(SS>>8)&255;
 P3L=66;P3H=15;
 Q1H=23;Q3L=1;
}

作っている時は夢中でしたので解っていたのでしょうが、今解説しろと云われても・・・???です。
ただ、プログラムですからデタラメに組んで動く訳はありません。
おそらく脳内に別の「私」が現れて作ったのでしょう。
同じプログラムが在ったら「ごめんなさい」です。

B1と云う変数が出て来ますが、此れは [F]から変換します。

 FB(){                            // F-->B1変換***
 B1=F*(1<<N)-7999828;
}

ついでに周波数スパン設定のプログラムも・・・

FS(){                            // 周波数スパン***
 if (F>=20000000)  F=20000000;
 if (F<=2500000)    F=2500000;
 if (F>=10000000)  {N=0;goto laop;}
 if (F>=5000000)    {N=1;goto laop;}
 if (F>=2500000)    {N=2;goto laop;}
 laop: ER=ER;
}

得意な? [goto]命令を使っています。

以上をもって、全てのプログラム関数は出尽くしました。
最後にメイン部分を下に・・・

/**Si5351**2.5-20MHz/1HzSTEP*12F683
 周波数補正あり**/

 #include <pic.h>
 
 __CONFIG(FOSC_INTOSCIO&WDTE_OFF
 &PWRTE_ON&BOREN_ON&MCLRE_OFF
 &CP_OFF&IESO_OFF&FCMEN_OFF);

 #define _XTAL_FREQ 8000000
 #define SDA GP1
 #define SCL GP0
 #define TRISSDA TRISIO1
 
 unsigned char data,regi,cmd,ER,EL,JJ,N;
 unsigned char P1H,P1L,P2H,P2L,P3H,P3L;
 unsigned char Q1H,Q3L;
 unsigned char h1,h2,h3,h4,h5,h6,h7,h8;
 unsigned long B1,F,J;
 
 void main(){
 OSCCON=0b01110000;
 ANSEL =0b00000000;
 CMCON0=0b00000111;
 TRISIO=0b00111100;
 GPIO  =0b00000000;
 
 F=15000000;J=100;JJ=133;      //スタート画面設定 F:発振周波数
 FS();FB();FA();VFO();             //J:エンコーダステップ周波数
                                             //JJ:Jのカーソル位置
  while(1){
 FC();LCN();CC();EN();
 FS();FB();FK();FABC1();
}
}

***********                                    
此処までがメインプログラムで、此れより下は全て関数プログラム。

 FB(){ }                            // F-->B1変換***
 
 FS(){ }                            // 周波数スパン***
 
 FC(){ }                         // 周波数カウンタ***

 EN(){ }                          // エンコーダ***
 
 FK(){ }                         // 発振周波数計算 P/Q***
 
 LCN(){ }                         // 8桁の数字を表示***
 
 LCC(){ }                         // カーソル操作***
 
 CC(){ }                           // カーソル表示***
 
 FABC1(){ }                     // P1,P2,P3の変化***
 
 FABC2(){ }                     // Q1,Q2,Q3の変化***
 
 VFO(){ }                         // VFO初期設定***
  
 STA(){ }                         // スタート条件出力***
 
 STP(){ }                         // ストップ条件出力***
 
 OUT(data){ }                   // I2Cで1バイト出力/ACK***
 
 FA(){ }                           // LCD初期化***
 
 LD(data){ }                     // LCD 1文字表示データ出力***
 
 VD(regi,data){ }               // VFO 1データ出力***
 
 LC(cmd){ }                     // LCD 1コマンド出力***
 
**********

ウンザリするほど長いです。
しかも 12F683のメモリを殆ど使い切っています。(98%以上)
ですから他の事をやらせたくても出来ません・・・悪しからず。
必ず居るんですね~・・・此れもアレモついでにやらせろと云う輩が・・・(独り言です)

肝心な性能の方は・・・
発振周波数範囲: 2.5~20MHz/1Hz~100kHzステップ
スプリアス(高調波を除く):-60~-70db
周波数精度:モジュールに付随している水晶発振子に聞いて下さい。

実験中に何個かの Si5351Aモジュールを壊してしまいました。
其の教訓を生かして?出力側に 2SK125のソースフロアを入れてます。配線図を下に・・・

イメージ 1

私の独断と偏見によるプログラムが多数有りますので、パクル人は自己責任でお願いします。

以上、大変長い間 Si5351Aのプログラムにお付き合い頂き有難うございました。

これからも宜しくお願いします。  by    JA1QVM

Viewing all 161 articles
Browse latest View live