⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lcd.c

📁 这个是黑白LCD的一个典型的驱动函数集 原创 请大家多支持下下!如果有什么问题请来信
💻 C
📖 第 1 页 / 共 4 页
字号:
/********************************************************************************************************
* 文 件 名 : LCD.c
* 日    期 : 2006-03-02
* 说    明 : 这一版本的软件是针对  深圳市松山电子科技有限公司  的CA12864K 系列LCM 模块的驱动
*            可以兼容   OCMJ(奥可拉中文集成模块) C系列液晶显示器 (带汉字库LCD开发的驱动)
*            驱动芯片ST7920 ST7921组成的驱动组 及其兼容芯片
*            适用型号 : OCMJ12864C_1   OCMJ4X8C   OCMJ4X10C  OCMJ4X8C  OCMJ4X16A   OCMJ4X16B 等
*            松山公司资料
*            网站     : http://www.sunson.net    Email : sunson@sunson.net
*            电话     : 0755-27891155 /0755-27890697 /0755-27890723/10/16/19
*            技术支持 :
*            奥可拉公司资料
*            网站     : http://www.gptlcm.cn        Email : syl@gptlcm.cn
*            电话     : 0758-2317153/2317143
*            技术支持 : 0758-2317156
* 程 序 员 : 蔡杰(hnclcj@163.com)
********************************************************************************************************/


#define  LCD_GLOBALS
#include "includes.h"
#include "FONT_MACRO.h"
#include "Font.h"

#if      LCD_MODULS_EN > 0

OS_EVENT *DispSem;                                // 显示信号量




/********************************************************************************************************
*  常数  LCM 支持的命令集  常用的命令 共18条
********************************************************************************************************/
                                       /* -----------------ST7920 ST7921  COMMANDS ------------------  */
                                       /* 基本指令集                                                   */
#define  DISP_CMD_BSCLS         0x01   /* 清屏 即屏幕用' ' 填充满                                      */
#define  DISP_CMD_BSACR         0x02   /* DDRAM位置计数器 复位到0 并将右边游标移动到00 不改变DDRAM内容 */
#define  DISP_CMD_BSRMOVE       0x05   /* 整体显示为右移                                               */
#define  DISP_CMD_BSMOVE        0x06   /* 整体显示不移动 光标右移                                      */
#define  DISP_CMD_BSLMOVE       0x07   /* 整体显示为左移                                               */
#define  DISP_CMD_BSOFF         0x08   /* D=0:整体关闭,DDRAM内容不改变, C=1游标ON, B=1游标位置显示反白 */
#define  DISP_CMD_BSON          0x0c   /* D=1:整体显示,C=0,B=0                                         */
#define  DISP_CMD_BSIO          0x30   /* DL=0; 4BIT接口 DL=1; 8BIT接口 RE=0:基本指令                  */

#define  DISP_CMD_BASIC         0x30   /* RE=1; 扩充指令集                                             */
#define  DISP_CMD_EXTEND        0x36   /* RE=1:扩充指令                                                */

                                       /* 扩充指令集                                                   */
#define  DISP_CMD_EXTWAIT       0x01   /* 待命模式                                                     */
#define  DISP_CMD_EXTEXSR       0x02   /* 允许输入IRAM 或CGRAM位置                                     */
#define  DISP_CMD_EXTENSR       0x03   /* 允许输入垂直卷动位置                                         */
#define  DISP_CMD_EXLINE1       0x04   /* 第一行反白显示                                               */
#define  DISP_CMD_EXLINE2       0x05   /* 第二行反白显示                                               */
#define  DISP_CMD_EXLINE3       0x06   /* 第三行反白显示                                               */
#define  DISP_CMD_EXLINE4       0x07   /* 第四行反白显示                                               */
#define  DISP_CMD_EXTENIDLE     0x08   /* 进入睡眠模式                                                 */
#define  DISP_CMD_EXTEXIDLE     0x0c   /* 退出睡眠模式                                                 */
#define  DISP_CMD_EXTIRAMADD    0x40   /* 起始IRAM位置或卷动位置 看SR命令SR=1卷动位置 SR=0ICOM RAM 地址*/


/********************************************************************************************************
* 本地函数
********************************************************************************************************/
#if DISP_GRH_EN > 0                           /* LCM 图形方式驱动的本地函数                            */

static void   DispGrhInit      (void);
static void   DispGrhDataWrExt (INT8U x0, INT8U y0, INT16U dat);
static void   DispGrhPosSetCur (INT8U x, INT8U y);
#endif

#if DISP_TXT_EN > 0                           /* TXT 文本方式驱动的本地函数                            */
static void   DispTxtCharExt     (INT8U row, INT8U col, char c);
static void   DispTxtInit        (void);
static void   DispTxtPosSetCur   (INT8U row, INT8U col);
static void   DispTxtPosSetFront (INT8U row, INT8U col);

static void   DispTxtStrExt      (INT8U row, INT8U col, const char *s, BOOL constsel);//AVR扩展
#endif

                                              /* 以下的函数与硬件有关 需要根据硬件来更改 是公用部分    */
#if DISP_TXT_EN > 0 || DISP_GRH_EN > 0

static void   DispCtrlCmdWr    (INT8U cmd);
static void   DispCtrlDataWr   (INT8U dat);
static INT8U  DispCtrlDataRd   (BOOL  par);

static void   DispInitHard     (void);
static void   DispLock         (void);
static void   DispUnLock       (void);

#endif





/********************************************************************************************************
* 功 能 : 向LCM命令寄存器写命令
* 入 口 : 'cmd'  是当前要写入的命令数据
* 返 回 : 无
* 说 明 :1> 如果送到数据端口的数据跟实际需要送出的数据不一样 表示LCM可能出问题或着有共享的I/O被利用了
*           则需要等待其他的释放共享的I/O 来保证数据的正确性
*        2> 这里的时序问题 这里再不能做精简了
*        3> 这里的各种延时是在AVR 4MHz环境下测试得到
********************************************************************************************************/
#if DISP_GRH_EN > 0 || DISP_TXT_EN > 0

static void DispCtrlCmdWr (INT8U cmd)
{
    LCDDATA_PORT_LOW  = 0xff << LCDDATA;          //
    LCDDATA_PORT_HIGH = cmd  << LCDDATA;          //

    SETBIT(LCDRS_PORT_LOW, LCDRS);                // 选择命令寄存器  Cmd Reg low
    SETBIT(LCDRW_PORT_LOW, LCDRW);                // 选择写状态
    SETBIT(LCDE_PORT_HIGH, LCDE);                 // 写入命令数据 _|---|_
    DelayNUs(83);                                 // 16US*5 的E线脉冲 经过测试必须>=5 85
    SETBIT(LCDE_PORT_LOW,  LCDE);                 //
    DelayNUs(9);                                  // 命令执行时间>=74uS
}
#endif


/********************************************************************************************************
* 功 能 : 从LCM数据寄存器读一字节数据
* 入 口 : 'bi' 如果是写地址后立即读 就需要虚读一次 连续读不需要 只能为 :  1地址立即读 0为连续读
* 返 回 : 当前读到的数据
* 说 明 : 1> 在调用此函数前需要写入要读数据的地址 如果是当前读 则不需要
*         2> 这里的时序问题 这里再不能做精简了
*        3> 这里的各种延时是在AVR 4MHz环境下测试得到
********************************************************************************************************/
#if DISP_GRH_EN > 0 || DISP_TXT_EN > 0

static INT8U DispCtrlDataRd (BOOL par)
{
    INT8U  dat;


    LCDDATA_DDR       &= ~(0xff << LCDDATA);      // 输入方式
    LCDDATA_PORT_HIGH |=  (0xff << LCDDATA);      // 处理数据

    SETBIT(LCDRS_PORT_HIGH, LCDRS);               // 选择数据寄存器
    SETBIT(LCDRW_PORT_HIGH, LCDRW);               // 选择为读方式
    DelayNUs(23);                                 // 等待信号稳定   >=2us
    if (par) {                                    //
        SETBIT(LCDE_PORT_HIGH, LCDE);             //
        DelayNUs(16);                             //
        SETBIT(LCDE_PORT_LOW,  LCDE);             //
        DelayNUs(16);                             //
    }
    SETBIT(LCDE_PORT_HIGH, LCDE);                 //
    DelayNUs(16);                                 // 等待信号稳定
    dat          = (INT8U)(LCDDATA_PIN >> LCDDATA);// 读LCM的数据
    SETBIT(LCDE_PORT_LOW, LCDE);                  //

    LCDDATA_DDR |= (0xff << LCDDATA);             // 恢复为输出方式

    return (dat);
}
#endif


/********************************************************************************************************
* 功 能 : 向LCM数据寄存器写一字节数据
* 入 口 : 'dat'  是当前要写入的命令
* 返 回 : 无
* 说 明 :1> 如果送到数据端口的数据跟实际需要送出的数据不一样 表示LCM可能出问题或着有共享的I/O被利用了
*           则需要等待其他的释放共享的I/O 来保证数据的正确性
*        2> 这里的时序问题 这里再不能做精简了
*        3> 这里的各种延时是在AVR 4MHz环境下测试得到
********************************************************************************************************/
#if DISP_GRH_EN > 0 || DISP_TXT_EN > 0

static void DispCtrlDataWr (INT8U dat)
{
    LCDDATA_PORT_LOW  = 0xff << LCDDATA;          //
    LCDDATA_PORT_HIGH = dat  << LCDDATA;          //

    SETBIT(LCDRS_PORT_HIGH, LCDRS);               // 选择数据寄存器
    SETBIT(LCDRW_PORT_LOW,  LCDRW);               // 选择写方式
    SETBIT(LCDE_PORT_HIGH,  LCDE);                // LCDE __/--
    DelayNUs(85);                                 // 16US*5 的E线脉冲 经过测试必须>=5  85
    SETBIT(LCDE_PORT_LOW,   LCDE);                //
    DelayNUs(9);                                  // 等待命令执行时间>=74uS
}
#endif


/********************************************************************************************************
* 功 能 : 图形方式全屏填充指定的数据
* 入 口 : 无
* 返 回 : 无
* 说 明 : 1>
********************************************************************************************************/
#if DISP_GRH_EN > 0

void DispGrhAllFill (INT8U dat)
{
    BOOL  bCS = 0;
    INT8U x;
    INT8U y;
    INT8U ex;
    INT8U bx;


    DispLock();                                   //
    while (1) {
        if (!bCS) {                               // 根据软片选信号选择上半屏还是下半屏
            bx = 0x80;                            //
            ex = 0x80 + 8;                        //
        } else {
            bx = 0x88;                            //
            ex = 0x88 + 8;                        //
        }

        for (y=0x80;  y<(0x80+32); y++) {         // 处理上下各半部分
            for (x=bx; x<ex; x++) {               //
                DispGrhDataWrExt(x, y, (dat<<8)+dat);// 写数据
            }
        }

        if (!bCS) {                               // 上下半部分起始地址选择
            bCS = 1;                              // 切换到下半屏地址
            continue;                             //
        }
        if (bCS) {                                // 已经是下半屏 退出
            break;                                //
        }
    }
    DispUnLock();                                 //
}
#endif


/********************************************************************************************************
* 功 能 : 图形方法显示BCD
* 入 口 : 'x'   显示的X坐标位置  范围0~DispMaxX
*         'y'   显示的Y坐标位置  范围0~DispMaxY
*         'dat' 显示的数据
* 返 回 : 无
* 说 明 : x y 方向大于DISP_GRH_MAX_X 和DISP_GRH_MAX_Y 时 不在显示范围内的部分会自动截掉
********************************************************************************************************/
#if DISP_GRH_EN > 0 && DISP_GRH_BCD_EN > 0

void   DispGrhBCD     (INT8U x0, INT8U y0, INT8U dat, COLORS colors)
{
    DispLock();
    dat %= 100;
    DispGrhChar57(x0,   y0, dat / 10  + '0', colors);
    DispGrhChar57(x0+6, y0, dat % 10  + '0', colors);
    DispUnLock();
}
#endif


/********************************************************************************************************
* 功 能 : 图形方法显示一个字符标准ASCII码 不包含控制字符
* 入 口 : 'x' 显示的X坐标位置  范围0~DispMaxX
*         'y' 显示的Y坐标位置  范围0~DispMaxY
*         'c' 显示的字符
* 返 回 : 无
* 说 明 : x y 方向大于DISP_GRH_MAX_X 和DISP_GRH_MAX_Y 时 不在显示范围内的部分会自动截掉
********************************************************************************************************/
#if DISP_GRH_EN > 0 && (DISP_GRH_CHAR_EN > 0 || DISP_GRH_STR_EN > 0 || DISP_GRH_BCD_EN > 0)

void  DispGrhChar (INT8U x0, INT8U y0, char c, COLORS colors)
{
    DispLock();
    DispGrhChar57(x0, y0, c, colors);
    DispUnLock();
}
#endif


/********************************************************************************************************
* 功 能 : 图形方法显示一个字符标准ASCII码 不包含控制字符
* 入 口 : 'x' 显示的X坐标位置  范围0~DispMaxX
*         'y' 显示的Y坐标位置  范围0~DispMaxY
*         'c' 显示的字符
* 返 回 : 无
* 说 明 : x y 方向大于DISP_GRH_MAX_X 和DISP_GRH_MAX_Y 时 不在显示范围内的部分会自动截掉
********************************************************************************************************/
#if DISP_GRH_EN > 0 && (DISP_GRH_CHAR_EN > 0 || DISP_GRH_STR_EN > 0 || DISP_GRH_BCD_EN > 0)

void  DispGrhCharExt (INT8U x0, INT8U y0, char c, COLORS colors)
{
    INT8U  temph;
    INT8U  templ;
    INT8U  y_offset;
    INT8U  xBak;


    if (x0 < DISP_GRH_MAX_X  && y0 < DISP_GRH_MAX_Y) {
        DispLock();
        xBak  = x0 >> 3;                          // 显示字节内位置 高8BIT跟低8BIT选择
        c    -= 0x20;                             //
        for (y_offset=0; y_offset<8; y_offset++) {//
            DispGrhPosSetCur(x0, y0+y_offset);    // 显示坐标
            DispCtrlCmdWr(DISP_CMD_BASIC);        // 基本命令集
            temph = DispCtrlDataRd(1);            // 数据高字节
            templ = DispCtrlDataRd(0);            // 数据低字节

            if ((xBak % 2) == 0) {                // 处理待显示数据
                //memcpy(&temph, &FONT5x7ASCII[(INT8U)c][y_offset], 1);// 是高字节写数据 取字库数据
                temph = FONT5x7ASCII[(INT8U)c][y_offset];
                if (colors) {                     // 判断颜色
                    temph  = ~temph;              //
                }
            } else {
                //memcpy(&templ, &FONT5x7ASCII[(INT8U)c][y_offset], 1);// 是低字节写数据 取字库数据

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -