自作電子小物/TIPS/グラフィックLCD S95160/STM32
自作電子小物/TIPS/グラフィックLCD S95160/STM32
小型グラフィックLCDモジュールの「S95160-32」を、STM32F4-Discoveryで制御するためのソフトウエアサブルーチンライブラリです。手軽にprintf()関数で簡単に文字表示を行う事が出来ます。4線抵抗型タッチスクリーンもサポートしています。 ※[2014.3.23] V0.2で簡単なGUI機能もサポートしました。
Graphic LCD S95160 Library for STM32
2013年4月13日
S95160 は、SUCCESS ELECTRONIC社で製造している3.2ンチ240×320ドットTFTの LCDモジュールで、aitendoで安価にて入手可能な表示装置です。接続が16bitパラレルと使いにくい面もありますが、3V単一電源でタッチパネル付き、1mmピッチで直接ハンダ付けも十分可能です。
これは、その制御ソフトウエアの部分を克服するためのサブルーチンです。
主な仕様
対応LCDモジュール: SUCCESS ELECTRONIC社 S95160
I/Oポート: 24本、内2本はアナログポート
座標: X方向左=0、X方向右=239、Y方向上=0、 Y方向下=319
表示図形: 塗りつぶし矩形、任意角度・任意幅の直線、固定6サイズの文字、円弧
文字種: ASCII 7bitコード0x20-0x7f
文字フォント: 6x8, 8x12, 12x16, 16x24, 18x24, 24x36ドット
文字数: 40桁×40行(6x8の場合)
カーソル機能: なし
スクロール機能: なし(ラップアラウンド表示されます)
バックライト制御: なし
ダウンロード
関連ソース全てとサンプルプログラムが入ったEclipse用のプロジェクトファイル
サンプル回路図のEAGLE用のプロジェクトファイル
<リセットピンの処理の仕方とバックライトの電源の取り方を変えています。2014.2.1>
サンプルの動かし方
・STM32F4-DiscoveryとLCDモジュール間を配線する。
・適当なディレクトリにダウンロードしたファイルを展開します。
・STM32F4-DiscoveryとPCをUSBケーブルで接続し、プログラム書込みツールでBINファイルを書込み。
・書込み完了と同時に、画面に”Hello world”の表示が出るはずです。
・バックライトの電源に関係なく、表示は行われます。
・IDE(eclipse)でビルドが出来る状態であれば、サンプルが4種類含まれていますので、ソースファイルの有効/無効にする操作を行う事で、色々試してみる事が出来ます。
・main_sample2.cでは、 画面を触ると、その位置に押した強さに応じた色が塗られます。
ユーザアプリケーションプログラムでの使い方
ソースコードで提供されるライブラリですので、ユーザプロジェクトでコンパイル対象に入れれば、本ライブラリを呼び出せる様になります。具体的には、ユーザのプロジェクトのディレクトリ内に本ライブラリソースファイル全てをコピーし、プロジェクトにもソースファイルを追加登録しておきます。
使用するI/Oポートを変更したい場合、下記のソースファイルの#define定義を変える事で対応できます。
文字を表示するだけのアプリケーションプログラムでは、printf()を使うだけで画面表示されます。#includeする必要もありあせん。それ以上の事を行いたい場合は、以下のAPIを使って下さい。
API(アプリケーションプログラムインタフェース)
ユーザアプリケーションプログラムは、 lcd_vcd.h, lcd_draw.h, lcd_touch.h, lcd_gui.h, lcd_font.h, lcd_color.hの、6つのAPIを利用する事が出来ます。
・キャラクタ表示
#include “lcd_vcd.h”
void lcd_setViewPort(unsigned char x, unsigned char y, unsigned char width, unsigned char height);
void lcd_prString(char *str);
void lcd_prCString(char *str);
void lcd_position(unsigned char column, unsigned char row);
void lcd_control(unsigned char command);
lcd_prStringのstrには、\n,\f等の制御コードを指定する事が出来ます。
lcd_positionで表示する桁column、行row位置を指定します。
lcd_controlは特殊機能を使う場合に使用します。
lcd_draw_strは任意ピクセル位置に文字を表示出来ます。
lcd_setViewPortは画面の一部のみをキャラクタディスプレイ領域として使いたい時のみ使用します。
使用される文字フォントは6x8です。
・グラフィック表示
#include “lcd_draw.h”
void lcd_drawOpen(void);
void lcd_drawRect(short x, short y, short width, short height, unsigned short color);
void lcd_drawLine(short x1, short y1, short x2, short y2, short line_size, unsigned short color);
void lcd_drawImage(short x, short y, short width, short height, unsigned short *image);
void lcd_drawChar(short x, short y, unsigned short face_color, unsigned short back_color, char c);
void lcd_drawStr(short x, short y, unsigned short face_color, unsigned short back_color, char *str);
void lcd_drawInit(void);
void lcd_drawChar2(short x, short y, unsigned short face_color, unsigned short back_color, char c, const struct lcd_font *font);
void lcd_drawStr2(short x, short y, unsigned short face_color, unsigned short back_color, char *str, const struct lcd_font *font);
void lcd_drawArc(short x, short y, short r, float startRad, float endRad, short line_size, unsigned short color);
各APIの機能は名前と引数から類推して下さい。
x,yはピクセル単位で絶対座標値で0〜239,0〜319の値を指定します。
値を超過した場合の動作は保証されません。
・文字フォントの種類
#include “lcd_font.h”
LCD_FONT_6x8
LCD_FONT_8x12
LCD_FONT_12x16
LCD_FONT_16x24
LCD_FONT_18x24
LCD_FONT_24x36
LCD_FONT_24x32
LCD_FONT_32x48
現時点では大きさのみの規定で、書体の区別はありません。
・色の管理
#include “lcd_font.h”
LCD_COLOR_BLACK
LCD_COLOR_RED
LCD_COLOR_GREEN
LCD_COLOR_BLUE
: 他、多数定義されていますが、任意の色をRGB成分で指定可能です。
unsigned short LCD_COLOR_CODE(float red, float green, float blue);
/* ユーティリティマクロ */
float LCD_COLOR_R_VALUE(unsigned short colorCode);
float LCD_COLOR_G_VALUE(unsigned short colorCode);
float LCD_COLOR_B_VALUE(unsigned short colorCode);
unsigned short LCD_COLOR_TO_DARK(unsigned short colorCode);
unsigned short LCD_COLOR_TO_LIGHT(unsigned short colorCode);
LCD_COLOR_TRANSPARENT(透明)に関しては、全ての場所で有効な訳でなく、透明にならない場合があります。
・タッチパネル検出
#include “lcd_touch.h”
void lcd_touchOpen(void);
short lcd_touchPoint(short *x, short *y);// PushRate[%]
void lcd_touchCalibrate(void);
lcd_touchPoint()は、コール時点でのタッチパネルの状態を返却します。変化を見るには定期的にチェックする必要があります。
・GUI部品
#include “lcd_gui.h”
void lcd_guiOpen();
void lcd_guiHandler(struct lcd_guiRoot *root);
/* 図形登録(静的にデータ定義出来る#defineマクロもあります) */
struct lcd_guiRect *
lcd_guiNewRect(struct lcd_guiGroup *group, short x, short y, short width, short height, unsigned short color);
struct lcd_guiLine *
lcd_guiNewLine(struct lcd_guiGroup *group, short sx, short sy, short ex, short ey, short lineWidth, unsigned short color);
struct lcd_guiPoly *
lcd_guiNewPoly(struct lcd_guiGroup *group, struct lcd_guiCoordinate *point, int n, int m, short lineWidth, unsigned short color);
struct lcd_guiArc *
lcd_guiNewArc(struct lcd_guiGroup *group, short x, short y, short r, float srad, float erad, short lineWidth, unsigned short color);
struct lcd_guiStr *
lcd_guiNewStr(struct lcd_guiGroup *group, short x, short y, unsigned short faceColor, unsigned short backColor, char *str);
struct lcd_guiText *
lcd_guiNewText(struct lcd_guiGroup *group, short x, short y, short width, short height, unsigned short faceColor, unsigned short backColor, int hAlign, int vAlign, char *str, const struct lcd_font *font);
struct lcd_guiImage *
lcd_guiNewImage(struct lcd_guiGroup *group, short x, short y, short width, short height, unsigned short *image);
struct lcd_gui7seg *
lcd_guiNew7seg(struct lcd_guiGroup *group, short x, short y, short width, short height, unsigned short faceColor, unsigned short backColor, short lineWidth, int column, unsigned char *pattern);
struct lcd_guiGage *
lcd_guiNewGage(struct lcd_guiGroup *group, short x, short y, short width, short height, unsigned short faceColor, unsigned short backColor, int vartical, float value);
struct lcd_guiBarChart *
lcd_guiNewBarChart(struct lcd_guiGroup *group, short x, short y, short width, short height, unsigned short
backColor, int vartical, int n, float *value, unsigned short *color);
struct lcd_guiGroup *
lcd_guiNewGroup(struct lcd_guiGroup *group, short x, short y, short width, short height, unsigned short backColor,
struct lcd_gui *
figures, void (*eventProg)(enum lcd_guiEvent event, struct lcd_guiCoordinate *touch, struct lcd_guiGroup *seg));
struct lcd_guiRoot *
lcd_guiNewRoot(unsigned short backColor, struct lcd_gui *figures, void (*eventProg)(enum lcd_guiEvent event, struct lcd_guiCoordinate *touch, struct lcd_guiGroup *seg));
struct lcd_guiButton *
lcd_guiNewButton(struct lcd_guiGroup *parent, short x, short y, short width, short height, char *caption, const struct lcd_font *font, unsigned short faceColor, unsigned short backColor, unsigned short touchColor, enum lcd_guiButtonMode mode, int state, void (*actionProg)(struct lcd_guiButton *seg));
struct lcd_guiFloatField *
lcd_guiNewFloatField(struct lcd_guiGroup *parent, short x, short y, short width, short height, unsigned short faceColor, unsigned short backColor, char *format, const struct lcd_font *font, float min, float max, float value, void (*actionProg)(struct lcd_guiFloatField *seg));
struct lcd_guiIntegerField *
lcd_guiNewIntegerField(struct lcd_guiGroup *parent, short x, short y, short width, short height, unsigned short faceColor, unsigned short backColor, char *format, const struct lcd_font *font, int min, int max, int value, void (*actionProg)(struct lcd_guiIntegerField *seg));
struct lcd_guiPullDown *
lcd_guiNewPullDown(struct lcd_guiGroup *parent, short x, short y, short width, short height, unsigned short faceColor, unsigned short backColor, char **label, const struct lcd_font *font, int number, int select, void (*actionProg)(struct lcd_guiPullDown *seg));
struct lcd_guiTextField *
lcd_guiNewTextField(struct lcd_guiGroup *parent, short x, short y, short width, short height, unsigned short faceColor, unsigned short backColor, int hAlign, int vAlign, char *str, size_t len, const struct lcd_font *font, void (*actionProg)(struct lcd_guiTextField *seg));
/* 図形データ操作 */
void lcd_guiSetDirtys(struct lcd_gui *seg);
void lcd_guiSetHiddens(struct lcd_gui *seg, int f);
struct lcd_guiGroup *lcd_guiGetParent(struct lcd_gui *seg);
void lcd_guiSet7segFixedPoint(struct lcd_gui7seg *seg, int value, int dotPoint);
void lcd_guiSetRelink(struct lcd_gui *seg);
各APIの機能は名前と引数から類推して下さい。
基本的に、まず図形グループを lcd_guiNewGroup() で生成し、それに図形を追加登録していくというスタイルをとります。図形グループとは、小さな矩形画面領域を設定し、その中に図形を描画するという考えです。これにより、グループ全体を移動したり、一括して非表示にしたりといった、図形部品としての操作を行いやすくします。また、グループの配下にグループを作る事も出来ますので、一つの図形として扱う事が出来ます。一番の大元のグループは「ルート」と呼び、 lcd_guiNewRoot() で生成します。
入力系は、基本的にコールバック形式になります。タッチされた場合、事前に設定した関数がコールされると言う仕組みです。この、機能を実装する為と、画面更新の為に「ハンドラ」という形で、定期的に lcd_guiHandler() をコールしてもらう必要があります。
具体的な使い方は、サンプルプログラムのソースコードを参照下さい。
各図形は、APIを介せず直接参照しても、更新しても構いませんが、思ったような結果にならない場合もあります。少なくとも、図形に変化があった場合は、lcd_guiDirtys()で変化があった事を通知して下さい。
C言語のイニシャライザで図形データを登録する#define定義も用意しています。詳細なドキュメントはありません。ヘッダファイルをご参照下さい。
設計情報
・開発環境
OS: MacOSX 10.8.3
Java: JRE 1.6.0_43
IDE: Eclipse 4.2.1.v20120814-120134
Eclipse IDE for C/C++ Developers 1.5.1.20121004-1506
Compiler: GNU toolchain from ARM Cortex-M & Cortex-R processors
GCC ARM Embedded in Lanchpad 4.7 2012q4
ROM Writer: QSTLink2
・ソースファイル
lcd_color.c 色管理
lcd_draw.h 図形表示API
lcd_font.c フォント供給
lcd_gui.c GUI機能
lcd_gui_create.c GUI機能(図形登録)
lcd_gui_create_button.c GUI機能(ボタン図形登録)
lcd_gui_create_floatfield.c GUI機能(浮動小数点フィールド図形登録)
lcd_gui_create_integerfield.c GUI機能(整数フィールド図形登録)
lcd_gui_create_keypad.c GUI機能(スクリーンキーボード展開)
lcd_gui_create_pulldown.c GUI機能(プルダウン図形登録)
lcd_gui_create_textfield.c GUI機能(テキストフィールド図形登録)
lcd_gui_display.c GUI機能(図形データ再表示管理)
lcd_gui_figure.h GUI機能(図形データ定義)
lcd_gui_manage.c GUI機能(図形データ管理)
lcd_gui_touch.c GUI機能(タッチアクション管理)
lcd_touch.h タッチパネル検出API
lcd_vcd.c キャラクタディスプレイエミュレーション
s95160_1.c 表示ドライバ(物理インタフェース)
s95160_2.c 表示ドライバ(論理インタフェース)
s95160_t1.c タッチパネルドライバ(物理インタフェース)
s95160_t2.c タッチパネルドライバ(論理インタフェース)
・ライブラリ内依存関係
中段のAPIは単に画面へ一発表示するだけ、入力状態をセンスするだけの、基本的な機能(API)です。自由度は高いですが、アプリケーションプログラムの負荷は高くなります。
下半分が、画面とタッチ動作を有機的に結びつけるためのGUI機能です。より、アプリケーションプログラムの負荷は軽くなります。なぜ、負荷が低いのかと言うと、一度描画した図形は「図形データ」と呼ぶメモリに保存され、自動的に再表示されるからです。アプリケーションによっては再表示なんて大した事はない場合もありますが、これによって再表示に関しては何も考える必要が無くなり、ソフトウエア設計が楽になります。また、ポップアップメニューや、オーバラップウインドウを実現するには、どうしても避けて通れない機能なのです。
図形データを用意する方法は二つあり、APIを通して動的に図形を登録するのと、予め画面レイアウトを決めて静的な図形データを用意するものです。
前者の、動的に図形を登録するのは、単に画面表示するイメージです。直線なら始点と終点の座標、色、線の太さ等の情報を与えれば、図形データとして登録され、画面にも即時表示されます。
後者の場合、C言語の初期値設定機能(イニシャライザ)で、図形データ構造体にデータを与えるものです。図形データは座標等の数値として表現するので、ちょっと面倒な面はありますが、図形データを生成する外部の画面設計ツールを用意できれば、より簡単に開発を行えるという拡張性を持っています。
・4線式タッチパネルについて
単純な仕組みだけれども、簡単にXYZ軸が検出できる、面白いデバイスです。
動的に回路を切り替える所がミソで、マイクロコントローラを使うと楽に実装可能です。
・文字フォントについて
当初、5x7ピクセルの最小フォントだけでしたが、やはり大きい文字が必要になり、何種類かの大きな文字フォントを作る事にしました。とは言え、ベクトルフォントの様な、任意サイズの文字表示を行う仕組みでは、ターゲットにしている規模には負荷が大き過ぎます。
そこで、最小限の種類のフォントを拡大縮小する事で、多くの文字フォントを表示出来るようにしたいと考えました。見栄えはぱっとしませんが、仕方ないと思っています。
具体的には1.5倍ベースでの拡大として
1.0 → 1.5 → 2.0 → 3.0 → 3.0 → 4.5
これだと、2種類の原始文字フォントを用意するだけで、6サイズの文字を表示出来ます。
拡大の仕方も、スムージングすれば、より見やすくなるでしょう。
1.0倍は5x7
1.5倍は7x11
のフォントを、英数字分、我慢して手作りレイアウトしC言語の初期値データで実装しています。
倍率は4種類までとし、合計8種類のサイズの文字フォントを扱えるようになっています。
権利関係
GPLに準じます。他から流用したソース部分はありません。参照した情報源は以下の通り。
(1)aitendo@shopping(株式会社 秋葉原)の「TFT液晶モジュール(3.2/240x320)[S95160-32]」の販売ページの接続ピン情報とLCDコントローラ SSD1289Z のデータシート http://www.aitendo.com/product/3140