打印
[STM32F1]

STM32F103xx TFT液晶显示ASCII字符串、中文、图片并且显示带有镜像和旋转功能

[复制链接]
212|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tpgf|  楼主 | 2023-6-13 08:33 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
编译器说明

1. Toolchain : MDK-ARM Community Version: 5.36.0.0(Kile V5)
2. Encoding  : Encode in UTF-8 without signature
3. Device Specific Packs : Keil.STM32F1xx_DFP.2.3.0.pack
4. C/C++ Preprocessor Symbols : STM32F10X_HD,USE_STDPERIPH_DRIVER
   USE_STDPERIPH_DRIVER :允许使用标准外设驱动
   STM32F10X_HD         :STM32F10x大容量产品
5. Chip Type :ARM Cortex-M3 STM32F103RET6, 72MHZ, Flash:512KByte, ROM:64KByte, LQFP144
6. 在stm32hf10x.h文件中HSE_VALUE为外部高速振荡器,默认8MHZ。此值必须与硬件保持一致。



例程说明

1. STM32F103xx OLED旋转显示图片。
2. 显示图片可实现0度旋转、90度旋转、180度旋转、270度旋转。
3. 提供两种图片取模方式的显示。


一、镜像显示说明


镜像前后图片显示的宽和高保持不变
不管何种镜像方式显示,图片的横坐标都要完全显示
不管何种镜像方式显示,需要先处理完一列的纵坐标,然后再处理横坐标
当图片的高度不为8的整数倍时,只需要显示完图片的实际高度即可,多余部分不用显示
原图显示原理。先显示完第一列,在显示第二例,依次类推直到最后一列;先显示第一列第一个像素,然后纵坐标加1,显示第一列第二个像素,依次类推直到显示完第一列最后一个像素;然后横坐标加一,纵坐标回归原始值,开始显示第二列第一个像素,显示第二列第二个像素,依次类推直到显示完第二列最后一个像素,按照此规律显示完最后一列最后一个像素。
二、旋转显示说明
横轴为图片实际宽度,纵轴为图片显示宽度,图片显示宽度大于等于图片实际宽度。
按列显示,先显示第一列,在显示第二列,以此类推,每显示列中的一个像素纵轴加一,横轴不变,直到纵轴加的数量等于图片显示宽度为止,然后横轴加一,纵轴重设为初始值,开始显示第二列,依次类推,直到显示完最后一列。
90度显示 :纵轴为图片实际高度,横轴为图片显示宽度,图片显示宽度大于等于图片实际宽度。行显示,先显示第一行,在显示第二行,以此类推,每显示行中的一个像素横轴加一,纵轴不变,直到横轴加的数量等于图片显示宽度为止,然后纵轴加一,横轴重设为初始值,开始显示第二行,依次类推,直到显示完最后一行。
三、数据结构和宏定义

/* 液晶显示方向 (0)竖屏 (1)横屏 */
#define LCD_SHOW_DIR                                                                    (0)
#if ( LCD_SHOW_DIR == 0 )
    #define LCD_PHY_SIZE_WIDTH_MAX                                                      (320)
    #define LCD_PHY_SIZE_HEIGHT_MAX                                                     (480)
#else
    #define LCD_PHY_SIZE_WIDTH_MAX                                                      (480)
    #define LCD_PHY_SIZE_HEIGHT_MAX                                                     (320)
#endif







/* 镜像模式 */
typedef enum
{
    MIR_MODE_NORMAL             = 0,    /* 正常模式(0度) */
    MIR_MODE_LEFT_RIGHT         = 1,    /* 左右镜像(90度) */
    MIR_MODE_LEFT_RIGHT_UP_DOWN = 2,    /* 左右上下镜像(180度) */
    MIR_MODE_UP_DOWN            = 3,    /* 上下镜像(270度) */
    MIR_MODE_MAX
}eMirrorMode;

/* 旋转模式 */
typedef enum
{
    ROTAT_MODE_DEG_0   = 0, /* 旋转0度 */
    ROTAT_MODE_DEG_90  = 1, /* 旋转90度 */
    ROTAT_MODE_DEG_180 = 2, /* 旋转180度 */
    ROTAT_MODE_DEG_270 = 3, /* 旋转270度 */
    ROTAT_MODE_MAX
}eRotateMode;

/* 显示模式 */
typedef enum
{
    DIS_MODE_NORMAL    = 0,  /* 正常模式 */
    DIS_MODE_OPPOSITE  = 1,  /* 反显示 */
    DIS_MODE_MAX
}eDisMode;

/* 字节对齐 */
#pragma pack(1)

typedef struct app_lcd
{
    u16 xWidth;         /* 宽度 */
    u16 yHeight;        /* 高度 */
    u32 ID;             /* ID */

    u8  ShowDir;        /* 显示方向 */

    u16 BackColor;       /* 背景色 */
    u16 ForeColor;       /* 前景色 */

    eDisMode    DisplayMode;    /* 显示模式 */
    eMirrorMode MirrorMode;     /* 镜像模式 */
    eRotateMode RotateMode;     /* 旋转模式 */
}LCD_DeviceTypeDef, * pLCD_DeviceTypeDef, * LCD_DeviceTypeDef_t, pLCD_DeviceTypeDef_t;

#pragma pack()








LCD_DeviceTypeDef AppDevLCD =
{
    .xWidth      = LCD_PHY_SIZE_WIDTH_MAX,
    .yHeight     = LCD_PHY_SIZE_HEIGHT_MAX,
    .ID          = 0,

    .ShowDir     = LCD_SHOW_DIR,            

    .BackColor   = WHITE,
    .ForeColor   = BLACK,  

    .DisplayMode = DIS_MODE_NORMAL,
    .MirrorMode  = MIR_MODE_NORMAL,
    .RotateMode  = ROTAT_MODE_DEG_0
};


四、显示的ASCII、中文、图片点阵库
ASCII点阵库
/****************************************************************************************************
  (0) !(1)  "(2)  #(3)  $(4)  %(5)  &(6)  '(7)  ((8)  )(9)  *(10) +(11) ,(12) -(13) .(14) /(15)
0(16) 1(17) 2(18) 3(19) 4(20) 5(21) 6(22) 7(23) 8(24) 9(25) :(26) ;(27) <(28) =(29) >(30) ?(31)
@(32) A(33) B(34) C(35) D(36) E(37) F(38) G(39) H(40) I(41) J(42) K(43) L(44) M(45) N(46) O(47)
P(48) Q(49) R(50) S(51) T(52) U(53) V(54) W(55) X(56) Y(57) Z(58) [(59) \(60) ](61) ^(62) _(63)
`(64) a(65) b(66) c(67) d(68) e(69) f(70) g(71) h(72) i(73) j(74) k(75) l(76) m(77) n(78) o(79)
p(80) q(81) r(82) s(83) t(84) u(85) v(86) w(87) x(88) y(89) z(90) {(91) |(92) }(93) ~(94)

* ASCII常规字符集:
* !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
*
* 1. PCtoLCD2018.exe : 宋体 + 阴码 + 逐列式 + 逆向(低位在前) + C51格式 + 等比缩放
* 2. 英文长宽点阵集(6x12),字宽(12),字高(12)
****************************************************************************************************/
const unsigned char ASCII_FONT_1206[95][12] =
{
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/
    {0x00,0x00,0x00,0x00,0x7C,0x02,0x00,0x00,0x00,0x00,0x00,0x00},/*"!",1*/
    {0x00,0x00,0x04,0x00,0x03,0x00,0x04,0x00,0x03,0x00,0x00,0x00},/*""",2*/
    {0x90,0x00,0xFC,0x03,0x90,0x00,0xFC,0x03,0x90,0x00,0x00,0x00},/*"#",3*/
    {0x18,0x01,0x24,0x02,0xFE,0x07,0x44,0x02,0x88,0x01,0x00,0x00},/*"$",4*/
    {0x38,0x00,0x44,0x03,0xF8,0x00,0xD0,0x01,0x2C,0x02,0xC0,0x01},/*"%",5*/
    {0xC0,0x01,0x38,0x02,0xE4,0x02,0x18,0x01,0xE0,0x02,0x20,0x01},/*"&",6*/
    ..............................
};



/****************************************************************************************************
* ASCII常规字符集:
* !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
*
* 1. PCtoLCD2018.exe : 宋体 + 阴码 + 逐列式 + 逆向(低位在前) + C51格式 + 等比缩放
* 2. 英文长宽点阵集(6x16),字宽(16),字高(16)
****************************************************************************************************/
const unsigned char ASCII_FONT_1608[95][16] =
{
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/
    {0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"!",1*/
    {0x00,0x00,0x10,0x00,0x0C,0x00,0x02,0x00,0x10,0x00,0x0C,0x00,0x02,0x00,0x00,0x00},/*""",2*/
    ..............................
};



/****************************************************************************************************
* ASCII常规字符集:
* !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
*
* 1. PCtoLCD2018.exe : 宋体 + 阴码 + 逐列式 + 逆向(低位在前) + C51格式 + 等比缩放
* 2. 英文长宽点阵集(12x24),字宽(24),字高(24)
****************************************************************************************************/
const unsigned char ASCII_FONT_2412[95][36] =
{
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/
    {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x77,0x1C,0xF0,0x0F,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"!",1*/
    {0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x60,0x00,0x00,0x30,0x00,0x00,0x1C,0x00,0x00,0x8C,0x00,0x00,0x60,0x00,0x00,0x30,0x00,0x00,0x1C,0x00,0x00,0x0C,0x00,0x00,0x00,0x00,0x00},/*""",2*/
    ..............................
};




中文点阵库
/* (16 X 16 , 宋体 ) */
const unsigned char ChineseDemo[10][54] =
{
    //  岑(0) 凌(1) 盛(2) 羽(3) 汉(4) 字(5) 显(6) 示(7) 例(8) 程(9)
    {0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x02,0x00,0x0E,0x02,0x00,0x08,0x01,0x00,0x08,0x05,0x00,0x88,0x04,0x00,0x48,0x04,0x00,0xB0,0x04,0x00,0x2F,0x07,0x00,0x48,0xC4,0x00,0x88,0x34,0x00,0x08,0x0D,0x00,0x08,0x01,0x00,0x1E,0x03,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"岑",0*/
    {0x00,0x00,0x00,0x02,0x04,0x00,0x0C,0x7C,0x00,0x18,0x07,0x00,0xE0,0x00,0x01,0x38,0x22,0x01,0x20,0x11,0x01,0xA0,0x88,0x00,0x44,0x86,0x00,0x24,0x4B,0x00,0x3F,0x32,0x00,0x24,0x52,0x00,0x44,0xCC,0x00,0xA4,0x86,0x00,0xA4,0x80,0x00,0xA0,0x81,0x01,0x00,0x00,0x00,0x00,0x00,0x00},/*"凌",1*/
    {0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x86,0x00,0x80,0x81,0x00,0x7C,0xFC,0x00,0x24,0x84,0x00,0x24,0x86,0x00,0xC4,0xFB,0x00,0x24,0x86,0x00,0x04,0x85,0x00,0x1F,0xF9,0x00,0xE4,0x84,0x00,0xC5,0x84,0x00,0x36,0xFD,0x00,0x14,0x82,0x00,0x04,0x82,0x00,0x80,0x03,0x00,0x00,0x00,0x00},/*"盛",2*/
    ..............................
};



图片点阵库
//Img2Lcd.exe ==> 垂直扫描 + 单色 + 字节内像素数据反序(低位在前)
const unsigned char Image_Tree_43x47[258] =
{
    0X00,0X00,0X00,0X80,0X00,0X00,0X00,0X00,0X00,0XC0,0X00,0X00,0X00,0X00,0X00,0XE0,
    0X00,0X00,0X00,0X00,0X20,0XF0,0X00,0X00,0X00,0X00,0X30,0XF8,0X00,0X00,0X00,0X00,
    0X38,0XFC,0X00,0X00,0X00,0X08,0X3C,0XFE,0X00,0X00,0X00,0X0C,0X3E,0XFF,0X00,0X00,
    0X00,0X0E,0XBF,0XFF,0X00,0X00,0X00,0X8F,0XFF,0XFF,0X00,0X00,0X80,0XCF,0XFF,0XFF,
    ..............................
};


//Img2Lcd.exe ==> 垂直扫描 + 单色 + 字节内像素数据反序(低位在前)
const unsigned char gImage_P2P_73x44[438] =
{
    0X80,0X01,0X00,0X00,0X00,0X00,0XE0,0X01,0X00,0X00,0X00,0X00,0X78,0X00,0X00,0X00,
    0X00,0X00,0X3C,0X00,0X00,0X00,0X00,0X00,0X27,0X00,0X00,0X00,0X00,0X00,0X27,0X30,
    0X00,0X00,0X00,0X00,0X3C,0X78,0X00,0X00,0X00,0X00,0X78,0XFC,0X00,0X00,0X00,0X00,
    0XE0,0XFD,0X00,0X00,0X00,0X00,0X80,0X79,0X00,0X00,0X00,0X00,0X00,0X30,0X00,0X00,
    ..............................
};



五、显示公共函数

/* 加操作 */
static void vHandler_Inc(u16 * pDat, u8 n)
{
    *pDat += n;
}


/* 减操作 */
static void vHandler_Sub(u16 * pDat, u8 n)
{
    *pDat -= n;
}




/* 获取字符数据源地址 */
static void vGet_CharSrc(u8 chr, u8 charSize, u8 ** pSrc)
{
    switch (charSize)
    {
        case ASCII_FONT_TYPE_1206 :
            *pSrc = (u8 *)(&ASCII_FONT_1206[chr - ' ']);
        break;

        case ASCII_FONT_TYPE_1608 :
            *pSrc = (u8 *)(&ASCII_FONT_1608[chr - ' ']);
        break;

        case ASCII_FONT_TYPE_2412 :
            *pSrc = (u8 *)(&ASCII_FONT_2412[chr - ' ']);
        break;

        default: *pSrc = NULL; break;
    }
}





六、显示ASCII常规字符串
/* 显示字符 */
static void vTFT_Display_Char(u16 x, u16 y, u8 chr, u8 charSize, eDisMode disMode)
{
    u8 charByte = 0, k = 0, i = 0;
    u8 dat = 0, * pSrcDat = NULL;
    u16 y0 = 0;


    //获取字符数据源地址
    vGet_CharSrc(chr, charSize, &pSrcDat);
    if (pSrcDat == NULL)
    {
        return;
    }


    y0 = y;// 原始纵坐标

    // 字符点阵占用字节数
    charByte = ((charSize >> 3) + ((charSize & 0x07) ? 1 : 0)) * (charSize >> 1);  

    // 遍历字符点阵数据
    for(k = 0; k < charByte; ++k)
    {
        dat = pSrcDat[k];
        for(i = 0; i < 8; ++i)
        {
            // 显示有效范围
            if ((x < AppDevLCD.xWidth) && (y < AppDevLCD.yHeight))
            {
                if ((dat >> i) & 0x01)//低位在前
                {
                    vTFT_DrawPoint(x, y, AppDevLCD.ForeColor);//正常模式
                }
                else if (disMode & DIS_MODE_OPPOSITE)
                {
                    vTFT_DrawPoint(x, y, AppDevLCD.BackColor);//反显模式
                }
            }

            y++;// 纵坐标自加
            if (abs(y - y0) == charSize)//纵坐标偏移量等于字符点阵高度
            {
                y = y0;
                x++;
                break;
            }
        }
    }
}


/* 显示字符串 */
void vTFT_Display_String(u16 x, u16 y, u8 * pStr, u8 strSize)
{
    /* 显示模式越界 */
    if (AppDevLCD.DisplayMode >= DIS_MODE_MAX)
    {
        return;
    }

    //显示ASCII常规字符
    while ((*pStr >= ' ') && (*pStr <= '~'))
    {
        /* 剩余纵轴小于字体高度 */
        if (y > (AppDevLCD.yHeight - strSize))
        {
            return;
        }

        /* 剩余的横纵小于字体宽度 换行显示 */
        if (x > (AppDevLCD.xWidth - (strSize >> 1)))
        {
            y += strSize;
            x  = 0;
        }

        vTFT_Display_Char(x, y, *pStr, strSize, AppDevLCD.DisplayMode);
        x += (strSize >> 1);
        pStr++;
    }
}



七、镜像显示公共函数/* 获取横纵轴的操作 */
static void vGet_xyHandler_Mirror(eMirrorMode mode, void (** xHand)(u16 * x, u8 n), void (** yHand)(u16 * y, u8 n))
{
    switch (mode)
    {
        case MIR_MODE_NORMAL:
        {
            *xHand = &vHandler_Inc;
            *yHand = &vHandler_Inc;
        }
        break;

        case MIR_MODE_LEFT_RIGHT:
        {
            *xHand = &vHandler_Sub;
            *yHand = &vHandler_Inc;
        }
        break;

        case MIR_MODE_LEFT_RIGHT_UP_DOWN:
        {
            *xHand = &vHandler_Sub;
            *yHand = &vHandler_Sub;
        }
        break;

        case MIR_MODE_UP_DOWN:
        {
            *xHand = &vHandler_Inc;
            *yHand = &vHandler_Sub;
        }
        break;

        default: break;
    }
}



八、显示ASCII常规字符串(带镜像)
/* 显示字符(带镜像) */
static void vTFT_DisplayChar_Mirror(u16 x, u16 y, u8 chr, u8 charSize, eDisMode disMode, eMirrorMode mirMode)
{
    u8 charByte = 0, k = 0, i = 0;
    u8 dat = 0, * pSrcDat = NULL;
    void (* xHandler)(u16 * x0, u8 n) = NULL;
    void (* yHandler)(u16 * y0, u8 n) = NULL;
    u16 y0 = 0;
        u8 count = 0;

       
    //横纵坐标的操作
    vGet_xyHandler_Mirror(mirMode, &xHandler, &yHandler);

    //获取字符数据源地址
    vGet_CharSrc(chr, charSize, &pSrcDat);
    if (pSrcDat == NULL)
    {
        return;
    }


    //显示ASCII常规字符
    y0 = y;

    // 字符点阵占用字节数
    charByte = ((charSize >> 3) + ((charSize & 0x07) ? 1 : 0)) * (charSize >> 1);  

    // 遍历字符点阵数据
    for(k = 0; k < charByte; ++k)
    {
        dat = pSrcDat[k];
        for(i = 0; i < 8; ++i)
        {
            // 显示有效范围
            if ((x < AppDevLCD.xWidth) && (y < AppDevLCD.yHeight))
            {
                if ((dat >> i) & 0x01)//低位在前
                {
                    vTFT_DrawPoint(x, y, AppDevLCD.ForeColor);//正常模式
                }
                else if (disMode & DIS_MODE_OPPOSITE)
                {
                    vTFT_DrawPoint(x, y, AppDevLCD.BackColor);//反显模式
                }
            }

                        count++;
            yHandler(&y, 1);//纵坐标处理
            if (count == charSize)
            {
                y = y0;
                count = 0;
                xHandler(&x, 1);//横坐标处理
                break;
            }
        }
    }
}


/* 显示字符串(带镜像) */
void vTFT_DisplayString_Mirror(u16 x, u16 y, u8 * pStr, u8 strSize)
{
    /* 显示模式越界 镜像模式越界 */
    if ((AppDevLCD.DisplayMode >= DIS_MODE_MAX) || (AppDevLCD.MirrorMode >= MIR_MODE_MAX))
    {
        return;
    }

    //显示ASCII常规字符
    while ((*pStr >= ' ') && (*pStr <= '~'))
    {
        /* 剩余纵轴小于字体高度 */
        if (y > (AppDevLCD.yHeight - strSize))
        {
            return;
        }

        /* 剩余的横纵小于字体宽度 换行显示 */
        if (x > (AppDevLCD.xWidth - (strSize >> 1)))
        {
            y += strSize;
            x  = 0;
        }

        vTFT_DisplayChar_Mirror(x, y, *pStr, strSize, AppDevLCD.DisplayMode, AppDevLCD.MirrorMode);
        x += strSize >> 1;
        pStr++;
    }
}



九、旋转显示公共函数
/* 获取横纵轴的操作 */
static void vGet_xyHandler_Rotate(eRotateMode mode, void (** prevHand)(u16 * prev, u8 n), void (** backHand)(u16 * back, u8 n))
{
    switch(mode)
    {
        case ROTAT_MODE_DEG_0:
        {
            *prevHand = &vHandler_Inc;
            *backHand = &vHandler_Inc;
        }
        break;

        case ROTAT_MODE_DEG_90:
        {
            *prevHand = &vHandler_Sub;
            *backHand = &vHandler_Inc;
        }
        break;

        case ROTAT_MODE_DEG_180:
        {
            *prevHand = &vHandler_Sub;
            *backHand = &vHandler_Sub;
        }
        break;

        case ROTAT_MODE_DEG_270:
        {
            *prevHand = &vHandler_Inc;
            *backHand = &vHandler_Sub;
        }
        break;

        default : break;
    }
}



十、显示ASCII常规字符串(带旋转)
/* 显示字符(带旋转) */
void vTFT_DisplayChar_Rotate(u16 x, u16 y, u8 chr, u8 charSize, eRotateMode rotateMode)
{
    void (* prevHandler)(u16 * prev, u8 n) = NULL;
    void (* backHandler)(u16 * back, u8 n) = NULL;

    u16 k = 0, j = 0, i = 0, n = 0;
    u16 * xyPrev = NULL; //前半部分
    u16 * xyBack = NULL; //后半部分
    u16 xyPrevInitVal = 0;
    u16 charByte = 0;
    u8 dat = 0, * pSrcDat = NULL;
    u8 count = 0;



    //获取字符数据源地址
    vGet_CharSrc(chr, charSize, &pSrcDat);
    if (pSrcDat == NULL)
    {
        return;
    }

       
    /* 前后部分值处理 xy初始值 间隔值处理 */
    if((ROTAT_MODE_DEG_0 == rotateMode) || (ROTAT_MODE_DEG_180 == rotateMode))
    {
        xyPrev = &y; //先处理纵轴
        xyBack = &x; //后处理横纵
        xyPrevInitVal = y;
    }
    else
    {
        xyPrev = &x;
        xyBack = &y;
        xyPrevInitVal = x;
    }


    /* 前后部分处理,x y坐标变化 */
    vGet_xyHandler_Rotate(rotateMode, &prevHandler, &backHandler);


    // 字符点阵占用字节数
    charByte = ((charSize >> 3) + ((charSize & 0x07) ? 1 : 0)) * (charSize >> 1);  

    // 遍历字符点阵数据
    for(k = 0; k < charByte; ++k)
    {
        dat = pSrcDat[k];
        for(i = 0; i < 8; ++i)
        {
            // 显示有效范围
            if ((x < AppDevLCD.xWidth) && (y < AppDevLCD.yHeight))
            {
                if ((dat >> i) & 0x01)//低位在前
                {
                    vTFT_DrawPoint(x, y, AppDevLCD.ForeColor);//正常模式
                }
                else if (AppDevLCD.DisplayMode & DIS_MODE_OPPOSITE)
                {
                    vTFT_DrawPoint(x, y, AppDevLCD.BackColor);//反显模式
                }
            }

            count++;//高度计数
            prevHandler(xyPrev, 1);//前部分处理
            if (count == charSize)
            {
                count   = 0;
                *xyPrev = xyPrevInitVal;//赋初值
                backHandler(xyBack, 1);//后部分处理
                break;
            }
        }
    }
}

/* 显示字符串(带旋转) */
void vTFT_DisplayString_Rotate(u16 x, u16 y, u8 * pStr, u8 strSize)
{
    /* 旋转模式越界 */
    if (AppDevLCD.RotateMode >= ROTAT_MODE_MAX)
    {
        return;
    }

    //显示ASCII常规字符
    while ((*pStr >= ' ') && (*pStr <= '~'))
    {
        /* 剩余纵轴小于字体高度 */
        if (y > (AppDevLCD.yHeight - strSize))
        {
            return;
        }

        /* 剩余的横纵小于字体宽度 换行显示 */
        if (x > (AppDevLCD.xWidth - (strSize >> 1)))
        {
            y += strSize;
            x  = 0;
        }

        vTFT_DisplayChar_Rotate(x, y, *pStr, strSize, AppDevLCD.RotateMode);
        x += (strSize >> 1);
        pStr++;
    }
}




十一、显示中文字符串(带镜像)
/* 显示中文字符(带镜像) */
static void vTFT_DisplayChineseChar_Mirror(u16 x, u16 y, u16 xWidth, u16 yHeight, const u8 * pData)
{
        void (* xHandler)(u16 * x0, u8 n) = NULL;
    void (* yHandler)(u16 * y0, u8 n) = NULL;
    u16 y0 = 0;
    u16 yMax = 0;
    u8 dat = 0;
    u16 count = 0;
    u16 k = 0, j = 0, n = 0, i = 0;
       

        //横纵坐标的操作
    vGet_xyHandler_Mirror(AppDevLCD.MirrorMode, &xHandler, &yHandler);

    y0 = y;// 原始纵坐标

    //高度
    yMax = (yHeight >> 3) + ((yHeight & 0x07) ? 1 : 0);

    for(k = 0; k < xWidth; k++)
    {
        for(j = 0; j < yMax; j++)
        {
            dat = pData[n++];
            for(i = 0; i < 8; i++)
            {
                if ((y < AppDevLCD.yHeight) && (x < AppDevLCD.xWidth))
                {
                    if ((dat >> i) & 0x01)//低位在前
                    {
                        vTFT_DrawPoint(x, y, AppDevLCD.ForeColor);//正常模式
                    }
                    else if (AppDevLCD.DisplayMode &  DIS_MODE_OPPOSITE)
                    {
                        vTFT_DrawPoint(x, y, AppDevLCD.BackColor);//反显模式
                    }
                }

                count++;
                yHandler(&y, 1);//纵坐标处理
                if (count == yHeight)
                {
                    y = y0;
                    count = 0;
                    xHandler(&x, 1);//横坐标处理
                    break;
                }
            }
        }
    }
}


/* 显示中文字符串(带镜像) */
void vTFT_Display_ChineseString_Mirror(u16 x, u16 y, u16 xWidth, u16 yHeight, u8 * pData, u16 num)
{
    u16 i = 0;
    u8 charByte = 0;
    u8 * pMem = pData;


    //镜像模式越界
    if ((!num) || (AppDevLCD.MirrorMode >= MIR_MODE_MAX))
    {
        return;
    }

        // 字符点阵占用字节数
    charByte = ((yHeight >> 3) + ((yHeight & 0x07) ? 1 : 0)) * xWidth;  

        for (i = 0; i < num; ++i)
        {
                /* 剩余纵轴小于字体高度 */
        if (y > (AppDevLCD.yHeight - yHeight))
        {
            return;
        }

        /* 剩余的横纵小于字体宽度 换行显示 */
        if (x > (AppDevLCD.xWidth - xWidth))
        {
            y += yHeight;
            x  = 0;
        }
       
                pMem = pData + (charByte * i);
                vTFT_DisplayChineseChar_Mirror(x, y, xWidth, yHeight, pMem);
                x += xWidth;
        }
}



十二、显示中文字符串(带旋转)
/* 显示中文字符(带旋转) */
static void vTFT_Display_ChineseChar_Rotate(u16 x, u16 y, u16 xWidth, u16 yHeight, const u8 * pData)
{

    void (* prevHandler)(u16 * prev, u8 n) = NULL;
    void (* backHandler)(u16 * back, u8 n) = NULL;

    u16 k = 0, j = 0, i = 0, n = 0;
    u16 * xyPrev = NULL; //前半部分
    u16 * xyBack = NULL; //后半部分
    u16 xyPrevInitVal = 0;
    u16 charByte = 0;
    u8 dat = 0, * pSrcDat = NULL;
    u8 count = 0;
    u16 yMax = 0;



    /* 前后部分值处理 xy初始值 */
    if((ROTAT_MODE_DEG_0 == AppDevLCD.RotateMode) || (ROTAT_MODE_DEG_180 == AppDevLCD.RotateMode))
    {
        xyPrev = &y; //先处理纵轴
        xyBack = &x; //后处理横纵
        xyPrevInitVal = y;
    }
    else
    {
        xyPrev = &x;
        xyBack = &y;
        xyPrevInitVal = x;
    }

    /* 前后部分处理,x y坐标变化 */
    vGet_xyHandler_Rotate(AppDevLCD.RotateMode, &prevHandler, &backHandler);

    //高度
    yMax = (yHeight >> 3) + ((yHeight & 0x07) ? 1 : 0);

    for(k = 0; k < xWidth; k++)
    {
        for(j = 0; j < yMax; j++)
        {
            dat = pData[n++];
            for(i = 0; i < 8; i++)
            {
                if ((y < AppDevLCD.yHeight) && (x < AppDevLCD.xWidth))
                {
                    if ((dat >> i) & 0x01)//低位在前
                    {
                        vTFT_DrawPoint(x, y, AppDevLCD.ForeColor);//正常模式
                    }
                    else if (AppDevLCD.DisplayMode &  DIS_MODE_OPPOSITE)
                    {
                        vTFT_DrawPoint(x, y, AppDevLCD.BackColor);//反显模式
                    }
                }


                count++;//高度计数
                prevHandler(xyPrev, 1);//前部分处理
                if (count == yHeight)
                {
                    count   = 0;
                    *xyPrev = xyPrevInitVal;//赋初值
                    backHandler(xyBack, 1);//后部分处理
                    break;
                }
            }
        }
    }
}

/* 显示中文字符串(带旋转) */
void vTFT_Display_ChineseString_Rotate(u16 x, u16 y, u16 xWidth, u16 yHeight, const u8 * pData, u16 num)
{
    u16 i = 0;
    u8 charByte = 0;
    u8 * pMem = (u8 * )pData;



    //镜像模式越界
    if ((!num) || (AppDevLCD.RotateMode >= ROTAT_MODE_MAX))
    {
        return;
    }


    // 字符点阵占用字节数
    charByte = ((yHeight >> 3) + ((yHeight & 0x07) ? 1 : 0)) * xWidth;  

    for (i = 0; i < num; ++i)
        {
                /* 剩余纵轴小于字体高度 */
        if (y > (AppDevLCD.yHeight - yHeight))
        {
            return;
        }

        /* 剩余的横纵小于字体宽度 换行显示 */
        if (x > (AppDevLCD.xWidth - xWidth))
        {
            y += yHeight;
            x  = 0;
        }
       
                pMem = (u8 * )pData + (charByte * i);
                vTFT_Display_ChineseChar_Rotate(x, y, xWidth, yHeight, pMem);
                x += xWidth;
        }
}




十三、显示图片(带镜像)
/* 显示图片(带镜像) */
void vTFT_ShowPicture_Mirror(u16 x, u16 y, u16 xWidth, u16 yHeight, const u8 * pImage)
{
    void (* xHandler)(u16 * x0, u8 n) = NULL;
    void (* yHandler)(u16 * y0, u8 n) = NULL;

    u16 k = 0, j = 0, i = 0, n = 0;
    u16 yMax  = 0;
    u16 y0    = 0;
    u16 y1    = 0;
    u8  dat   = 0;
    u16 count = 0;

    //镜像模式越界
    if (MIR_MODE_MAX <= AppDevLCD.MirrorMode )
    {
        return;
    }

    //横纵坐标的操作
    vGet_xyHandler_Mirror(AppDevLCD.MirrorMode , &xHandler, &yHandler);


    //图片高度
    yMax = (yHeight >> 3) + ((yHeight & 0x07) ? 1 : 0);

    //原始纵坐标
    y0 = y;

    //图片宽度
    for(k = 0; k < xWidth; k++)
    {
        for(j = 0; j < yMax; j++)
        {
            dat = pImage[n++];
            for(i = 0; i < 8; i++)
            {
                if ((y < AppDevLCD.yHeight) && (x < AppDevLCD.xWidth))
                {
                    if ((dat >> i) & 0x01)//低位在前
                    {
                        vTFT_DrawPoint(x, y, AppDevLCD.ForeColor);//正常模式
                    }
                    else if (AppDevLCD.DisplayMode &  DIS_MODE_OPPOSITE)
                    {
                        vTFT_DrawPoint(x, y, AppDevLCD.BackColor);//反显模式
                    }
                }

                count++;
                yHandler(&y, 1);//纵坐标处理
                if (count == yHeight)
                {
                    y = y0;
                    count = 0;
                    xHandler(&x, 1);//横坐标处理
                    break;
                }
            }
        }
    }
}



十四、显示图片(带旋转)
/* 显示图片(带旋转) */
void vTFT_ShowPicture_Rotate(u16 x, u16 y, u16 xWidth, u16 yHeight, const u8 * pImage)
{
    void (* prevHandler)(u16 * prev, u8 n) = NULL;
    void (* backHandler)(u16 * back, u8 n) = NULL;

    u16 k = 0, j = 0, i = 0, n = 0;
    u16 * xyPrev = NULL; //前半部分
    u16 * xyBack = NULL; //后半部分
    u16 xyPrevInitVal = 0;
    u16 charByte = 0;
    u8 dat = 0, * pSrcDat = NULL;
    u8 count = 0;
    u16 yMax = 0;


    /* 旋转模式越界 */
    if (AppDevLCD.RotateMode >= ROTAT_MODE_MAX)
    {
        return;
    }


    /* 前后部分值处理 xy初始值 */
    if((ROTAT_MODE_DEG_0 == AppDevLCD.RotateMode) || (ROTAT_MODE_DEG_180 == AppDevLCD.RotateMode))
    {
        xyPrev = &y; //先处理纵轴
        xyBack = &x; //后处理横纵
        xyPrevInitVal = y;
    }
    else
    {
        xyPrev = &x;
        xyBack = &y;
        xyPrevInitVal = x;
    }

    /* 前后部分处理,x y坐标变化 */
    vGet_xyHandler_Rotate(AppDevLCD.RotateMode, &prevHandler, &backHandler);

    //高度
    yMax = (yHeight >> 3) + ((yHeight & 0x07) ? 1 : 0);

    //图片宽度
    for(k = 0; k < xWidth; k++)
    {
        for(j = 0; j < yMax; j++)
        {
            dat = pImage[n++];
            for(i = 0; i < 8; i++)
            {
                if ((dat >> i) & 0x01)//低位在前
                {
                    vTFT_DrawPoint(x, y, AppDevLCD.ForeColor);//正常模式
                }
                else if (AppDevLCD.DisplayMode &  DIS_MODE_OPPOSITE)
                {
                    vTFT_DrawPoint(x, y, AppDevLCD.BackColor);//反显模式
                }

                count++;//高度计数
                prevHandler(xyPrev, 1);//前部分处理
                if (count == yHeight)
                {
                    count   = 0;
                    *xyPrev = xyPrevInitVal;//赋初值
                    backHandler(xyBack, 1);//后部分处理
                    break;
                }
            }
        }
    }
}



十五、例程测试代码
extern const unsigned char Image_Tree_43x47[258];
extern const unsigned char gImage_P2P_73x44[438];
extern const unsigned char ChineseDemo[10][54];
/* TFT初始化 */
void vLCD_Init(void)
{
    vInit_LCD_GPIO();
    vInit_FSMC();
    vTFT_Write_Factory_Parameter();

    AppDevLCD.ID = ulLCD_Read_ID();
    vTFT_Display_Dir(LCD_SHOW_DIR);
    vTFT_Clear_Screen(WHITE);
    vShow_DeviceTFT_Info();


    AppDevLCD.ForeColor   = BLUE;
    AppDevLCD.BackColor   = BLACK;
        AppDevLCD.DisplayMode = DIS_MODE_NORMAL;
    AppDevLCD.MirrorMode  = MIR_MODE_NORMAL;
        AppDevLCD.RotateMode  = ROTAT_MODE_DEG_0;
       

        // 显示字符串
    vTFT_Display_String(270,   7,  (u8 *)"Sys Res", ASCII_FONT_TYPE_1206);
       
        AppDevLCD.DisplayMode = DIS_MODE_OPPOSITE;
        AppDevLCD.ForeColor   = YELLOW;
    vTFT_Display_String(160, 5,  (u8 *)"System Resets", ASCII_FONT_TYPE_1608);
       
        AppDevLCD.ForeColor   = RED;
        AppDevLCD.DisplayMode = DIS_MODE_NORMAL;
    vTFT_Display_String(0,   0, (u8 *)"System Resets", ASCII_FONT_TYPE_2412);
        vTFT_DrawLine(0, 30, AppDevLCD.xWidth, 30, BLUE);


        // 显示字符串(镜像)
        AppDevLCD.ForeColor   = BLUE;
        AppDevLCD.BackColor   = BLACK;
        AppDevLCD.DisplayMode = DIS_MODE_NORMAL;
        vTFT_DisplayString_Mirror(10, 35, (u8 * )"Resets Clock", ASCII_FONT_TYPE_1608);

        AppDevLCD.MirrorMode = MIR_MODE_LEFT_RIGHT;
        vTFT_DisplayString_Mirror(160, 35, (u8 * )"Resets Clock", ASCII_FONT_TYPE_1608);

        AppDevLCD.MirrorMode = MIR_MODE_UP_DOWN;
        vTFT_DisplayString_Mirror(10, 70, (u8 * )"Resets Clock", ASCII_FONT_TYPE_1608);

        AppDevLCD.MirrorMode = MIR_MODE_LEFT_RIGHT_UP_DOWN;
        vTFT_DisplayString_Mirror(160, 70, (u8 * )"Resets Clock", ASCII_FONT_TYPE_1608);
        vTFT_DrawLine(0, 75, AppDevLCD.xWidth, 75, YELLOW);



        //显示字符串(旋转)
        AppDevLCD.RotateMode = ROTAT_MODE_DEG_0;
        vTFT_DisplayString_Rotate(10, 80, (u8 * )"Resets system", ASCII_FONT_TYPE_1608);

        AppDevLCD.RotateMode = ROTAT_MODE_DEG_90;
        vTFT_DisplayString_Rotate(170, 85, (u8 * )"Resets system", ASCII_FONT_TYPE_1608);

        AppDevLCD.RotateMode = ROTAT_MODE_DEG_180;
        vTFT_DisplayString_Rotate(15, 115, (u8 * )"Resets system", ASCII_FONT_TYPE_1608);

        AppDevLCD.RotateMode = ROTAT_MODE_DEG_270;
        vTFT_DisplayString_Rotate(155, 110, (u8 * )"Resets system", ASCII_FONT_TYPE_1608);
        vTFT_DrawLine(0, 120, AppDevLCD.xWidth, 120, RED);

       

        // 显示中文(镜像)
        AppDevLCD.ForeColor  = RED;
        AppDevLCD.MirrorMode = MIR_MODE_NORMAL;
    vTFT_Display_ChineseString_Mirror(10, 130, 18, 18, (u8 *)ChineseDemo[1], 7);

    AppDevLCD.MirrorMode = MIR_MODE_UP_DOWN;
    vTFT_Display_ChineseString_Mirror(170, 145, 18, 18, (u8 *)ChineseDemo[1], 7);

    AppDevLCD.MirrorMode = MIR_MODE_LEFT_RIGHT;
    vTFT_Display_ChineseString_Mirror(25, 155, 18, 18, (u8 *)ChineseDemo[1], 7);

    AppDevLCD.MirrorMode = MIR_MODE_LEFT_RIGHT_UP_DOWN;
        vTFT_Display_ChineseString_Mirror(185, 170, 18, 18, (u8 *)ChineseDemo[1], 7);
        vTFT_DrawLine(0, 180, AppDevLCD.xWidth, 180, RED);



        // 显示中文(旋转)
        AppDevLCD.ForeColor  = BLUE;
    AppDevLCD.RotateMode = ROTAT_MODE_DEG_0;
    vTFT_Display_ChineseString_Rotate(10,  190, 18, 18, (const u8 *)ChineseDemo[1], 7);
       
        AppDevLCD.RotateMode = ROTAT_MODE_DEG_90;
    vTFT_Display_ChineseString_Rotate(185,  190, 18, 18, (const u8 *)ChineseDemo[1], 7);
       
        AppDevLCD.RotateMode = ROTAT_MODE_DEG_180;
    vTFT_Display_ChineseString_Rotate(25,  230, 18, 18, (const u8 *)ChineseDemo[1], 7);
       
        AppDevLCD.RotateMode = ROTAT_MODE_DEG_270;
    vTFT_Display_ChineseString_Rotate(165,  230, 18, 18, (const u8 *)ChineseDemo[1], 7);
        vTFT_DrawLine(0, 240, AppDevLCD.xWidth, 240, RED);


    AppDevLCD.ForeColor  = BLACK;
        AppDevLCD.MirrorMode = MIR_MODE_NORMAL;
    vTFT_ShowPicture_Mirror(10,  250, 43, 47, Image_Tree_43x47);
    AppDevLCD.MirrorMode = MIR_MODE_UP_DOWN;
    vTFT_ShowPicture_Mirror(80,  295, 43, 47, Image_Tree_43x47);
    AppDevLCD.MirrorMode = MIR_MODE_LEFT_RIGHT;
    vTFT_ShowPicture_Mirror(210, 250, 43, 47, Image_Tree_43x47);
    AppDevLCD.MirrorMode = MIR_MODE_LEFT_RIGHT_UP_DOWN;
    vTFT_ShowPicture_Mirror(280, 295, 43, 47, Image_Tree_43x47);


    AppDevLCD.ForeColor  = RED;
    AppDevLCD.RotateMode = ROTAT_MODE_DEG_0;
    vTFT_ShowPicture_Rotate(0,   310, 73, 44, gImage_P2P_73x44);
    AppDevLCD.RotateMode = ROTAT_MODE_DEG_90;
    vTFT_ShowPicture_Rotate(140,  300, 73, 44, gImage_P2P_73x44);
    AppDevLCD.RotateMode = ROTAT_MODE_DEG_180;
    vTFT_ShowPicture_Rotate(220, 360, 73, 44, gImage_P2P_73x44);
    AppDevLCD.RotateMode = ROTAT_MODE_DEG_270;
    vTFT_ShowPicture_Rotate(240, 370, 73, 44, gImage_P2P_73x44);
    vTFT_DrawLine(0, 375, AppDevLCD.xWidth, 375, RED);



    AppDevLCD.ForeColor = BLUE;
    vTFT_Display_String(10,  380,  (u8 *)"1 ASCII String",  ASCII_FONT_TYPE_1608);
    vTFT_Display_String(170, 380,  (u8 *)"2 String Mirror", ASCII_FONT_TYPE_1608);

    AppDevLCD.ForeColor = RED;
    vTFT_Display_String(10,  405,  (u8 *)"3 String Rotate", ASCII_FONT_TYPE_1608);
    vTFT_Display_String(170, 405,  (u8 *)"4 Chinese Mirror", ASCII_FONT_TYPE_1608);

    AppDevLCD.ForeColor = GREEN;
    vTFT_Display_String(10, 430,  (u8 *)"5 Chinese Rotate", ASCII_FONT_TYPE_1608);
    vTFT_Display_String(170, 430,  (u8 *)"6 Pictrue Mirror", ASCII_FONT_TYPE_1608);

    AppDevLCD.ForeColor = BLACK;
    vTFT_Display_String(10, 455,  (u8 *)"7 Pictrue Rotate", ASCII_FONT_TYPE_1608);
}





————————————————
版权声明:本文为CSDN博主「凌盛羽」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Ceosat/article/details/127679253





使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2028

主题

15903

帖子

14

粉丝