找回密码
 立即注册
查看: 57|回复: 1

61-DMA-LCM液晶屏接口测试,STC32G144K246实验箱演示程序

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

231

主题

168

回帖

1069

积分

版主

积分
1069
发表于 2026-7-3 15:32:25 | 显示全部楼层 |阅读模式
61-DMA-LCM液晶屏接口测试,STC32G144K246实验箱演示程序
LCD1602显示程序-硬件M6800并行接口+DMA刷新,主程序main.C代码如下(汇编版本在附件中):


/*---------------------------------------------------------------------*/
/* --- Web: www.STCAI.com ---------------------------------------------*/
/* --- BBS: www.STCAIMCU.com  -----------------------------------------*/
/*---------------------------------------------------------------------*/

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

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

LCM1602字符液晶模块,8位数据,全部由LCM DMA驱动,节省CPU时间(LCD1602用IO方式访问速度很慢!)。

使用3.3V的LCD1602模块。

请先别修改程序, 直接下载"LCD1602.hex"测试.

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

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

#include "..\..\comm\STC32G144K246.h"

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

/****************  用户定义宏  ****************/

#define     MAIN_Fosc        48000000UL    //定义主时钟

/****************  IO口定义  ******************/

sfr     LCD_DATA = 0xa0;    //P0--0x80,  P1--0x90,  P2--0xa0,  P3--0xb0
sbit    LCD_B7  = P2^7;     //Pin 14     B3--Pin 10     LED+ -- Pin 15
                            //Pin 13     B2--Pin 9      LED- -- Pin 16
                            //Pin 12     B1--Pin 8      Vo   -- Pin 3
                            //Pin 11     B0--Pin 7      VDD  -- Pin 2      VSS -- Pin 1

sbit    LCD_ENA = P4^4;     //Pin 6
sbit    LCD_RW  = P4^2;     //Pin 5  //LCD_RS      R/W   DB7--DB0        FOUNCTION
sbit    LCD_RS  = P4^5;     //Pin 4  //    0        0     INPUT      write the command to LCD model
                                     //    0        1     OUTPUT     read BF and AC pointer from LCD model
                                     //    1        0     INPUT      write the data to LCD  model
                                     //    1        1     OUTPUT     read the data from LCD model

/****************  本地常量声明  **************/

const u8  text1[] = {" LCD1602 8-DATA "};
const u8  text2[] = {" STC32G144K246  "};
const u8  text3[] = {"2025-12-25 18:59"};
const u8  text4[] = {" www.STCAI.com  "};

/****************  本地变量声明  **************/

u16 LCM_TxCnt;          //LCM DMA触发发送次数, 一次16字节, 一共64次
bit B_LCM_DMA_busy;     //LCM DMA忙标志, 1标志LCM-DMA忙,LCM DMA中断中清除此标志,使用LCM DMA前要确认此标志为0
bit B_TxCmd;            //已发送命令标志
u8  xdata CmdTmp[2];    //命令缓冲
u8  xdata DisTmp1[16];  //第一行显示缓冲,将要显示的内容放在显存里,启动DMA即可.
u8  xdata DisTmp2[16];  //第二行显示缓冲,将要显示的内容放在显存里,启动DMA即可.

/****************  本地函数声明  **************/


/******************************************************************************
                 HD44780U    LCD_MODUL DRIVE PROGRAMME
*******************************************************************************

total 2 lines, 16x2= 32
first line address:  0~15
second line address: 64~79

total 2 lines, 20x2= 40
first line address:  0~19
second line address: 64~83

total 2 lines, 40x2= 80
first line address:  0~39
second line address: 64~103
*/

#define C_CLEAR            0x01        //clear LCD
#define C_HOME             0x02        //cursor go home
#define C_CUR_L            0x04        //cursor shift left after input
#define C_RIGHT            0x05        //picture shift right after input
#define C_CUR_R            0x06        //cursor shift right after input
#define C_LEFT             0x07        //picture shift left after input
#define C_OFF              0x08        //turn off LCD
#define C_ON               0x0C        //turn on  LCD
#define C_FLASH            0x0D        //turn on  LCD, flash
#define C_CURSOR           0x0E        //turn on  LCD and cursor
#define C_FLASH_ALL        0x0F        //turn on  LCD and cursor, flash
#define C_CURSOR_LEFT      0x10        //single cursor shift left
#define C_CURSOR_RIGHT     0x10        //single cursor shift right
#define C_PICTURE_LEFT     0x10        //single picture shift left
#define C_PICTURE_RIGHT    0x10        //single picture shift right
#define C_BIT8             0x30        //set the data is 8 bits
#define C_BIT4             0x20        //set the data is 8 bits
#define C_L1DOT7           0x30        //8 bits,one line 5*7  dots
#define C_L1DOT10          0x34        //8 bits,one line 5*10 dots
#define C_8bitL2DOT7       0x38        //8 bits,tow lines 5*7 dots
#define C_4bitL2DOT7       0x28        //4 bits,tow lines 5*7 dots
#define C_CGADDRESS0       0x40        //CGRAM address0 (addr=40H+x)
#define C_DDADDRESS0       0x80        //DDRAM address0 (addr=80H+x)

//========================================================================
// 函数: void delay_ms(unsigned int ms)
// 描述: 延时函数。
// 参数: ms,要延时的ms数.
// 返回: none.
// 版本: VER1.0
// 日期: 2025-11-01
// 备注: 由于芯片使能了Cache功能,软件延时时间可能不太准确
//========================================================================
void delay_ms(u16 ms)
{
    u16 i;
    do{
        i = MAIN_Fosc / 6000;
        while(--i);
    }while(--ms);
}

//******************** LCD40 Module END ***************************

//========================================================================
// 函数: void LCM_Config(void)
// 描述: LCM配置函数。ST7920 @540KHz,清屏指令典型时间为1.6ms,读忙信号0us, 写入、读出数据、命令72us. 本例子DMA刷新时间84ms @24MHz.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2024-8-17
// 备注:
//========================================================================
//LCMIFCFG  (7EFE50H)    TFT彩屏接口配置寄存器
#define    LCMIFIE         (0<<7)   //TFT彩屏接口中断使能控制位(bit7), 1->允许中断,0->禁止
#define    LCMIFIP         (0<<4)   //TFT彩屏接口中断优先级控制位(bit5~bit4), (最低)0~3(最高).
#define    LCMIFDPS        (0<<2)   //TFT彩屏接口数据脚选择位(bit3~bit2), D18_D8=0: 0或2->8位数据在P2, D18_D8=1: 0: P2-高字节, P0低字节, 2: P2-高字节,低字节P0[7:4] P4.7 P4.6 P4.3 P4.1.
#define    LCM_D16_D8      (0<<1)   //TFT彩屏接口数据宽度控制位(bit1), 0: 8位数据,1:16位数据
#define    LCM_M68_I80     1        //TFT彩屏接口数据模式选择位(bit0), 0: I8080模式,1:M6800模式

//LCMIFCFG2  (7EFE51H)    TFT彩屏接口配置寄存器2
#define    LCMIFCPS        (0<<5)   //TFT彩屏接口控制脚选择位(bit6~bit5), RS RD(E) WR(RW), 0->P4.5 P4.4 P4.2,1->P4.5 P3.7 P3.6, 2->P4.0 P4.4 P4.2, 3->P4.0 P3.7 P3.6
#define    LCMSETUPT       (4<<2)   //TFT彩屏接口数据建立时间控制位(bit4~bit2), 0~7, 对应1~8个LCMIF时钟, 对于6800模式就是E高电平时间, 至少20us.
#define    LCMHOLDT        3        //TFT彩屏接口数据保持时间控制位(bit1~bit0), 0~3, 对应1~4个LCMIF时钟

//LCMIFCR  (7EFE52H)    TFT彩屏接口控制寄存器
#define    ENLCMIF         (1<<7)   //TFT彩屏接口使能控制位(bit7), 1->允许TFT彩屏接口功能, 0->禁止
#define    LCM_WRCMD       4        //TFT彩屏接口触发命令(bit2~bit0), 4->写命令
#define    LCM_WRDAT       5        //TFT彩屏接口触发命令(bit2~bit0), 5->写数据
#define    LCM_RDCMD       6        //TFT彩屏接口触发命令(bit2~bit0), 6->读命令/状态
#define    LCM_RDDAT       7        //TFT彩屏接口触发命令(bit2~bit0), 7->读数据

void LCM_Config(void)
{
    LCMIFCFG  = LCMIFIE  | LCMIFIP   | LCMIFDPS | LCM_D16_D8 | LCM_M68_I80;
    LCMIFCFG2 = LCMIFCPS | LCMSETUPT | LCMHOLDT;    //RS:P45,E:P44,RW:P42; Setup Time,HOLD Time
    LCMIFSTA  = 0x00;    //TFT彩屏接口中断请求标志,软件清0
    LCMIFPSCR = (u8)(MAIN_Fosc/250000UL-1);    //TFT彩屏接口时钟预分频0~255, LCMIF时钟频率 = SYSclk/(LCMIFPSCR+1), LCD1602速度慢,最快250KHz
    LCMIFCR   = ENLCMIF;
}

void CheckBusy(void)    //检测忙标志
{
    LCMIFSTA = 0;       //清除完成标志
    do
    {
        LCMIFCR   = ENLCMIF | LCM_RDCMD;    //读状态
        while((LCMIFSTA & 1) == 0);         //等待读完成
        LCMIFSTA = 0;   //清除完成标志
        LCD_ENA = 0;
    }while(LCMIFDATL & 0x80);   //bit7==0则空闲
}

/**********************************************/
void IniSendCMD(u8 cmd) //write the command to LCD
{
    LCMIFDATL = cmd;
    LCMIFCR   = ENLCMIF | LCM_WRCMD;    //写命令
    while((LCMIFSTA & 1) == 0);         //等待写完成
    LCMIFSTA = 0;   //清除完成标志
}

/**********************************************/
void Write_CMD(u8 cmd)  //write the command to LCD
{
    CheckBusy();    //检测忙
    LCMIFDATL = cmd;
    LCMIFCR   = ENLCMIF | LCM_WRCMD;    //写命令
    while((LCMIFSTA & 1) == 0);         //等待写完成
    LCMIFSTA = 0;   //清除完成标志
}

/********* 初始化函数 **************************/
void Initialize_LCD(void)   //intilize LCD, input none, output none
{
    LCD_ENA = 0;
    LCD_RS  = 0;
    LCD_RW  = 0;

    delay_ms(100);
    IniSendCMD(C_BIT8);         //set the data is 4 bits

    delay_ms(10);
    IniSendCMD(C_BIT8);         //set the data is 4 bits

    delay_ms(10);
    IniSendCMD(C_8bitL2DOT7);   //tow lines 5*7 dots

    delay_ms(6);
    Write_CMD(C_CLEAR);         //clear LCD RAM
    Write_CMD(C_CUR_R);         //Curror Shift Right
    Write_CMD(C_ON);            //turn on  LCD
}

//========================================================================
// 函数: void DMA_Config(u8 xdata *pic)
// 描述: LCM DMA配置函数。
// 参数: *pic: 数据首地址.
// 返回: none.
// 版本: V1.0, 2024-8-17
// 备注:
//========================================================================
//DMA_LCM_CR (7EfA71H)     LCM_DMA控制寄存器
#define        DMA_ENLCM     (1<<7)    // LCM DMA功能使能控制位,    bit7, 0:禁止LCM DMA功能,  1:允许LCM DMA功能。
#define        LCM_TRIGWC    (1<<6)    // LCM DMA触发写命令,bit6, 0:写0无效,          1:写1开始LCM DMA开始写命令。
#define        LCM_TRIGWD    (1<<5)    // LCM DMA触发写数据,bit5, 0:写0无效,          1:写1开始LCM DMA开始写数据。
#define        LCM_TRIGRC    (1<<4)    // LCM DMA触发读命令,bit4, 0:写0无效,          1:写1开始LCM DMA开始读命令。
#define        LCM_TRIGRD    (1<<3)    // LCM DMA触发读数据,bit3, 0:写0无效,          1:写1开始LCM DMA开始读数据。
#define        LCM_CLRFIFO   0         // 清除LCM DMA接收FIFO控制位,bit0, 0:写0无效,  1:写1复位FIFO指针。

//DMA_LCM_CFG  (7EfA70H)   LCM_DMA配置寄存器
#define        DMA_LCMIE     (1<<7)    // LCM DMA中断使能控制位,bit7, 0:禁止SPI DMA中断,     1:允许中断。
#define        DMA_LCMIP     (0<<2)    // LCM DMA中断优先级控制位,bit3~bit2, (最低)0~3(最高).
#define        DMA_LCMPTY    0         // LCM DMA数据总线访问优先级控制位,bit1~bit0, (最低)0~3(最高).

//DMA_LCM_STA  (7EfA72)     LCM_DMA状态寄存器
#define        LCM_TXOVW     (1<<1)    // LCM DMA数据覆盖标志位,bit1, 软件清0.
#define        DMA_LCMIF     1         // LCM DMA中断请求标志位,bit0, 软件清0.

void LCM_DMA_Trig(void)
{
    DMA_LCM_STA  = 0x00;
    DMA_LCM_CFG  = DMA_LCMIE | DMA_LCMIP | DMA_LCMPTY;;
    DMA_LCM_ITVH = 0;           //设置传输间隔时间(高8位),对应N+1个LCMIF时钟(1~65536个LCMIF时钟)
    DMA_LCM_ITVL = 9-1;         //设置传输间隔时间(低8位)

    B_TxCmd   = 0;              //已发送命令标志
    LCM_TxCnt = 0;              //LCM DMA触发发送次数, 一次16字节, 一共64次
    B_LCM_DMA_busy = 1;         //标志LCM-DMA忙,LCM DMA中断中清除此标志,使用LCM DMA前要确认此标志为0
    DMA_LCM_STA = DMA_LCMIF;    //软件触发LCM DMA中断,启动发送
}

//========================================================================
// 函数: void LCMIF_DMA_ISR(void) interrupt DMA_LCM_VECTOR
// 描述: LCM DMA中断函数。中断处理时间:2.3us @24MHz. 刷新时间:84ms @24MHz.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2024-8-17
// 备注:
//========================================================================
void LCMIF_DMA_ISR(void) interrupt DMA_LCM_VECTOR
{
    if(DMA_LCM_STA & DMA_LCMIF)
    {
        if(LCM_TxCnt >= 2)      //判断发送是否完毕
        {
            DMA_LCM_CR = 0;
            B_LCM_DMA_busy = 0; //清除LCM-DMA忙标志,LCM DMA中断中清除此标志,使用LCM DMA前要确认此标志为0
        }
        else        //仍有数据要发送
        {
            if(!B_TxCmd)    //还没有发设置地址命令,则先发设置地址命令
            {
                B_TxCmd = 1;            //指示已发地址命令
                if(LCM_TxCnt == 0)      //第一行地址设置命令
                {
                    LCD_RS = 0;         //写命令
                    LCD_RW = 0;
                    CmdTmp[0] = 0x80;   //第一行AC地址
                }
                else if(LCM_TxCnt == 1) //第二行地址设置命令
                {
                    LCD_RS = 0;         //写命令
                    LCD_RW = 0;
                    CmdTmp[0] = 0x80 | 64;  //第二行AC地址
                }
                DMA_LCM_TXAH = (u8)((u16)CmdTmp >> 8);  //LCM DMA发送命令首地址
                DMA_LCM_TXAL = (u8)CmdTmp;
                DMA_LCM_AMTH = 0;       //设置传输总字节数(高8位), 设置传输总字节数 = N+1
                DMA_LCM_AMT  = 1-1;     //设置传输总字节数(低8位).
                DMA_LCM_CR   = DMA_ENLCM | LCM_TRIGWC;    //启动LCM DMA发送命令
            }
            else    //写数据
            {
                LCD_RS = 1;     //写显示数据
                LCD_RW = 0;
                B_TxCmd = 0;    //清除已发地址命令
                if(LCM_TxCnt == 0)   //第一行显示缓冲地址
                {
                    DMA_LCM_TXAH = (u8)((u16)DisTmp1 >> 8);    //LCM DMA发送数据首地址
                    DMA_LCM_TXAL = (u8)DisTmp1;
                }
                else //if(LCM_TxCnt == 1)   //第二行显示缓冲地址
                {
                    DMA_LCM_TXAH = (u8)((u16)DisTmp2 >> 8);    //LCM DMA发送数据首地址
                    DMA_LCM_TXAL = (u8)DisTmp2;
                }
                DMA_LCM_AMTH = 0;       //设置传输总字节数(高8位), 设置传输总字节数 = N+1
                DMA_LCM_AMT  = 16-1;    //设置传输总字节数(低8位).
                DMA_LCM_CR   = DMA_ENLCM | LCM_TRIGWD;  //启动LCM DMA发送数据
                LCM_TxCnt++;        //发送行数+1
            }
        }
    }
    DMA_LCM_STA = 0;
}

/*************** 主函数 *******************************/

void main(void)
{
    u16 i;

    EAXFR = 1; //扩展寄存器(XFR)访问使能
    CKCON = 1; //避免 DMA 与 CPU 同时访问 xdata 时产生总线冲突

    P4M0 |= 0x34;       //RS,WR,RD设置成推挽输出
    P4M1 &= ~0x34;

    P5M0 |= 0x02;       //RST设置成推挽输出
    P5M1 &= ~0x02;

    P2BP &= ~0xff;      //使能LCM的D8~D15数据脚硬件自动设置端口模式

    delay_ms(100);    //等待一下,等LCD讲入工作状态
    LCM_Config();
    Initialize_LCD();    //初始化LCD
    EA = 1;

    while (1)
    {
        if(!B_LCM_DMA_busy)        //DMA空闲
        {
            for(i=0; i<16; i++)    //将要显示的文本装载到显存
            {
                DisTmp1= text1;    //加载第一行显存
                DisTmp2 = text2;    //加载第二行显存
            }
            LCM_DMA_Trig();        //启动DMA,显示文本
        }
        delay_ms(2000);

        if(!B_LCM_DMA_busy)        //DMA空闲
        {
            for(i=0; i<16; i++)    //将要显示的文本装载到显存
            {
                DisTmp1 = text3;    //加载第一行显存
                DisTmp2 = text4;    //加载第二行显存
            }
            LCM_DMA_Trig();        //启动DMA,显示文本
        }
        delay_ms(2000);
    }
}



61-DMA-LCM液晶屏接口测试.zip (42.33 KB, 下载次数: 0)
回复

使用道具 举报 送花

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

231

主题

168

回帖

1069

积分

版主

积分
1069
发表于 2026-7-3 15:34:52 | 显示全部楼层
61-DMA-LCM液晶屏接口测试,STC32G144K246实验箱演示程序
TFT320240显示程序-硬件I8080并行接口+DMA刷新,主程序main.C代码如下(汇编版本在附件中):


/*---------------------------------------------------------------------*/
/* --- Web: www.STCAI.com ---------------------------------------------*/
/* --- BBS: www.STCAIMCU.com  -----------------------------------------*/
/*---------------------------------------------------------------------*/

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

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

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

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

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

16bit I8080模式, P0口接D0~D7, P2口接D8~D15

sbit    LCD_RS      =   P4^5;
sbit    LCD_WR      =   P4^2;
sbit    LCD_RD      =   P4^4;
sbit    LCD_RESET   =   P5^1;

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

下载时, 选择IRC频率 48MHz,主时钟使用 PLL 90MHz 时钟频率.

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

#include "..\..\comm\STC32G144K246.h"
#include "font.h"

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

/****************  用户定义宏  ****************/

#define SEL_HPLL1       1
#define SEL_HPLL2       2
#define HPLL_SEL        SEL_HPLL2

#if(HPLL_SEL==SEL_HPLL1)
    #define MAIN_Fosc   120000000L //定义主时钟(超频)
#else
    #define MAIN_Fosc   90000000L  //定义主时钟
#endif

/****************  IO口定义  ******************/

sbit    LCD_RS      =   P4^5;
sbit    LCD_WR      =   P4^2;
sbit    LCD_RD      =   P4^4;
sbit    LCD_RESET   =   P5^1;

#define LCD_CS_H()  P9SETB  = 0x08  //P93 = 1
#define LCD_CS_L()  P9CLRB  = 0x08  //P93 = 0

//IO连接
//#define  LCD_DataPortH P2   //高8位数据口,8位模式下只使用高8位
//#define  LCD_DataPortL P0   //低8位数据口,8位模式下低8位可以不接线

/****************  本地常量声明  **************/

//支持横竖屏快速定义切换
#define USE_HORIZONTAL      3   //定义液晶屏顺时针旋转方向         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 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 HPLL_config(void);
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)
{
    EAXFR = 1; //扩展寄存器(XFR)访问使能
    CKCON = 1; //避免 DMA 与 CPU 同时访问 xdata 时产生总线冲突

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

        while(1)
        {
                Test_Color();
        }
}

//========================================================================
// 函数: void HPLL_config(void)
// 描述: PLL时钟配置函数。
// 参数: none.
// 返回: none.
// 版本: VER1.0
// 日期: 2025-11-01
// 备注:
//========================================================================
void HPLL_config(void)
{
#if(HPLL_SEL==SEL_HPLL2)
    WTST = 2;           //通过WTST增加等待时钟控制Flash读取速度在33MHz以内, 主时钟:360MHz/2/2=90MHz, 读Flash速度:90MHz/(1+2)=30MHz

    HPLLCR |= 0x80;     //使能HPLL(高速外设默认使用HPLL时钟,切换到HPLL2前要先使能HPLL,切换完再关闭HPLL)

                        //首先需要将HIRC主频调节到48MHz
    HPLL2CR &= ~0x10;   //选择HPLL2输入时钟源为HIRC
//    HPLL2CR |= 0x10;    //选择HPLL2输入时钟源为IRCM
    HPLL2PDIV = 8;      //设置HPLL2输入时钟预分频为8(HPLL输入频率必须为6MHz)
//    HPLL2CR |= 0x00;    //HPLL2=6MHz*52=312MHz
//    HPLL2CR |= 0x01;    //HPLL2=6MHz*54=324MHz
//    HPLL2CR |= 0x02;    //HPLL2=6MHz*56=336MHz
//    HPLL2CR |= 0x03;    //HPLL2=6MHz*58=348MHz
    HPLL2CR |= 0x04;    //HPLL2=6MHz*60=360MHz
//    HPLL2CR |= 0x05;    //HPLL2=6MHz*62=372MHz
//    HPLL2CR |= 0x06;    //HPLL2=6MHz*64=384MHz
//    HPLL2CR |= 0x07;    //HPLL2=6MHz*66=396MHz
//    HPLL2CR |= 0x08;    //HPLL2=6MHz*68=408MHz
//    HPLL2CR |= 0x09;    //HPLL2=6MHz*70=420MHz
//    HPLL2CR |= 0x0a;    //HPLL2=6MHz*72=432MHz
//    HPLL2CR |= 0x0b;    //HPLL2=6MHz*74=444MHz
//    HPLL2CR |= 0x0c;    //HPLL2=6MHz*76=456MHz
//    HPLL2CR |= 0x0d;    //HPLL2=6MHz*78=468MHz
//    HPLL2CR |= 0x0e;    //HPLL2=6MHz*80=480MHz
//    HPLL2CR |= 0x0f;    //HPLL2=6MHz*82=492MHz
    HPLL2CR |= 0x20;    //高速外设时钟选择 HPLL2/2
    HPLL2CR |= 0x80;    //使能HPLL2

    HPLLCR &= ~0x80;    //关闭HPLL(高速外设默认使用HPLL时钟,切换到HPLL2前要先使能HPLL,切换完再关闭HPLL)
   
    CLKDIV = 2;         //系统时钟 = 主时钟源/2 = HPLL2/2/2 = 90MHz
    CLKSEL = 0x08;      //选择HPLL2/2作为主时钟源

#else
    WTST = 3;           //通过WTST增加等待时钟控制Flash读取速度在33MHz以内, 主时钟:480MHz/2/2=120MHz, 读Flash速度:120MHz/(1+3)=30MHz
                        //首先需要将HIRC主频调节到48MHz
    HPLLCR &= ~0x10;    //选择HPLL输入时钟源为HIRC
//    HPLLCR |= 0x10;     //选择HPLL输入时钟源为IRCM
    HPLLPDIV = 8;       //设置HPLL输入时钟预分频为8(HPLL输入频率必须为6MHz)
//    HPLLCR |= 0x00;     //HPLL=6MHz*52=312MHz
//    HPLLCR |= 0x01;     //HPLL=6MHz*54=324MHz
//    HPLLCR |= 0x02;     //HPLL=6MHz*56=336MHz
//    HPLLCR |= 0x03;     //HPLL=6MHz*58=348MHz
//    HPLLCR |= 0x04;     //HPLL=6MHz*60=360MHz
//    HPLLCR |= 0x05;     //HPLL=6MHz*62=372MHz
//    HPLLCR |= 0x06;     //HPLL=6MHz*64=384MHz
//    HPLLCR |= 0x07;     //HPLL=6MHz*66=396MHz
//    HPLLCR |= 0x08;     //HPLL=6MHz*68=408MHz
//    HPLLCR |= 0x09;     //HPLL=6MHz*70=420MHz
//    HPLLCR |= 0x0a;     //HPLL=6MHz*72=432MHz
//    HPLLCR |= 0x0b;     //HPLL=6MHz*74=444MHz
//    HPLLCR |= 0x0c;     //HPLL=6MHz*76=456MHz
//    HPLLCR |= 0x0d;     //HPLL=6MHz*78=468MHz
    HPLLCR |= 0x0e;     //HPLL=6MHz*80=480MHz
//    HPLLCR |= 0x0f;     //HPLL=6MHz*82=492MHz
    HPLL2CR &= ~0x60;   //高速外设时钟选择 HPLL/2
    HPLLCR |= 0x80;     //使能HPLL

    CLKDIV = 2;         //系统时钟=主时钟源/2 = HPLL/2/2 = 120MHz
    CLKSEL = 0x04;      //选择HPLL/2作为主时钟源
#endif

//    P5M0 |= 0x10; P5M1 &= ~0x10;//设置P5.4口为推挽输出
//    P5SR &= ~0x10;              //设置P5.4口为快速模式
//    HIRCCR |= 0x10;             //输出系统时钟
//    MCLKOCR = 10;               //系统时钟 10 分频到P5.4
}

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_L();
    DmaFlag = 1;
        DMA_LCM_CR = 0xa0;        //Write dat
        while(DmaFlag);
}

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(unsigned int ms)
// 描述: 延时函数。
// 参数: ms,要延时的ms数.
// 返回: none.
// 版本: VER1.0
// 日期: 2025-11-01
// 备注: 由于芯片使能了Cache功能,软件延时时间可能不太准确
//========================================================================
void delay_ms(u16 ms)
{
    u16 i;
    do{
        i = MAIN_Fosc / 6000;
        while(--i);
    }while(--ms);
}

/*****************************************************************************
* @name       :void LCD_WR_REG(u16 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(u16 Reg)     
{
    LCMIFDATH = Reg>>8;
        LCMIFDATL = Reg;
        LCD_CS_L();
        LCMIFCR = 0x84;                //Enable interface, write command out
    while(!LCMIFSTA);
    LCMIFSTA = 0x00;
    LCD_CS_H();
}

/*****************************************************************************
* @name       :void LCD_WR_DATA(u16 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(u16 Data)
{
    LCMIFDATH = Data>>8;
        LCMIFDATL = Data;
        LCD_CS_L();
        LCMIFCR = 0x85;                //Enable interface, write data out
    while(!LCMIFSTA);
    LCMIFSTA = 0x00;
    LCD_CS_H();
}

/*****************************************************************************
* @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(Data);
}

/*****************************************************************************
* @name       :void LCD_WriteReg(u16 LCD_Reg, u16 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(u16 LCD_Reg, u16 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)
{
    P4M0 |= 0x34;       //RS,WR,RD设置成推挽输出
    P4M1 &= ~0x34;

    P5M0 |= 0x02;       //RST设置成推挽输出
    P5M1 &= ~0x02;

    P9M0 |= 0x08;       //CS设置成推挽输出
    P9M1 &= ~0x08;

    P0BP &= ~0xff;      //使能LCM的D0~D7 数据脚硬件自动设置端口模式
    P2BP &= ~0xff;      //使能LCM的D8~D15数据脚硬件自动设置端口模式
}

/*****************************************************************************
* @name       :void LCM_Config(void)
* @date       :2025-12-25
* @function   :Config LCM
* @parameters :None
* @retvalue   :None
******************************************************************************/        
void LCM_Config(void)
{
    LCMIFCFG = 0x02;    //16位模式
    LCMIFCFG2 = 0x0d;
    LCMIFSTA = 0x00;
}

/*****************************************************************************
* @name       :void DMA_Config(void)
* @date       :2025-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_H();
        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);                     //根据不同晶振速度可以调整延时,保障稳定显示

//*************3.2inch 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<<5)|(1<<6));
        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<<7)|(1<<5)|(1<<4));
        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       :2025-12-25
* @function   :None
* @parameters :None
* @retvalue   :
******************************************************************************/
void LCM_Interrupt(void) interrupt LCM_VECTOR
{
        if(LCMIFSTA & 0x01)
        {
                LCMIFSTA = 0x00;
                LcmFlag = 0;
        }
}

void LCM_DMA_Interrupt(void) interrupt DMA_LCM_VECTOR
{
        if(DMA_LCM_STA & 0x01)
        {
        index--;
        if(index == 0)
        {
            DMA_LCM_CR = 0;
            DmaFlag = 0;
            LCD_CS_H();
        }
        else
        {
            DMA_LCM_CR = 0xa0;        //Write dat
        }

        DMA_LCM_STA = 0;
        }
}


61-DMA-LCM液晶屏接口测试.zip (42.33 KB, 下载次数: 0)
回复

使用道具 举报 送花

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

本版积分规则

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

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

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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