PICとの通信にテラタームを利用しているが、さらにExcel_VBAでPICとのデータ通信を試みた。Excelのシリアル通信には、widowsAPIを利用する例がよく紹介されているが、記述コードが多く、使い方も難しそうである。
そこで、さらに探してみると、APIを含むVBモジュールとしてEasyCommが見つかった。
EasyCommは木下隆さんが開発されたモジュールで、既にサポートは終了しているが、未だに多くの方がフォローされているようである(以下のHPを参考にさせていただいた)。
・ HatenaBlog[NOB]さん
・ jizilogさん
使用したパソコン環境は、windows10、Excel2019で、以上のような簡単な記述(コメント行を除くと数行)のみで、(USB)シリアル通信が行えた。なお、USB接続PICターミナルは、次項のバックライトLCD付きのものを用いた(テストは次項の写真参照)。
EasyCommは、windowsAPIを理解しなくても、VBAで簡単かつ手軽に使えるシリアル通信ツールで、改めて木下隆さんに感謝!
P PICミニBBシリーズ(10) 〜Myライブラリーとプリプロセッサ
by fjk
abc899まで、プロジェクトに合わせていくつかのライブラリを作成し、個々に利用していたが、使用するPICによって、その一部を書き換える必要があるなど、使いづらかった。
そこで、MPLABXProjectsフォルダーの下に「myXC8lib」フォルダーを作って、これまでのライブラリをまとめて格納することにした。
しかし、I2CライブラリなどMCCがGenerateしたファイルをライブラリーで利用するには、ライブラリーに現在プロジェクトのパス・ファイル名を記述しなければならず、共有のライブラリとして使えなくなる。それゆえ、共有ライブラリーをmyXC8libから現在プロジェクトフォルダーにコピーすることは避けられなかった(今後の課題)。なお、MCCがGenerateしたファイルを使わないライブラリはコピー不要で使用可能。
そして、現在プロジェクトフォルダーに「myProject.h」ファイルを作成し、このファイルに「#define文」などを記述することで、使用するPICやハードなどプロジェクト毎の違いを吸収することにした。
【ハードウェア】
キャラクター表示LCDに16文字x2行のAQM1602Y-RN-GBWを使ってきたが、ミニBBでもバックライト付のAQM1602Y-NLW-FBWを使えるようにLCDボードの配線を変更した。
LCDの接続には11ピンの丸ピンヘッダーを利用し、バックライト配線を両端のピンに接続した。また、ボードの上隅にLCDを支えるスペーサー用のピンヘッダーも配置した。
LCD表示ボードの配線図 (バックライト用抵抗は220Ω)
(抵抗は交換が容易な位置に配置)
|
LCDバックライトの配線
|
PIC-Base14と接続した状態 (RA4はLEDに接続) |
テラターム画面例 |
【ソフトウェア】 (EUSARTの設定については後述の「おまけ」を参照)
新ボードのテストとライブラリの動作確認を兼ねて、シリアル受信ターミナルソフトを作成した。
(ターミナルの機能は、受信データーに"Received"を頭に付けて返送するだけ)
<ターミナルのエコー設定>
シリアル通信のエコーの有無はON/OFFで設定でき、
VBA用ターミナルでは ECHO = OFF
テラタームでは ECHO = ON/OFF のどちらでもOK
<I2Cライブラリの設定例>
例えば、I2Cの場合、
@I2Cが2つ以上あるPICの場合は、I2C番号をセット
#define I2C 1
AI2Cが1つしかないPICの場合は
文字列I2Cは宣言しない
Excelとシリアル通信中画面例
|
Excel画面例(再掲)
|
- 【myProject.hファイル】 myProject.h(zip)
/**************************(myProject.h)***
* プロジェクト個別条件指定ファイル *
* (main.cと同じフォルダーに作成) *
******************************************/
#include "mcc_generated_files/mcc.h"
#include "i2cLCDST7032i.h"
#define ON 1
#define OFF 0
/***** 使用電源電圧 ***********************/
//--- VCC宣言無しは5V(VCC=50と同じ)
#define VCC 50 // 電源電圧は5V
//#define VCC 33 // 電源電圧は3.3V
/***** EUSARTモジュール *******************/
#define BFSIZE 80
//--- ECHO宣言はどちらかを必ず行うこと
//#define ECHO ON // エコー有り
#define ECHO OFF // エコー無し
/***** MSSPモジュール *********************/
#define MASTER 1
#define SRAVE 2
#define I2CMODE MASTER // マスターとして使用
//#define I2CMODE SRAVE // スレーブとして使用
//--- MSSPが一つしか無い場合は I2C宣言無し
#define I2C 1 // I2C1を使用
//#define I2C 2 // I2C2を使用
#if I2CMODE == MASTER
#if I2C == 1
#include "mcc_generated_files/examples/i2c1_master_example.h"
#elif I2C == 2
#include "mcc_generated_files/examples/i2c2_master_example.h"
#else
#include "mcc_generated_files/examples/i2c_master_example.h"
#endif
// #define I2CLCD_Adr 0x3c // LCDのI2Cアドレス(i2cLCD_ST7032i.hで設定)
#endif
|
- 【i2cLCD_ST7032i.c/hファイル】 i2cLCD_St7032i.c/h(zip)
/*****************************(i2cLCD_ST7032i.c)***
* LCD ライブラリ use for AQM0802A,AQM1602Y,.. *
**************************************************/
#include "myProject.h"
#include "i2cLCD_ST7032i.h"
#if VCC == 33
#define CONTRAST 0x30 // for 3.3V
#define BOOST 0x04 // for 3.3V Bon=on
#else
#define CONTRAST 0x18 // for 5.0V
#define BOOST 0x00 // for 5.0V Bon=off
#endif
//-------- send command -------------------------
void LCD_cmd(char cmd){
#if I2C == 1
I2C1_Write1ByteRegister(I2CLCD_Adr, 0x00, cmd);
#elif I2C == 2
I2C2_Write1ByteRegister(I2CLCD_Adr, 0x00, cmd);
#else
I2C_Write1ByteRegister(I2CLCD_Adr, 0x00, cmd);
#endif
//-- Clear かHomeか?
if(cmd & 0xFC) // bit6 = 1
__delay_us(30); // 30us
else
__delay_ms(2); // 2ms Clear or Home
}
//-------- send data ----------------------
void LCD_dat(char chr){
#if I2C == 1
I2C1_Write1ByteRegister(I2CLCD_Adr, 0x40, chr);
#elif I2C == 2
I2C2_Write1ByteRegister(I2CLCD_Adr, 0x40, chr);
#else
I2C_Write1ByteRegister(I2CLCD_Adr, 0x40, chr);
#endif
__delay_us(30); // 30us
}
・・・・(以下省略)・・・
|
- 【abc900-18325.cファイル】 abc900-18325.c(zip)
/*****************************(abc900-18325.c)***
* ライブラリーテスト
*************************************************/
#include "mcc_generated_files/mcc.h"
#include "myProject.h"
#define VBA
char RBuf[BFSIZE];
uint8_t SFlg;
/*===============================
* Main application
*==============================*/
void main(void){
SYSTEM_Initialize();
LCD_init();
INTERRUPT_GlobalInterruptEnable();
INTERRUPT_PeripheralInterruptEnable();
puts("ready!\r");
LCD_str("Ready!");
while (1)
{
if(SFlg){
#if ECHO==OFF
#ifdef VBA
printf("Received %s\r",RBuf);
#else
printf("Received %s\n\r",RBuf);
#endif
#else
puts("\n--next\r");
#endif
LCD_clr();
LCD_str(RBuf);
SFlg = 0;
}
IO_RA4_Toggle();
__delay_ms(500);
}
}
/*** End of File ***/
|
【おまけ】
<EUSARTの設定>
これまでは、mcc_generated_filesにあるeusart.cとeusart.hの両方を修正していたが、eusart.cのみを変更することにした。
また、EUSART_Receive_ISRの中に追加部分の全てを記述していたが、myEusart()関数を作成し、ISRの中ではこの関数を呼ぶだけにした。
なお、 myEusart()はプロトタイプ宣言していないので、EUSART_Receive_ISR(使用場所)より前に記述すること。
- 【eusart.cファイル】 (eusart.cファイルで赤字の部分が追加部分)
/**
Section: Included Files
*/
#include "eusart.h"
#include "../myProject.h"
/**
Section: Macro Declarations
*/
#define EUSART_TX_BUFFER_SIZE 8
#define EUSART_RX_BUFFER_SIZE 8
/**
Section: Global Variables
*/
extern char RBuf[]; // シリアル受信バッファー
extern uint8_t SFlg; // 受信完了フラグ
static uint8_t sIdx; // 受信文字列インデックス
volatile uint8_t eusartTxHead = 0;
・・・<途中省略>・・・
void myEusart(){
char ch;
ch = getch();
#if ECHO == ON
putch(ch);
#endif
if((ch == 0x0a)||(ch == 0x0d)){ // 改行処理
SFlg = 1;
RBuf[sIdx] = 0;
sIdx = 0;
}else if((ch == 0x08)&&(sIdx > 0)){ // BS処理
sIdx--;
}else{
if(sIdx < BFSIZE) RBuf[sIdx++] = ch;
}
}
void EUSART_Receive_ISR(void)
{
eusartRxStatusBuffer[eusartRxHead].status = 0;
if(RC1STAbits.FERR){
eusartRxStatusBuffer[eusartRxHead].ferr = 1;
EUSART_FramingErrorHandler();
}
if(RC1STAbits.OERR){
eusartRxStatusBuffer[eusartRxHead].oerr = 1;
EUSART_OverrunErrorHandler();
}
if(eusartRxStatusBuffer[eusartRxHead].status){
EUSART_ErrorHandler();
} else {
EUSART_RxDataHandler();
}
// or set custom function using EUSART_SetRxInterruptHandler()
myEusart();
}
・・・<以下省略>・・・
|
※ 本レポートの参考・利用は、あくまでも自己責任でお願いします。