しばらくぶりに、PICの記事を書きます。
先日製作した3.5MHz/7MHz用SDRフロントエンド+パソコンを受信機とし、簡単な7MHz CW送信機と組み合わせて交信してみたいと考えました。
そこで、3チャンネルクロックジェネレータSi5351AをVFOとして使い、BS170 E級のファイナルとして、2~3Wの送信機を作ってみようと思います。
Si5351Aのコントロールは、PIC12F1840を使うことにします。
今日は、第一段階として、PIC12F1840でロータリーエンコーダを使うテストをしました。
回路図です。ロータリーエンコーダの回転方向を判定して、シリアル通信でパソコンに結果を送り、TeraTermの「RIGHT」「LEFT」と表示します。シリアルUSB変換は、FT234モジュールを使用します。
OPTION_REGのnWPUEN=0として、ウィークプルアップを有効にします。
更にWPUA=0b00110000として、RA4とRA5をウィークプルアップします。これにより、プルアップ抵抗を省略しています。
ロータリーエンコーダは、回転させると接点A,Bの状態(+か0)が変化し、RA4とRA5の状態が変化します。このピンの状態が変化したときに割り込みがかかるようにして(IOC割り込み)、回転方向を判定します。
IOCIE=1として、ピン状態変化割り込みを有効にします。
更に、IOCAP=0b00110000として、RA4とRA5のピン状態の立ち上がり検出を有効にし、IOCAN=0b00110000として、ピン状態の立下り検出も有効にします。
回転方向に判定方法については、JH7UBCホームページのここを見てください。
ブレッドボードです。
プログラムです。
/*
* File: main.c
* Author: JH7UBC Keiji Hata
* PIC12F1840 Rotary Encoder test
* Created on 2019/06/22
*/
* File: main.c
* Author: JH7UBC Keiji Hata
* PIC12F1840 Rotary Encoder test
* Created on 2019/06/22
*/
#include <stdio.h>
#include <stdlib.h>
#include <xc.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
#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
#pragma config WRT = OFF
#pragma config PLLEN = ON
#pragma config STVREN = ON
#pragma config BORV = HI
#pragma config LVP = OFF
#define _XTAL_FREQ 32000000
/* ロータリーエンコーダ関係定義*/
#define ECA RA5 //エンコーダA
#define ECB RA4 //エンコーダB
volatile unsigned char curDat;
volatile unsigned char befDat;
volatile signed char count= 0;
#define ECA RA5 //エンコーダA
#define ECB RA4 //エンコーダB
volatile unsigned char curDat;
volatile unsigned char befDat;
volatile signed char count= 0;
void serial_init(unsigned long BR){
TXSTA = 0x24; //SYNC=0 TXEN = 1 BRGH = 1
BRG16 = 1; //BRG 16bit mode
RCSTA = 0x90; //非同期、継続受信可
unsigned int X= _XTAL_FREQ/BR/4 - 1;
SPBRGH = X / 256;
SPBRGL = X % 256;
}
TXSTA = 0x24; //SYNC=0 TXEN = 1 BRGH = 1
BRG16 = 1; //BRG 16bit mode
RCSTA = 0x90; //非同期、継続受信可
unsigned int X= _XTAL_FREQ/BR/4 - 1;
SPBRGH = X / 256;
SPBRGL = X % 256;
}
void putch(unsigned char byte){
while(!TXIF);
TXREG = byte;
}
while(!TXIF);
TXREG = byte;
}
void __interrupt() isr(){
IOCIF = 0; //割り込みフラッグクリア
IOCAF = 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){
printf("RIGHT\r\n");
count = 0;
}else if(count <= -4){
printf("LEFT\r\n");
count = 0;
}
}
IOCAF = 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){
printf("RIGHT\r\n");
count = 0;
}else if(count <= -4){
printf("LEFT\r\n");
count = 0;
}
}
void main() {
OSCCON = 0b01110000 ; // 内部クロック8MHz
ANSELA = 0b00000000 ; // アナログは使用しない
TRISA = 0b00110010 ; // RA1,RA4,RA5は入力、他は出力
PORTA = 0b00000000 ; // 出力ピンの初期化
OPTION_REGbits.nWPUEN = 0;//ウィークプルアップ許可
WPUA = 0b00110000; //RA4,RA5をウィークプルアップ
/* 割り込み関係設定 */
IOCIE = 1; //状態変化割り込み許可
IOCAP = 0b00110000; //RA4,RA5立ち上がりエッジ検出
IOCAN = 0b00110000; //RA4,RA5立ち下りエッジ検出
PEIE = 1; //周辺割り込み許可
GIE = 1; //全割り込み許可
/* シリアル通信設定 */
serial_init(9600);
while(1){
}
}
OSCCON = 0b01110000 ; // 内部クロック8MHz
ANSELA = 0b00000000 ; // アナログは使用しない
TRISA = 0b00110010 ; // RA1,RA4,RA5は入力、他は出力
PORTA = 0b00000000 ; // 出力ピンの初期化
OPTION_REGbits.nWPUEN = 0;//ウィークプルアップ許可
WPUA = 0b00110000; //RA4,RA5をウィークプルアップ
/* 割り込み関係設定 */
IOCIE = 1; //状態変化割り込み許可
IOCAP = 0b00110000; //RA4,RA5立ち上がりエッジ検出
IOCAN = 0b00110000; //RA4,RA5立ち下りエッジ検出
PEIE = 1; //周辺割り込み許可
GIE = 1; //全割り込み許可
/* シリアル通信設定 */
serial_init(9600);
while(1){
}
}
TeraTernの画面です。時計方向に回転させると「RIGHT」、反時計回りに回転させると「LEFT」と表示されます。
コンパイラは、xc8 Ver2.05を使っています。
コンパイルエラーが出るときは、Project PropartiesでXC8 Global OptionのC standerdをC99からC90に変更してください。