回路図です。AD9834DDSの出力に簡単なバッファアンプをつけました。
また、ICSPでプログラムの変更ができるように、ロータリーエンコーダーの接続を変更しました。
ケースは、以前周波数カウンタに使っていたものを流用しました。
内部の様子です。
出力は、最大で約12.5dBm(17.8mW)です。周波数設定範囲は、10Hz~約24MHzで、周波数STEPは、1MHz→100KHz→10KHz→1KHz→100Hz→10Hzを循環で変更できます。
1MHzの出力波形です。
参考までにXC8のソースリストを掲載します。
-----------------------------------------------------------------------------------------------------
/*
* File: main.c
* Author: JH7UBC Keiji Hata
* PIC16F1827_AD9834_SG
* Created on 2021/02/01
*/
#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 RB2 //エンコーダA
#define ECB RB3 //エンコーダB
unsigned char EA;
unsigned char EB;
volatile unsigned char curDat;
volatile unsigned char befDat;
volatile signed char count= 0;
/* STEP関係設定 */
unsigned long Step = 1000000; //STEP初期値 1MHz
#define STEP_SW RB5
/* AD9834DDS関係定義 */
#define FSYNC RA0
#define SCLK RA1
#define SDATA RA2
unsigned long Freq = 1000000; //周波数初期値 1MHz
unsigned long Freq_old; //周波数の前の値
/* 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_cursor(4,0);
printf("%8ld",frequency);
}
void Step_disp(unsigned long stp){
LCD_cursor(5,1);
printf("%7ld",stp);
}
void Step_change(){
__delay_ms(5);
if(Step == 10){
Step = 1000000;
}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; //割り込みフラッグクリア
IOCBF2 = 0;
IOCBF3 = 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 = 0b00111110 ; // RB1(SDA),RB2(REA),RB3(REB),RB4(SDA),RB5は入力他は出力
PORTA = 0b00000000 ; // PORTA初期化
PORTB = 0b00000000 ; // PORTB初期化
OPTION_REGbits.nWPUEN=0; // ウィークプルアップ許可
WPUB = 0b00101100; // RB2,RB3,RB5をプルアップ
/* IOC割り込み設定 */
IOCBN = 0b00001100; //RB2,RB3立下り割り込み設定
IOCBP = 0b00001100; //RB2,RB3立ち上がり割り込み設定
IOCIE = 1; //IOC割り込み許可
GIE = 1; //全割り込み許可
I2C_init(); //I2C初期化
LCD_init(); //LCD初期化
/* Roatry Encoder 初期値 */
EA = ECA;
EB = ECB;
befDat = EA + (EB<<1);
/* 初期表示と初期周波数設定 */
LCD_cursor(13,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){
Fnc_DDS(Freq);
Freq_disp(Freq);
Freq_old = Freq;
}
}
}