2.2 液晶制御への応用


本ページの内容及び制御方法はとんすけさんのブログの記述を参考,引用しています。
氏のブログではSTM32の応用方法が数多く解説されており、とても参考になります。



【サンプルプロジェクト】
  まず今回の動画再生で使用したSTM32の動画再生サンプルプロジェクトを公開します。
  以後の説明の参考にご利用ください。

  サンプルプロジェクトダウンロード

  ※注意:高速アクセスの為、SDIOライブラリを変更しています。
       実際にmiqnnnet環境で利用される際は、既存のSDIOフォルダは削除してから
       サンプルプロジェクトをコピーしてください。

      



【QVGA液晶について】

  QVGA液晶とはQVGA(320×240pixel)の表現力を持つ液晶を指します。
  このサイズの液晶は従来の携帯電話などに多く用いられていました。
  多くの場合、液晶素子ごとにカラーフィルタが設けられておりカラー表示が可能です。

  最近はaitendoさんや液晶市場さん等から
  1000~3000円台と非常に安価に手に入るようになりました。

  中でも内部メモリであるGRAM内臓のコントローラを搭載している
  液晶は扱いやすく人気があります。

  今回はaitendoさんの[YHY024006A-PCB]を使用しています。

 
 


 ○YHY024006Aの特徴
   ①液晶表示の自動リフレッシュ機能を持つコントローラーを内臓
   ②1画面分の表示データを内部に保持できるGRAMを搭載
   ③抵抗膜式タッチパネル付き
   ④比較的良質な画質が得られる。
   ⑤安価。キャリーボード付きで1980円(2011年10月18日時点)

以下、液晶はLCDと呼ぶ事にします。



【アクセス方法】
  LCDのコマンド等については商品ページのデータシートを参照していただければと思います。
    また、このLCDの使用方法はコマンドやタッチパネルも含めて
  後閑さんの「LCD&タッチセンサ活用の素」で丁寧に解説されていますので
  そちらを参照されるのも良いと思います。

  ここではアクセス信号の内容を紹介します。
  LCD書き込み信号は下図のようになります。

 

  
  各信号の内容

信号名  信号の意味 Lowレベル  Highレベル 
 RS  送信するデータの種別を決定する。  データ  コマンド
 CS チップセレクト(LCDを選択する)  イネーブル  ディスエーブル 
 D0-D15 データの内容 
 WR  データ書込み要求 書込み要求 書込み完了

  信号のタイミングスペック
タイミング名  MIN[nsec] MAX [nsec]
Tas 10
Twl 50  500 
Twh 50 
Twcycle 100

【FSMCとの連携】
  FSMCの機能を応用した例としてSTマイクロエレクトロニクスから
  LCD制御のアプリケーションノートが公開されています。(英文)
  「TFT LCD interfacing with the high-density STM32F10xxx FSMC」
 
  この例ではLCDを下記のように擬似SRAMのように扱います。
  ☆ LCDへのデータはFSMCのデータバスを使用する。
  ☆ コマンド/データのRS信号はFSMCのアドレスバスの1ピンのみを使用する。
  ☆ チップセレクト信号はFSMCのバンク選択信号を使用する。
  ☆ 書き込み要求は、FSMCのSRAM書き込み信号を使用する。
 
  以上の内容からSTBeeの使用マイコンに合わせてLCDと結線しました。(クリックで拡大)
  (読み込み信号のRDはSTBeeのLEDと干渉する事や表示には不要である事からFSMCとは結線していません。)

 
  操作の為にタッチパネル,動画データの読み込みの為にSDカードを結線しています。
    (回路図左下にmp3デコーダーのVS1011eが有りますが今回は取り扱いません。)

【FSMCの設定方法】
  下記の手順で設定します。

  ①FSMCにクロックを供給する。
  ②FSMCの各種レジスタを設定する。
  ③FSMC機能をイネーブルにする。

  特に③を忘れると例外が発生するので注意します。
  下記に設定例を記します。
  構造体のポインタを指定するなど通常の設定と少し異なりますのでご注意ください。

void LCD_FSMC_Ini(void)
{
    FSMC_NORSRAMInitTypeDef FSMC_Ini_st;
    FSMC_NORSRAMTimingInitTypeDef FSMC_Time_st;
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC,ENABLE);

    //FSMCタイミング設定(アクセスモードB)
    FSMC_Time_st.FSMC_AddressSetupTime = 4;
    FSMC_Time_st.FSMC_AddressHoldTime = 0;
    FSMC_Time_st.FSMC_DataSetupTime = 4;
    FSMC_Time_st.FSMC_BusTurnAroundDuration = 0x00;
    FSMC_Time_st.FSMC_CLKDivision = 0x00;
    FSMC_Time_st.FSMC_DataLatency = 0x00;
    FSMC_Time_st.FSMC_AccessMode = FSMC_AccessMode_B;

    //FSMC初期設定 NORフラッシュとして使用
    FSMC_Ini_st.FSMC_Bank = FSMC_Bank1_NORSRAM1;
    FSMC_Ini_st.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
    FSMC_Ini_st.FSMC_MemoryType = FSMC_MemoryType_NOR;
    FSMC_Ini_st.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
    FSMC_Ini_st.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
    FSMC_Ini_st.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
    FSMC_Ini_st.FSMC_WrapMode = FSMC_WrapMode_Disable;
    FSMC_Ini_st.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
    FSMC_Ini_st.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
    FSMC_Ini_st.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
    FSMC_Ini_st.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
    FSMC_Ini_st.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
    FSMC_Ini_st.FSMC_ReadWriteTimingStruct = &FSMC_Time_st;
    FSMC_Ini_st.FSMC_WriteTimingStruct = &FSMC_Time_st;
    FSMC_NORSRAMInit(&FSMC_Ini_st);

    FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1,ENABLE);
}

【LCDアクセス方法】
  設定項目は多いですが、設定が終わった後の使用方法は至ってシンプルです。
  ①ポインタにFSMCのSRAMアドレスを指定する。
  ②ポインタのアドレスに対して読み書きを行う。

  順を追って解説します。
  ①アドレスの指定
    LCDを通常のペリフェラルと同様に扱えるようマクロ定義します。

 
//LCDアクセス用構造体の定義
typedef struct{
    volatile uint16_t CMD;
    volatile uint16_t DATA;
}LCD_TypeDef;

//構造体のアドレスを定義
#define LCD_BASE ((uint32_t)(0x607ffffe))
#define LCD ((LCD_TypeDef*)LCD_BASE)

    
    RS信号はアドレスピン(FSMC_A22)によって制御します。
    つまりアクセスするアドレスによってRS信号を変化させます。
    上記のマクロ定義によって下記のように定義します。

    LCD->CMDのアドレス  = 0x607ffffe    (22bit目が1(信号High))
    LCD->DATAのアドレス  = 0x60800000   (22bit目が0(信号Low))

  ②アドレスへの読み書き
    マクロ定義によってデータの書き込みができるようになります。

    コマンド書き込み:
    LCD->CMD   =  value;

    データ書き込み :
    LCD->DATA  =  value;
    ※valueは任意のuint16_t即値または変数

    さらにLCD特有のアクセスシーケンスを関数化します。
    高速にアクセスする為にスタック操作が発生する通常の関数ではなく
    ソースコードに直接展開されるマクロ関数を定義しています。


//LCDアクセスを行うマクロ関数。
/**
* @brief :LCDへのインデックス指定のデータ送信
* @param :コマンドインデックス,データ
* @retval : None
*/
#define LCD_OUT(index,data) \
{\
    LCD->CMD = index;\
    LCD->DATA = data;\
}

/**
* @brief : GRAM開始アドレスの指定
* @param : None
* @retval : None
*/
#define SET_LCD_ADDRESS(x,y) \
{\
    LCD_OUT(0x020, y);\
    LCD_OUT(0x021, x);\
}

/**
* @brief : 1pixelの書き込み
* @param : None
* @retval : None
*/
#define WRITE_PIXEL(x,y,color) \
{\
    SET_LCD_ADDRESS(x,y);\
    LCD_OUT(0x0022,color);\
}

    ※マクロ関数の引数は任意のunit16_t即値または変数を指定します。



以上のようにFSMC機能を活用する事で
従来GPIOやタイマを操作してRSやCSを操作していたLCDアクセスが
非常にシンプルかつ高速に行えるようになります。