Update: Sep. 22, 2018

有機EL (OLED)をPICマイコンで制御


秋月から販売されている64x128dotの有機EL (OLED ) をPICマイコンで制御する実験を行いましたで紹介します。


 


OLEDをPICマイコンで制御する

近頃、小型の有機EL ( OLED )が廉価で販売されています。
液晶と比べ、自発光で視認性が良く、綺麗な表示を行うので一度試してみることにしました。

今回試用したものは、秋月から販売されている 0.96インチ 64 x 128 dot の非常に小型のモジュールで、OLEDのドライバとしてSSD1306が実装されています。

ところがWeb上で発表されいるSSD1306を制御するプログラムのほとんどは、マイコンにArduinoを用いたもので、PICマイコンの情報はあまり検索されないようです。
そこで、8ビットミドルレンジのPICマイコンPIC16F1827を用いてSSD1306を制御する実験を行いましたので、ソースリストも含めて情報を公開します。


回路図


64x128dot OLED と ドライバIC SSD1306

今回試用したSSD1306内蔵のOLEDモジュールは I2Cで制御を行います。色の制御は出来ず、白色の発光のみとなりますが、明るさの制御は出来ます。
チャージポンプが内蔵されており、OLEDの駆動に必要な7.5Vが内部で生成されるため、モジュールとしては3.3Vの単一電源で使用できます。
また、Aitendo や Amazon などでも似たようなモジュールが販売されており、上部のSegmentだけ黄色で発光する物もあるようです。
ただ、秋月の物とは電源とグランドのピン配が逆になっていたりしますので注意して下さい。

SSD1306は64x128dot のOLED を縦方向にPage 0~7, 横方向に Segment0~127 で制御します。
各Segmentは縦に8dot (1byte、上がLSB) となっています。


表示データをI2CでSSD1306 のGDDRAM へSegment単位(1byte)で書込むことによりOLEDに表示されますが、書込んだGDDRAMの内容を読み出すことは出来ません。
同じSegment内に前のデータは保持したまま、別のデータを書込もうとした場合、一旦GDDRAMのデータを読出して新たなデータとORをとり、再びGDDRAMへ書き戻す必要がありますが、SSD1306の場合は新しいデータを上書きすることしか出来ません。

これを回避するため、Arduino などのプログラムではGDDRAMと同じサイズのメモリー ( 7pagex128seg=1kbye)をマイコンのSRAMに確保してSRAM上で表示データを加工してからSSD1306のGDDRAMへ転送するというようなことをやっているようです。
ところが、PIC16F1827などのミドルレンジのPICマイコンではSRAMは256byte程度しか搭載されていませんので、このような手法は使えません。
(最近は、PIC16F18326 など SRAMが2kバイトも搭載されているものもリリースされているようですが。ハイエンドのPICとの差が無くなってきていますネ)

ただ、画面の表示デザインが絶えず変わるアプリケーションで無ければ、画面の配置を工夫すればなんとかなりますので、今回はPIC16F1827を使って制御してみることにしました。


SSD1306の制御プログラム

SSD1306 の I2C フォーマットは以下のようになっています。


SSD1306のスレーブアドレスは 0x78 です。(Arduino ではこれを 0x3Cと表現しているようです。R/W#の部分をアドレスと見るかどうかの違いです。)

Co は仕様書では Continuation bit と表現されていますが、どうもこの意味が判りにくい説明になっています。
このビットの意味は、 Co を 0 とすると以後、連続して1バイトづつ送ることが出来るようになります。
Co を 1 にすると1バイト送るごとにストップコンディションを入れて再びスレーブアドレスから送る必要があります。

Co=0のとき、D/C# を 0 とすると次から順次送る1バイトづつはコマンドを意味します。
Co=0のとき、D/C# を 1 とすると次から順次送る1バイトづつは表示データとしてGDDRAMへ書込まれていきます。

OLED (実際には SSD1306のGDDRAM)へのデータ書込みにはページ内のSegmentへ順番に書込むPage addressing mode、水平方向へ順番にSegmentへ書込む Horizontal addressing mode、垂直方向へ順番にSegmentへ書込む Vartical addressing mode があります。

  Page Addressing Mode


  Horizontal Addressing Mode


  Vertical Addressing Mode

今回のプログラムでは、基本的にPage addressing mode を使用していますが、OLEDクリア関数には Horizontal addressing mode を使っています。

Page addressing mode ではSSD1306のGDDRAMへ1バイトずつ表示データを書き込んでゆくと自動的にSegment (上の図ではCOLと表現されています)順に書込まれます。
最後のSegment127 (COL127)に達すると同じページ内の初めのSegmentへ戻ります。

Horizontal addressing mode では1バイトずつ水平方向に順番にSegmentへ書込まれ、Segment127 (COL127)に達すると次のページの最初のSegmentに自動的に移動して行き、表示エリアを最後まで書替えます。

今回のプログラムで表示するフォントは、6x8ドットのものと12x16ドットのものです。(隣接文字とのスペースも含めたドット数となっています)
6x8ドットフォントは、1ページ内で文字を表示しますので、かなり小さい表示となります。
12x16ドットフォントは、2ページにまたがり表示します。
例として’4’の場合のドット配置を示します。

6x8 ドットフォント

配列データ { 0x18, 0x14, 0x12, 0x7f, 0x10, 0x00 },


12x16ドットフォント

配列データ {0x00, 0x00, 0x00, 0x80, 0xC0, 0x60, 0x30, 0x18, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x0E, 0x0F, 0x0D, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x3F, 0x0C, 0x00},

12x16ドットフォントは上半分を nページに表示し、下半分をn+1ページに表示します。
最初に上半分のデータ (12バイト)を転送し、次に下半分のデータ (12バイト)を転送します。

フォントデータはデータサイズが大きいので、データに const修飾子を付けることにより読出し専用のデータとしてプログラムメモリーへ配置しています。
プログラムメモリーへのデータの配置は、実際には RETLW命令としてプログラムの形で書込まれます。

文字列は、printf 関数で表示できるように、プログラムの最後にprintf 関数で使用するpuchを定義してあります。



制御プログラムのソースリスト

今回製作したプログラムのソースリストを添付します。

コンパイラは XC8 、マイコンは PIC16F1827 を使用します。
無線機の表示に使用することを想定してSメーター用のシグナルバーを一番下に表示しています。
最初はシグナルバーがゆっくり左右に移動し、次にwaitを入れずにプログラムの最高速度で左右に移動させていますが、I2Cで制御している割には追従性は充分です。

コメントに詳細を記載してありますので、参考にしてください。


  1. /******************************************************************
  2.                       OLED Ver 0.0
  3.                      I2C 接続 OLED テスト
  4.                      Author JR3TGS
  5.              I2Cモジュールは、SSP1を使用
  6.                          XC8 Ver 1.30
  7.                           PIC16F1827
  8.                      Sep. 9, 2018
  9. ********************************************************************/
  10. /*
  11. 秋月 OLED(64 x 128 dot)は 原点を左上 (0,0)として縦方向に Page 0?7, 横方向に Column 0?127。
  12. (1columnは縦方向に8bit (上がLSB))
  13. このソフトウェアでは、OLEDをPage addressing mode で動作させるので、データ書込みに従いcolumn方向
  14. に自動的にインクルメントされ、同Page内でcolumnゼロに戻り、表示を繰り返す。
  15. (ただし oled_clr()関数, oled_fill()関数は Horizontal addressing mode で動作する)
  16. 6x8dotフォントは、1Page 内での表示。12x16dotフォントは2Pageにまたがり、フォントの上半分を
  17. n Pageに表示、フォントの下半分を n+1 Page に表示する。
  18. */
  19. #include <xc.h>
  20. #include <stdio.h>
  21. #include "font6.h"
  22. #include "font12.h"
  23. #define _XTAL_FREQ 16000000
  24. #pragma config CPD = OFF, BOREN = OFF, IESO = OFF, FOSC = INTOSC, FCMEN = OFF
  25. #pragma config MCLRE = ON, WDTE = OFF, CP = OFF, PWRTE = ON, CLKOUTEN = OFF
  26. #pragma config PLLEN = OFF, WRT = OFF, STVREN = OFF, BORV = LO, LVP = OFF
  27. void i2c_start();
  28. void i2c_stop();
  29. void i2c_write(unsigned char byte);
  30. void font6_posi(unsigned char page, unsigned char column);    // 5x8dotフォントの表示開始位置指定
  31. void font12_posi(unsigned char page, unsigned char column);    // 12x16dotフォントの表示開始位置指定
  32. void chr5(unsigned char c);        // 5x8dotフォントの1文字表示関数
  33. void chr12(unsigned char c);    // 12x16dotフォントの1文字表示関数
  34. void oled_ini(void);            // OLED イニシャライズ
  35. void oled_clr(void);            // OLED 画面消去
  36. void h_line(unsigned char page, unsigned char start_column, unsigned char end_column, unsigned x_position);    // 水平線描画
  37. void v_line(unsigned char page, unsigned char column, unsigned char pattern);    // 垂直線描画
  38. void sig_bar(unsigned char sig_strong);    // Signalバー表示
  39. unsigned char Page;
  40. unsigned char Column;
  41. unsigned char Low_col;
  42. unsigned char Hi_col;
  43. unsigned char Size;
  44. //************* h_line (水平線描画用 1columnデータ配列 ) ************************
  45. char line[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
  46. // 0x01はcolumnの1番上(LSB)にだけdot表示、0x80はColumnの1番下(MSB)にだけdot表示
  47. //************ sig (Signalバー用 1columnデータ配列 6x8dot) **********************
  48. char sig[2][6] =
  49. {
  50.     {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
  51.     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
  52. };
  53. //********************************************************************************
  54. void main(void)
  55. {
  56.     unsigned char i;
  57.     unsigned char j;
  58.     TRISA = 0b00000000;
  59.     TRISB = 0b00010010;    // SCL, SDA input (I2C(SSP1モジュール)使用するので入力に設定必要)
  60.     PORTA = 0b00000000;
  61.     PORTB = 0b00000000;
  62.     ANSELA = 0b00000000;
  63.     ANSELB = 0b00000000;
  64.     OSCCON = 0b01111100;    // INTOSC 16MHz
  65.     SSP1CON1 = 0b00101000;     // I2C master mode, Clock 100kHz = Fosc / ( 4 * (SSPADD + 1 ))
  66.     SSP1STAT = 0b00000000;    // Slew rate control Enabled
  67.     SSP1ADD = 0b00100111;    // SSPADD 39d, Clock = Fosc / ( 4 * (SSPADD + 1 )) = 100kHz
  68.     oled_ini();
  69.     oled_clr();
  70.     font6_posi(1, 70);
  71.     printf("12.34 [V]");
  72.     font12_posi(3, 4);
  73.     printf("50.2346MHz");
  74.     font6_posi(6, 0);
  75.     printf("ABCDEFGHIJklmnopqrstu");
  76. //枠の表示
  77.     h_line(2, 2, 125, 7);    //上の横線
  78.     h_line(5, 2, 125, 0);    //下の横線
  79.     h_line(3, 1, 1, 0);        //左上隅
  80.     v_line(3, 0, 0xFE);
  81.     h_line(4, 1, 1, 7);        //左下隅
  82.     v_line(4, 0, 0x7F);
  83.     h_line(3, 126, 126, 0);    //右上隅
  84.     v_line(3, 127, 0xFE);
  85.     h_line(4, 126, 126, 7);    //右下隅
  86.     v_line(4, 127, 0x7F);
  87. //Signalバーの表示
  88.     for(i=0; i<2; i++)
  89.     {
  90.         for(j=14; j>0; j--)
  91.         {
  92.             sig_bar(j);
  93.             __delay_ms(200);
  94.         }
  95.         for(j=0; j<15; j++)
  96.         {
  97.             sig_bar(j);
  98.             __delay_ms(200);
  99.         }
  100.     }
  101.     while(1)
  102.     {
  103.         PORTAbits.RA0 = 1;
  104.         for(j=5; j<10; j++)
  105.         sig_bar(j);
  106.         PORTAbits.RA0 = 0;
  107.         for(j=9; j>4; j--)
  108.         sig_bar(j);
  109.     }
  110. }// main
  111. //*************************************************************************************
  112. void oled_ini(void)        // OLED イニシャライズ
  113. {
  114.     i2c_start();
  115.     i2c_write(0x78);    // OLED slave address
  116.     i2c_write(0x00);    // Control byte Co=0, D/C#=0
  117.     // Co=0 とすると以後連続して1バイトづつ送れる
  118.     // Co=1 とすると1バイト送る毎にControl byte を入れる必要がある
  119.     i2c_write(0x8D);    // Set charge pump
  120.     i2c_write(0x14);    // Enable charge pump
  121.     i2c_write(0xAF);    // Display ON
  122.     i2c_stop();
  123.     // その他の初期設定値はパワーオンリセット時のディフォルト値のままとする
  124. }
  125. void oled_clr(void)        // OLED 画面消去
  126. {
  127.     unsigned int i;
  128.     i2c_start();
  129.     i2c_write(0x78);    // OLED slave address
  130.     i2c_write(0x00);    // Control byte Co=0, D/C#=0
  131.     i2c_write(0x20);    // Set memory addressing mode
  132.     i2c_write(0x00);    // Horizontal addressing mode
  133.     i2c_write(0x21);    // Set column address
  134.     i2c_write(0x00);    // Column start address 0
  135.     i2c_write(0x7F);    // Column end address 127d
  136.     i2c_write(0x22);    // Set page address
  137.     i2c_write(0x00);    // Page start address 0
  138.     i2c_write(0x07);    // Page end address 7d
  139.     i2c_stop();
  140.     i2c_start();
  141.     i2c_write(0x78);    // OLED slave address
  142.     i2c_write(0x40);    // Control byte Co=0, D/C#=1 (The following data bytes are stored at the GDDRAM)
  143.     for(i=0; i<1024; i++)    // 128culomn * 8page
  144.         i2c_write(0x00);    // filled with 0 (OLED clear)
  145.     i2c_stop();
  146. }
  147. void h_line(unsigned char page, unsigned char start_column, unsigned char end_column, unsigned x_position)    // 水平線描画
  148. {                                                                                                            // x_position はカラム上のdotを表示するビット位置
  149.                                                                                                             //(一番上がLSBで0, 一番下がMSBで7)
  150.     char low_col;
  151.     char hi_col;
  152.     char i;
  153.     i = end_column - start_column;
  154.     page = page + 0xB0;        // ページ情報をコマンドにする為に 0xB0 を加算
  155.     low_col = start_column & 0x0F;
  156.     start_column = start_column >> 4;
  157.     hi_col = start_column + 0x10;
  158.     i2c_start();
  159.     i2c_write(0x78);    // OLED slave address
  160.     i2c_write(0x00);    // Control byte Co=0, D/C#=0
  161.     i2c_write(0x20);    // Set memory addressing mode
  162.     i2c_write(0x02);    // Page addressing mode
  163.     i2c_write(page);    // Set page start addres
  164.     i2c_write(low_col);// Set lower column start address
  165.     i2c_write(hi_col);    // Set higher column start address
  166.     i2c_stop();
  167.     i2c_start();
  168.     i2c_write(0x78);    // OLED slave address
  169.     i2c_write(0x40);    // Control byte Co=0, D/C#=1 (The following data bytes are stored at the GDDRAM)
  170.     do
  171.     {
  172.         i2c_write(line[x_position]);
  173.     }
  174.     while(i--);
  175.     i2c_stop();
  176. }
  177. void v_line(unsigned char page, unsigned char column, unsigned char pattern)    // 垂直線描画
  178. {                                                                                // pattern はカレントページ内で表示する垂直線のパターン
  179.                                                                                 //(一番上がLSB。 pattern 0x1E なら 上から2番目のビットから上から5番目のビットまでdot表示)
  180.     char low_col;
  181.     char hi_col;
  182.     page = page + 0xB0;        // ページ情報をコマンドにする為に 0xB0 を加算
  183.     low_col = column & 0x0F;
  184.     column = column >> 4;
  185.     hi_col = column + 0x10;
  186.     i2c_start();
  187.     i2c_write(0x78);    // OLED slave address
  188.     i2c_write(0x00);    // Control byte Co=0, D/C#=0
  189.     i2c_write(0x20);    // Set memory addressing mode
  190.     i2c_write(0x02);    // Page addressing mode
  191.     i2c_write(page);    // Set page start addres
  192.     i2c_write(low_col);// Set lower column start address
  193.     i2c_write(hi_col);    // Set higher column start address
  194.     i2c_stop();
  195.     i2c_start();
  196.     i2c_write(0x78);    // OLED slave address
  197.     i2c_write(0x40);    // Control byte Co=0, D/C#=1 (The following data bytes are stored at the GDDRAM)
  198.     i2c_write(pattern);
  199.     i2c_stop();
  200. }
  201. void font6_posi(unsigned char page, unsigned char column)    // 6x8dotフォントの表示開始位置指定
  202. {
  203.     char low_col;
  204.     char hi_col;
  205.     Size = 0;                // printf で使用するputch のフォントサイズ指定
  206.     Page = page;            // ページ情報をfont12用にグローバル変数に保存しておく
  207.     Column = column;        // カラム情報をfont12用にグローバル変数に保存しておく
  208.     page = page + 0xB0;        // ページ情報をコマンドにする為に 0xB0 を加算
  209.     low_col = column & 0x0F;
  210.     column = column >> 4;
  211.     hi_col = column + 0x10;
  212.     i2c_start();
  213.     i2c_write(0x78);    // OLED slave address
  214.     i2c_write(0x00);    // Control byte Co=0, D/C#=0
  215.     i2c_write(0x20);    // Set memory addressing mode
  216.     i2c_write(0x02);    // Page addressing mode
  217.     i2c_write(page);    // Set page start addres
  218.     i2c_write(low_col);// Set lower column start address
  219.     i2c_write(hi_col);    // Set higher column start address
  220.     i2c_stop();
  221. }
  222. void font12_posi(unsigned char page, unsigned char column)    // 12x16dotフォントの表示開始位置指定
  223. {
  224.     char low_col;
  225.     char hi_col;
  226.     Size = 1;                // printf で使用するputch のフォントサイズ指定
  227.     Page = page;            // ページ情報をfont12用にグローバル変数に保存しておく
  228.     Column = column;        // カラム情報をfont12用にグローバル変数に保存しておく
  229.     page = page + 0xB0;        // ページ情報をコマンドにする為に 0xB0 を加算
  230.     low_col = column & 0x0F;
  231.     column = column >> 4;
  232.     hi_col = column + 0x10;
  233.     i2c_start();
  234.     i2c_write(0x78);    // OLED slave address
  235.     i2c_write(0x00);    // Control byte Co=0, D/C#=0
  236.     i2c_write(0x20);    // Set memory addressing mode
  237.     i2c_write(0x02);    // Page addressing mode
  238.     i2c_write(page);    // Set page start addres
  239.     i2c_write(low_col);// Set lower column start address
  240.     i2c_write(hi_col);    // Set higher column start address
  241.     i2c_stop();
  242. }
  243. void chr6(unsigned char c)        // 6x8dotフォントの1文字表示関数
  244. {
  245.     unsigned char i;
  246.     c = c - 0x20;
  247.     i2c_start();
  248.     i2c_write(0x78);    // OLED slave address
  249.     i2c_write(0x40);    // Control byte Co=0, D/C#=1 (The following data bytes are stored at the GDDRAM)
  250.     for(i=0; i<6; i++)
  251.     {
  252.         i2c_write(font6[c][i]);
  253.     }
  254.     i2c_stop();
  255. }
  256. void chr12(unsigned char c)        // 12x16dotフォントの1文字表示関数
  257. {
  258.         unsigned char i;
  259.         unsigned char temp;
  260.         c = c + 6 - 0x30;
  261.         Page = Page + 0xB0;
  262.         Low_col = Column & 0x0F;
  263.         temp = Column >> 4;
  264.         Hi_col = temp + 0x10;
  265.         i2c_start();
  266.         i2c_write(0x78);    // OLED slave address
  267.         i2c_write(0x00);    // Control byte Co=0, D/C#=0
  268.         i2c_write(0x20);    // Set memory addressing mode
  269.         i2c_write(0x02);    // Page addressing mode
  270.         i2c_write(Page);    // Set page start addres
  271.         i2c_write(Low_col);// Set lower column start address
  272.         i2c_write(Hi_col);    // Set higher column start address
  273.         i2c_stop();
  274.         i2c_start();
  275.      i2c_write(0x78);    // OLED slave address
  276.      i2c_write(0x40);    // Control byte Co=0, D/C#=1 (The following data bytes are stored at the GDDRAM)
  277.         
  278.      for(i=0; i<12; i++)
  279.      {
  280.          i2c_write(font12[c][i]);
  281.      }
  282.      i2c_stop();
  283.         Page = Page + 1;        // グローバル変数ペーシ情報 Page を次の lower 12bytes 描画の為に 1 進める
  284.         i2c_start();
  285.         i2c_write(0x78);    // OLED slave address
  286.         i2c_write(0x00);    // Control byte Co=0, D/C#=0
  287.         i2c_write(0x20);    // Set memory addressing mode
  288.         i2c_write(0x02);    // Page addressing mode
  289.         i2c_write(Page);    // Set page start addres
  290.         i2c_write(Low_col);// Set lower column start address
  291.         i2c_write(Hi_col);    // Set higher column start address
  292.         i2c_stop();
  293.         i2c_start();
  294.      i2c_write(0x78);    // OLED slave address
  295.      i2c_write(0x40);    // Control byte Co=0, D/C#=1 (The following data bytes are stored at the GDDRAM)
  296.         
  297.      for(i=12; i<24; i++)
  298.      {
  299.          i2c_write(font12[c][i]);
  300.      }
  301.      i2c_stop();
  302.         Page = Page - 1 - 0xB0;    // グローバル変数ページ番号 Page を次の1文字描画の為、進めたページ番号を元に戻す (0xB0はコマンドをページ情報に戻す為)
  303.         Column = Column + 12;    // グローバル変数カラム情報を次の次の1文字描画の為、12アドレス進める
  304. }
  305. void sig_bar(unsigned char sig_strong)    // Signalバー表示 ( Sig_strong の範囲は 0 ? 14 )
  306. {
  307.     unsigned char i;
  308.     unsigned char j;
  309.     i2c_start();        // Signal bar 書込みアドレスリセット (page 7, column 30d)
  310.     i2c_write(0x78);    // OLED slave address
  311.     i2c_write(0x00);    // Control byte Co=0, D/C#=0
  312.     i2c_write(0x20);    // Set memory addressing mode
  313.     i2c_write(0x02);    // Page addressing mode
  314.     i2c_write(0xB7);    // Set page start addres : page 7
  315.     i2c_write(0x0E);    // Set lower column start address : column 30d (0x1E)
  316.     i2c_write(0x11);    // Set higher column start address
  317.     i2c_stop();
  318.     if(sig_strong == 0)            // Signal レベル 0 の時の処理
  319.     {
  320.         i2c_start();    // Signal bar 全消去
  321.         i2c_write(0x78);    // OLED slave address
  322.         i2c_write(0x40);    // Control byte Co=0, D/C#=1 (The following data bytes are stored at the GDDRAM)
  323.         for(i=0; i<15; i++)
  324.         {
  325.             for(j=0; j<6; j++)
  326.             {
  327.                 i2c_write(sig[1][j]);    // Signal bar にブランク書込み
  328.             }
  329.         }
  330.         i2c_stop();
  331.     }
  332.     else                    // Signal レベル 1 以上の場合
  333.     {
  334.         for(i=0; i<sig_strong; i++)    // Signal bar 書込み
  335.         {
  336.             i2c_start();
  337.             i2c_write(0x78);    // OLED slave address
  338.             i2c_write(0x40);    // Control byte Co=0, D/C#=1 (The following data bytes are stored at the GDDRAM)
  339.     
  340.             for(j=0; j<6; j++)
  341.             {
  342.                 i2c_write(sig[0][j]);    // Signal bar 書込み
  343.             }
  344.         }
  345.         for(i=sig_strong; i<15; i++)
  346.         {
  347.             for(j=0; j<6; j++)
  348.             {
  349.                 i2c_write(sig[1][j]);    // 表示レベルより上のエリアに Signal bar をブランク書込み、表示レベルより上のエリアを消去する
  350.             }
  351.         }
  352.         i2c_stop();
  353.     }
  354. }
  355. void i2c_start()
  356. {
  357.     SSP1CON2bits.SEN = 1;
  358.     while(SSP1CON2bits.SEN);
  359. }
  360. void i2c_stop()
  361. {
  362.     SSP1CON2bits.PEN = 1;
  363.     while(SSP1CON2bits.PEN);
  364. }
  365. void i2c_write(unsigned char byte)
  366. {
  367.     PIR1bits.SSP1IF = 0;
  368.     SSP1BUF = byte;
  369.     while(!PIR1bits.SSP1IF);
  370.     SSP1CON1bits.CKP = 1;
  371. }
  372. //********* printfで使用するputchの定義 ***********
  373. void putch(unsigned char c)
  374. {
  375.     if(Size)
  376.     {
  377.         if(c==0x20)
  378.             c = 0x2A;    // " "
  379.         if(c==0x2E)        // .
  380.             c = 0x2B;
  381.         if(c==0x48)        // H
  382.             c = 0x2C;
  383.         if(c==0x4D)        // M
  384.             c = 0x2D;
  385.         if(c==0x6B)        // k
  386.             c = 0x2E;
  387.         if(c==0x7A)        // z
  388.             c = 0x2F;
  389.         chr12(c);
  390.     }
  391.     else
  392.         chr6(c);
  393. }
  394. //*************************************************


  1. //******************** font6 (6x8dotフォント) ***********************
  2. const char font6[91][6] =
  3. {
  4.     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // " " 0x20
  5.     { 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00 }, // ! 0x21
  6.     { 0x00, 0x07, 0x00, 0x07, 0x00, 0x00 }, // " 0x22
  7.     { 0x14, 0x7f, 0x14, 0x7f, 0x14, 0x00 }, // # 0x23
  8.     { 0x24, 0x2a, 0x7f, 0x2a, 0x12, 0x00 }, // $ 0x24
  9.     { 0x23, 0x13, 0x08, 0x64, 0x62, 0x00 }, // % 0x25
  10.     { 0x36, 0x49, 0x55, 0x22, 0x50, 0x00 }, // & 0x26
  11.     { 0x00, 0x05, 0x03, 0x00, 0x00, 0x00 }, // ' 0x27
  12.     { 0x00, 0x1c, 0x22, 0x41, 0x00, 0x00 }, // ( 0x28
  13.     { 0x00, 0x41, 0x22, 0x1c, 0x00, 0x00 }, // ) 0x29
  14.     { 0x14, 0x08, 0x3e, 0x08, 0x14, 0x00 }, // * 0x2A
  15.     { 0x08, 0x08, 0x3e, 0x08, 0x08, 0x00 }, // + 0x2B
  16.     { 0x00, 0x50, 0x30, 0x00, 0x00, 0x00 }, // , 0x2C
  17.     { 0x08, 0x08, 0x08, 0x08, 0x08, 0x00 }, // - 0x2D
  18.     { 0x00, 0x60, 0x60, 0x00, 0x00, 0x00 }, // . 0x2E
  19.     { 0x20, 0x10, 0x08, 0x04, 0x02, 0x00 }, // / 0x2F
  20.     { 0x3e, 0x51, 0x49, 0x45, 0x3e, 0x00 }, // 0 0x30
  21.     { 0x00, 0x42, 0x7f, 0x40, 0x00, 0x00 }, // 1 0x31
  22.     { 0x42, 0x61, 0x51, 0x49, 0x46, 0x00 }, // 2 0x32
  23.     { 0x21, 0x41, 0x45, 0x4b, 0x31, 0x00 }, // 3 0x33
  24.     { 0x18, 0x14, 0x12, 0x7f, 0x10, 0x00 }, // 4 0x34
  25.     { 0x27, 0x45, 0x45, 0x45, 0x39, 0x00 }, // 5 0x35
  26.     { 0x3c, 0x4a, 0x49, 0x49, 0x30, 0x00 }, // 6 0x36
  27.     { 0x01, 0x71, 0x09, 0x05, 0x03, 0x00 }, // 7 0x37
  28.     { 0x36, 0x49, 0x49, 0x49, 0x36, 0x00 }, // 8 0x38
  29.     { 0x06, 0x49, 0x49, 0x29, 0x1e, 0x00 }, // 9 0x39
  30.     { 0x00, 0x36, 0x36, 0x00, 0x00, 0x00 }, // : 0x3A
  31.     { 0x00, 0x56, 0x36, 0x00, 0x00, 0x00 }, // ; 0x3B
  32.     { 0x08, 0x14, 0x22, 0x41, 0x00, 0x00 }, // < 0x3C
  33.     { 0x14, 0x14, 0x14, 0x14, 0x14, 0x00 }, // = 0x3D
  34.     { 0x00, 0x41, 0x22, 0x14, 0x08, 0x00 }, // > 0x3E
  35.     { 0x02, 0x01, 0x51, 0x09, 0x06, 0x00 }, // ? 0x3F
  36.     { 0x32, 0x49, 0x79, 0x41, 0x3e, 0x00 }, // @ 0x40
  37.     { 0x7e, 0x11, 0x11, 0x11, 0x7e, 0x00 }, // A 0x41
  38.     { 0x7f, 0x49, 0x49, 0x49, 0x36, 0x00 }, // B 0x42
  39.     { 0x3e, 0x41, 0x41, 0x41, 0x22, 0x00 }, // C 0x43
  40.     { 0x7f, 0x41, 0x41, 0x22, 0x1c, 0x00 }, // D 0x44
  41.     { 0x7f, 0x49, 0x49, 0x49, 0x41, 0x00 }, // E 0x45
  42.     { 0x7f, 0x09, 0x09, 0x09, 0x01, 0x00 }, // F 0x46
  43.     { 0x3e, 0x41, 0x49, 0x49, 0x7a, 0x00 }, // G 0x47
  44.     { 0x7f, 0x08, 0x08, 0x08, 0x7f, 0x00 }, // H 0x48
  45.     { 0x00, 0x41, 0x7f, 0x41, 0x00, 0x00 }, // I 0x49
  46.     { 0x20, 0x40, 0x41, 0x3f, 0x01, 0x00 }, // J 0x4A
  47.     { 0x7f, 0x08, 0x14, 0x22, 0x41, 0x00 }, // K 0x4B
  48.     { 0x7f, 0x40, 0x40, 0x40, 0x40, 0x00 }, // L 0x4C
  49.     { 0x7f, 0x02, 0x0c, 0x02, 0x7f, 0x00 }, // M 0x4D
  50.     { 0x7f, 0x04, 0x08, 0x10, 0x7f, 0x00 }, // N 0x4E
  51.     { 0x3e, 0x41, 0x41, 0x41, 0x3e, 0x00 }, // O 0x4F
  52.     { 0x7f, 0x09, 0x09, 0x09, 0x06, 0x00 }, // P 0x50
  53.     { 0x3e, 0x41, 0x51, 0x21, 0x5e, 0x00 }, // Q 0x51
  54.     { 0x7f, 0x09, 0x19, 0x29, 0x46, 0x00 }, // R 0x52
  55.     { 0x46, 0x49, 0x49, 0x49, 0x31, 0x00 }, // S 0x53
  56.     { 0x01, 0x01, 0x7f, 0x01, 0x01, 0x00 }, // T 0x54
  57.     { 0x3f, 0x40, 0x40, 0x40, 0x3f, 0x00 }, // U 0x55
  58.     { 0x1f, 0x20, 0x40, 0x20, 0x1f, 0x00 }, // V 0x56
  59.     { 0x3f, 0x40, 0x38, 0x40, 0x3f, 0x00 }, // W 0x57
  60.     { 0x63, 0x14, 0x08, 0x14, 0x63, 0x00 }, // X 0x58
  61.     { 0x07, 0x08, 0x70, 0x08, 0x07, 0x00 }, // Y 0x59
  62.     { 0x61, 0x51, 0x49, 0x45, 0x43, 0x00 }, // Z 0x5A
  63.     { 0x00, 0x7f, 0x41, 0x41, 0x00, 0x00 }, // [ 0x5B
  64.     { 0x02, 0x04, 0x08, 0x10, 0x20, 0x00 }, // "\" 0x5C
  65.     { 0x00, 0x41, 0x41, 0x7f, 0x00, 0x00 }, // ] 0x5D
  66.     { 0x04, 0x02, 0x01, 0x02, 0x04, 0x00 }, // ^ 0x5E
  67.     { 0x40, 0x40, 0x40, 0x40, 0x40, 0x00 }, // _ 0x5F
  68.     { 0x00, 0x01, 0x02, 0x04, 0x00, 0x00 }, // ` 0x60
  69.     { 0x20, 0x54, 0x54, 0x54, 0x78, 0x00 }, // a 0x61
  70.     { 0x7f, 0x48, 0x44, 0x44, 0x38, 0x00 }, // b 0x62
  71.     { 0x38, 0x44, 0x44, 0x44, 0x20, 0x00 }, // c 0x63
  72.     { 0x38, 0x44, 0x44, 0x48, 0x7f, 0x00 }, // d 0x64
  73.     { 0x38, 0x54, 0x54, 0x54, 0x18, 0x00 }, // e 0x65
  74.     { 0x08, 0x7e, 0x09, 0x01, 0x02, 0x00 }, // f 0x66
  75.     { 0x0c, 0x52, 0x52, 0x52, 0x3e, 0x00 }, // g 0x67
  76.     { 0x7f, 0x08, 0x04, 0x04, 0x78, 0x00 }, // h 0x68
  77.     { 0x00, 0x44, 0x7d, 0x40, 0x00, 0x00 }, // i 0x69
  78.     { 0x20, 0x40, 0x44, 0x3d, 0x00, 0x00 }, // j 0x6A
  79.     { 0x7f, 0x10, 0x28, 0x44, 0x00, 0x00 }, // k 0x6B
  80.     { 0x00, 0x41, 0x7f, 0x40, 0x00, 0x00 }, // l 0x6C
  81.     { 0x7c, 0x04, 0x18, 0x04, 0x78, 0x00 }, // m 0x6D
  82.     { 0x7c, 0x08, 0x04, 0x04, 0x78, 0x00 }, // n 0x6E
  83.     { 0x38, 0x44, 0x44, 0x44, 0x38, 0x00 }, // o 0x6F
  84.     { 0x7c, 0x14, 0x14, 0x14, 0x08, 0x00 }, // p 0x70
  85.     { 0x08, 0x14, 0x14, 0x18, 0x7c, 0x00 }, // q 0x71
  86.     { 0x7c, 0x08, 0x04, 0x04, 0x08, 0x00 }, // r 0x72
  87.     { 0x48, 0x54, 0x54, 0x54, 0x20, 0x00 }, // s 0x73
  88.     { 0x04, 0x3f, 0x44, 0x40, 0x20, 0x00 }, // t 0x74
  89.     { 0x3c, 0x40, 0x40, 0x20, 0x7c, 0x00 }, // u 0x75
  90.     { 0x1c, 0x20, 0x40, 0x20, 0x1c, 0x00 }, // v 0X76
  91.     { 0x3c, 0x40, 0x30, 0x40, 0x3c, 0x00 }, // w 0x77
  92.     { 0x44, 0x28, 0x10, 0x28, 0x44, 0x00 }, // x 0x78
  93.     { 0x0c, 0x50, 0x50, 0x50, 0x3c, 0x00 }, // y 0x79
  94.     { 0x44, 0x64, 0x54, 0x4c, 0x44, 0x00 } // z 0x7A
  95. }; // 6x8dot


  1. //******************** font12(12x16dotフォント) ***********************
  2. const char font12[16][24] =
  3. {
  4.     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // " " 0x20
  5.     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00}, // . 0x2E
  6.     {0x00, 0xFC, 0xFC, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xFC, 0xFC, 0x00, 0x00, 0x3F, 0x3F, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x3F, 0x3F, 0x00}, // H 0x48
  7.     {0x00, 0xFC, 0xFC, 0x78, 0xE0, 0xC0, 0xC0, 0xE0, 0x78, 0xFC, 0xFC, 0x00, 0x00, 0x3F, 0x3F, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x3F, 0x3F, 0x00}, // M 0x4D
  8.     {0x00, 0xFC, 0xFC, 0x00, 0x80, 0xC0, 0x60, 0x30, 0x10, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x3F, 0x03, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x20, 0x00, 0x00}, // k 0x6B
  9.     {0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xF0, 0x70, 0x30, 0x00, 0x00, 0x00, 0x30, 0x38, 0x3C, 0x36, 0x33, 0x31, 0x30, 0x30, 0x30, 0x00, 0x00}, // z 0x7A
  10.     {0x00, 0xF0, 0xF8, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xF8, 0xF0, 0x00, 0x00, 0x0F, 0x1F, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x1F, 0x0F, 0x00}, // 0 0x30
  11.     {0x00, 0x00, 0x00, 0x00, 0x0C, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x3F, 0x3F, 0x30, 0x00, 0x00, 0x00, 0x00}, // 1 0x31
  12.     {0x00, 0x30, 0x38, 0x0C, 0x0C, 0x0C, 0x8C, 0x8C, 0xCC, 0xF8, 0x70, 0x00, 0x00, 0x38, 0x3C, 0x3E, 0x37, 0x33, 0x31, 0x31, 0x30, 0x30, 0x30, 0x00}, // 2 0x32
  13.     {0x00, 0x18, 0x1C, 0x0C, 0x8C, 0x8C, 0x8C, 0x8C, 0xCC, 0xF8, 0x70, 0x00, 0x00, 0x18, 0x38, 0x30, 0x31, 0x31, 0x31, 0x31, 0x33, 0x1F, 0x0E, 0x00}, // 3 0x33
  14.     {0x00, 0x00, 0x00, 0x80, 0xC0, 0x60, 0x30, 0x18, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x0E, 0x0F, 0x0D, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x3F, 0x0C, 0x00}, // 4 0x34
  15.     {0x00, 0xFC, 0xFC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x8C, 0x0C, 0x00, 0x00, 0x18, 0x38, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x1F, 0x0F, 0x00}, // 5 0x35
  16.     {0x00, 0xF0, 0xF8, 0x9C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x18, 0x18, 0x00, 0x00, 0x0F, 0x1F, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x1F, 0x0E, 0x00}, // 6 0x36
  17.     {0x00, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x8C, 0xCC, 0x7C, 0x3C, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x3F, 0x01, 0x00, 0x00, 0x00, 0x00}, // 7 0x37
  18.     {0x00, 0x70, 0xF8, 0x88, 0x8C, 0x8C, 0x8C, 0x8C, 0x88, 0xF8, 0x70, 0x00, 0x00, 0x0E, 0x1F, 0x11, 0x31, 0x31, 0x31, 0x31, 0x11, 0x1F, 0x0E, 0x00}, // 8 0x38
  19.     {0x00, 0x78, 0xFC, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0xF8, 0xF0, 0x00, 0x00, 0x00, 0x30, 0x31, 0x31, 0x31, 0x31, 0x31, 0x39, 0x1F, 0x0F, 0x00}, // 9 0x39
  20. }; // 12x16dot