PIC用のコンパイラであるXC8にも、標準文字出力関数である printf が標準で装備されています。標準文字出力関数のうち特に有益な関数は printf でしょう。整数値を自由に構成(フォーマット)して出力することが可能です。XC8の場合、この関数の初期設定は、UARTによる出力に指定されていますから、シリアルデータの出力にはそのまま使用することが可能です。 PIC回路で最も頻繁に使用するLCD表示で printf を利用可能にするには、今までのプログラムに以下を追加する必要があります。
これで、標準出力チャネルはユーザー出力(LCD)に変更されます。
printf で使用れることの多いフォーマット例は、「その他ーLCD表示にprintf」 に書いておきます。
*注意*
SCL SDAの2ピンで通信を行いますが、これらは、PPSでどのピンを使用するかを指定できます。これらは双方向で使うため、ピンはオープンドレイン回路にし、TRISレジスタは入力モードに設定する必要があります。
以下に printf の使用例を示します。
使用例 | 表示結果 | 説明 |
---|---|---|
printf("%d",123); | 123 | 10進表示 |
printf("%X",123); | 7B | 16進大文字表示 %x は小文字表示 |
printf("%4X",123); | 7B | 桁数指定 数値の前に2つスペースが入る |
char num = 0x3B; printf("%04X",num); |
003B | 16進4桁 変数を指定する 桁数指定のまえにゼロを付加するとゼロ詰めになる |
printf("LCD test"); | LCD test | 文字列を表示 |
char str[] = "LCD test"; printf(str); |
LCD test | 文字列の配列変数を表示 |
char num = 0xA7; printf("out=%04X",num); |
out=00A7 | 文字列"out="と変数を表示 |
char num = 0xA7; char str[] = "IN"; printf("%s=%04X",str,num); |
IN=00A7 | 文字列配列と数値変数、及び 直接指定文字 "=" を組み合わせて表示 |
<回路図>
I2Cを利用したLCD表示器(LCD-AQM0802A)を使用するプログラムです。main.c を短くするために、LCD関連は、i2cLCD.h, i2cLCD.c に分離してあります。
<プログラム>
main.c
/************************************* * File: main.c * データをLCDに表示する。 * 秋月(ACM1602NI)I2C LCD表示器を使用 * 1MHz (内部クロック) * RB4 SDA * RB6 SCL * PIC16F18346 MPLAB XC8 v2.10 * Created on May 22, 2020, 2:37 PM **************************************/ #include <xc.h> #include <stdio.h> #include "i2cLCD.h" #define _XTAL_FREQ 1000000 // delay_ms(x) のための定義 #pragma config FEXTOSC = OFF,RSTOSC = HFINT1 // HFINTOSC (1MHz) #pragma config CLKOUTEN = OFF,CSWEN = OFF,FCMEN = OFF #pragma config MCLRE = ON,PWRTE = OFF,WDTE = OFF,LPBOREN = OFF #pragma config BOREN = OFF,BORV = LOW,PPS1WAY = OFF,STVREN = ON #pragma config DEBUG = OFF #pragma config WRT = OFF,LVP = ON,CP = OFF,CPD = OFF // ******************************************************** void main() { char num=30; char ch[]="abcd"; i2c_MasterInit(100000); LCD_int(); // LCDを初期化 printf("%04X",num); // 上段に追記 LCD_posyx(1,1); // 下段にカーソル移動 printf("[%s]",ch); // 下段に追記 while(1); }
LCDi2c.h
/************************************* * File: i2cLCD.h * データをLCDに表示する。 * 秋月(ACM1602NI)I2C LCD表示器を使用 * 1MHz (内部クロック) * RB4 SDA * RB6 SCL * PIC16F18346 MPLAB XC8 v2.10 * Created on May 22, 2020, 2:37 PM **************************************/ //********************************************************************* // 調整用定数 //********************************************************************* #define CONTRAST 0x28 // for 3.3V // #define CONTRAST 0x18 // for 5.0V #define _XTAL_FREQ 1000000 // delay_ms(x) のための定義 // -------------- I2C関連定義 ---------------------------- // 各シーケンスの終了を待って復帰 // I2C特殊 condition #define i2c_Idle() while((SSP1CON2&0x1F)|(SSP1STATbits.R_nW)) #define i2c_Start() SSP1CON2bits.SEN=1;while(SSP1CON2bits.SEN) #define i2c_Stop() SSP1CON2bits.PEN=1;while(SSP1CON2bits.PEN) void i2c_MasterInit(const unsigned long baud); char i2c_Write(char data); // -------------- LCD関連定義 ---------------------------- void i2cByteWrite(char, char, char); void i2cTxData(char); void LCD_dat(char); void LCD_cmd(char); void LCD_clr(void); void LCD_posyx(char,char); void LCD_int(void); void LCD_str(char *);
LCDi2c.c
// file: i2cLCD.c #include <xc.h> #include "i2cLCD.h" #include <stdio.h> //****************************************************** // LCD で printf関数が使用できるようにするため putch を設定する //****************************************************** void putch(char data) { LCD_dat(data); // LCD への一文字表示関数 } //******************************************************************** // I2C 関連 //******************************************************************** void i2c_MasterInit(const unsigned long baud){ // pin設定 ------------------------------------------------ TRISB4 = 1; // RB4を入力 TRISB6 = 1; // RB6を入力 ANSB4 = 0; // RB4をデジタル ANSB6 = 0; // RB6をデジタル ODCB4 = 1; // RB4をオープンドレイン ODCB6 = 1; // RB6をオープンドレイン // PPS設定 ----------------------------------------------- SSP1CLKPPS = 0x0E; // RB6をCLK入力に指定 RB6PPS = 24; // RB6をCLK出力に指定 SSP1DATPPS = 0x0C; // RB4をDATに入力指定 RB4PPS = 25; // RB4をDAT出力に指定 // SSP1設定 ----------------------------------------------- SSP1STAT = 0b10000000; // スルーレート制御はOff SSP1ADD = (_XTAL_FREQ/(4*baud))-1; // SSP1ADD = 0x77; SSP1CON1 = 0b00101000; // I2C Master modeにする } char i2c_Write(char data){ SSP1BUF = data; // データセット PIR1bits.SSP1IF = 0; // 終了フラグクリア while(!PIR1bits.SSP1IF); // 送信終了待ち return SSP1CON2bits.ACKSTAT; // ACKなら「0」で復帰 } // NACKは「1」で復帰 //-------- ByteI2C送信 void i2cByteWrite(char addr, char cont, char data){ i2c_Idle(); // Bus アイドル確認 i2c_Start(); // Start bit送信 i2c_Write(addr); // アドレス送信 i2c_Write(cont); // 制御コード送信 i2c_Write(data); // データ送信 i2c_Stop(); // Stop bit送信 } //******************************************************************** // LCD 関連 //******************************************************************** //-------- 1文字表示 void LCD_dat(char chr){ i2cByteWrite(0x7C, 0x40, chr); __delay_us(50); // 50μsec } //-------- コマンド出力 void LCD_cmd(char cmd){ i2cByteWrite(0x7C, 0x00, cmd); if(cmd & 0xFC) // 上位6ビットに1がある命令 __delay_us(50); // 50usec else __delay_ms(2); // 2msec ClearおよびHomeコマンド } //-------- 全消去 void LCD_clr(void){ LCD_cmd(0x01); //Clearコマンド出力 } //-------- カーソル位置指定 void LCD_posyx(char ypos, char xpos){ unsigned char pcode; switch(ypos & 0x03){ case 0: pcode=0x80;break; case 1: pcode=0xC0;break; } LCD_cmd(pcode += xpos); } //-------- 初期化 void LCD_int(void){ __delay_ms(100); LCD_cmd(0x38); // 8bit 2行 表示命令モード LCD_cmd(0x39); // 8bit 2行 拡張命令モード LCD_cmd(0x14); // OSC BIAS 設定1/5 // コントラスト設定 LCD_cmd(0x70 + (CONTRAST & 0x0F)); LCD_cmd(0x5C + (CONTRAST >> 4)); LCD_cmd(0x6B); // Ffollwer __delay_ms(100); __delay_ms(100); LCD_cmd(0x38); // 表示命令モード LCD_cmd(0x0C); // Display On LCD_cmd(0x01); // Clear Display } //-------- 文字列出力 void LCD_str(char *str){ while(*str) //文字列の終わり(00)まで継続 LCD_dat(*str++); //文字出力しポインタ+1 }