ANALOG DEVICES Co.のAD9834のDDS用ICをつかったVFOを作りたくなりました。突然といっても、Windows10でMPLAB X IDEをインストールしたため、何か一つプログラムを組んでつくってみようと思ったのが事のきっかけです。参考となったホームページは、下記になります。
[AD9834を使った実験用DDS-VFOの制作]
このホームページでは、MPLAB Version8.90にCコンパイラはフリーのC18でのサンプルコードでした。いろいろなデバイスで対応できる方なので、無線をやっているものとしては、とても参考になります。特にメインのコードを全部載せてくれているのがありがたいです。(LCDドライバ(lcd.c ,lcd.h )は残念ながら載せていません。)
私のインストールした MPLAB X IDEは、バージョンが最新のv3.30でCコンパイラーはXC8になります。コードの若干の手直しが必要ですが、ほぼ特別なファンクション(EEPROMコード)とLCDのライブラリでのファンクション名が異なるのを除いては、ほぼまるまるコードは使えそうです。??
まずは、最初にPIC18F14K50にLCD(SC1602BBWB-XA-LG-G)を繋ぐことから始めました。久々なので、前のLCD動作したサンプルコードを思い出し参考にしてみました。今回のVFOの参考としたホームページの回路図での配線をそのままPIC18F14K50とLCDに行います。このことが、LCD表示のドライバのプログラムを手直しすることになってしまいました。こだわりではないですが、汎用のLCDドライバでは、動作しなかったためです。前もブログに載せて対応できたドライバも使えません。
ことは、「連続でのポート以外は使えないLCDドライバがほとんど」ということです。私の今回参考とした回路図では、たまたま、不連続なポートでの動作サンプルだったのです。
通常はLCD側のポートD4,D5,D6,D7に対してPIC側も連続のポートRC4,RC5,RC6,RC7などとして使うので、WEBで出回っている一般のLCDドライバは動作します。
PIC側のポートが今回は、RC7,RC6,RC3,RC4の不連続なしかもバラバラな接続ではまったく動作しません。動作しない問題となるLCDドライバでのメイン下記のコード部分です。他は問題ありません。
void LCD_out(char c){
LCD_DB = (c>>4) | (LCD_DB & 0xF0);
LCD_EN = 1; // Enable Hi
NOP(); // NOP
LCD_EN = 0; // Enable Low
}
LCD_DB = (c>>4) | (LCD_DB & 0xF0);
LCD_EN = 1; // Enable Hi
NOP(); // NOP
LCD_EN = 0; // Enable Low
}
以前はこの部分を下記のように書き換えて任意のポートで問題ありませんでした。
void LCD_out(char c){
LCD_DB4 = ((c) & 0x01);
LCD_DB5 = ((c >> 1 ) & 0x01);
LCD_DB6 = ((c >> 2 ) & 0x01);
LCD_DB7 = ((c >> 3 ) & 0x01);
LCD_STROBE;
}
PIC18F14K50での連続ポート使用の際は下記で動作します。
void LCD_out(char c){
LCD_DB = (c & 0xF0) | (LCD_DB & 0x0F);
LCD_DB = (c & 0xF0) | (LCD_DB & 0x0F);
LCD_EN = 1; // Enable Hi
//Delay1TCY(); // NOP
NOP(); // NOP
LCD_EN = 0; // Enable Low
}
//Delay1TCY(); // NOP
NOP(); // NOP
LCD_EN = 0; // Enable Low
}
任意ポート対応にするには、下記の LCD_DB = (c & 0xF0) | (LCD_DB & 0x0F);を下記のように書き換える必要があります。
void LCD_out(char c){
//LCD_DB = (c & 0xF0) | (LCD_DB & 0x0F);
if((c & 0x80) != 0){
LCD_DB7 = 1 ;
}else{
LCD_DB7 = 0 ;
}
if((c & 0x40) != 0){
LCD_DB6 = 1 ;
}else{
LCD_DB6 = 0 ;
}
if((c & 0x20) != 0){
LCD_DB5 = 1;
}else{
LCD_DB5 =0;
}
if((c & 0x10) != 0){
LCD_DB4 = 1;
}else{
LCD_DB4 = 0;
}
LCD_EN = 1; // Enable Hi
//Delay1TCY(); // NOP
NOP(); // NOP
LCD_EN = 0; // Enable Low
}
//LCD_DB = (c & 0xF0) | (LCD_DB & 0x0F);
if((c & 0x80) != 0){
LCD_DB7 = 1 ;
}else{
LCD_DB7 = 0 ;
}
if((c & 0x40) != 0){
LCD_DB6 = 1 ;
}else{
LCD_DB6 = 0 ;
}
if((c & 0x20) != 0){
LCD_DB5 = 1;
}else{
LCD_DB5 =0;
}
if((c & 0x10) != 0){
LCD_DB4 = 1;
}else{
LCD_DB4 = 0;
}
LCD_EN = 1; // Enable Hi
//Delay1TCY(); // NOP
NOP(); // NOP
LCD_EN = 0; // Enable Low
}
上記にlcd.cを書き換えて、同郡内のどんな接続順番でもLCDが表示可能になりました。案外とこれが便利で使い道(パターン作成都合とか、あまりポート使用とか)があると思います。
※参考書籍
電子工作のためのPIC16F1ファミリ活用ガイドブック
後閑哲也著;技術評論社
つづく