Vol.839 25.Feb.2022

Excelの表示拡大・縮小 PICでUSB通信とI2C液晶表示

E Excelのチップス 〜表示画面の拡大・縮小

by fjk

 Excelで、データが多くなると表示画面に収まらなくなり、画面をを縮小しより多くのデータを表示したいことがある。逆に、一部を拡大したいこともある。画面の拡大縮小には以下の方法がある。

@ショートカットキー
最も簡単だが、テンキーの「−」では動作しない。
【拡大】 −> 「Ctrl」+「Alt」+「=」(すなわち「Ctrl」+「Alt」+「Shift」+「ー」)
【縮小】 −> 「Ctrl」+「Alt」+「−」
A 右下のスライダー
マウスで操作するが、倍率はアバウト
B 表示メニューの@「ズーム」で表示倍率を変更
「200%、100%、75%、50%、25%、選択範囲、任意に指定」が指定できる


P PICのUSB通信データをI2C液晶で表示 〜PIC16F1459

by fjk

 PICでUSB通信とI2C通信を同時に使うテストを行った。PICは今まで使用してきた16F1455(14pin)でも良いが、I2CとICSPのピンが別々に使用できる16F1459(20pin)を用いた。
 LCDは秋月電子の「I2C接続小型LCDモジュールピッチ変換キット(AQM0802A、700円、K-12238)を用いた。コントローラのST7032iの電源は3.3V-5Vまで、液晶は7VまでOKで、ST7032iの昇圧回路は2倍に液晶電源を上げので、VDD=5V の場合は昇圧回路はOFFにする(VDD=3.3V なら昇圧回路ON)。I2C液晶の使い方の詳細についてはabc765を参照
 PICでI2Cを使うには、MSSPでI2Cを割込有で設定し、generateするとI2Cクロックが100kHzになるように設定された。I2CバスのプルアップとしてPinModuleでWPUをチェックし、RegisterでnWPUENもenableに設定。
 クロックやADC、USB設定はabc838と同じ。

テスト回路(PIC16F1459) MCCでsystem設定

ピン設定
タイマー2設定 WPUの設定

MSSPの設定 割込設定

 LCD表示用として以前abc765で自作したLCD表示ライブラリを使おうとしたが、コンパイル時にエラーが出た。この原因をネットで調べてみると、最近のXC8ではi2c2.hやi2c2.cというファイルがなくなり、i2c_master.hとi2c_master.cにファイルが代わっていた。そして、mcc_genarate_files/exampleフォルダーの下にi2c_master_example.cという参考ファイルがあり、これを利用すると良いことが判った。 ※JH7UBCさんKazHatBさんを参考にさせて頂いた。
 また、変数の型チェックも厳密となり、前回までuint_8を使って整数や文字データを宣言していたが、標準関数を呼び出すとエラーとなったので、エラー発生箇所をintまたはcharに変更した。
※exampleデータを使うと、使わない機能も含まれるため、使用メモリが多くなるので、以下の2つの関数だけを使う(コピーする)方法もある。

static i2c_operations_t wr1RegCompleteHandler(void *ptr)
void I2C_Write1ByteRegister(i2c_address_t address, uint8_t reg, uint8_t data)
 
・Exampleを使わない場合、プロジェクトからi2c_master_example.cを削除する必要があり、Project/SouceceFiles/MCCGeneratedFiles/exsampleフォルダから除外するファイルを右クリック後、Remove From Projectを実行する。
(ただし,MPLAB Xを再起動しないと登録の解除は有効にならない)。
・自作ライブラリなど既存のファイルをプロジェクトに追加する場合は、Project/SourceFilesを右クリック後、Add Exsisting Item...を選び、追加ファイルを指定する。

 スケッチを作成しPICに書込、USBケーブル(電源も供給)を繋いで実行してみると、LCDに”Hello!“の文字が出るが、AD変換データが表示されない。DIPスイッチを押してADCのモードを変えてみるがダメである。
 しかし、この状態のままで、PCのターミナルソフト(abc834参照)を立ち上げると、ADCが動作し、PCのターミナル画面とLCDにAD変換データが表示された。また、LCDにもPCからの送信データが表示された。どうも、USB通信も同時に実行しないとタイマー割込が実行されていないようである(tmFlg=1にならない)。
 一応、USBとI2Cの同時動作が確認できた。そしてUSB送受信データは正常に行えているようだが、相変わらずPCのターミナル画面で、改行が時々うまく実行できない課題が残っている(VB側?)。

試作したブレッドボード パソコンのターミナル画面
Timer2.c

/*----- Timer2.c ----*/
extern int tmFlg;
void TMR2_CallBack(void){
    // Add your custom callback code here
    tmFlg = 1;
    // this code executes every TMR2_INTERRUPT_TICKER_FACTOR periods of TMR2
    if(TMR2_InterruptHandler)    {
        TMR2_InterruptHandler();
    }
}

main.c

/********************
 *     main.c       *
********************//

#include "mcc_generated_files/mcc.h"
#include "mcc_generated_files/examples/i2c_master_example.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*=== USB library ===*/

#define  BFSIZE 32

char NEWLINE[] = "\r\n";
static char rBuf[BFSIZE];       // USB Read Buffer
static char wBuf[BFSIZE];       // USB Write Buffer

int tmFlg;                      //?Timer2?Flag

void SendUSB_char(char c){
    do
	CDCTxService();
    while (!USBUSARTIsTxTrfReady());
    putUSBUSART((char *)&c, 1);
    CDCTxService();
}
 
void SendUSB_str(char *str){
    do
    	CDCTxService();
    while (!USBUSARTIsTxTrfReady());
    putsUSBUSART((char *)str);
    CDCTxService();
}

void SendUSB_int(int val){
    unsigned char iBuf[10];
    sprintf(iBuf,"%d: ",val);
    SendUSB_str(iBuf);
}
     
/*====  LCD library ===*/

#define I2CLCD_AQM0802A 0x3e
#define   CONTRAST   0x18       // for 5.0V
//#define  CONTRAST   0x30       // for 3.3V
#define   BOOST      0x00       // for 5.0V Bon=off
//#define  BOOST      0x04       // for 3.3V Bon=on

void LCD_dat(char chr){
    I2C_Write1ByteRegister(I2CLCD_AQM0802A, 0x40, chr);
    __delay_us(30); // 30us
}

//-------- send command -------------------------
void LCD_cmd(char cmd){
    I2C_Write1ByteRegister(I2CLCD_AQM0802A, 0x00, cmd);
    if(cmd & 0xFC)     	// bit6 = 1
        __delay_us(30); 	// 30us
    else
        __delay_ms(2); 	// 2ms Clear or Home
}

//-------- clear LCD--------------------------
void LCD_clr(void){
    LCD_cmd(0x01);
}

//--------- Home -----------------------------
void LCD_home(void){
    LCD_cmd(0x02);
}

//--------- Cursor X,Y -----------------------
void LCD_cursor(int x, int y){
    if (y == 0)
        LCD_cmd(0x80 + x);
    else if (y == 1)
        LCD_cmd(0xc0 + x);
}

//-------- display strings -------------------------
void LCD_str(char *str){
    while(*str)
 	LCD_dat(*str++); //pointer increment
}

//-------- write 1 character to LCD ----------------
void putch(char ch){
    LCD_dat(ch);
}

//-------- LCD initialize ---------------------------
void LCD_init(){
    __delay_ms(40);       // 40ms wait
    LCD_cmd(0x38);        // 8bit,2line
    LCD_cmd(0x39);        // IS=1 : extention mode set
    LCD_cmd(0x14);        // Internal OSC Frequency
    LCD_cmd(0x70 + (CONTRAST & 0x0F)); // Contrast set
    LCD_cmd(0x58 + BOOST + (CONTRAST >> 4)); 
			 // Power/ICON/Contrast Control
    LCD_cmd(0x6C);       // Follower control
    __delay_ms(200);     // 200ms wait
    LCD_cmd(0x38);       // IS=0 : extention mode cancel
    LCD_cmd(0x0C);       // Display ON
    LCD_cmd(0x01);       // Clear Display
    __delay_ms(2);       // wait more than 1.08ms
}

/*====   Main application  ==== */

void main(void)
{
    SYSTEM_Initialize();	// initialize device
    INTERRUPT_GlobalInterruptEnable(); // Enable Global
    INTERRUPT_PeripheralInterruptEnable(); // Enable Peripheral 
    int swFlg = 0;              // Switch Flag
    int adFlg = 0;              // ADconvert Flag
    int num, i;
    unsigned short aVal;        // AD Converted data
    
    LCD_init();
    char msg[] = "Hello!";
    LCD_str(msg);
 
    while (1) {
 	num = getsUSBUSART(rBuf,sizeof(rBuf));
        if(num > 0) {
            for(i = 0; i < num; i++) {
                switch (rBuf[i])  {
                   	case 0x0A:
                   	case 0x0D:
                    	wBuf[i] = 0x00;
                    	break;
                    default:
                        wBuf[i] = rBuf[i];
                        break;
                }
            }
            LCD_clr();
            LCD_str(wBuf);    
            SendUSB_str("PIC> ");
            SendUSB_str(wBuf);
            SendUSB_str(NEWLINE);
            if(( wBuf[0] & 0x01) == 0)
               	LED_SetLow();
            else
               	LED_SetHigh();
        }
        if((SWC3_GetValue() == 0) & (swFlg == 0)){
            swFlg = 1;
            if(adFlg == 0){
           	SendUSB_str("ADC Start");
               	SendUSB_str(NEWLINE);
               	adFlg = 1;
            }else{
               	SendUSB_str("ADC Hold");
               	SendUSB_str(NEWLINE);
               	adFlg = 0;                
            }
        }else if((SWC3_GetValue() > 0)& (swFlg == 1)){
           wFlg = 0;
        }
        aVal = ADC_GetConversion(3);
        if((tmFlg > 0) & (adFlg > 0)){
            sprintf(wBuf,"ADC:%4d\n\r",aVal);
            LCD_cursor(0,1);
            LCD_str(wBuf);
            SendUSB_str(wBuf);
            SendUSB_str(NEWLINE);
            tmFlg = 0;
        }
    } 
}


Excelの表示拡大・縮小 PICでUSB通信とI2C液晶表示