找回密码
 立即注册
查看: 55|回复: 2

65-DMA-LCM液晶屏接口测试,STC32G12K128实验箱演示程序,STC32G8K64,STC32CL8K64

[复制链接]
  • 打卡等级:常住居民I
  • 打卡总天数:78
  • 最近打卡:2026-07-21 13:27:09
已绑定手机

231

主题

168

回帖

1069

积分

版主

积分
1069
发表于 2026-6-27 11:31:54 | 显示全部楼层 |阅读模式
65-DMA-LCM液晶屏接口测试,STC32G12K128实验箱演示程序,STC32G8K64,STC32CL8K64
LCM_Test_6800_DMA_8bit_ST7920主程序main.C代码如下(汇编版本在附件中):



/*---------------------------------------------------------------------*/
/* --- Web: www.STCAI.com ---------------------------------------------*/
/* --- BBS: www.STCAIMCU.com  -----------------------------------------*/
/* 如果要在程序中使用此代码,请在程序中注明使用了STC的资料及程序            */
/*---------------------------------------------------------------------*/


/*************  功能说明    **************

本例程基于STC32G为主控芯片的实验箱9.6进行编写测试。

9.6之前实验箱版本,12864模块接口,P4.2与P4.4接口需要进行调换才能使用硬件LCM接口通信.

使用Keil C251编译器,Memory Model推荐设置XSmall模式,默认定义变量在edata,单时钟存取访问速度快。

edata建议保留1K给堆栈使用,空间不够时可将大数组、不常用变量加xdata关键字定义到xdata空间。

LCM接口驱动液晶屏程序

8bit M6800模式, P6口接D0~D7

sbit LCD_RS = P4^5;      //数据/命令切换
sbit LCD_RW = P4^2;      //读写控制
sbit LCD_E = P4^4;       //使能
sbit LCD_RESET = P3^4;   //复位

LCM指令通过中断方式等待发送完成

DMA设置长度16字节,通过中断方式判断传输完成

设置时钟 1.2MHz (128*64屏, ST7920驱动, 速度太快显示会不正常).
(通过USB下载不能自定义时钟,需要使用串口方式下载)

******************************************/

#include "..\..\comm\STC32G.h"
#include "stdio.h"
#include "intrins.h"
#include "LCD_IMG.h"

#define     MAIN_Fosc       1200000L   //定义计算时钟参数

typedef     unsigned char   u8;
typedef     unsigned int    u16;
typedef     unsigned long   u32;

sbit LCD_RS = P4^5;      //数据/命令切换
sbit LCD_RW = P4^2;      //读写控制
sbit LCD_E = P4^4;       //使能
//sbit LCD_PSB = P3^5;     //PSB脚为12864的串、并通讯功能切换,我们使用8位并行接口,PSB=1
sbit LCD_RESET = P3^4;   //复位


//IO连接
#define  LCD_DataPort P6     //8位数据口

#define  USR_LCM_IF     1                        //1: use LCM Interface

u16 index;
bit DmaFlag=0;
bit LcmFlag=0;

u8  code uctech[] = {"南通国芯微电子  "};
u8  code net[]    = {" www.stcmcu.com "};
u8  code mcu[]    = {"专业制造51单片机"};
u8  code qq[]     = {" QQ: 800003751  "};

void delay_ms(u16 ms);
void GPIO_Init(void);
void LCM_Config(void);
void DMA_Config(void);
void LCD_Init(void);
void DisplayImage (u8 *DData);
void DisplayListChar(u8 X, u8 Y, u8 code *DData);
void Write_Cmd(unsigned char WCLCD,unsigned char BuysC);
void Write_Data(unsigned char WDLCD);
void LCDClear(void);

void main(void)
{
//    WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快(本例程需要降低速度才能正常显示)
    EAXFR = 1; //扩展寄存器(XFR)访问使能
    CKCON = 1; //避免 DMA 与 CPU 同时访问 xdata 时产生总线冲突

    P0M1 = 0x30;   P0M0 = 0x30;   //设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
    P1M1 = 0x32;   P1M0 = 0x32;   //设置P1.1、P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V), P1.1在PWM当DAC电路通过电阻串联到P2.3
    P2M1 = 0x3c;   P2M0 = 0x3c;   //设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V),设置开漏模式需要断开PWM当DAC电路中的R2电阻
    P3M1 = 0x50;   P3M0 = 0x50;   //设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
    P4M1 = 0x3c;   P4M0 = 0x3c;   //设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
    P5M1 = 0x0c;   P5M0 = 0x0c;   //设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
    P6M1 = 0xff;   P6M0 = 0xff;   //设置为漏极开路(实验箱加了上拉电阻到3.3V)
    P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口

//        GPIO_Init();
#if USR_LCM_IF == 1       
        LCM_Config();
        DMA_Config();
        EA = 1;
#endif
       
//        delay_ms(100); //启动等待,等LCD进入工作状态
        LCD_Init(); //LCM初始化

        while(1)
        {
                LCDClear();
                DisplayImage(gImage_gxw);
                delay_ms(200);
                LCDClear();
                DisplayListChar(0,1,uctech);    //显示字库中的中文数字
                DisplayListChar(0,2,net);       //显示字库中的中文数字
                DisplayListChar(0,3,mcu);       //显示字库中的中文
                DisplayListChar(0,4,qq);        //显示字库中的中文数字
                delay_ms(200);
        }
}

//按指定位置显示一串字符
void DisplayListChar(u8 X, u8 Y, u8 code *DData)
{
    u8 ListLength,X2;
    ListLength = 0;
    X2 = X;
    if(Y < 1)   Y=1;
    if(Y > 4)   Y=4;
    X &= 0x0F; //限制X不能大于16,Y在1-4之内
    switch(Y)
    {
        case 1: X2 |= 0X80; break;  //根据行数来选择相应地址
        case 2: X2 |= 0X90; break;
        case 3: X2 |= 0X88; break;
        case 4: X2 |= 0X98; break;
    }
    Write_Cmd(X2, 1); //发送地址码
    while (DData[ListLength] >= 0x20) //若到达字串尾则退出
    {
        if (X <= 0x0F) //X坐标应小于0xF
        {
            Write_Data(DData[ListLength]); //
            ListLength++;
            X++;
        }
    }
}

//图形显示122*32
void DisplayImage (u8 *DData)
{
#if USR_LCM_IF == 0
    u8 y;
#endif
    u8 x,i;
    unsigned int tmp=0;
       
    for(i=0;i<9;)       //分两屏,上半屏和下半屏,因为起始地址不同,需要分开
    {
        for(x=0;x<32;x++)   //32行
        {
            Write_Cmd(0x34,1);
            Write_Cmd((u8)(0x80+x),1);    //列地址
            Write_Cmd((u8)(0x80+i),1);    //行地址,下半屏,即第三行地址0X88
            Write_Cmd(0x30,1);
                                       
#if USR_LCM_IF == 1

            DMA_LCM_TXAH = (u8)((u16)&DData[tmp] >> 8);
            DMA_LCM_TXAL = (u8)((u16)&DData[tmp]);
            while(DmaFlag);
            DmaFlag = 1;
            DMA_LCM_CR = 0xa0;        //Write data

#else

            for(y=0;y<16;y++)
                Write_Data(DData[tmp+y]);//读取数据写入LCD

#endif
            tmp+=16;
        }
        i+=8;
    }
    Write_Cmd(0x36,1);    //扩充功能设定
    Write_Cmd(0x30,1);
}

//========================================================================
// 函数: void delay_ms(u16 ms)
// 描述: 延时函数。
// 参数: ms,要延时的ms数, 自动适应主时钟.
// 返回: none.
// 版本: VER1.0
// 日期: 2013-4-1
// 备注:
//========================================================================
void delay_ms(u16 ms)
{
    u16 i;
    do{
        i = MAIN_Fosc / 6000;
        while(--i);
    }while(--ms);
}

#if USR_LCM_IF == 0
void LCD_delay(void)
{
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
}
#endif

//读状态
void ReadStatusLCD(void)
{
#if USR_LCM_IF == 1

    do{
        LcmFlag = 1;
        LCMIFCR = 0x86;                //Enable interface, Read command
        while(LcmFlag);
        LCD_E = 0;
    }while(LCMIFDATL & 0x80);
       
#else
       
        LCD_RS = 0;
        LCD_RW = 1;
        LCD_delay();
        LCD_E = 1;
        LCD_delay();
        while (LCD_DataPort & 0x80); //检测忙信号
        LCD_E = 0;

#endif
}

void Write_Cmd(unsigned char WCLCD,unsigned char BuysC)
{
#if USR_LCM_IF == 1
       
        if (BuysC) ReadStatusLCD(); //根据需要检测忙
        LCMIFDATL = WCLCD;
        LcmFlag = 1;
        LCMIFCR = 0x84;                //Enable interface, write command out
        while(LcmFlag);
       
#else
       
        if (BuysC) ReadStatusLCD(); //根据需要检测忙
        LCD_RS = 0;
        LCD_RW = 0;
        LCD_DataPort = WCLCD;
        LCD_delay();
        LCD_E = 1;
        LCD_delay();
        LCD_E = 0;  
       
#endif
}

void Write_Data(unsigned char WDLCD)
{
#if USR_LCM_IF == 1
       
        LCMIFDATL = WDLCD;
        LcmFlag = 1;
        LCMIFCR = 0x85;                //Enable interface, write data out
        while(LcmFlag);
       
#else
       
        ReadStatusLCD(); //检测忙
        LCD_RS = 1;
        LCD_RW = 0;
        LCD_DataPort = WDLCD;
        LCD_delay();
        LCD_E = 1;
        LCD_delay();
        LCD_E = 0;
       
#endif
}

/*****************************************************************************
* @name       :void GPIO_Init(void)
* @date       :2018-11-13
* @function   :Set the gpio to push-pull mode
* @parameters :None
* @retvalue   :None
******************************************************************************/       
//void GPIO_Init(void)
//{
//        //P6口设置成推挽输出
//        P6M0 |= 0xff;
//        P6M1 &= 0x00;

//        //P3.4口设置成推挽输出
//        P3M0 |= 0x10;
//        P3M1 &= ~0x10;

//        //P4.2,P4.4,P4.5口设置成推挽输出
//        P4M0 |= 0x34;
//        P4M1 &= ~0x34;
//}

#if USR_LCM_IF == 1       
/*****************************************************************************
* @name       :void LCM_Config(void)
* @date       :2018-11-13
* @function   :Config LCM
* @parameters :None
* @retvalue   :None
******************************************************************************/       
void LCM_Config(void)
{
        LCMIFCFG = 0x85;   //bit7 1:Enable Interrupt, bit1 0:8bit mode; bit0 0:8080,1:6800
        LCMIFCFG2 = 0x1f;  //RS:P45,RD:P44,WR:P42; Setup Time,HOLD Time
        LCMIFSTA = 0x00;
}

/*****************************************************************************
* @name       :void DMA_Config(void)
* @date       :2020-12-09
* @function   :Config DMA
* @parameters :None
* @retvalue   :None
******************************************************************************/       
void DMA_Config(void)
{
        DMA_LCM_AMT = 0x0f;                //设置传输总字节数(低8位):n+1
        DMA_LCM_AMTH = 0x00;        //设置传输总字节数(高8位):n+1
        DMA_LCM_TXAH = (u8)((u16)&gImage_gxw >> 8);
        DMA_LCM_TXAL = (u8)((u16)&gImage_gxw);
        DMA_LCM_STA = 0x00;
        DMA_LCM_CFG = 0x82;
        DMA_LCM_CR = 0x80;
}
#endif

/*****************************************************************************
* @name       :void LCDReset(void)
* @date       :2018-08-09
* @function   :Reset LCD screen
* @parameters :None
* @retvalue   :None
******************************************************************************/       
void LCDReset(void)
{
//        LCD_PSB = 1;    //并口
        delay_ms(10);
        LCD_RESET = 0;
        delay_ms(10);
        LCD_RESET = 1;
        delay_ms(100);
}

/*****************************************************************************
* @name       :void LCD_Init(void)
* @date       :2018-08-09
* @function   :Initialization LCD screen
* @parameters :None
* @retvalue   :None
******************************************************************************/                  
void LCD_Init(void)
{
        LCDReset(); //初始化之前复位
//*************LCD 初始化**********//       
        Write_Cmd(0x30,1); //显示模式设置,开始要求每次检测忙信号
        Write_Cmd(0x01,1); //显示清屏
        Write_Cmd(0x06,1); // 显示光标移动设置
        Write_Cmd(0x0C,1); // 显示开及光标设置
}

void LCDClear(void) //清屏
{
        Write_Cmd(0x01,1); //显示清屏
        Write_Cmd(0x34,1); // 显示光标移动设置
        Write_Cmd(0x30,1); // 显示开及光标设置
}

/*****************************************************************************
* @name       :void LCM_Interrupt(void)
* @date       :2018-11-13
* @function   :None
* @parameters :None
* @retvalue   :
******************************************************************************/
void LCMIF_DMA_Interrupt(void) interrupt 13
{
        if(LCMIFSTA & 0x01)
        {
                LCMIFSTA = 0x00;
                LcmFlag = 0;
        }
       
        if(DMA_LCM_STA & 0x01)
        {
                DmaFlag = 0;
                DMA_LCM_CR = 0;
                DMA_LCM_STA = 0;
        }
}






65-DMA-LCM液晶屏接口测试.zip

67.29 KB, 下载次数: 3

回复

使用道具 举报 送花

  • 打卡等级:常住居民I
  • 打卡总天数:78
  • 最近打卡:2026-07-21 13:27:09
已绑定手机

231

主题

168

回帖

1069

积分

版主

积分
1069
发表于 2026-6-27 11:32:45 | 显示全部楼层
65-DMA-LCM液晶屏接口测试,STC32G12K128实验箱演示程序,STC32G8K64,STC32CL8K64
LCM_Test_8080_DMA_8bit_ILI9341主程序main.C代码如下(汇编版本在附件中):


/*---------------------------------------------------------------------*/
/* --- Web: www.STCAI.com ---------------------------------------------*/
/* --- BBS: www.STCAIMCU.com  -----------------------------------------*/
/* 如果要在程序中使用此代码,请在程序中注明使用了STC的资料及程序            */
/*---------------------------------------------------------------------*/


/*************  功能说明    **************

本例程基于STC32G为主控芯片的实验箱进行编写测试。

使用Keil C251编译器,Memory Model推荐设置XSmall模式,默认定义变量在edata,单时钟存取访问速度快。

edata建议保留1K给堆栈使用,空间不够时可将大数组、不常用变量加xdata关键字定义到xdata空间。

LCM接口+DMA驱动液晶屏程序

8bit I8080模式, P6口接D8~D15

sbit LCD_RS = P4^5;      //数据/命令切换
sbit LCD_WR = P4^2;      //写控制
sbit LCD_RD = P4^4;      //读控制
sbit LCD_CS = P3^4;      //片选
sbit LCD_RESET = P4^3;   //复位

LCM指令通过中断方式等待发送完成

DMA设置长度256字节,通过中断方式判断传输完成

下载时, 选择时钟 24MHz (用户可自行修改频率).

******************************************/

#include "..\..\comm\STC32G.h"
#include "stdio.h"
#include "intrins.h"
#include "font.h"

#define     MAIN_Fosc       24000000L   //定义主时钟

typedef     unsigned char   u8;
typedef     unsigned int    u16;
typedef     unsigned long   u32;

sbit LCD_RS = P4^5;      //数据/命令切换
sbit LCD_WR = P4^2;      //写控制
sbit LCD_RD = P4^4;      //读控制
sbit LCD_CS = P3^4;      //片选
sbit LCD_RESET = P4^3;   //复位

//IO连接
#define  LCD_DataPort P6     //8位数据口

//支持横竖屏快速定义切换
#define USE_HORIZONTAL            0   //定义液晶屏顺时针旋转方向         0-0度旋转,1-90度旋转,2-180度旋转,3-270度旋转

//画笔颜色
#define WHITE                  0xFFFF
#define BLACK                  0x0000          
#define BLUE             0x001F  
#define BRED             0XF81F
#define GRED             0XFFE0
#define GBLUE            0X07FF
#define RED                    0xF800
#define MAGENTA                0xF81F
#define GREEN                  0x07E0
#define CYAN                   0x7FFF
#define YELLOW                 0xFFE0
#define BROWN            0XBC40 //棕色
#define BRRED            0XFC07 //棕红色
#define GRAY             0X8430 //灰色

#define DARKBLUE               0X01CF        //深蓝色
#define LIGHTBLUE               0X7D7C        //浅蓝色  
#define GRAYBLUE                0X5458 //灰蓝色
#define LIGHTGREEN              0X841F //浅绿色
#define LGRAY            0XC618 //浅灰色(PANNEL),窗体背景色
#define LGRAYBLUE        0XA651 //浅灰蓝色(中间层颜色)
#define LBBLUE           0X2B12 //浅棕蓝色(选择条目的反色)

//定义LCD的尺寸
#define LCD_W 240
#define LCD_H 320

#define DMA_AMT_LEN  2047  //n+1

u16 POINT_COLOR=0x0000;        //画笔颜色

u16 index;
//u16 xdata Buffer[8]={0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88};
u16 xdata Color[DMA_AMT_LEN+1];
bit DmaFlag;
bit LcmFlag;

typedef struct  
{                                                                                    
        u16 width;                        //LCD 宽度
        u16 height;                        //LCD 高度
        u16 id;                                //LCD ID
        u8  dir;                        //横屏还是竖屏控制:0,竖屏;1,横屏。       
        u8 wramcmd;                //开始写gram指令
        u8 rramcmd;   //开始读gram指令
        u8 setxcmd;                //设置x坐标指令
        u8 setycmd;                //设置y坐标指令         
}_lcd_dev;        

_lcd_dev lcddev;

void delay_ms(u16 ms);
void GPIO_Init(void);
void LCM_Config(void);
void DMA_Config(void);
void LCD_Init(void);
void Test_Color(void);
void LCD_WR_DATA_16Bit(u16 Data);
void LCD_SetWindows(u16 xStar, u16 yStar,u16 xEnd,u16 yEnd);
void Show_Str(u16 x, u16 y, u16 fc, u16 bc, u8 *str,u8 size,u8 mode);
void LCD_direction(u8 direction);

void main(void)
{
    WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    EAXFR = 1; //扩展寄存器(XFR)访问使能
    CKCON = 1; //避免 DMA 与 CPU 同时访问 xdata 时产生总线冲突

    P0M1 = 0x30;   P0M0 = 0x30;   //设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
    P1M1 = 0x32;   P1M0 = 0x32;   //设置P1.1、P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V), P1.1在PWM当DAC电路通过电阻串联到P2.3
    P2M1 = 0x3c;   P2M0 = 0x3c;   //设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V),设置开漏模式需要断开PWM当DAC电路中的R2电阻
    P3M1 = 0x50;   P3M0 = 0x50;   //设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
    P4M1 = 0x3c;   P4M0 = 0x3c;   //设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
    P5M1 = 0x0c;   P5M0 = 0x0c;   //设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
    P6M1 = 0xff;   P6M0 = 0xff;   //设置为漏极开路(实验箱加了上拉电阻到3.3V)
    P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口

        GPIO_Init();
        LCM_Config();
        DMA_Config();
        EA = 1;
       
        LCD_Init(); //LCM初始化

        while(1)
        {
                Test_Color();
        }
}

void LCD_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u16 color)
{         
        u16 i,j;                       
        u16 width=ex-sx+1;                 //得到填充的宽度
        u16 height=ey-sy+1;                //高度
        LCD_SetWindows(sx,sy,ex,ey);//设置显示窗口

        for(j=0,i=0;i<=DMA_AMT_LEN;i++)
        {
                Color = color;
        }
        index = 75;     //(320 * 240 * 2) / 2048 = 75
        LCD_CS=0;
        DMA_LCM_CR = 0xa0;        //Write dat
        while(!LCD_CS);
}

void Test_Color(void)
{
        u8 buf[10] = {0};

        LCD_Fill(0,0,lcddev.width,lcddev.height,WHITE);
        Show_Str(20,30,BLUE,YELLOW,"LCM Test",16,1);delay_ms(800);
        LCD_Fill(0,0,lcddev.width,lcddev.height,RED);
        Show_Str(20,30,BLUE,YELLOW,"RED ",16,1);delay_ms(800);
        LCD_Fill(0,0,lcddev.width,lcddev.height,GREEN);
        Show_Str(20,30,BLUE,YELLOW,"GREEN ",16,1);delay_ms(800);
        LCD_Fill(0,0,lcddev.width,lcddev.height,BLUE);
        Show_Str(20,30,RED,YELLOW,"BLUE ",16,1);delay_ms(800);
}

//========================================================================
// 函数: void delay_ms(u16 ms)
// 描述: 延时函数。
// 参数: ms,要延时的ms数, 自动适应主时钟.
// 返回: none.
// 版本: VER1.0
// 日期: 2013-4-1
// 备注:
//========================================================================
void delay_ms(u16 ms)
{
    u16 i;
    do{
        i = MAIN_Fosc / 6000;
        while(--i);
    }while(--ms);
}

/*****************************************************************************
* @name       :void LCD_WR_REG(u8 Reg)       
* @date       :2018-08-09
* @function   :Write an 16-bit command to the LCD screen
* @parameters :data:Command value to be written
* @retvalue   :None
******************************************************************************/
void LCD_WR_REG(u8 Reg)         
{
        LCMIFDATL = Reg;
        LCD_CS=0;
        LCMIFCR = 0x84;                //Enable interface, write command out
        while(LcmFlag);
        LCD_CS = 1 ;
}

/*****************************************************************************
* @name       :void LCD_WR_DATA(u8 Data)
* @date       :2018-08-09
* @function   :Write an 16-bit data to the LCD screen
* @parameters :data:data value to be written
* @retvalue   :None
******************************************************************************/
void LCD_WR_DATA(u8 Data)
{
        LCMIFDATL = Data;
        LCD_CS=0;
        LCMIFCR = 0x85;                //Enable interface, write data out
        while(LcmFlag);
        LCD_CS = 1 ;
}

/*****************************************************************************
* @name       :void LCD_WR_DATA_16Bit(u16 Data)
* @date       :2018-08-09
* @function   :Write an 16-bit command to the LCD screen
* @parameters :Data:Data to be written
* @retvalue   :None
******************************************************************************/         
void LCD_WR_DATA_16Bit(u16 Data)
{
        LCD_WR_DATA((u8)(Data>>8));
        LCD_WR_DATA((u8)Data);
}

/*****************************************************************************
* @name       :void LCD_WriteReg(u8 LCD_Reg, u8 LCD_RegValue)
* @date       :2018-08-09
* @function   :Write data into registers
* @parameters :LCD_Reg:Register address
                LCD_RegValue:Data to be written
* @retvalue   :None
******************************************************************************/
void LCD_WriteReg(u8 LCD_Reg, u8 LCD_RegValue)
{
    LCD_WR_REG(LCD_Reg);
    LCD_WR_DATA(LCD_RegValue);
}

/*****************************************************************************
* @name       :void LCD_WriteRAM_Prepare(void)
* @date       :2018-08-09
* @function   :Write GRAM
* @parameters :None
* @retvalue   :None
******************************************************************************/       
void LCD_WriteRAM_Prepare(void)
{
        LCD_WR_REG(lcddev.wramcmd);          
}

/*****************************************************************************
* @name       :void LCD_DrawPoint(u16 x,u16 y)
* @date       :2018-08-09
* @function   :Write a pixel data at a specified location
* @parameters :x:the x coordinate of the pixel
                y:the y coordinate of the pixel
* @retvalue   :None
******************************************************************************/       
void LCD_DrawPoint(u16 x,u16 y)
{
        LCD_SetWindows(x,y,x,y);//设置光标位置
        LCD_WR_DATA_16Bit(POINT_COLOR);             
}          

/*****************************************************************************
* @name       :void GPIO_Init(void)
* @date       :2018-11-13
* @function   :Set the gpio to push-pull mode
* @parameters :None
* @retvalue   :None
******************************************************************************/       
void GPIO_Init(void)
{
        //P6口设置成推挽输出
        P6M0 |= 0xff;
        P6M1 &= 0x00;

        //P3.4口设置成推挽输出
        P3M0 |= 0x10;
        P3M1 &= ~0x10;

        //P4.2,P4.3,P4.4,P4.5口设置成推挽输出
        P4M0 |= 0x3c;
        P4M1 &= ~0x3c;
}

/*****************************************************************************
* @name       :void LCM_Config(void)
* @date       :2018-11-13
* @function   :Config LCM
* @parameters :None
* @retvalue   :None
******************************************************************************/       
void LCM_Config(void)
{
        LCMIFCFG = 0x84;        //bit7 1:Enable Interrupt, bit1 0:8bit mode; bit0 0:8080,1:6800
        LCMIFCFG2 = 0x09;        //RS:P45,RD:P44,WR:P42; Setup Time=2,HOLD Time=1
        LCMIFSTA = 0x00;
}

/*****************************************************************************
* @name       :void DMA_Config(void)
* @date       :2020-12-09
* @function   :Config DMA
* @parameters :None
* @retvalue   :None
******************************************************************************/       
void DMA_Config(void)
{
        DMA_LCM_AMT = (u8)DMA_AMT_LEN;                                //设置传输总字节数(低8位):n+1
        DMA_LCM_AMTH = (u8)(DMA_AMT_LEN>>8);        //设置传输总字节数(高8位):n+1
        DMA_LCM_TXAH = (u8)((u16)&Color >> 8);
        DMA_LCM_TXAL = (u8)((u16)&Color);
//        DMA_LCM_RXAH = (u8)((u16)&Buffer >> 8);
//        DMA_LCM_RXAL = (u8)((u16)&Buffer);
        DMA_LCM_STA = 0x00;
        DMA_LCM_CFG = 0x82;
        DMA_LCM_CR = 0x00;
}

/*****************************************************************************
* @name       :void LCDReset(void)
* @date       :2018-08-09
* @function   :Reset LCD screen
* @parameters :None
* @retvalue   :None
******************************************************************************/       
void LCDReset(void)
{
        LCD_CS=1;
        delay_ms(50);       
        LCD_RESET=0;
        delay_ms(150);
        LCD_RESET=1;
        delay_ms(50);
}

/*****************************************************************************
* @name       :void LCD_Init(void)
* @date       :2018-08-09
* @function   :Initialization LCD screen
* @parameters :None
* @retvalue   :None
******************************************************************************/                  
void LCD_Init(void)
{
        LCDReset(); //初始化之前复位
//        delay_ms(150);                     //根据不同晶振速度可以调整延时,保障稳定显示

//*************2.4inch ILI9341初始化**********//       
        LCD_WR_REG(0xCF);  
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0xD9); //0xC1
        LCD_WR_DATA(0X30);
        LCD_WR_REG(0xED);  
        LCD_WR_DATA(0x64);
        LCD_WR_DATA(0x03);
        LCD_WR_DATA(0X12);
        LCD_WR_DATA(0X81);
        LCD_WR_REG(0xE8);  
        LCD_WR_DATA(0x85);
        LCD_WR_DATA(0x10);
        LCD_WR_DATA(0x7A);
        LCD_WR_REG(0xCB);  
        LCD_WR_DATA(0x39);
        LCD_WR_DATA(0x2C);
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0x34);
        LCD_WR_DATA(0x02);
        LCD_WR_REG(0xF7);  
        LCD_WR_DATA(0x20);
        LCD_WR_REG(0xEA);  
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0x00);
        LCD_WR_REG(0xC0);    //Power control
        LCD_WR_DATA(0x1B);   //VRH[5:0]
        LCD_WR_REG(0xC1);    //Power control
        LCD_WR_DATA(0x12);   //SAP[2:0];BT[3:0] 0x01
        LCD_WR_REG(0xC5);    //VCM control
        LCD_WR_DATA(0x08);          //30
        LCD_WR_DATA(0x26);          //30
        LCD_WR_REG(0xC7);    //VCM control2
        LCD_WR_DATA(0XB7);
        LCD_WR_REG(0x36);    // Memory Access Control
        LCD_WR_DATA(0x08);
        LCD_WR_REG(0x3A);   
        LCD_WR_DATA(0x55);
        LCD_WR_REG(0xB1);   
        LCD_WR_DATA(0x00);   
        LCD_WR_DATA(0x1A);
        LCD_WR_REG(0xB6);    // Display Function Control
        LCD_WR_DATA(0x0A);
        LCD_WR_DATA(0xA2);
        LCD_WR_REG(0xF2);    // 3Gamma Function Disable
        LCD_WR_DATA(0x00);
        LCD_WR_REG(0x26);    //Gamma curve selected
        LCD_WR_DATA(0x01);
        LCD_WR_REG(0xE0);    //Set Gamma
        LCD_WR_DATA(0x0F);
        LCD_WR_DATA(0x1D);
        LCD_WR_DATA(0x1A);
        LCD_WR_DATA(0x0A);
        LCD_WR_DATA(0x0D);
        LCD_WR_DATA(0x07);
        LCD_WR_DATA(0x49);
        LCD_WR_DATA(0X66);
        LCD_WR_DATA(0x3B);
        LCD_WR_DATA(0x07);
        LCD_WR_DATA(0x11);
        LCD_WR_DATA(0x01);
        LCD_WR_DATA(0x09);
        LCD_WR_DATA(0x05);
        LCD_WR_DATA(0x04);                  
        LCD_WR_REG(0XE1);    //Set Gamma
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0x18);
        LCD_WR_DATA(0x1D);
        LCD_WR_DATA(0x02);
        LCD_WR_DATA(0x0F);
        LCD_WR_DATA(0x04);
        LCD_WR_DATA(0x36);
        LCD_WR_DATA(0x13);
        LCD_WR_DATA(0x4C);
        LCD_WR_DATA(0x07);
        LCD_WR_DATA(0x13);
        LCD_WR_DATA(0x0F);
        LCD_WR_DATA(0x2E);
        LCD_WR_DATA(0x2F);
        LCD_WR_DATA(0x05);
        LCD_WR_REG(0x2B);
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0x01);
        LCD_WR_DATA(0x3f);
        LCD_WR_REG(0x2A);
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0xef);         
        LCD_WR_REG(0x11); //Exit Sleep
        delay_ms(120);
        LCD_WR_REG(0x29); //display on       

        //设置LCD属性参数
        LCD_direction(USE_HORIZONTAL);//设置LCD显示方向
}

/*****************************************************************************
* @name       :void LCD_SetWindows(u16 xStar, u16 yStar,u16 xEnd,u16 yEnd)
* @date       :2018-08-09
* @function   :Setting LCD display window
* @parameters :xStar:the bebinning x coordinate of the LCD display window
                                                                yStar:the bebinning y coordinate of the LCD display window
                                                                xEnd:the endning x coordinate of the LCD display window
                                                                yEnd:the endning y coordinate of the LCD display window
* @retvalue   :None
******************************************************************************/
void LCD_SetWindows(u16 xStar, u16 yStar,u16 xEnd,u16 yEnd)
{       
        LCD_WR_REG(lcddev.setxcmd);       
        LCD_WR_DATA((u8)(xStar>>8));
        LCD_WR_DATA((u8)(0x00FF&xStar));               
        LCD_WR_DATA((u8)(xEnd>>8));
        LCD_WR_DATA((u8)(0x00FF&xEnd));

        LCD_WR_REG(lcddev.setycmd);       
        LCD_WR_DATA((u8)(yStar>>8));
        LCD_WR_DATA((u8)(0x00FF&yStar));               
        LCD_WR_DATA((u8)(yEnd>>8));
        LCD_WR_DATA((u8)(0x00FF&yEnd));       

        LCD_WriteRAM_Prepare();        //开始写入GRAM                               
}   

/*****************************************************************************
* @name       :void LCD_direction(u8 direction)
* @date       :2018-08-09
* @function   :Setting the display direction of LCD screen
* @parameters :direction:0-0 degree
                          1-90 degree
                                                                                                        2-180 degree
                                                                                                        3-270 degree
* @retvalue   :None
******************************************************************************/
void LCD_direction(u8 direction)
{
    lcddev.setxcmd=0x2A;
    lcddev.setycmd=0x2B;
    lcddev.wramcmd=0x2C;
    lcddev.rramcmd=0x2E;
        switch(direction){                  
                case 0:                                                                         
                        lcddev.width=LCD_W;
                        lcddev.height=LCD_H;               
                        LCD_WriteReg(0x36,(1<<3));
                break;
                case 1:
                        lcddev.width=LCD_H;
                        lcddev.height=LCD_W;
                        LCD_WriteReg(0x36,(1<<3)|(1<<7)|(1<<5)|(1<<4));
                break;
                case 2:                                                                         
                        lcddev.width=LCD_W;
                        lcddev.height=LCD_H;       
                        LCD_WriteReg(0x36,(1<<3)|(1<<4)|(1<<6)|(1<<7));
                break;
                case 3:
                        lcddev.width=LCD_H;
                        lcddev.height=LCD_W;
                        LCD_WriteReg(0x36,(1<<3)|(1<<5)|(1<<6));
                break;       
                default:break;
        }               
       
}         

/*****************************************************************************
* @name       :void LCD_ShowChar(u16 x,u16 y,u16 fc, u16 bc, u8 num,u8 size,u8 mode)
* @date       :2018-08-09
* @function   :Display a single English character
* @parameters :x:the beginning x coordinate of the Character display position
                y:the beginning y coordinate of the Character display position
                                                                fc:the color value of display character
                                                                bc:the background color of display character
                                                                num:the ascii code of display character(0~94)
                                                                size:the size of display character
                                                                mode:0-no overlying,1-overlying
* @retvalue   :None
******************************************************************************/
void LCD_ShowChar(u16 x,u16 y,u16 fc, u16 bc, u8 num,u8 size,u8 mode)
{  
        u8 temp;
        u8 pos,t;
        u16 colortemp=POINT_COLOR;      

        num=num-' ';//得到偏移后的值
        LCD_SetWindows(x,y,x+size/2-1,y+size-1);//设置单个文字显示窗口
        if(!mode) //非叠加方式
        {
                for(pos=0;pos<size;pos++)
                {
                        if(size==12)temp=asc2_1206[num][pos];//调用1206字体
                        else temp=asc2_1608[num][pos];                 //调用1608字体
                        for(t=0;t<size/2;t++)
                    {                 
                        if(temp&0x01)LCD_WR_DATA_16Bit(fc);
                                else LCD_WR_DATA_16Bit(bc);
                                temp>>=1;
                               
                    }
                }       
        }
    else//叠加方式
        {
                for(pos=0;pos<size;pos++)
                {
                        if(size==12)temp=asc2_1206[num][pos];//调用1206字体
                        else temp=asc2_1608[num][pos];                 //调用1608字体
                        for(t=0;t<size/2;t++)
                    {   
                                POINT_COLOR=fc;              
                        if(temp&0x01)LCD_DrawPoint(x+t,y+pos);//画一个点   
                        temp>>=1;
                    }
                }
        }
        POINT_COLOR=colortemp;       
        LCD_SetWindows(0,0,lcddev.width-1,lcddev.height-1);//恢复窗口为全屏                                  
}

/*****************************************************************************
* @name       :void Show_Str(u16 x, u16 y, u16 fc, u16 bc, u8 *str,u8 size,u8 mode)
* @date       :2018-08-09
* @function   :Display Chinese and English strings
* @parameters :x:the beginning x coordinate of the Chinese and English strings
                y:the beginning y coordinate of the Chinese and English strings
                                                                fc:the color value of Chinese and English strings
                                                                bc:the background color of Chinese and English strings
                                                                str:the start address of the Chinese and English strings
                                                                size:the size of Chinese and English strings
                                                                mode:0-no overlying,1-overlying
* @retvalue   :None
******************************************************************************/                             
void Show_Str(u16 x, u16 y, u16 fc, u16 bc, u8 *str,u8 size,u8 mode)
{                                       
        u16 x0=x;                                                                    
        u8 bHz=0;     //字符或者中文
        while(*str!=0)//数据未结束
        {
                if(!bHz)
                {
                        if(x>(lcddev.width-size/2)||y>(lcddev.height-size))
                        return;
                        if(*str>0x80)        bHz=1;//中文
                        else              //字符
                        {
                                if(*str==0x0D)//换行符号
                                {
                                        y+=size;
                                        x=x0;
                                        str++;
                                }
                                else
                                {
                                        if(size>16)//字库中没有集成12X24 16X32的英文字体,用8X16代替
                                        {  
                                                LCD_ShowChar(x,y,fc,bc,*str,16,mode);
                                                x+=8; //字符,为全字的一半
                                        }
                                        else
                                        {
                                                LCD_ShowChar(x,y,fc,bc,*str,size,mode);
                                                x+=size/2; //字符,为全字的一半
                                        }
                                }
                                str++;
                        }
                }
                else//中文
                {
//                        if(x>(lcddev.width-size)||y>(lcddev.height-size))
//                        return;
//                        bHz=0;//有汉字库
//                        if(size==32)
//                        GUI_DrawFont32(x,y,fc,bc,str,mode);
//                        else if(size==24)
//                        GUI_DrawFont24(x,y,fc,bc,str,mode);
//                        else
//                        GUI_DrawFont16(x,y,fc,bc,str,mode);

                        str+=2;
                        x+=size;//下一个汉字偏移
                }
        }
}

/*****************************************************************************
* @name       :void LCM_Interrupt(void)
* @date       :2018-11-13
* @function   :None
* @parameters :None
* @retvalue   :
******************************************************************************/
void LCMIF_DMA_Interrupt(void) interrupt 13
{
        if(LCMIFSTA & 0x01)
        {
                LCMIFSTA = 0x00;
                LcmFlag = 0;
        }
       
        if(DMA_LCM_STA & 0x01)
        {
                if(DmaFlag)
                {
                        DmaFlag = 0;
                        DMA_LCM_CR = 0;
                }
                else
                {
                        index--;
                        if(index == 0)
                        {
                                DMA_LCM_CR = 0;
                                LCD_CS=1;
                        }
                        else
                        {
                                DMA_LCM_CR = 0xa0;        //Write dat
                        }
                }
                DMA_LCM_STA = 0;
        }
}


65-DMA-LCM液晶屏接口测试.zip

67.29 KB, 下载次数: 3

回复

使用道具 举报 送花

  • 打卡等级:常住居民I
  • 打卡总天数:78
  • 最近打卡:2026-07-21 13:27:09
已绑定手机

231

主题

168

回帖

1069

积分

版主

积分
1069
发表于 2026-6-27 11:33:41 | 显示全部楼层
65-DMA-LCM液晶屏接口测试,STC32G12K128实验箱演示程序,STC32G8K64,STC32CL8K64
LCM_Test_8080_LCM_8bit_ILI9341主程序main.C代码如下(汇编版本在附件中):



/*---------------------------------------------------------------------*/
/* --- Web: www.STCAI.com ---------------------------------------------*/
/* --- BBS: www.STCAIMCU.com  -----------------------------------------*/
/* 如果要在程序中使用此代码,请在程序中注明使用了STC的资料及程序            */
/*---------------------------------------------------------------------*/


/*************  功能说明    **************

本例程基于STC32G为主控芯片的实验箱进行编写测试。

使用Keil C251编译器,Memory Model推荐设置XSmall模式,默认定义变量在edata,单时钟存取访问速度快。

edata建议保留1K给堆栈使用,空间不够时可将大数组、不常用变量加xdata关键字定义到xdata空间。

LCM接口+DMA驱动液晶屏程序

8bit I8080模式, P6口接D8~D15

sbit LCD_RS = P4^5;      //数据/命令切换
sbit LCD_WR = P4^2;      //写控制
sbit LCD_RD = P4^4;      //读控制
sbit LCD_CS = P3^4;      //片选
sbit LCD_RESET = P4^3;   //复位

LCM指令通过中断方式等待发送完成

DMA设置长度256字节,通过中断方式判断传输完成

下载时, 选择时钟 24MHz (用户可自行修改频率).

******************************************/

#include "..\..\comm\STC32G.h"
#include "stdio.h"
#include "intrins.h"
#include "font.h"

#define     MAIN_Fosc       24000000L   //定义主时钟

typedef     unsigned char   u8;
typedef     unsigned int    u16;
typedef     unsigned long   u32;

sbit LCD_RS = P4^5;      //数据/命令切换
sbit LCD_WR = P4^2;      //写控制
sbit LCD_RD = P4^4;      //读控制
sbit LCD_CS = P3^4;      //片选
sbit LCD_RESET = P4^3;   //复位

//IO连接
#define  LCD_DataPort P6     //8位数据口

//支持横竖屏快速定义切换
#define USE_HORIZONTAL            0   //定义液晶屏顺时针旋转方向         0-0度旋转,1-90度旋转,2-180度旋转,3-270度旋转

//画笔颜色
#define WHITE                  0xFFFF
#define BLACK                  0x0000          
#define BLUE             0x001F  
#define BRED             0XF81F
#define GRED             0XFFE0
#define GBLUE            0X07FF
#define RED                    0xF800
#define MAGENTA                0xF81F
#define GREEN                  0x07E0
#define CYAN                   0x7FFF
#define YELLOW                 0xFFE0
#define BROWN            0XBC40 //棕色
#define BRRED            0XFC07 //棕红色
#define GRAY             0X8430 //灰色

#define DARKBLUE               0X01CF        //深蓝色
#define LIGHTBLUE               0X7D7C        //浅蓝色  
#define GRAYBLUE                0X5458 //灰蓝色
#define LIGHTGREEN              0X841F //浅绿色
#define LGRAY            0XC618 //浅灰色(PANNEL),窗体背景色
#define LGRAYBLUE        0XA651 //浅灰蓝色(中间层颜色)
#define LBBLUE           0X2B12 //浅棕蓝色(选择条目的反色)

//定义LCD的尺寸
#define LCD_W 240
#define LCD_H 320

u16 POINT_COLOR=0x0000;        //画笔颜色

typedef struct  
{                                                                                    
        u16 width;                        //LCD 宽度
        u16 height;                        //LCD 高度
        u16 id;                                //LCD ID
        u8  dir;                        //横屏还是竖屏控制:0,竖屏;1,横屏。       
        u8 wramcmd;                //开始写gram指令
        u8 rramcmd;   //开始读gram指令
        u8 setxcmd;                //设置x坐标指令
        u8 setycmd;                //设置y坐标指令         
}_lcd_dev;        

_lcd_dev lcddev;

void delay_ms(u16 ms);
void GPIO_Init(void);
void LCM_Config(void);
void LCD_Init(void);
void Test_Color(void);
void LCD_WR_DATA_16Bit(u16 Data);
void LCD_SetWindows(u16 xStar, u16 yStar,u16 xEnd,u16 yEnd);
void Show_Str(u16 x, u16 y, u16 fc, u16 bc, u8 *str,u8 size,u8 mode);
void LCD_direction(u8 direction);

void main(void)
{
    WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    EAXFR = 1; //扩展寄存器(XFR)访问使能
    CKCON = 0; //提高访问XRAM速度

    P0M1 = 0x30;   P0M0 = 0x30;   //设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
    P1M1 = 0x32;   P1M0 = 0x32;   //设置P1.1、P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V), P1.1在PWM当DAC电路通过电阻串联到P2.3
    P2M1 = 0x3c;   P2M0 = 0x3c;   //设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V),设置开漏模式需要断开PWM当DAC电路中的R2电阻
    P3M1 = 0x50;   P3M0 = 0x50;   //设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
    P4M1 = 0x3c;   P4M0 = 0x3c;   //设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
    P5M1 = 0x0c;   P5M0 = 0x0c;   //设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
    P6M1 = 0xff;   P6M0 = 0xff;   //设置为漏极开路(实验箱加了上拉电阻到3.3V)
    P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口

        GPIO_Init();
        LCM_Config();
        EA = 1;
       
        LCD_Init(); //LCM初始化

        while(1)
        {
                Test_Color();
        }
}

void LCD_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u16 color)
{         
        u16 i,j;                       
        u16 width=ex-sx+1;                 //得到填充的宽度
        u16 height=ey-sy+1;                //高度
        LCD_SetWindows(sx,sy,ex,ey);//设置显示窗口

        for(i=0;i<height;i++)
        {
                for(j=0;j<width;j++)
                LCD_WR_DATA_16Bit(color);        //写入数据          
        }
}

void Test_Color(void)
{
        u8 buf[10] = {0};

        LCD_Fill(0,0,lcddev.width,lcddev.height,WHITE);
        Show_Str(20,30,BLUE,YELLOW,"LCM Test",16,1);delay_ms(800);
        LCD_Fill(0,0,lcddev.width,lcddev.height,RED);
        Show_Str(20,30,BLUE,YELLOW,"RED ",16,1);delay_ms(800);
        LCD_Fill(0,0,lcddev.width,lcddev.height,GREEN);
        Show_Str(20,30,BLUE,YELLOW,"GREEN ",16,1);delay_ms(800);
        LCD_Fill(0,0,lcddev.width,lcddev.height,BLUE);
        Show_Str(20,30,RED,YELLOW,"BLUE ",16,1);delay_ms(800);
}

//========================================================================
// 函数: void delay_ms(u16 ms)
// 描述: 延时函数。
// 参数: ms,要延时的ms数, 自动适应主时钟.
// 返回: none.
// 版本: VER1.0
// 日期: 2013-4-1
// 备注:
//========================================================================
void delay_ms(u16 ms)
{
    u16 i;
    do{
        i = MAIN_Fosc / 6000;
        while(--i);
    }while(--ms);
}

/*****************************************************************************
* @name       :void LCD_WR_REG(u8 Reg)       
* @date       :2018-08-09
* @function   :Write an 16-bit command to the LCD screen
* @parameters :data:Command value to be written
* @retvalue   :None
******************************************************************************/
void LCD_WR_REG(u8 Reg)         
{
        LCMIFDATL = Reg;
        LCD_CS=0;
        LCMIFCR = 0x84;                //Enable interface, write command out
        while(!LCD_CS);
}

/*****************************************************************************
* @name       :void LCD_WR_DATA(u8 Data)
* @date       :2018-08-09
* @function   :Write an 16-bit data to the LCD screen
* @parameters :data:data value to be written
* @retvalue   :None
******************************************************************************/
void LCD_WR_DATA(u8 Data)
{
        LCMIFDATL = Data;
        LCD_CS=0;
        LCMIFCR = 0x85;                //Enable interface, write data out
        while(!LCD_CS);
}

/*****************************************************************************
* @name       :void LCD_WR_DATA_16Bit(u16 Data)
* @date       :2018-08-09
* @function   :Write an 16-bit command to the LCD screen
* @parameters :Data:Data to be written
* @retvalue   :None
******************************************************************************/         
void LCD_WR_DATA_16Bit(u16 Data)
{
        LCD_WR_DATA((u8)(Data>>8));
        LCD_WR_DATA((u8)Data);
}

/*****************************************************************************
* @name       :void LCD_WriteReg(u8 LCD_Reg, u8 LCD_RegValue)
* @date       :2018-08-09
* @function   :Write data into registers
* @parameters :LCD_Reg:Register address
                LCD_RegValue:Data to be written
* @retvalue   :None
******************************************************************************/
void LCD_WriteReg(u8 LCD_Reg, u8 LCD_RegValue)
{
    LCD_WR_REG(LCD_Reg);
    LCD_WR_DATA(LCD_RegValue);
}

/*****************************************************************************
* @name       :void LCD_WriteRAM_Prepare(void)
* @date       :2018-08-09
* @function   :Write GRAM
* @parameters :None
* @retvalue   :None
******************************************************************************/       
void LCD_WriteRAM_Prepare(void)
{
        LCD_WR_REG(lcddev.wramcmd);          
}

/*****************************************************************************
* @name       :void LCD_DrawPoint(u16 x,u16 y)
* @date       :2018-08-09
* @function   :Write a pixel data at a specified location
* @parameters :x:the x coordinate of the pixel
                y:the y coordinate of the pixel
* @retvalue   :None
******************************************************************************/       
void LCD_DrawPoint(u16 x,u16 y)
{
        LCD_SetWindows(x,y,x,y);//设置光标位置
        LCD_WR_DATA_16Bit(POINT_COLOR);             
}          

/*****************************************************************************
* @name       :void GPIO_Init(void)
* @date       :2018-11-13
* @function   :Set the gpio to push-pull mode
* @parameters :None
* @retvalue   :None
******************************************************************************/       
void GPIO_Init(void)
{
        //P6口设置成推挽输出
        P6M0 |= 0xff;
        P6M1 &= 0x00;

        //P3.4口设置成推挽输出
        P3M0 |= 0x10;
        P3M1 &= ~0x10;

        //P4.2,P4.3,P4.4,P4.5口设置成推挽输出
        P4M0 |= 0x3c;
        P4M1 &= ~0x3c;
}

/*****************************************************************************
* @name       :void LCM_Config(void)
* @date       :2018-11-13
* @function   :Config LCM
* @parameters :None
* @retvalue   :None
******************************************************************************/       
void LCM_Config(void)
{
        LCMIFCFG = 0x84;        //bit7 1:Enable Interrupt, bit1 0:8bit mode; bit0 0:8080,1:6800
        LCMIFCFG2 = 0x09;        //RS:P45,RD:P44,WR:P42; Setup Time=2,HOLD Time=1
        LCMIFSTA = 0x00;
}

/*****************************************************************************
* @name       :void LCDReset(void)
* @date       :2018-08-09
* @function   :Reset LCD screen
* @parameters :None
* @retvalue   :None
******************************************************************************/       
void LCDReset(void)
{
        LCD_CS=1;
        delay_ms(50);       
        LCD_RESET=0;
        delay_ms(150);
        LCD_RESET=1;
        delay_ms(50);
}

/*****************************************************************************
* @name       :void LCD_Init(void)
* @date       :2018-08-09
* @function   :Initialization LCD screen
* @parameters :None
* @retvalue   :None
******************************************************************************/                  
void LCD_Init(void)
{
        LCDReset(); //初始化之前复位
//        delay_ms(150);                     //根据不同晶振速度可以调整延时,保障稳定显示

//*************2.4inch ILI9341初始化**********//       
        LCD_WR_REG(0xCF);  
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0xD9); //0xC1
        LCD_WR_DATA(0X30);
        LCD_WR_REG(0xED);  
        LCD_WR_DATA(0x64);
        LCD_WR_DATA(0x03);
        LCD_WR_DATA(0X12);
        LCD_WR_DATA(0X81);
        LCD_WR_REG(0xE8);  
        LCD_WR_DATA(0x85);
        LCD_WR_DATA(0x10);
        LCD_WR_DATA(0x7A);
        LCD_WR_REG(0xCB);  
        LCD_WR_DATA(0x39);
        LCD_WR_DATA(0x2C);
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0x34);
        LCD_WR_DATA(0x02);
        LCD_WR_REG(0xF7);  
        LCD_WR_DATA(0x20);
        LCD_WR_REG(0xEA);  
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0x00);
        LCD_WR_REG(0xC0);    //Power control
        LCD_WR_DATA(0x1B);   //VRH[5:0]
        LCD_WR_REG(0xC1);    //Power control
        LCD_WR_DATA(0x12);   //SAP[2:0];BT[3:0] 0x01
        LCD_WR_REG(0xC5);    //VCM control
        LCD_WR_DATA(0x08);          //30
        LCD_WR_DATA(0x26);          //30
        LCD_WR_REG(0xC7);    //VCM control2
        LCD_WR_DATA(0XB7);
        LCD_WR_REG(0x36);    // Memory Access Control
        LCD_WR_DATA(0x08);
        LCD_WR_REG(0x3A);   
        LCD_WR_DATA(0x55);
        LCD_WR_REG(0xB1);   
        LCD_WR_DATA(0x00);   
        LCD_WR_DATA(0x1A);
        LCD_WR_REG(0xB6);    // Display Function Control
        LCD_WR_DATA(0x0A);
        LCD_WR_DATA(0xA2);
        LCD_WR_REG(0xF2);    // 3Gamma Function Disable
        LCD_WR_DATA(0x00);
        LCD_WR_REG(0x26);    //Gamma curve selected
        LCD_WR_DATA(0x01);
        LCD_WR_REG(0xE0);    //Set Gamma
        LCD_WR_DATA(0x0F);
        LCD_WR_DATA(0x1D);
        LCD_WR_DATA(0x1A);
        LCD_WR_DATA(0x0A);
        LCD_WR_DATA(0x0D);
        LCD_WR_DATA(0x07);
        LCD_WR_DATA(0x49);
        LCD_WR_DATA(0X66);
        LCD_WR_DATA(0x3B);
        LCD_WR_DATA(0x07);
        LCD_WR_DATA(0x11);
        LCD_WR_DATA(0x01);
        LCD_WR_DATA(0x09);
        LCD_WR_DATA(0x05);
        LCD_WR_DATA(0x04);                  
        LCD_WR_REG(0XE1);    //Set Gamma
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0x18);
        LCD_WR_DATA(0x1D);
        LCD_WR_DATA(0x02);
        LCD_WR_DATA(0x0F);
        LCD_WR_DATA(0x04);
        LCD_WR_DATA(0x36);
        LCD_WR_DATA(0x13);
        LCD_WR_DATA(0x4C);
        LCD_WR_DATA(0x07);
        LCD_WR_DATA(0x13);
        LCD_WR_DATA(0x0F);
        LCD_WR_DATA(0x2E);
        LCD_WR_DATA(0x2F);
        LCD_WR_DATA(0x05);
        LCD_WR_REG(0x2B);
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0x01);
        LCD_WR_DATA(0x3f);
        LCD_WR_REG(0x2A);
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0xef);         
        LCD_WR_REG(0x11); //Exit Sleep
        delay_ms(120);
        LCD_WR_REG(0x29); //display on       

        //设置LCD属性参数
        LCD_direction(USE_HORIZONTAL);//设置LCD显示方向
}

/*****************************************************************************
* @name       :void LCD_SetWindows(u16 xStar, u16 yStar,u16 xEnd,u16 yEnd)
* @date       :2018-08-09
* @function   :Setting LCD display window
* @parameters :xStar:the bebinning x coordinate of the LCD display window
                                                                yStar:the bebinning y coordinate of the LCD display window
                                                                xEnd:the endning x coordinate of the LCD display window
                                                                yEnd:the endning y coordinate of the LCD display window
* @retvalue   :None
******************************************************************************/
void LCD_SetWindows(u16 xStar, u16 yStar,u16 xEnd,u16 yEnd)
{       
        LCD_WR_REG(lcddev.setxcmd);       
        LCD_WR_DATA((u8)(xStar>>8));
        LCD_WR_DATA((u8)(0x00FF&xStar));               
        LCD_WR_DATA((u8)(xEnd>>8));
        LCD_WR_DATA((u8)(0x00FF&xEnd));

        LCD_WR_REG(lcddev.setycmd);       
        LCD_WR_DATA((u8)(yStar>>8));
        LCD_WR_DATA((u8)(0x00FF&yStar));               
        LCD_WR_DATA((u8)(yEnd>>8));
        LCD_WR_DATA((u8)(0x00FF&yEnd));       

        LCD_WriteRAM_Prepare();        //开始写入GRAM                               
}

/*****************************************************************************
* @name       :void LCD_direction(u8 direction)
* @date       :2018-08-09
* @function   :Setting the display direction of LCD screen
* @parameters :direction:0-0 degree
                          1-90 degree
                                                                                                        2-180 degree
                                                                                                        3-270 degree
* @retvalue   :None
******************************************************************************/
void LCD_direction(u8 direction)
{
    lcddev.setxcmd=0x2A;
    lcddev.setycmd=0x2B;
    lcddev.wramcmd=0x2C;
    lcddev.rramcmd=0x2E;
        switch(direction){                  
                case 0:                                                                         
                        lcddev.width=LCD_W;
                        lcddev.height=LCD_H;               
                        LCD_WriteReg(0x36,(1<<3));
                break;
                case 1:
                        lcddev.width=LCD_H;
                        lcddev.height=LCD_W;
                        LCD_WriteReg(0x36,(1<<3)|(1<<7)|(1<<5)|(1<<4));
                break;
                case 2:                                                                         
                        lcddev.width=LCD_W;
                        lcddev.height=LCD_H;       
                        LCD_WriteReg(0x36,(1<<3)|(1<<4)|(1<<6)|(1<<7));
                break;
                case 3:
                        lcddev.width=LCD_H;
                        lcddev.height=LCD_W;
                        LCD_WriteReg(0x36,(1<<3)|(1<<5)|(1<<6));
                break;       
                default:break;
        }
}

/*****************************************************************************
* @name       :void LCD_ShowChar(u16 x,u16 y,u16 fc, u16 bc, u8 num,u8 size,u8 mode)
* @date       :2018-08-09
* @function   :Display a single English character
* @parameters :x:the beginning x coordinate of the Character display position
                y:the beginning y coordinate of the Character display position
                                                                fc:the color value of display character
                                                                bc:the background color of display character
                                                                num:the ascii code of display character(0~94)
                                                                size:the size of display character
                                                                mode:0-no overlying,1-overlying
* @retvalue   :None
******************************************************************************/
void LCD_ShowChar(u16 x,u16 y,u16 fc, u16 bc, u8 num,u8 size,u8 mode)
{  
        u8 temp;
        u8 pos,t;
        u16 colortemp=POINT_COLOR;      

        num=num-' ';//得到偏移后的值
        LCD_SetWindows(x,y,x+size/2-1,y+size-1);//设置单个文字显示窗口
        if(!mode) //非叠加方式
        {
                for(pos=0;pos<size;pos++)
                {
                        if(size==12)temp=asc2_1206[num][pos];//调用1206字体
                        else temp=asc2_1608[num][pos];                 //调用1608字体
                        for(t=0;t<size/2;t++)
                    {                 
                        if(temp&0x01)LCD_WR_DATA_16Bit(fc);
                                else LCD_WR_DATA_16Bit(bc);
                                temp>>=1;
                               
                    }
                }       
        }else//叠加方式
        {
                for(pos=0;pos<size;pos++)
                {
                        if(size==12)temp=asc2_1206[num][pos];//调用1206字体
                        else temp=asc2_1608[num][pos];                 //调用1608字体
                        for(t=0;t<size/2;t++)
                    {   
                                POINT_COLOR=fc;              
                        if(temp&0x01)LCD_DrawPoint(x+t,y+pos);//画一个点   
                        temp>>=1;
                    }
                }
        }
        POINT_COLOR=colortemp;       
        LCD_SetWindows(0,0,lcddev.width-1,lcddev.height-1);//恢复窗口为全屏                                  
}

/*****************************************************************************
* @name       :void Show_Str(u16 x, u16 y, u16 fc, u16 bc, u8 *str,u8 size,u8 mode)
* @date       :2018-08-09
* @function   :Display Chinese and English strings
* @parameters :x:the beginning x coordinate of the Chinese and English strings
                y:the beginning y coordinate of the Chinese and English strings
                                                                fc:the color value of Chinese and English strings
                                                                bc:the background color of Chinese and English strings
                                                                str:the start address of the Chinese and English strings
                                                                size:the size of Chinese and English strings
                                                                mode:0-no overlying,1-overlying
* @retvalue   :None
******************************************************************************/                             
void Show_Str(u16 x, u16 y, u16 fc, u16 bc, u8 *str,u8 size,u8 mode)
{                                       
        u16 x0=x;                                                                    
        u8 bHz=0;     //字符或者中文
        while(*str!=0)//数据未结束
        {
                if(!bHz)
                {
                        if(x>(lcddev.width-size/2)||y>(lcddev.height-size))
                        return;
                        if(*str>0x80)        bHz=1;//中文
                        else              //字符
                        {
                                if(*str==0x0D)//换行符号
                                {
                                        y+=size;
                                        x=x0;
                                        str++;
                                }
                                else
                                {
                                        if(size>16)//字库中没有集成12X24 16X32的英文字体,用8X16代替
                                        {  
                                                LCD_ShowChar(x,y,fc,bc,*str,16,mode);
                                                x+=8; //字符,为全字的一半
                                        }
                                        else
                                        {
                                                LCD_ShowChar(x,y,fc,bc,*str,size,mode);
                                                x+=size/2; //字符,为全字的一半
                                        }
                                }
                                str++;
                        }
                }
                else//中文
                {
//                        if(x>(lcddev.width-size)||y>(lcddev.height-size))
//                        return;
//                        bHz=0;//有汉字库
//                        if(size==32)
//                        GUI_DrawFont32(x,y,fc,bc,str,mode);
//                        else if(size==24)
//                        GUI_DrawFont24(x,y,fc,bc,str,mode);
//                        else
//                        GUI_DrawFont16(x,y,fc,bc,str,mode);

                        str+=2;
                        x+=size;//下一个汉字偏移
                }
        }
}

/*****************************************************************************
* @name       :void LCM_Interrupt(void)
* @date       :2018-11-13
* @function   :None
* @parameters :None
* @retvalue   :
******************************************************************************/
void LCMIF_DMA_Interrupt(void) interrupt 13
{
        if(LCMIFSTA & 0x01)
        {
                LCMIFSTA = 0x00;
                LCD_CS=1;
        }
}


65-DMA-LCM液晶屏接口测试.zip

67.29 KB, 下载次数: 3

回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-7-22 10:20 , Processed in 0.076480 second(s), 50 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表