stm32f103zet红牛开发板STMcubeMX hal库版LCD01 test 利用stmcubeMX直接生成fsmc配置文件

先上原理图  

 

 

使用fsmc  norsram bank4,对应的ne4是片选 ,使用a0地址线接显示器的RS来区分是命令还是数据。红牛的驱动里一部分是fsmc的初始化,另一部分是lcd的操作。移植hal库,只需要把fsmc的部分用cubeMX自动生成就行。

 

 时序的部分只要data setup time至少填2就可以,其他的可以尽量小。扩展模式不开也可以,开成A,D都可以。不一定非要照搬原版的B模式

把原程序里的延时程序都换成 hal-delay(),注释掉fsmc相关的初始化程序。修改过的程序如下

WB_LCD.h

#ifndef __WB_LCD_H
#define __WB_LCD_H

#include "stm32f1xx_hal.h"//这里引用hal库,删掉了自定义的延时程序   其他的都不动
#include "stdio.h"
#include "stdlib.h"



#define LCD_RAM       *(__IO uint16_t *)((uint32_t)0x6C000002) //地址寄存器
#define LCD_REG       *(__IO uint16_t *)((uint32_t)0x6C000000) //指令寄存器

#define MAX_HZ_POSX   224
#define MAX_HZ_POSY   304

#define MAX_CHAR_POSX 232
#define MAX_CHAR_POSY 304

#define Horizontal    0x00
#define Vertical      0x01

/*Private define-------------------------*/
#define POINT_COLOR WHITE
#define BACK_COLOR  BLACK

/*--------16位颜色值---------------*/
#define WHITE   0xFFFF
#define BLACK   0x0000
#define BLUE    0x001F
#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 LGRAY   0XC618 //浅灰色

/**
 * @brief  ili9325/ili9328 LCD Registers
 */
#define LCD_REG_0   0x00
#define LCD_REG_1   0x01
#define LCD_REG_2   0x02
#define LCD_REG_3   0x03
#define LCD_REG_4   0x04
#define LCD_REG_5   0x05
#define LCD_REG_6   0x06
#define LCD_REG_7   0x07
#define LCD_REG_8   0x08
#define LCD_REG_9   0x09
#define LCD_REG_10  0x0A
#define LCD_REG_12  0x0C
#define LCD_REG_13  0x0D
#define LCD_REG_14  0x0E
#define LCD_REG_15  0x0F
#define LCD_REG_16  0x10
#define LCD_REG_17  0x11
#define LCD_REG_18  0x12
#define LCD_REG_19  0x13
#define LCD_REG_20  0x14
#define LCD_REG_21  0x15
#define LCD_REG_22  0x16
#define LCD_REG_23  0x17
#define LCD_REG_24  0x18
#define LCD_REG_25  0x19
#define LCD_REG_26  0x1A
#define LCD_REG_27  0x1B
#define LCD_REG_28  0x1C
#define LCD_REG_29  0x1D
#define LCD_REG_30  0x1E
#define LCD_REG_31  0x1F
#define LCD_REG_32  0x20
#define LCD_REG_33  0x21
#define LCD_REG_34  0x22
#define LCD_REG_36  0x24
#define LCD_REG_37  0x25
#define LCD_REG_40  0x28
#define LCD_REG_41  0x29
#define LCD_REG_43  0x2B
#define LCD_REG_45  0x2D
#define LCD_REG_48  0x30
#define LCD_REG_49  0x31
#define LCD_REG_50  0x32
#define LCD_REG_51  0x33
#define LCD_REG_52  0x34
#define LCD_REG_53  0x35
#define LCD_REG_54  0x36
#define LCD_REG_55  0x37
#define LCD_REG_56  0x38
#define LCD_REG_57  0x39
#define LCD_REG_58  0x3A
#define LCD_REG_59  0x3B
#define LCD_REG_60  0x3C
#define LCD_REG_61  0x3D
#define LCD_REG_62  0x3E
#define LCD_REG_63  0x3F
#define LCD_REG_64  0x40
#define LCD_REG_65  0x41
#define LCD_REG_66  0x42
#define LCD_REG_67  0x43
#define LCD_REG_68  0x44
#define LCD_REG_69  0x45
#define LCD_REG_70  0x46
#define LCD_REG_71  0x47
#define LCD_REG_72  0x48
#define LCD_REG_73  0x49
#define LCD_REG_74  0x4A
#define LCD_REG_75  0x4B
#define LCD_REG_76  0x4C
#define LCD_REG_77  0x4D
#define LCD_REG_78  0x4E
#define LCD_REG_79  0x4F
#define LCD_REG_80  0x50
#define LCD_REG_81  0x51
#define LCD_REG_82  0x52
#define LCD_REG_83  0x53
#define LCD_REG_96  0x60
#define LCD_REG_97  0x61
#define LCD_REG_106 0x6A
#define LCD_REG_118 0x76
#define LCD_REG_128 0x80
#define LCD_REG_129 0x81
#define LCD_REG_130 0x82
#define LCD_REG_131 0x83
#define LCD_REG_132 0x84
#define LCD_REG_133 0x85
#define LCD_REG_134 0x86
#define LCD_REG_135 0x87
#define LCD_REG_136 0x88
#define LCD_REG_137 0x89
#define LCD_REG_139 0x8B
#define LCD_REG_140 0x8C
#define LCD_REG_141 0x8D
#define LCD_REG_143 0x8F
#define LCD_REG_144 0x90
#define LCD_REG_145 0x91
#define LCD_REG_146 0x92
#define LCD_REG_147 0x93
#define LCD_REG_148 0x94
#define LCD_REG_149 0x95
#define LCD_REG_150 0x96
#define LCD_REG_151 0x97
#define LCD_REG_152 0x98
#define LCD_REG_153 0x99
#define LCD_REG_154 0x9A
#define LCD_REG_157 0x9D
#define LCD_REG_192 0xC0
#define LCD_REG_193 0xC1
#define LCD_REG_229 0xE5

extern uint16_t DeviceCode;

/*----------函数声明------------*/
/* 刷屏 */
void LCD_Clear(uint16_t Color);
void LCD_Fill(uint8_t xsta, uint16_t ysta, uint8_t xend, uint16_t yend, uint16_t colour);
void LCD_DrawLine(uint16_t xsta, uint16_t ysta, uint16_t xend, uint16_t yend);
void LCD_DrawHVLine(uint8_t xsta, uint16_t ysta, uint16_t Length, uint16_t Color, uint8_t Direction);
void LCD_DrawCircle(uint16_t x0, uint16_t y0, uint8_t r);
void LCD_DrawRectangle(uint16_t xsta, uint16_t ysta, uint16_t xend, uint16_t yend);
void LCD_WindowMax(unsigned int x, unsigned int y, unsigned int x_end, unsigned int y_end);
void LCD_ShowNum(uint8_t x, uint8_t y, uint32_t num, uint8_t len, uint16_t PenColor, uint16_t BackColor); //显示数字
void LCD_DrawPicture(uint16_t StartX, uint16_t StartY, uint16_t Xend, uint16_t Yend, uint8_t *pic);       //显示图片 gImage取模 bmp格式

void LCD_IOConfig(void);
void LCD_Init(void);
void LCD_DisplayStr(unsigned int x, unsigned int y, unsigned char *s, uint16_t PenColor, uint16_t BackColor);
void LCD_WriteReg(uint16_t LCD_Reg, uint16_t LCD_RegValue);
void LCD_ShowLEDNum(uint16_t x, uint16_t y, uint16_t num, uint16_t PenColor, uint16_t BackColor);
void Display_Test(void);
#endif

WB_LCD.c

/**
 * @file    WB_LCD.c
 * @author  WB R&D Team - openmcu666
 * @version V1.0
 * @date    2016.05.04
 * @brief   LCD Driver
 * @description 红牛2.8/3.2/3.5寸LCD屏的驱动(支持的驱动IC为SSD1298、ili9325/ili9328、SSD2119)
 */
#include "WB_LCD.h"
#include "font.h"



uint16_t DeviceCode; //用于存取设备ID
#define Font_Size 16 // 默认字体为16*8
#define XY        1  //文字支持横竖屏切换,竖屏:1;横屏:0

/*********************************************************
** Function name:       void Delay_10ms (uint32_t nCount)
** Descriptions:        LCD延时函数 10MS  这里用hal-delay重写了
** input parameters:    nCount
** output parameters:   无
** Returned value:      无
*********************************************************/
void Delay_10ms(uint32_t nCount)
{
    HAL_Delay(nCount * 10);
}

/*********************************************************
** Function name:       void LCD_WR_REG(uint16_t LCD_Reg)
** Descriptions:        写寄存器
** input parameters:    LCD_Reg
** output parameters:   无
** Returned value:      无
*********************************************************/
void LCD_WR_REG(uint16_t LCD_Reg)
{
    LCD_REG = LCD_Reg; //往指令寄存器写指令
}

/*********************************************************
** Function name:       void LCD_WR_DATA(uint16_t LCD_Data)
** Descriptions:        写数据
** input parameters:    LCD_Data
** output parameters:   无
** Returned value:      无
*********************************************************/
void LCD_WR_DATA(uint16_t LCD_Data)
{
    LCD_RAM = LCD_Data; //往数据寄存器写数据
}

/*********************************************************************************
** Function name:     void LCD_WriteReg(uint16_t LCD_Reg ,uint16_t LCD_RegValue)
** Descriptions:      配置寄存器
** input parameters:  寄存器地址:LCD_Reg   数据:RegValue
** output parameters: 无
** Returned value:    无
**********************************************************************************/
void LCD_WriteReg(uint16_t LCD_Reg, uint16_t LCD_RegValue)
{
    LCD_WR_REG(LCD_Reg);       //写寄存器
    LCD_WR_DATA(LCD_RegValue); //写数据
}

/*********************************************************
** Function name:       void LCD_WriteRAM_Prepare(void)
** Descriptions:        开始写GRAM
** input parameters:    无
** output parameters:   无
** Returned value:      无
*********************************************************/
void LCD_WriteRAM_Prepare(void)
{
    LCD_WR_REG(0x22);
}

/*********************************************************
** Function name:       void LCD_WriteRAM(uint16_t RGB_Code)
** Descriptions:        LCD写GRAM
** input parameters:    颜色值
** output parameters:   无
** Returned value:      无
*********************************************************/
void LCD_WriteRAM(uint16_t RGB_Code)
{
    LCD_WR_DATA(RGB_Code); //写十六位GRAM
}

/*********************************************************
** Function name:       uint16_t Read_LCDReg(uint16_t LCD_Reg)
** Descriptions:        读寄存器
** input parameters:    LCD_Reg:寄存器
** output parameters:   无
** Returned value:      返回寄存器值
*********************************************************/
uint16_t Read_LCDReg(uint16_t LCD_Reg)
{
    uint16_t temp;

    LCD_REG = LCD_Reg;

    temp = LCD_RAM;

    return temp;
}

/**********************************************************************************
** Function name:       void LCD_Configuration(void)
** Descriptions:        LCD相关引脚配置,fsmc能用的针脚是固定的    这里已作废不用
** input parameters:      无
** output parameters:   无
** Returned value:      无
************************************************************************************/
void LCD_IOConfig(void)//作废
{

    // GPIO_InitTypeDef GPIO_InitStructure;

    // RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE |
    //                            RCC_APB2Periph_GPIOF | RCC_APB2Periph_GPIOG |
    //                            RCC_APB2Periph_AFIO,
    //                        ENABLE);

    // /* Set PD.00(D2), PD.01(D3), PD.04(NOE), PD.05(NWE), PD.08(D13), PD.09(D14),
    //    PD.10(D15), PD.14(D0), PD.15(D1) as alternate
    //    function push pull */
    // GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 |
    //                               GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_14 |
    //                               GPIO_Pin_15;
    // GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    // GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    // GPIO_Init(GPIOD, &GPIO_InitStructure);

    // /* Set PE.07(D4), PE.08(D5), PE.09(D6), PE.10(D7), PE.11(D8), PE.12(D9), PE.13(D10),
    //    PE.14(D11), PE.15(D12) as alternate function push pull */
    // GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 |
    //                               GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 |
    //                               GPIO_Pin_15;
    // GPIO_Init(GPIOE, &GPIO_InitStructure);

    // GPIO_WriteBit(GPIOE, GPIO_Pin_6, Bit_SET);
    // /* Set PF.00(A0 (RS)) as alternate function push pull */
    // GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    // GPIO_Init(GPIOF, &GPIO_InitStructure);

    // /* Set PG.12(NE4 (LCD/CS)) as alternate function push pull - CE3(LCD /CS) */
    // GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
    // GPIO_Init(GPIOG, &GPIO_InitStructure);

   
}

/**********************************************************************************
** Function name:       void FSMC_LCDInit(void)
** Descriptions:        FSMC时序配置
** input parameters:      无
** output parameters:   无
** Returned value:      无
************************************************************************************/
void FSMC_LCDInit(void)//作废
{
    //     FSMC_NORSRAMInitTypeDef  FSMC_NORSRAMInitStructure;           //定义一个NOR初始化结构体
    //     FSMC_NORSRAMTimingInitTypeDef  w,r;                                  //定义一个NOR时序初始化结构体

    //     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);                        //使能FSMC总线时钟

    //   w.FSMC_AddressSetupTime = 0x00;                                              //地址建立时间:0x1
    //   w.FSMC_AddressHoldTime = 0x00;                                              //地址保持时间:0x00
    //   w.FSMC_DataSetupTime = 0x01;                                                //数据建立时间:0x2
    //   w.FSMC_BusTurnAroundDuration = 0x00;
    //   w.FSMC_CLKDivision = 0x00;
    //   w.FSMC_DataLatency = 0x00;
    //   w.FSMC_AccessMode = FSMC_AccessMode_B;

    //     r.FSMC_AddressSetupTime = 0x00;                                               //地址建立时间:0x1
    //   r.FSMC_AddressHoldTime = 0x00;                                               //地址保持时间:0x00
    //   r.FSMC_DataSetupTime = 0x07;                                                 //数据建立时间:0x2
    //   r.FSMC_BusTurnAroundDuration = 0x00;
    //   r.FSMC_CLKDivision = 0x00;
    //   r.FSMC_DataLatency = 0x0f;
    //   r.FSMC_AccessMode = FSMC_AccessMode_B;

    //   FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM4;           //扩展NOR BANK 的第1个子BANK
    //   FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;//不使用总线复用

    //   FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_NOR;//扩展类型为NOR FLASH
    //   FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;//扩展总线宽度为16位

    //   FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;

    //   FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;

    //   FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
    //   FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
    //   FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
    //   FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
    //   FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Enable;
    //   FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
    //   FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &r;
    //   FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &w;

    //   FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);                             //根据指定参数初始化结构体

    //   FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM4, ENABLE);                             //使能FSMC_Bank1_NORSRAM4 内存

    
}
/**********************************************************************************
** Function name:       void LCD_Init(void)
** Descriptions:        LCD初始化
** input parameters:      无
** output parameters:   无
** Returned value:      无
************************************************************************************/
void LCD_Init(void)
{
    //LCD_IOConfig();

    //FSMC_LCDInit(); //这两个函数就是fsmc初始化,现在由cubeMX自动生成的代码替代

    Delay_10ms(5);                    // delay 50 ms
    Delay_10ms(5);                    // delay 50 ms
    DeviceCode = Read_LCDReg(0x0000); // 读驱动IC
    Delay_10ms(5);                    // delay 50 ms
    // printf("lcd id is 0x%x",DeviceCode);
    // DeviceCode=0x8999;
    if (DeviceCode == 0x8999) // 对应的驱动IC为SSD1298
    {
        /*-----   Start Initial Sequence ------*/
        LCD_WriteReg(0x00, 0x0001); /*Start internal OSC */
        LCD_WriteReg(0x01, 0x3B3F); /*Driver output control */
        LCD_WriteReg(0x02, 0x0600); /* set 1 line inversion    */
        /*-------- Power control setup --------*/
        LCD_WriteReg(0x0C, 0x0007); /* Adjust VCIX2 output voltage */
        LCD_WriteReg(0x0D, 0x0006); /* Set amplitude magnification of VLCD63 */
        LCD_WriteReg(0x0E, 0x3200); /* Set alternating amplitude of VCOM */
        LCD_WriteReg(0x1E, 0x00BB); /* Set VcomH voltage */
        LCD_WriteReg(0x03, 0x6A64); /* Step-up factor/cycle setting  */
        /*-------- RAM position control --------*/
        LCD_WriteReg(0x0F, 0x0000); /* Gate scan position start at G0 */
        LCD_WriteReg(0x44, 0xEF00); /* Horizontal RAM address position */
        LCD_WriteReg(0x45, 0x0000); /* Vertical RAM address start position*/
        LCD_WriteReg(0x46, 0x013F); /* Vertical RAM address end position */
        /* ------ Adjust the Gamma Curve -------*/
        LCD_WriteReg(0x30, 0x0000);
        LCD_WriteReg(0x31, 0x0706);
        LCD_WriteReg(0x32, 0x0206);
        LCD_WriteReg(0x33, 0x0300);
        LCD_WriteReg(0x34, 0x0002);
        LCD_WriteReg(0x35, 0x0000);
        LCD_WriteReg(0x36, 0x0707);
        LCD_WriteReg(0x37, 0x0200);
        LCD_WriteReg(0x3A, 0x0908);
        LCD_WriteReg(0x3B, 0x0F0D);
        /*--------- Special command -----------*/
        LCD_WriteReg(0x28, 0x0006); /* Enable test command    */
        LCD_WriteReg(0x2F, 0x12EB); /* RAM speed tuning     */
        LCD_WriteReg(0x26, 0x7000); /* Internal Bandgap strength */
        LCD_WriteReg(0x20, 0xB0E3); /* Internal Vcom strength */
        LCD_WriteReg(0x27, 0x0044); /* Internal Vcomh/VcomL timing */
        LCD_WriteReg(0x2E, 0x7E45); /* VCOM charge sharing time */
        /*--------- Turn On display ------------*/
        LCD_WriteReg(0x10, 0x0000); /* Sleep mode off */
        Delay_10ms(3);              /* Wait 30mS  */
        LCD_WriteReg(0x11, 0x6870); /* Entry mode setup. 262K type B, take care on the data bus with 16it only */
        LCD_WriteReg(0x07, 0x0033); /* Display ON    */
    }

    if (DeviceCode == 0x9325 || DeviceCode == 0x9328) // ILI9325
    {
        LCD_WriteReg(LCD_REG_0, 0x0001);  /* Start internal OSC. */
        LCD_WriteReg(LCD_REG_1, 0x0100);  /* Set SS and SM bit */
        LCD_WriteReg(LCD_REG_2, 0x0700);  /* Set 1 line inversion */
        LCD_WriteReg(LCD_REG_3, 0x1018);  /* Set GRAM write direction and BGR=1. */
        LCD_WriteReg(LCD_REG_4, 0x0000);  /* Resize register */
        LCD_WriteReg(LCD_REG_8, 0x0202);  /* Set the back porch and front porch */
        LCD_WriteReg(LCD_REG_9, 0x0000);  /* Set non-display area refresh cycle ISC[3:0] */
        LCD_WriteReg(LCD_REG_10, 0x0000); /* FMARK function */
        LCD_WriteReg(LCD_REG_12, 0x0000); /* RGB interface setting */
        LCD_WriteReg(LCD_REG_13, 0x0000); /* Frame marker Position */
        LCD_WriteReg(LCD_REG_15, 0x0000); /* RGB interface polarity */

        /* Power On sequence -----------------------------------------------------*/
        LCD_WriteReg(LCD_REG_16, 0x0000); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
        LCD_WriteReg(LCD_REG_17, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
        LCD_WriteReg(LCD_REG_18, 0x0000); /* VREG1OUT voltage */
        LCD_WriteReg(LCD_REG_19, 0x0000); /* VDV[4:0] for VCOM amplitude */
        Delay_10ms(130);                  /* Dis-charge capacitor power voltage (200ms) */
        LCD_WriteReg(LCD_REG_16, 0x17B0); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
        LCD_WriteReg(LCD_REG_17, 0x0137); /* DC1[2:0], DC0[2:0], VC[2:0] */
        Delay_10ms(50);                   /* Delay 50 ms */
        LCD_WriteReg(LCD_REG_18, 0x009c); /*0x0139 VREG1OUT voltage */
        Delay_10ms(50);                   /* Delay 50 ms */
        LCD_WriteReg(LCD_REG_19, 0x1900); /* 0x1d00VDV[4:0] for VCOM amplitude */
        LCD_WriteReg(LCD_REG_41, 0x0013); /* VCM[4:0] for VCOMH */
        Delay_10ms(50);                   /* Delay 50 ms */
        LCD_WriteReg(LCD_REG_32, 0x0000); /* GRAM horizontal Address */
        LCD_WriteReg(LCD_REG_33, 0x0000); /* GRAM Vertical Address */

        /* Adjust the Gamma Curve (ILI9325)---------------------------------------*/
        LCD_WriteReg(LCD_REG_48, 0x0007);
        LCD_WriteReg(LCD_REG_49, 0x0302);
        LCD_WriteReg(LCD_REG_50, 0x0105);
        LCD_WriteReg(LCD_REG_53, 0x0206);
        LCD_WriteReg(LCD_REG_54, 0x0808);
        LCD_WriteReg(LCD_REG_55, 0x0206);
        LCD_WriteReg(LCD_REG_56, 0x0504);
        LCD_WriteReg(LCD_REG_57, 0x0007);
        LCD_WriteReg(LCD_REG_60, 0x0105);
        LCD_WriteReg(LCD_REG_61, 0x0808);

        /* Set GRAM area ---------------------------------------------------------*/
        LCD_WriteReg(LCD_REG_80, 0x0000); /* Horizontal GRAM Start Address */
        LCD_WriteReg(LCD_REG_81, 0x00EF); /* Horizontal GRAM End Address */
        LCD_WriteReg(LCD_REG_82, 0x0000); /* Vertical GRAM Start Address */
        LCD_WriteReg(LCD_REG_83, 0x013F); /* Vertical GRAM End Address */

        LCD_WriteReg(LCD_REG_96, 0xA700);  /* Gate Scan Line(GS=1, scan direction is G320~G1) */
        LCD_WriteReg(LCD_REG_97, 0x0001);  /* NDL,VLE, REV */
        LCD_WriteReg(LCD_REG_106, 0x0000); /* set scrolling line */

        /* Partial Display Control -----------------------------------------------*/
        LCD_WriteReg(LCD_REG_128, 0x0000);
        LCD_WriteReg(LCD_REG_129, 0x0000);
        LCD_WriteReg(LCD_REG_130, 0x0000);
        LCD_WriteReg(LCD_REG_131, 0x0000);
        LCD_WriteReg(LCD_REG_132, 0x0000);
        LCD_WriteReg(LCD_REG_133, 0x0000);

        /* Panel Control ---------------------------------------------------------*/
        LCD_WriteReg(LCD_REG_144, 0x0010);
        LCD_WriteReg(LCD_REG_146, 0x0000);
        LCD_WriteReg(LCD_REG_147, 0x0003);
        LCD_WriteReg(LCD_REG_149, 0x0110);
        LCD_WriteReg(LCD_REG_151, 0x0000);
        LCD_WriteReg(LCD_REG_152, 0x0000);

        /* set GRAM write direction and BGR = 1 */
        /* I/D=00 (Horizontal : increment, Vertical : decrement) */
        /* AM=1 (address is updated in vertical writing direction) */
        // LCD_WriteReg(LCD_REG_3, 0x1018);  //横屏
        LCD_WriteReg(LCD_REG_3, 0x1030);
        LCD_WriteReg(LCD_REG_7, 0x0133); /* 262K color and display ON */
    }
    else if (DeviceCode == 0x9919) // SSD2119
    {
        LCD_WriteReg(0x28, 0x0006);
        LCD_WriteReg(0x00, 0x0001);
        LCD_WriteReg(0x10, 0x0000);
        LCD_WriteReg(0x01, 0x72ef); //
        LCD_WriteReg(0x02, 0x0600);
        LCD_WriteReg(0x03, 0x6a38);
        LCD_WriteReg(0x11, 0x6874); // 74
        //  RAM WRITE DATA MASK
        LCD_WriteReg(0x0f, 0x0000);
        //  RAM WRITE DATA MASK
        LCD_WriteReg(0x0b, 0x5308);
        LCD_WriteReg(0x0c, 0x0000); // 3
        LCD_WriteReg(0x0d, 0x000a);
        LCD_WriteReg(0x0e, 0x2e00); // 0030
        LCD_WriteReg(0x1e, 0x00be);
        LCD_WriteReg(0x25, 0x8000);
        LCD_WriteReg(0x26, 0x7800);
        LCD_WriteReg(0x27, 0x0078);
        LCD_WriteReg(0x4e, 0x0000);
        LCD_WriteReg(0x4f, 0x0000);
        LCD_WriteReg(0x12, 0x08d9);
        // -----------------Adjust the Gamma Curve----//
        LCD_WriteReg(0x30, 0x0000); // 0007
        LCD_WriteReg(0x31, 0x0104); // 0203
        LCD_WriteReg(0x32, 0x0100); // 0001
        LCD_WriteReg(0x33, 0x0305); // 0007
        LCD_WriteReg(0x34, 0x0505); // 0007
        LCD_WriteReg(0x35, 0x0305); // 0407
        LCD_WriteReg(0x36, 0x0707); // 0407
        LCD_WriteReg(0x37, 0x0300); // 0607
        LCD_WriteReg(0x3a, 0x1200); // 0106
        LCD_WriteReg(0x3b, 0x0800);
        LCD_WriteReg(0x07, 0x0033);
        // LCD_WriteReg(0x11,0x6040|0x30);
    }
    Delay_10ms(5); //延时50ms
    LCD_Clear(BLACK);
}

/************************************************************************
** Function name:       void LCD_SetCursor(uint16_t Xpos, uint16_t Ypos)
** Descriptions:        设置光标位置
** input parameters:    x轴坐标:uint8_t Xpos ;  y轴坐标:uint16_t Ypos
** output parameters:   无
** Returned value:      无
**************************************************************************/
void LCD_SetCursor(uint16_t Xpos, uint16_t Ypos)
{
    if (DeviceCode == 0x8999 || DeviceCode == 0x9919)
    {
        LCD_WriteReg(0x4E, Xpos);
        LCD_WriteReg(0x4F, Ypos);
    }
    else
    {
        LCD_WriteReg(0x20, Xpos);
        LCD_WriteReg(0x21, Ypos);
    }
}

/***********************************************************
** Function name:       void LCD_Clear(uint16_t Color)
** Descriptions:        刷屏函数
** input parameters:    颜色值
** output parameters:   无
** Returned value:      无
************************************************************/
void LCD_Clear(uint16_t Color)
{
    uint32_t index = 0;
    LCD_SetCursor(0x00, 0x0000); //设置光标位置
    LCD_WriteRAM_Prepare();      //开始写入GRAM
    for (index = 0; index < 76800; index++)
    {
        LCD_WR_DATA(Color);
    }
}

/****************************************************************************
 * 名    称:uint16_t LCD_GetPoint(uint16_t x,uint16_t y)
 * 功    能:获取指定座标的颜色值
 * 入口参数:x      行座标
 *           y      列座标
 * 出口参数:当前座标颜色值
 * 说    明:
 * 调用方法:CurrentColor = LCD_GetPoint(10,10);
 * 备注:此函数有待验证,此处屏蔽
 ****************************************************************************/
// uint16_t LCD_GetPoint(uint16_t x,uint16_t y)
//{
//   LCD_SetCursor(x,y);
//   if(DeviceCode=0X8999)
//     return (LCD_ReadRAM());
//   else
//     return (LCD_BGRtoRGB(LCD_ReadRAM()));
// }

/***********************************************************************
** Function name:       void LCD_DrawPoint(uint16_t xsta, uint16_t ysta)
** Descriptions:        打点
** input parameters:    xsta X起始坐标 0~239;ysta    Y起始坐标 0~319
** output parameters:   无
** Returned value:      无
***********************************************************************/
void LCD_DrawPoint(uint16_t xsta, uint16_t ysta)
{
    LCD_SetCursor(xsta, ysta); //设置光标位置
    LCD_WR_REG(0x22);          //开始写入GRAM
    LCD_WR_DATA(POINT_COLOR);
}

/*************************************************************************************************************
** Function name:       void LCD_XYRAM(uint16_t xstart ,uint16_t ystart ,uint16_t xend ,uint16_t yend)
** Descriptions:        设置显存区域,用完以后要恢复起点(0,0)和终点(239,319)(ili9325/ili9328调用)
** input parameters:    xsta 起始X坐标
                            ysta 起始Y坐标
                            xend 结束X坐标
                            yend 结束Y坐标
** output parameters:   无
** Returned value:      无
**************************************************************************************************************/
void LCD_XYRAM(uint16_t xsta, uint16_t ysta, uint16_t xend, uint16_t yend)
{
    LCD_WriteReg(0x0050, xsta);     // 设置横坐标GRAM起始地址
    LCD_WriteReg(0x0051, xend - 1); // 设置横坐标GRAM结束地址
    LCD_WriteReg(0x0052, ysta);     // 设置纵坐标GRAM起始地址
    LCD_WriteReg(0x0053, yend - 1); // 设置纵坐标GRAM结束地址
}

/*******************************************************************************************************
** Function name:       void LCD_WindowMax (unsigned int x,unsigned int y,unsigned int x_end,unsigned int y_end)
** Descriptions:        设置窗口最大化240*320
** input parameters:    xsta X起始坐标 0~239;ysta    Y起始坐标 0~319
** output parameters:   无
** Returned value:      无
******************************************************************************************************/
void LCD_WindowMax(unsigned int x, unsigned int y, unsigned int x_end, unsigned int y_end)
{
    if (DeviceCode == 0x8999 || DeviceCode == 0x9919)
    {
        LCD_WriteReg(0x44, x | ((x_end - 1) << 8));
        LCD_WriteReg(0x45, y);
        LCD_WriteReg(0x46, y_end - 1);
    }
    else
    {
        LCD_WriteReg(0x50, x);         //水平方向GRAM起始地址
        LCD_WriteReg(0x51, x + x_end); //水平方向GRAM结束地址
        LCD_WriteReg(0x52, y);         //垂直方向GRAM起始地址
        LCD_WriteReg(0x53, y + y_end); //垂直方向GRAM结束地址
                                       // LCD_SetCursor(x, y);                   //设置光标位置
    }
}

/*************************************************************************************************************
** Function name:       void LCD_Fill(uint8_t xsta, uint16_t ysta, uint8_t xend, uint16_t yend, uint16_t colour)
** Descriptions:        在指定矩形区域填充指定颜色,区域大小(xend-xsta)*(yend-ysta)
** input parameters:    xsta 起始X坐标
                            ysta 起始Y坐标
                            xend 结束X坐标
                            yend 结束Y坐标
                            color 待填充颜色
** output parameters:   无
** Returned value:      无
**************************************************************************************************************/
void LCD_Fill(uint8_t xsta, uint16_t ysta, uint8_t xend, uint16_t yend, uint16_t colour)
{
    uint32_t n;
    if (DeviceCode == 0x8999 || DeviceCode == 0x9919) // 对应的驱动IC为SSD1298
    {
        LCD_WindowMax(xsta, ysta, xend, yend); //设置窗口
    }
    else
    {
        LCD_XYRAM(xsta, ysta, xend, yend); // 设置GRAM坐标
    }
    LCD_SetCursor(xsta, ysta); //设置光标位置
    LCD_WriteRAM_Prepare();    //开始写入GRAM*6
    n = (uint32_t)(yend - ysta + 1) * (xend - xsta + 1);
    while (n--) { LCD_WR_DATA(colour); } //显示所填充的颜色

    LCD_WindowMax(0, 0, 240, 320); //恢复窗口
}

/****************************************************************************************************
** Function name:       void LCD_DrawLine(uint16_t xsta, uint16_t ysta, uint16_t xend, uint16_t yend)
** Descriptions:        画线
** input parameters:    xsta X起始坐标
                          ysta Y起始坐标
                            xend X终点坐标
                            yend Y终点坐标
** output parameters:   无
** Returned value:      无
****************************************************************************************************/
void LCD_DrawLine(uint16_t xsta, uint16_t ysta, uint16_t xend, uint16_t yend)
{
    uint16_t x, y, t;
    if ((xsta == xend) && (ysta == yend))
        LCD_DrawPoint(xsta, ysta);
    else if (abs(yend - ysta) > abs(xend - xsta)) //斜率大于1
    {
        if (ysta > yend)
        {
            t    = ysta;
            ysta = yend;
            yend = t;
            t    = xsta;
            xsta = xend;
            xend = t;
        }
        for (y = ysta; y < yend; y++) //以y轴为基准
        {
            x = (uint32_t)(y - ysta) * (xend - xsta) / (yend - ysta) + xsta;
            LCD_DrawPoint(x, y);
        }
    }
    else //斜率小于等于1
    {
        if (xsta > xend)
        {
            t    = ysta;
            ysta = yend;
            yend = t;
            t    = xsta;
            xsta = xend;
            xend = t;
        }
        for (x = xsta; x <= xend; x++) //以x轴为基准
        {
            y = (uint32_t)(x - xsta) * (yend - ysta) / (xend - xsta) + ysta;
            LCD_DrawPoint(x, y);
        }
    }
}

/****************************************************************************************************
** Function name:       void LCD_DrawHVLine(uint8_t xsta, uint16_t ysta, uint16_t Length,uint16_t Color,uint8_t Direction)
** Descriptions:        绘制水平或垂直的线条
** input parameters:    xsta X起始坐标
                          ysta Y起始坐标
                            Length 线条长度
                            Color 线条颜色
                        Direction: Horizontal 水平; Vertical 垂直
** output parameters:   无
** Returned value:      无
****************************************************************************************************/
void LCD_DrawHVLine(uint8_t xsta, uint16_t ysta, uint16_t Length, uint16_t Color, uint8_t Direction)
{
    uint32_t i = 0;

    LCD_SetCursor(xsta, ysta);

    if (Direction == Horizontal)
    {
        // LCD_WindowMax(ysta,xsta,ysta+Length,xsta-1);
        LCD_WriteRAM_Prepare(); /* Prepare to write GRAM */
        for (i = 0; i < Length; i++)
        {
            LCD_WriteRAM(Color);
        }
    }
    else
    {
        for (i = 0; i < Length; i++)
        {

            LCD_WriteRAM_Prepare(); /* Prepare to write GRAM */
            LCD_WriteRAM(Color);
            xsta++;
            LCD_SetCursor(xsta, ysta);
        }
    }
}
/*****************************************************************************
** Function name:       void LCD_DrawCircle(uint16_t x0, uint16_t y0, uint8_t r)
** Descriptions:        画圆
** input parameters:    x0 中心点横坐标
                          y0 中心点纵坐标
                            r  半径
** output parameters:   无
** Returned value:      无
******************************************************************************/
void LCD_DrawCircle(uint16_t x0, uint16_t y0, uint8_t r)
{
    int a, b;
    int di;
    a  = 0;
    b  = r;
    di = 3 - (r << 1); //判断下个点位置的标志
    while (a <= b)
    {
        LCD_DrawPoint(x0 - b, y0 - a); // 3
        LCD_DrawPoint(x0 + b, y0 - a); // 0
        LCD_DrawPoint(x0 - a, y0 + b); // 1
        LCD_DrawPoint(x0 - b, y0 - a); // 7
        LCD_DrawPoint(x0 - a, y0 - b); // 2
        LCD_DrawPoint(x0 + b, y0 + a); // 4
        LCD_DrawPoint(x0 + a, y0 - b); // 5
        LCD_DrawPoint(x0 + a, y0 + b); // 6
        LCD_DrawPoint(x0 - b, y0 + a);
        a++;

        /*使用Bresenham算法画圆*/
        if (di < 0)
            di += 4 * a + 6;
        else
        {
            di += 10 + 4 * (a - b);
            b--;
        }
        LCD_DrawPoint(x0 + a, y0 + b);
    }
}

/*****************************************************************************
** Function name:       void Draw_Circle(uint16_t x0, uint16_t y0, uint8_t r)
** Descriptions:        画矩形
** input parameters:    xsta X起始坐标
                          ysta Y起始坐标
                            xend X结束坐标
                            yend Y结束坐标
** output parameters:   无
** Returned value:      无
******************************************************************************/
void LCD_DrawRectangle(uint16_t xsta, uint16_t ysta, uint16_t xend, uint16_t yend)
{
    LCD_DrawLine(xsta, ysta, xend, ysta);
    LCD_DrawLine(xsta, ysta, xsta, yend);
    LCD_DrawLine(xsta, yend, xend, yend);
    LCD_DrawLine(xend, ysta, xend, yend);
}

void LCD_DrawPixel(uint16_t xsta, uint16_t ysta, uint16_t color)
{
    LCD_SetCursor(xsta, ysta); //设置光标位置                  */
    LCD_WriteRAM_Prepare();
    LCD_WR_DATA(color);
}
/***************************************************************************************************
** Function name:       void LCD_ShowChar(uint8_t x, uint16_t y, uint8_t num, uint8_t size, uint16_t PenColor, uint16_t BackColor)
** Descriptions:        显示一个字符
** input parameters:    x,y      起始坐标(x:0~234 y:0~308)
                            num       字符ASCII码值
                            size      字符大小,使用默认8*16
                            PenColor  字体颜色
                            BackColor 字体背景颜色
** output parameters:   无
** Returned value:      无
****************************************************************************************************/
void LCD_ShowChar(uint8_t x, uint16_t y, uint8_t num, uint8_t size, uint16_t PenColor, uint16_t BackColor)
{
    uint8_t temp;
    uint8_t pos, t;
    if (x > MAX_CHAR_POSX || y > MAX_CHAR_POSY) return;
    if (DeviceCode == 0x8999) //驱动IC为SSD1298
    {
        if (XY) //竖屏显示
        {
            LCD_WindowMax(x, y, x + size / 2, y + size); //设置窗口
            LCD_WriteReg(0x11, 0x6870);
            LCD_SetCursor(x, y);
        }
        else //横屏显示
        {
            LCD_WindowMax(x, y - size / 2, x + size, y); //设置窗口
            LCD_WriteReg(0x11, 0x6858);
            LCD_SetCursor(x, y - 1); //设置光标位置
        }
    }
    else if (DeviceCode == 0x9919) //驱动IC为SSD2119
    {
        if (XY) //竖屏显示
        {
            LCD_WindowMax(x, y, x + size / 2, y + size); //设置窗口
            LCD_WriteReg(0x01, 0x32EF);                  //输出控制寄存器01
            LCD_WriteReg(0x11, 0x6038);                  //设置GRAM自增方向
            LCD_SetCursor(y, x);
        }
        else //横屏显示
        {
            LCD_WindowMax(x, y, x + size, y + size / 2); //设置窗口
            LCD_SetCursor(y, x);                         //设置光标位置
        }
    }
    else if (DeviceCode == 0x9325 || DeviceCode == 0x9328)
    {
        if (XY)
        {
            LCD_WindowMax(x, y, (size / 2 - 1), size - 1); //设置窗口    驱动IC为ILI9325/9328
            LCD_WriteReg(LCD_REG_3, 0x1030);
            LCD_SetCursor(x, y); //设置光标位置
        }
        else
        {
            LCD_WindowMax(x, y + (size / 2), size - 1, (size / 2) - 1);
            LCD_WriteReg(LCD_REG_3, 0x1098); // 0x1068
            LCD_SetCursor(x, y);
        }
    }
    LCD_WriteRAM_Prepare(); //开始写入GRAM
    num = num - ' ';        //得到偏移后的值
    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(PenColor); //画字体颜色 一个点
            }
            else
                LCD_WR_DATA(BackColor); //画背景颜色 一个点
            temp >>= 1;
        }
    }
    LCD_WindowMax(0x0000, 0x0000, 240, 320); //恢复窗体大小
}
/**********************************************************************************
** Function name:       unsigned int mypow(unsigned int m,unsigned int n)
** Descriptions:        m的n次方 用于取出数值每一位
** input parameters:      m进制:unsigned int m
**                                            n次方:unsigned int n
** output parameters:   m^n
** Returned value:      无
************************************************************************************/
uint32_t mypow(uint8_t m, uint8_t n)
{
    uint32_t result = 1;
    while (n--) result *= m;
    return result;
}

/*********************************************************************************************
** Function name:       void LCD_ShowNum(uint8_t x,uint8_t y,uint32_t num,uint8_t len, uint16_t PenColor, uint16_t BackColor)
** Descriptions:        显示数字(0~4294967295);
** input parameters:      x起始:     uint8_t x
                                            y起始:     uint8_t y
                                            数值:       num
                                            有效长度:  len
                        字体颜色:   PenColor
                        背景颜色:  BackColor
** output parameters:   无
** Returned value:      无
************************************************************************************************/
void LCD_ShowNum(uint8_t x, uint8_t y, uint32_t num, uint8_t len, uint16_t PenColor, uint16_t BackColor)
{
    uint8_t size = 16; // 这里使用默认的16*8
    uint8_t t, temp;
    uint8_t enshow = 0;
    for (t = 0; t < len; t++)
    {
        temp = (num / mypow(10, len - t - 1)) % 10;
        if (enshow == 0 && t < (len - 1))
        {
            if (temp == 0)
            {
                LCD_ShowChar(x + (size / 2) * t, y, ' ', size, PenColor, BackColor);
                LCD_ShowChar(x + (size / 2) * t, y, '0', size, PenColor, BackColor);
                continue;
            }
            else
                enshow = 1;
        }
        LCD_ShowChar(x + (size / 2) * t, y, temp + '0', size, PenColor, BackColor);
    }
}

/*********************************************************************************************
** Function name:       void LCD_ShowCharString(uint16_t x, uint16_t y, const uint8_t *p, uint16_t PenColor, uint16_t BackColor)
** Descriptions:        显示字符(此函数不能单独调用)
** input parameters:      x,y      起始坐标
                          p         指向字符串起始地址
                            PenColor  字符颜色
                            BackColor 背景颜色
** output parameters:   无
** Returned value:      无
************************************************************************************************/
void LCD_ShowCharString(uint16_t x, uint16_t y, const uint8_t *p, uint16_t PenColor, uint16_t BackColor)
{
    uint8_t size = 16; //字符大小默认16*8

    if (x > MAX_CHAR_POSX)
    {
        x = 0;
        y += size;
    } //超出X轴字体最小单位,换行
    if (y > MAX_CHAR_POSY)
    {
        y = x = 0;
        LCD_Clear(WHITE);
    }                                                        //超出Y轴字体最小单位,回到原点,并且清屏
    LCD_ShowChar(x, 320 - y, *p, size, PenColor, BackColor); // 0表示非叠加方式
}

/**********************************************************************************
** Function name:       uint16_t findHzIndex(uint8_t *hz)
** Descriptions:        索引汉字存储的内存地址
** input parameters:      hz
** output parameters:   无
** Returned value:      无
************************************************************************************/
uint16_t findHzIndex(uint8_t *hz) // 在自定义汉字库在查找所要显示
                                  // 的汉字的位置
{
    uint16_t i       = 0;
    FNT_GB16 *ptGb16 = (FNT_GB16 *)GBHZ_16; // ptGb16指向GBHZ_16
    while (ptGb16[i].Index[0] > 0x80)
    {
        if ((*hz == ptGb16[i].Index[0]) && (*(hz + 1) == ptGb16[i].Index[1])) //汉字用两位来表示地址码
        {
            return i;
        }
        i++;
        if (i > (sizeof((FNT_GB16 *)GBHZ_16) / sizeof(FNT_GB16) - 1)) //搜索下标约束
        {
            break;
        }
    }
    return 0;
}

/************************************************************************************************
** Function name:       void WriteOneHz(uint16_t x0, uint16_t y0, uint8_t *pucMsk, uint16_t PenColor, uint16_t BackColor)
** Descriptions:        显示一个汉字(此函数不能单独作为汉字字符显示)
** input parameters:      x0,y0      起始坐标
                            *pucMsk    指向字符串地址
                            PenColor     字符颜色
                            BackColor  背景颜色
** output parameters:   无
** Returned value:      无
************************************************************************************************/
void WriteOneHz(uint16_t x0, uint16_t y0, uint8_t *pucMsk, uint16_t PenColor, uint16_t BackColor)
{
    uint16_t i, j;
    uint16_t mod[16]; //当前字模 16*16
    uint16_t *pusMsk; //当前字库地址
    uint16_t y;

    uint16_t size = 16; //汉字默认大小16*16

    pusMsk = (uint16_t *)pucMsk;

    for (i = 0; i < 16; i++) //保存当前汉字点阵式字模
    {
        mod[i] = *pusMsk;                                             //取得当前字模,半字对齐访问
        mod[i] = ((mod[i] & 0xff00) >> 8) | ((mod[i] & 0x00ff) << 8); //字模交换高低字节
        pusMsk = pusMsk + 1;
    }
    y = x0;
    if (DeviceCode == 0x8999) //驱动IC为SSD1298
    {
        if (XY) //竖屏显示
        {
            LCD_WindowMax(x0, y0, x0 + size, y0 + size); //设置窗口
            LCD_WriteReg(0x11, 0x6870);
            LCD_SetCursor(x0, y0);
        }
        else //横屏显示
        {
            LCD_WindowMax(x0, y0 - size, x0 + size, y0); //设置窗口
            LCD_WriteReg(0x11, 0x6858);                  //
            LCD_SetCursor(x0, y0 - 1);                   //设置光标位置
        }
    }
    else if (DeviceCode == 0x9919) //驱动IC为SSD2119
    {
        if (XY) //竖屏显示
        {

            LCD_WindowMax(x0, y0, x0 + size, y0 + size); //设置窗口
            LCD_WriteReg(0x01, 0x32EF);                  //输出控制寄存器01
            LCD_WriteReg(0x11, 0x6038);                  //设置GRAM自增方向
            LCD_SetCursor(y0, x0);
        }
        else //横屏显示
        {
            LCD_WindowMax(x0, y0, x0 + size, y0 + size);
            LCD_SetCursor(y0, x0); //设置光标位置
        }
    }

    else if (DeviceCode == 0x9325 || DeviceCode == 0x9328) //驱动IC为ILI9325/9328
    {
        LCD_WindowMax(x0, y0, (size - 1), size - 1);
        if (XY)
            LCD_WriteReg(LCD_REG_3, 0x1030);
        else
            LCD_WriteReg(LCD_REG_3, 0x1098);
        LCD_SetCursor(x0, y0);
    }

    LCD_WriteRAM_Prepare();  //开始写入GRAM
    for (i = 0; i < 16; i++) // 16行
    {
        for (j = 0; j < 16; j++) // 16列
        {
            if ((mod[i] << j) & 0x8000) //显示第i行 共16个点
            {
                LCD_WriteRAM(PenColor);
            }
            else
            {
                LCD_WriteRAM(BackColor); //用读方式跳过写空白点的像素
            }
        }
        y++;
    }
    LCD_WindowMax(0x0000, 0x0000, 240, 320); //恢复窗体大小
}

/**********************************************************************************
** Function name:       void LCD_ShowHzString(uint16_t x0, uint16_t y0, uint8_t *pcStr, uint16_t PenColor, uint16_t BackColor)
** Descriptions:        显示汉字字符串(不能单独调用)
** input parameters:      x0,y0    起始坐标
                            pcStr     指向字符串地址
                            PenColor  字体颜色
                            BackColor 字体背景
** output parameters:   无
** Returned value:      无
************************************************************************************/
void LCD_ShowHzString(uint16_t x0, uint16_t y0, uint8_t *pcStr, uint16_t PenColor, uint16_t BackColor)
{

    uint16_t usIndex;
    uint8_t size     = 16;
    FNT_GB16 *ptGb16 = 0;
    ptGb16           = (FNT_GB16 *)GBHZ_16;

    if (x0 > MAX_HZ_POSX)
    {
        x0 = 0;
        y0 += size;
    } //超出X轴字体最小单位,换行
      // if(y0>MAX_HZ_POSY){y0=x0=0;LCD_Clear(WHITE);}        //超出Y轴字体最小单位,回到原点,并且清屏

    usIndex = findHzIndex(pcStr);
    WriteOneHz(x0, y0, (uint8_t *)&(ptGb16[usIndex].Msk[0]), PenColor, BackColor); //显示一个汉字
}

/**********************************************************************************
** Function name:       void LCD_DisplayStr(unsigned int x, unsigned int y, unsigned char *s,uint16_t PenColor, uint16_t BackColor)
** Descriptions:        显示字符串(可以和汉字混合显示,支持横竖屏切换)
** input parameters:      x,y    起始坐标
                            *s     指向字符串地址
                            PenColor  字体颜色
                            BackColor 字体背景
** output parameters:   无
** Returned value:      无
************************************************************************************/
void LCD_DisplayStr(unsigned int x, unsigned int y, unsigned char *s, uint16_t PenColor, uint16_t BackColor)
{
    if (XY == 0)
    {
        uint16_t change = 0;
        change          = x;
        x               = y;
        y               = change;
    }
    while (*s)
    {
        if (*s > 0x80) //显示汉字
        {
            if (XY)
            {
                LCD_ShowHzString(x, y, s, PenColor, BackColor);
                x += 16;
            }
            else
            {
                switch (DeviceCode)
                {
                    case 0x8999:
                        LCD_ShowHzString(x, 319 - y, s, PenColor, BackColor);
                        break;
                    case 0x9919:
                        LCD_ShowHzString(x, y, s, PenColor, BackColor);
                        break;
                    default:
                        LCD_ShowHzString(x, 303 - y, s, PenColor, BackColor); // 319-16
                        break;
                }
                y += 16;
            }
            s += 2;
        }
        else //非汉字
        {
            if (XY) //竖屏显示
            {
                LCD_ShowChar(x, y, *s++, 16, PenColor, BackColor);
                x += Font_Size / 2;
                if (x >= 232)
                {
                    x = 0;
                    y += Font_Size;
                    if (y >= 304) y = 0;
                }
            }
            else //横屏显示
            {
                switch (DeviceCode)
                {
                    case 0x8999:
                        LCD_ShowChar(x, 319 - y, *s++, 16, PenColor, BackColor);
                        break;
                    case 0x9919:
                        LCD_ShowChar(x, y, *s++, 16, PenColor, BackColor);
                        break;
                    default:
                        LCD_ShowChar(x, 303 - y, *s++, 16, PenColor, BackColor); // 319-16
                        break;
                }
                y += Font_Size / 2;
                if (y >= 312)
                {
                    y = 0;
                    x += Font_Size;
                    if (x >= 224) y = 0;
                }
            }
        }
    }
}

/**********************************************************************************
** Function name:       uint16_t LCD_RGBtoBGR(uint16_t Color)
** Descriptions:        RRRRRGGGGGGBBBBB 改为 BBBBBGGGGGGRRRRR 格式
** input parameters:      Color      RGB 颜色值
** output parameters:   BGR 颜色值
** Returned value:      无
************************************************************************************/
uint16_t LCD_RGBtoBGR(uint16_t Color)
{
    uint16_t r, g, b, bgr;

    b = (Color >> 0) & 0x1f;  //提取B
    g = (Color >> 5) & 0x3f;  //中间六位
    r = (Color >> 11) & 0x1f; //提取R

    bgr = (b << 11) + (g << 5) + (r << 0);

    return (bgr);
}

/**********************************************************************************
** Function name:       void LCD_DrawPicture(uint16_t StartX,uint16_t StartY,uint16_t Xend,uint16_t Yend,uint8_t *pic)
** Descriptions:        图片取模格式为水平扫描,16位颜色模式
** input parameters:      StartX     行起始座标
                        StartY     列起始座标
                        EndX       行结束座标
                        EndY       列结束座标
                        pic        图片头指针
** output parameters:   无
** Returned value:      无
************************************************************************************/
void LCD_DrawPicture(uint16_t StartX, uint16_t StartY, uint16_t Xend, uint16_t Yend, uint8_t *pic)
{
    static uint16_t i = 0, j = 0;
    uint16_t *bitmap = (uint16_t *)pic;
    if (DeviceCode == 0x8999 || DeviceCode == 0x9919)
    {
        LCD_WindowMax(StartX, StartY, Xend, Yend); //设置图片显示窗口大小
    }
    else
    {
        LCD_XYRAM(StartX, StartY, Xend, Yend); // 设置GRAM坐标
    }

    LCD_SetCursor(StartX, StartY);
    LCD_WriteRAM_Prepare();
    for (j = 0; j < Yend - StartY; j++)
    {
        for (i = 0; i < Xend - StartX; i++) LCD_WriteRAM(*bitmap++);
    }

    LCD_WindowMax(0, 0, 240, 320); //恢复窗口
}

/**********************************************************************************
** Function name:      void LCD_ShowLEDNum(uint16_t x,uint16_t y,uint16_t num,uint16_t PenColor, uint16_t BackColor)
** Descriptions:        显示数字数码管字体(暂只支持ili9325/ili9328的竖屏显示)
** input parameters:      x     行起始座标
                        y     列起始座标
                        num   要显示的数字
                        PenColor     字体颜色
                        BackColor    背景颜色
** output parameters:   无
** Returned value:      无
************************************************************************************/
void LCD_ShowLEDNum(uint16_t x, uint16_t y, uint16_t num, uint16_t PenColor, uint16_t BackColor)
{
    uint8_t temp;
    uint8_t pos, i, j;
    LCD_SetCursor(x, y);
    LCD_XYRAM(x, y, x + 24, y + 48); // 设置GRAM坐标
    LCD_WriteRAM_Prepare();          //指向RAM寄存器,准备写数据到RAM
    num = num * 9;
    for (j = 0; j < 9; j++)
    {
        for (pos = 0; pos < 16; pos++)
        {
            temp = led_ma[num][pos];
            for (i = 0; i < 8; i++)
            {
                if (temp & 0x80)
                    LCD_WR_DATA(PenColor);
                else
                    LCD_WR_DATA(BackColor);
                temp <<= 1;
            }
        }
        num++;
    }
}

/**********************************************************************************
** Function name:      void Display_Test(void)
** Descriptions:        显示测试
** input parameters:      无
** output parameters:   无
** Returned value:      无
************************************************************************************/
void Display_Test(void)
{
    char charPData[12];
    uint16_t i = 0, Offset = 0;
    uint16_t color_tab[10] = {WHITE, BLUE, RED, GREEN, MAGENTA, YELLOW, CYAN, BROWN, LGRAY, GRAY};
    for (i = 0; i < 10; i++)
    {
        LCD_ShowLEDNum(Offset, 0, i, color_tab[i], BLACK);
        Offset += 24;
    }
    Offset = 0;
    for (i = 10; i > 0; i--)
    {
        LCD_ShowLEDNum(Offset, 50, i - 1, color_tab[i - 1], BLACK);
        Offset += 24;
    }
    LCD_DisplayStr(96, 120, "SZWB-RedBull", RED, BLACK);
    LCD_DisplayStr(110, 180, "梦想", RED, BLACK);
    LCD_DisplayStr(100, 150, "LCD-Test", RED, BLACK);
    LCD_DisplayStr(50, 210, "旺宝电子-红牛开发板", RED, BLACK);
    LCD_DisplayStr(10, 250, "ILI", RED, BLACK);

    sprintf(charPData, "%0x", DeviceCode);//显示主控型号
    LCD_DisplayStr(50, 250, charPData, RED, BLACK);

    //HAL_Delay(5000);
}

 

main.c

/* USER CODE BEGIN Header */
/**
 ******************************************************************************
 * @file           : main.c
 * @brief          : Main program body
 ******************************************************************************
 * @attention
 *
 * Copyright (c) 2022 STMicroelectronics.
 * All rights reserved.
 *
 * This software is licensed under terms that can be found in the LICENSE file
 * in the root directory of this software component.
 * If no LICENSE file comes with this software, it is provided AS-IS.
 *
 ******************************************************************************
 */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "gpio.h"
#include "fsmc.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_FSMC_Init();
  /* USER CODE BEGIN 2 */
    uint8_t x;
    LCD_Init();//MX_FSMC_Init() 函数已经完成针脚跟fsmc的初始化


  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
    while (1)
    {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
        x++;
        Display_Test();
         if(x>11) x=0;
        HAL_Delay(200);
        switch(x)
         {
                case 0:LCD_Clear(WHITE);break;
               case 1:LCD_Clear(BLACK);break;
               case 2:LCD_Clear(BLUE);break;
               case 3:LCD_Clear(RED);break;
               case 4:LCD_Clear(MAGENTA);break;
               case 5:LCD_Clear(GREEN);break;
               case 6:LCD_Clear(CYAN);break;

               case 7:LCD_Clear(YELLOW);break;
               case 8:LCD_Clear(BRRED);break;
               case 9:LCD_Clear(GRAY);break;
               case 10:LCD_Clear(LGRAY);break;
               case 11:LCD_Clear(BROWN);break;
             
         }
        
    
    
    }
    
    
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
    /* User can add his own implementation to report the HAL error return state */
    __disable_irq();
    while (1)
    {
    }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
    /* User can add his own implementation to report the file name and line number,
       ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

实验现象  

3.00 xSl:/ 复制打开抖音,看看【人在蒙古刚下航母的作品】明白了原理用cubeMX从标准库移植到hal是这么... https://v.douyin.com/6jcfLrT/

 

posted @ 2022-09-09 22:02  kyo413  阅读(252)  评论(0编辑  收藏  举报