JH7UBCブログ

アマチュア無線、マイコンなど趣味のブログです。

全体表示

[ リスト | 詳細 ]

記事検索
検索

全257ページ

[1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11]

[ 次のページ ]

ブログを引っ越します

 このブログは、2006年5月に開設しました。長い間お世話になり、ありがとうございました。

 Yahoo!ブログサービスが12月15日に終了するというアナウンスがあり、引っ越すことにしました。

 私のもう一つのブログであるgooブログの「ゆめの森」を新たに「JH7UBCブログ」として、そちらに引っ越すことにしました。

 PIC16F1705の勉強の記事から既にそちらに書き始めました。どうぞよろしくお願いします。

 こちらの記事は、12月15日までは、そのままにします。それ以降は消滅するようです。

開く コメント(1)

開く トラックバック(0)

 PIC16F1827を使って、周波数カウンタを作ってみました。

 これまで、PIC16F88,PIC16F628Aなどで製作した「電子工作etc」というサイトで紹介された「周波数カウンタV7」と基本的には同じアルゴリズムです。

 残念ながら「電子工作etc」というサイトは既に見えなくなっているようです。

 PIC 1個で、どのようにして周波数カウンタを作るかを簡単に説明します。

 周波数カウンタを作るには、周波数を測定するカウンタとカウント時間(普通は1秒)を発生するタイムベースが必要です。

 PICは、内部に複数のタイマー(カウンタ)を持っています。そのうち16bitタイマーであるTimer1(TMR1)を周波数を測定するカウンタに使い、8bitタイマーTimer2(TMR2)を使って1秒を発生させます。

 TMR2を利用したタイムベースからの1秒の合図で、TMR1へのゲートを開けたり閉めたりして、周波数をカウントします。

 詳細は、JH7UBCホームページのここを見てください。

回路図です。

イメージ 1

 入力信号は、2SC1815GRの簡単なアンプを通して、T1CKI(RB6)に加えます。

 クロックは、正確に測定するために20MHzのクリスタルオシレータを使い、外部クロック入力CLKIN(RA7)に入れます。

 周波数表示は、I2Cアダプタ付きのLCD1602を使いました。

 動作確認のために、TMR1のゲートが開いている間点灯するLEDをつけました。

 ブレッドボードです。自作SGからの1MHz(1000000Hz)の信号を測定しています。

イメージ 2

プログラムです。
------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
// CONFIG1
#pragma config FOSC = ECH   //外部クロック CLKIN (4-32MHz)
#pragma config WDTE = OFF
#pragma config PWRTE = ON
#pragma config MCLRE = OFF
#pragma config CP = OFF
#pragma config CPD = OFF
#pragma config BOREN = ON
#pragma config CLKOUTEN = OFF
#pragma config IESO = OFF
#pragma config FCMEN = OFF
// CONFIG2
#pragma config WRT = OFF
#pragma config PLLEN = OFF
#pragma config STVREN = ON
#pragma config BORV = HI
#pragma config LVP = OFF

#define _XTAL_FREQ 20000000   //クロック20MHz
#define LED RA4

//LCD関係定義
#define LCD_EN 0b00000100   //Enable
#define LCD_BL 0b00001000   //Back Light
#define LCD_CMD 0x00
#define LCD_CHR 0x01
#define LCD_LINE1 0x80
#define LCD_LINE2 0xC0
#define LCD_addr 0x4E   //0x27<<1

/* I2C 初期化*/
void I2C_init(){
    SSP1CON1 = 0x28;        //SSPEN = 1,I2C Master Mode
    SSP1STATbits.SMP = 1;   //標準速度モード(100KHz)
    SSP1ADD = 0x31;         //Fosc/(4*Clock)-1  Clock=100kHz,Fosc=20MHz
}

/* スタートコンディション */
void I2C_start(){
    SSP1CON2bits.SEN = 1;
    while(SSP1CON2bits.SEN);
}

/* ストップコンディション */
void I2C_stop(){
    SSP1IF = 0;
    SSP1CON2bits.PEN = 1;
    while(SSP1CON2bits.PEN);
    SSP1IF = 0;
}

/* I2Cに1byte送信 */
void I2C_write(unsigned char dat){
    SSP1IF = 0;
    SSP1BUF = dat;
    while(!SSP1IF);
}

void Write_data(unsigned char data){
    I2C_start();
    I2C_write(LCD_addr);
    I2C_write(data | LCD_EN | LCD_BL);
    I2C_write(data | LCD_BL);
    I2C_stop();
    __delay_us(100);
}

void LCD_write(unsigned char bits,unsigned char mode){
    //send High 4bits
    Write_data((bits & 0xF0) | mode);
    //send Low 4bits
    Write_data(((bits << 4) & 0xF0) | mode);
}

void LCD_init(){
    LCD_write(0x33,LCD_CMD);
    LCD_write(0x32,LCD_CMD);
    LCD_write(0x06,LCD_CMD);
    LCD_write(0x0C,LCD_CMD);
    LCD_write(0x28,LCD_CMD);
    LCD_write(0x01,LCD_CMD);
    __delay_ms(1);
}

void LCD_clear(){
    LCD_write(0x01,LCD_CMD);
    __delay_ms(1);
}

void LCD_home(){
    LCD_write(0x02,LCD_CMD);
    __delay_ms(1);
}

void LCD_cursor(unsigned char x,unsigned char y){
    if (y == 0){
        LCD_write(LCD_LINE1+x,LCD_CMD);
    }
    if (y == 1){
        LCD_write(LCD_LINE2+x,LCD_CMD);
    }
}
void putch(unsigned char ch){
    LCD_write(ch,LCD_CHR);
}

static unsigned int MeassuremmentCnt;

/*TMR2のオーバーフロー割り込み*/
void interrupt isr(){
    TMR2IF = 0;//TMR2割り込みフラッグクリア
    MeassuremmentCnt --;
    if (MeassuremmentCnt == 0){
        TMR1ON = 0;//ゲートを閉める。
        TMR2ON = 0;//TMR2を停止する。
    }
}

/*周波数測定*/
unsigned long FreqMeassurement(){
    static unsigned long freq;
    /*TIMERの初期化*/
    TMR1IF = 0; //TMR1割り込みフラッグクリア
    TMR1L = 0;  //TMR1クリア
    TMR1H = 0;
    /*TMR2の初期化*/
    TMR2IF = 0; //TMR2割り込みフラッグクリア
    MeassuremmentCnt = 1221;
    TMR2 = 0x4C;
    /*counter 初期化*/
    freq = 0;
    /*割り込み許可*/
    PEIE = 1;
    GIE = 1;
    //count start
    TMR2ON = 1;
    /*gate time調整 NOP 25*/
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    NOP();
    /*ゲートを開ける*/
    TMR1ON = 1;
    while(TMR2ON){
        if(TMR1IF == 1){
            TMR1IF = 0;
            freq ++;
        }
    }
    if(TMR1IF == 1){
        TMR1IF = 0;
        freq ++;
    }
    /*換算*/
    freq = freq * 65536;
    freq = freq + ((unsigned)TMR1H * 256) + (unsigned)TMR1L;
   
    return(freq);
}
   
void main() {
    ANSELA = 0b00000000 ;     // AN0-AN4は使用しない
    ANSELB = 0b00000000 ;     // AN5-AN11は使用しない
    TRISA  = 0b10000000 ;     // RA7は入力  他は出力(RA5は入力)
    TRISB  = 0b01010010 ;     // RB1(SDA),RB4(SDA),RB6は入力他は出力
    PORTA  = 0b00000000 ;     // PORTA初期化
    PORTB  = 0b00000000 ;     // PORTB初期化
   
    I2C_init();
    LCD_init();
    LCD_cursor(12,0);
    printf("Hz");
   
     /*TMR2の設定*/
    TMR2IE = 1;     //TMR2割り込み許可
    TMR2IF = 0;     //TMR2割り込みフラッグクリア
    T2OUTPS0 = 0;   //TMR2 output poststscaler 1:1
    T2OUTPS1 = 0;
    T2OUTPS2 = 0;
    T2OUTPS3 = 0;
    TMR2ON = 0;     //TMR2 off
    T2CKPS0 = 0;    //TMR2 prescaler 1:16
    T2CKPS1 = 1;
    TMR2 = 0;       //TMR2 clear
   
    /*TMR1の設定*/
    TMR1IE = 0;     //TMR1割り込み禁止
    TMR1IF = 0;     //TMR1割り込みフラッグクリア
    T1CKPS0 = 0;    //TMR1 prescaler 1:1
    T1CKPS1 = 0;
    T1OSCEN = 0;    //TMR1 Clock source = T1CKI
    TMR1CS1 = 1;
    TMR1CS0 = 0;
    nT1SYNC = 1;
    TMR1ON = 0;     //TMR1 stop
    TMR1L = 0;      //TMR1 clear
    TMR1H = 0;
   
    while(1){
    /*周波数の測定*/
    LED = 1;//RA4 LED ON
    unsigned long frequency = FreqMeassurement();
    LED = 0;//RA4 LED OFF
    LCD_cursor(2,0);
    printf("%9ld",frequency);
    __delay_ms(500);
    }
}

開く コメント(0)

開く トラックバック(0)

 2月9日〜10日に開催されたKCJトップバンドコンテストの結果が、今朝メールで届きました。

 届いたのは、当局の照合結果ですが、KCJのホームページに全体の結果が発表されていました。


 当局JH7UBCの結果は、全国23位(171局中)、福島県1位(5局中)でした。

 初めての参加でしたので、まずまずの結果だと思います。

 しかし、当局が相手局コールサインをミスコピーしたのが3局ありました。

 まだまだですね。

 来年も頑張ろうと思います。

開く コメント(0)

PIC16F1827 PWM テスト

 PIC16F1827は、CCP1からCCP4の4つのMWP出力を持っています。

イメージ 1

 PWMの動作原理は、JH7UBCホームページのPIC16F628A PWM テストの記事をご覧ください。

 PWMのPeriod(周期)とDuty Cycle、Duty比は、次の式で設定します。

イメージ 2

 テストとして、CCP3に1000Hz(周期1ms=1×10^-3s) デューティ比50%のPWM信号を出力してみます。

 PICのクロックは、内臓クロック8MHz(Tosc=1/8×10^6)とし、Timerは、Timer2を使います

 上記の式からPWM周期を決定するTimer2のPR2の値は

PR2 = Period / (4×Tosc × TMR2Prescale Value) - 1= 1×10^-3/(4×(1/8×10^6)×TMR2 Prescale Value) -1

       = 2×10^3/TMR2 Prescale Value  となります。

TMR2のプリスケーラの値によってPR2の値は次のようになります。

 Prescale Value   PR2
     1                   1999
     4                     499
     16                   124

 PR2レジスタは8bitですから0〜255の値でなければなりませんので

 Prescale Value = 16     PR2 = 124 となります。

 デューティ比を50%としますので、CCPR3L = (PR2 + 1)/2 = 125/2 = 62 となります。

 プログラムです。

 CCP3CONレジスタのbit3:2=11でPWM modeに設定し、bit1:0=00で出力をactive highに設定します。

 CCPTMRSレジスタのbit5:4=00でCCP3にTMR2を割り当てます。

 T2CONレジスタのbit1:0=10でプリスケーラ値を1:16に設定します。同じT2CONレジスタのbit2=1とするとTMR2が有効になり、PWM信号が出力されます。

 実際に出力されたPWM信号の周波数を測定してみました。

イメージ 3

 998Hzでした。誤差2%というところです。
 #include <stdio.h>
#include <stdlib.h>
#include <xc.h>
// CONFIG1
#pragma config FOSC = INTOSC
#pragma config WDTE = OFF
#pragma config PWRTE = ON
#pragma config MCLRE = OFF
#pragma config CP = OFF
#pragma config CPD = OFF
#pragma config BOREN = ON
#pragma config CLKOUTEN = OFF
#pragma config IESO = OFF
#pragma config FCMEN = OFF
// CONFIG2
#pragma config WRT = OFF
#pragma config PLLEN = OFF
#pragma config STVREN = ON
#pragma config BORV = HI
#pragma config LVP = OFF
#define _XTAL_FREQ 8000000   //クロック8MHz
void main() {
    OSCCON = 0b01110010 ;     // 内蔵クロック8MHz
    ANSELA = 0b00000000 ;     // AN0-AN4は使用しない。全てデジタルポート
    ANSELB = 0b00000000 ;     // AN5-AN11は使用しない。全てデジタルポート
    TRISA  = 0b00000000 ;     // PORTAは全て出力(  RA5は入力のみ)
    TRISB  = 0b00000000 ;     // RORTBは全て出力
    PORTA  = 0b00000000 ;     // PORTA初期化
    PORTB  = 0b00000000 ;     // PORTB初期化
   
    /* PWMに関する設定
     * CCP3(RA3,2番ピン)を使う
     * PWMの周波数は、1000Hz(周期は1ms)
     * デューティ比は、50%とする
     */
   
    CCP3CON = 0b00001100;   //PWM mode P3A,P3C active high,P3B,P3D active high
    CCPTMRS = 0b00000000;   //bit5-bit4=00,CCP3にTimer2を割り当てる
    PR2 = 124;              //Timer2の周期を設定
    CCPR3L = 62;            //デューティ比 50%
    T2CON = 0b00000110;     //prescale 1:16 Timer2 start
   
    while(1){
       
    }
}

開く コメント(0)

開く トラックバック(0)

PIC16F1827 AD9834DDS VFO

 先日製作した3.5/7MHz SDRフロントエンドと組み合わせて実際の交信をしてみようと思い、7MHzのCW送信機を作ろうと思います。

 まず、AD9834DDSをPIC16F1827でコントロールして7MHz VFOを作ります。

 PIC16F883+AD9834 VFOのプログラムをPIC16F1827用に若干変更し、ロータリーエンコーダは、IOC割り込みを利用した方法にしました。

 回路図です。

イメージ 1

ブレッドボードです。

イメージ 2

AD9834DDSの出力の波形です。

イメージ 3

参考までに、プログラムです。

-----------------------------------------
/*
 * File:   main.c
 * Author: JH7UBC Keiji Hata
 * PIC16F1827_AD9834_VFO
 * Created on 2019/03/27
 */

#include <stdio.h>
#include <stdlib.h>
#include <xc.h>

// CONFIG1
#pragma config FOSC = INTOSC
#pragma config WDTE = OFF
#pragma config PWRTE = ON
#pragma config MCLRE = OFF
#pragma config CP = OFF
#pragma config CPD = OFF
#pragma config BOREN = ON
#pragma config CLKOUTEN = OFF
#pragma config IESO = OFF
#pragma config FCMEN = OFF

// CONFIG2
#pragma config WRT = OFF
#pragma config PLLEN = ON
#pragma config STVREN = ON
#pragma config BORV = HI
#pragma config LVP = OFF
#define _XTAL_FREQ 32000000   //クロック32MHz

//LCD関係定義
#define LCD_EN 0b00000100   //Enable
#define LCD_BL 0b00001000   //Back Light
#define LCD_CMD 0x00
#define LCD_CHR 0x01
#define LCD_LINE1 0x80
#define LCD_LINE2 0xC0
#define LCD_addr 0x4E   //0x27<<1

/* ロータリーエンコーダ関係定義*/
#define ECA RB6 //エンコーダA
#define ECB RB7 //エンコーダB
unsigned char EA;
unsigned char EB;
volatile unsigned char curDat;
volatile unsigned char befDat;
volatile signed char count= 0;

/* STEP関係設定 */
unsigned int Step = 1000;       //STEP初期値
#define STEP_SW RB5

/* AD9834DDS関係定義 */
#define FSYNC RA0
#define SCLK RA1
#define SDATA RA2
unsigned long Freq = 7000000;   //周波数初期値
unsigned long Freq_old;         //周波数の前の値
const unsigned long Fre_Hi = 7200000; //周波数上限
const unsigned long Fre_Lo = 7000000; //周波数下限

/* I2C 初期化*/
void I2C_init(){
    SSP1CON1 = 0x28;        //SSPEN = 1,I2C Master Mode
    SSP1STATbits.SMP = 1;   //標準速度モード(100KHz)
    SSP1ADD = 0x4F;         //Fosc/(4*Clock)-1  Clock=100kHz,Fosc=32MHz
}

/* スタートコンディション */
void I2C_start(){
    SSP1CON2bits.SEN = 1;
    while(SSP1CON2bits.SEN);
}

/* ストップコンディション */
void I2C_stop(){
    SSP1IF = 0;
    SSP1CON2bits.PEN = 1;
    while(SSP1CON2bits.PEN);
    SSP1IF = 0;
}

/* I2Cに1byte送信 */
void I2C_write(unsigned char dat){
    SSP1IF = 0;
    SSP1BUF = dat;
    while(!SSP1IF);
}

void Write_data(unsigned char data){
    I2C_start();
    I2C_write(LCD_addr);
    I2C_write(data | LCD_EN | LCD_BL);
    I2C_write(data | LCD_BL);
    I2C_stop();
    __delay_us(100);
}

void LCD_write(unsigned char bits,unsigned char mode){
    //send High 4bits
    Write_data((bits & 0xF0) | mode);
    //send Low 4bits
    Write_data(((bits << 4) & 0xF0) | mode);
}

void LCD_init(){
    LCD_write(0x33,LCD_CMD);
    LCD_write(0x32,LCD_CMD);
    LCD_write(0x06,LCD_CMD);
    LCD_write(0x0C,LCD_CMD);
    LCD_write(0x28,LCD_CMD);
    LCD_write(0x01,LCD_CMD);
    __delay_ms(1);
}

void LCD_clear(){
    LCD_write(0x01,LCD_CMD);
    __delay_ms(1);
}

void LCD_home(){
    LCD_write(0x02,LCD_CMD);
    __delay_ms(1);
}

void LCD_cursor(unsigned char x,unsigned char y){
    if (y == 0){
        LCD_write(LCD_LINE1+x,LCD_CMD);
    }
    if (y == 1){
        LCD_write(LCD_LINE2+x,LCD_CMD);
    }
}

void putch(unsigned char ch){
    LCD_write(ch,LCD_CHR);
}

void Freq_disp(unsigned long frequency){
    LCD_home();
    printf("%8ld",frequency);
}

void Step_disp(unsigned int stp){
    LCD_cursor(4,1);
    printf("%4d",stp);
}

void Step_change(){
    __delay_ms(5);
    if(Step == 10){
        Step = 1000;
    }else{
    Step = Step/10;
    }
    Step_disp(Step);
    while(!STEP_SW){
    __delay_ms(5);
    }
}

/* AD9834DDSに16ビット送信 */
void Data_send(unsigned long data){
    for(unsigned char i = 0;i<16;i++){
        if(data & 0x8000){
            SDATA = 1;
        }else{
            SDATA = 0;
        }
        __delay_us(1);
        SCLK = 0;
        __delay_us(1);
        SCLK = 1;
        data <<= 1;
    }
}

/* AD9834DDSに周波数データを送る */
void Fnc_DDS(unsigned long frequency){
    unsigned long wrk = frequency << 2;
    unsigned int wrk1,wrk2,wrk3;
   
    wrk1 = 0x2000;          //コントロールワード
    wrk2 = wrk & 0x3fff;    //周波数データ下位
    wrk2 = wrk2 | 0x4000;
    wrk3 = wrk >> 14;
    wrk3 = wrk3 & 0x3fff;   //周波数データ上位
    wrk3 = wrk3 | 0x4000;
    SCLK = 1;
    FSYNC = 0;
    Data_send(wrk1);
    Data_send(wrk2);
    Data_send(wrk3);
    FSYNC = 1;
}

void interrupt isr(){
    IOCIF = 0;   //割り込みフラッグクリア
    IOCBF6 = 0;
    IOCBF7 = 0;
    __delay_ms(2);
    curDat = ECA + (ECB<<1);
    if (befDat != curDat){
        unsigned char d = ((befDat<<1)^curDat) & 3; //回転方向判定
        if(d < 2){
            count++;
        }else{
            count--;
        }
        befDat = curDat;
    }
    if(count >= 4){
        Freq += Step;
        count = 0;
    }else if(count <= -4){
        Freq -= Step;
        count = 0;
    }
}

void main(){
    OSCCON = 0b01110000 ;     // 内部クロック8MHz
    ANSELA = 0b00000000 ;     // AN0-AN4は使用しない
    ANSELB = 0b00000000 ;     // AN5-AN11は使用しない
    TRISA  = 0b00000000 ;     // PORTAは全て出力(RA5は入力)
    TRISB  = 0b11110010 ;     // RB1(SDA),RB4(SDA),RB5,RB6(REA),RB7(REB)は入力他は出力
    PORTA  = 0b00000000 ;     // PORTA初期化
    PORTB  = 0b00000000 ;     // PORTB初期化
    OPTION_REGbits.nWPUEN=0;  // ウィークプルアップ許可
    WPUB = 0b11100000;        // RB5,RB6,RB7をプルアップ
       
    /* IOC割り込み設定 */
    IOCBN = 0b11000000;     //RB6,RB7立下り割り込み設定
    IOCBP = 0b11000000;     //RB6,RB7立ち上がり割り込み設定
    IOCIE = 1;              //IOC割り込み許可
    GIE = 1;                //全割り込み許可
           
    I2C_init();             //I2C初期化
    LCD_init();             //LCD初期化
   
    /* Roatry Encoder 初期値 */
    EA = ECA;
    EB = ECB;
    befDat = EA + (EB<<1);  
  
    /* 初期表示と初期周波数設定 */
    LCD_cursor(9,0);
    printf("Hz");
    Freq_disp(Freq);
    Fnc_DDS(Freq);
    LCD_cursor(0,1);
    printf("STEP");
    Step_disp(Step);
   
   
    while(1){
        if(STEP_SW == 0){
            Step_change();
        }
        if(Freq != Freq_old){
            if(Freq < Fre_Lo)Freq = Fre_Lo;
            if(Freq > Fre_Hi)Freq = Fre_Hi;
            Fnc_DDS(Freq);
            Freq_disp(Freq);
            Freq_old = Freq;
        }
    }
}

開く コメント(0)

開く トラックバック(0)

全257ページ

[1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11]

[ 次のページ ]


.


プライバシー -  利用規約 -  メディアステートメント -  ガイドライン -  順守事項 -  ご意見・ご要望 -  ヘルプ・お問い合わせ

Copyright (C) 2019 Yahoo Japan Corporation. All Rights Reserved.

みんなの更新記事