アマチュア無線のCW モールス信号は、なかなか正確な符号を送信するのが難しいものです。自分で送っている信号を耳で聞くだけでは、どこがどう不正確なタイミングなのか客観的に評価することができません。そこで、PIC16F1619のSMTを利用してキーイング信号のパルス幅を測定し、測定結果はEUSARTからシリアルUSB変換器を経由してPCに送信します。PCの通信ソフトでこの信号を読むことで、短点と長点の長さや符号の間隔の比較など理解しやすくなります。自分の癖に驚くことでしょう。
PICのペリフェラルは以下の用途に使用しています。
USBシリアル変換器とPCをUSBケーブルで接続し、CoolTermなどの通信ソフトを立ち上げます。
通信ソフトの設定画面で
に設定し接続を有効にします。
PICをリセットすると『Ready』表示され、信号待ちの状態になります。電鍵のキーを押すとサイドトーンが聞こえ、CoolTerm画面にパルス幅が表示されます。 PushSWを押すと、トーン周波数数を、666、800、1000Hzから選ぶことができます。PCのCoolTermでの受信例は下図の様に、モールス送信した信号のパルス幅がms単位の一覧形式で表示されます。mark が電鍵を押している時間、space が離れている時間です。2秒以上離れていると文章が終了したと判断して「 - - - 」を表示します。
プログラムは、main.c, IOCNFG.h, IOCNFG.c から構成されています。
IOCNFGには、コンフィグレーションと周辺機器などの初期設定がまとめられ、プログラムの主要フローは、main.c に書かれています。main.c を下に示します。IOCNFG.h, IOCNFG.c は、ダウンロードして確認ください。
モールス練習機 B04_CW_pulse.X.zip |
main.c
/*******************************************************
* CW_pulse
* SMT Hight-Low mode で、電鍵のOnOffパルス幅をms単位で
* 測定し、EUSART経由しUSBに変換してPCに送信する
*******************************************************/
#include "IOCNFG.h"
uint8_t wave[] = { // Sin定数 20分割 MAX 99
97,90,79,65,50,34,20,9,2,0,2,9,20,34,50,65,79,90,97,99
};
uint16_t Pdata; // work data
uint8_t num; // Space配列ポインタ
uint8_t p_wave;
uint8_t data;
void main(void){
IO_Init(); // SYSTEM_Initialize(); // デバイス初期化
INTCONbits.GIE = 1; // 割り込みを有効にする
INTCONbits.PEIE = 1;
while (1) // 繰り返し
{
num = 1; // 信号番号
SMT1PWAIF = 0; // フラッグクリア
SMT1PRAIF = 0;
SMT1IF = 0;
SMT1CON0bits.EN = 1; // SMT有効
SMT1CON1bits.SMT1GO = 1; // 測定開始
printf("\r\nready 21\r\n"); // 準備完了メッセージ送信
printf(" - mark space (ms)\r\n"); // タイトル送信
// ---------- 赤外線信号を受信する -------------------------------
while(!SMT1IF){ // Gapまで繰返
// Side Tone の変更 _______________________________________
if(!RC4){ // SWが押されたら
LATA5 = 1; // LED を点灯
while(!RC4); // SW が離れるのを待つ
LATA5 = 0; // LED を消灯
switch(T2CON){ // トーン周波数変更
case 0x84: T2CON = 0x85; break; // 666Hz
case 0x85: T2CON = 0x83; break; // 1 kHz
default: T2CON = 0x84; break; // 800Hz
}
}
// ------------------------
if(SMT1PWAIF){ // mark終了なら
SMT1PWAIF = 0; // フラグクリア
Pdata = SMT1CPW*32/125;
printf("%2d %5d",num++,Pdata); // mark時間
}
if(SMT1PRAIF){ // space終了なら
SMT1PRAIF = 0; // フラグクリア
Pdata = SMT1CPR * 32 / 125; // msに変換し負数で保存
printf(" %5d\r\n",Pdata); // mark時間
}
}
SMT1IF = 0; // フラグクリア
printf(" ---\r\n"); // Gap時間
//------------ 受信結果を送信する ------------------------------
SMT1CON1bits.SMT1GO = 0; // 測定終了
SMT1CON0bits.EN = 0; // SMT無効
}
}
// ------------ 割り込み処理 ---------------
void __interrupt() INTERRUPT_InterruptManager (void){
if(PIR1bits.TMR2IF == 1){ // TMR2割り込みなら
PIR1bits.TMR2IF = 0; // フラグクリア
PWM3DCH = wave[p_wave]; // 波形定数を更新
if(p_wave >= 19){ // 零点なら
if(!RC7) p_wave = 0; // SW ON で継続
}else{ // 零点以外なら
p_wave ++; // 波形定数を進める
}
}
}
/** End of File **/