AQM1248A グラフィックLCD (for PIC)

AQM1248Aは以前Arduino用にプログラムを書きましたが今回はそのPIC版です。検証に使ったPICはPIC24FJGB002です。AMQ1248Aとは以下の用につないでいます。

プログラム

今回は初設定をMCCを使って行っています。SPIのクロックですが、PrimaryとSecondaryのPrescalerを共に1:1として最速としました。これで2MHzとなります。

次はIOポートの設定です。矢印の部分が変更箇所です。

このLCDにはMISOポートが無いので回路にその記述は有りませんが、MISOポートをRB15に設定しています。RB7のLEDはデバック用に付ました。その他の項目は変更無しでGenerateしています。

プログラムの説明

今回書いたプログラムは、AQM1248A_PIC.c(本体)とAQM1248A_PIC.h(ヘッダーファイル)の2です。それと文字表示用のフォント、font_data.hを使用しています。それ以外はMCCが作成したコードです。メインプログラム。”main.c”では 点、直線、文字表示等 簡単なデモを行っています。

AQM1248A_PIC.cは、AQM1248A グラフィックLCD (for Arduino)に有るArduino用のプログラムをMCCで作成した関数(ほとんど、”SPI1_Exchange8bit()”)を使って書き直したのもです。各関数の説明はリンク先を参照して下さい。

AQM1248A_PIC.c

/*
 * File:   AQM1248A_PIC.c
 *
 * Created on December 7, 2021, 10:35 PM
 */

#include "xc.h"
#include "AQM1248A_PIC.h"
#include "font_data.h"
#include "mcc_generated_files/spi1.h"

uint8_t v_buf[128][6];

void Init_LCD()
{
    LCD_CS =  LOW;
    LCD_RS =  LOW;

    SPI1_Exchange8bit(0xAE);
    SPI1_Exchange8bit(0xA0);
    SPI1_Exchange8bit(0xC8);
    SPI1_Exchange8bit(0xA3);

    SPI1_Exchange8bit(0x2C);
    __delay_ms(50);
    SPI1_Exchange8bit(0x2E);
    __delay_ms(50);

    SPI1_Exchange8bit(0x2F);

    SPI1_Exchange8bit(0x23);
    SPI1_Exchange8bit(0x81);
    SPI1_Exchange8bit(0x1C);

    SPI1_Exchange8bit(0xA4);
    SPI1_Exchange8bit(0x40);
    SPI1_Exchange8bit(0xA6);
    SPI1_Exchange8bit(0xAF);

   LCD_CS = HIGH;
}

void LCD_CLS(uint8_t data)
{
    uint8_t a,b;

    LCD_CS = LOW;
    for(b = 0; b < 6; b ++)
    {
        LCD_RS = LOW;
        SPI1_Exchange8bit(0xB0 + b);
        SPI1_Exchange8bit(0x10);
        SPI1_Exchange8bit(0x00);

        LCD_RS = HIGH;
        for(a = 0; a < 128; a ++)
        {
            SPI1_Exchange8bit(data);
            v_buf[a][b] = data;
        }
    }
    LCD_CS = HIGH;
}

//----------------------------------------------------
//  点の描画
//  int x_data  X positon   0 -> 128
//  int x_data  Y positon   0 -> 48
//  int cl      color 0: white  1:black
//----------------------------------------------------
void LCD_PSET(int x_data, int y_data, int cl)
{
    uint8_t a,b,c;

//  y_data
    a = y_data >> 3; b = y_data & 0x07;
    c = 0x1;
    while(b) { c <<= 1; b --; }

    if(cl) v_buf[x_data][a] |= c;
    else { c = ~c; v_buf[x_data][a] &= c; }

    LCD_CS = LOW;
    LCD_RS = LOW;
    SPI1_Exchange8bit(0xB0 + a);
    c = x_data >> 4; c |= 0x10;
    SPI1_Exchange8bit(c);
    c = x_data & 0xf;
    SPI1_Exchange8bit(c);
   
    LCD_RS = HIGH;
    SPI1_Exchange8bit(v_buf[x_data][a]);
    
    LCD_CS = HIGH;
}

//----------------------------------------------------
//  Fontの描画
//  int x_data  X positon   0 -> 128
//  int y_data  Y positon   0 -> 48
//  char c_data Data
//  int cl      color 0: white  1:black
//----------------------------------------------------
void LCD_Print_C(int x_data, int y_data, char c_data, int cl)
{
    int a,b,c,d;
    unsigned char s,data_c;
    
    data_c = c_data;
    if(data_c > 0xbf) data_c -= 0x40;
    a = data_c - 0x20;
    for(b = 0; b < 5; b ++)
    {
        s = 0x1;
        for(c = 0; c < 8; c ++)
        {
            d = 0;
            if(Font[a][b] & s) d=1;
            if(cl == 0) d = !d;
            LCD_PSET(x_data,y_data + c,d);
            s <<= 1;
        }
        x_data ++;
    }
    for(c = 0; c < 8; c ++)
    {
        d = 0;
        if(cl == 0) d = 1;
        LCD_PSET(x_data,y_data + c,d);
    }
}

//----------------------------------------------------
//  Strの描画
//  int x_data  X positon   0 -> 128
//  int y_data  Y positon   0 -> 48
//  char *c_data Data
//  int cl      color 0: white  1:black
//----------------------------------------------------
void LCD_Print_Str(int x_data, int y_data, char * c_data, int cl)
{
    int a;

    a = strlen((char *)c_data);
    while(a)
    {
        if(*c_data == 0xff) 
            { c_data ++; a --; }
        
        LCD_Print_C(x_data,y_data,*c_data,cl);
        a --; x_data += 6; c_data ++;
    }
}

//----------------------------------------------------
//   直線描画関数
//
//  int x0      start x
//  int y0      start y
//  int x1      end x
//  int y1      end y
//  int cl      color 0: white  1:black
//----------------------------------------------------
#define abs(a)  (((a)>0) ? (a) : -(a))
void LCD_LINE(int x0, int y0, int x1, int y1, int cl)
{
    int steep, t;
    int deltax, deltay, error;
    int x, y;
    int ystep;

    /// 差分の大きいほうを求める
    steep = (abs(y1 - y0) > abs(x1 - x0));
    /// x、yの入れ替え
    if(steep)
    {
        t = x0; x0 = y0; y0 = t;
        t = x1; x1 = y1; y1 = t;
    }
    if(x0 > x1)
    {
        t = x0; x0 = x1; x1 = t;
        t = y0; y0 = y1; y1 = t;
    }
    deltax = x1 - x0;                       //  傾き計算
    deltay = abs(y1 - y0);
    error = 0;
    y = y0;
    /// 傾きでステップの正負を切り替え
    if(y0 < y1) ystep = 1; else ystep = -1;
    /// 直線を点で描画
    for(x = x0; x < x1 + 1; x++)
    {
        if(steep) LCD_PSET(y,x,cl); else LCD_PSET(x,y,cl);
        error += deltay;
        if((error << 1) >= deltax)
        {
            y += ystep;
            error -= deltax;
        }
    }
}

添付したコードを実行するとAQM1248A グラフィックLCD (for Arduino)と同じデモプログラムを実行します。システムクロックは変更していないので4MHzですが、とても速く描写します。試しにシステムクロックを挙げたら描写が見えない位速くなりました。今回使用したコード一式を以下に保存します。