硬汉嵌入式论坛

 找回密码
 立即注册
查看: 362|回复: 3
收起左侧

[emWin] emwin自带FontCvtDemo软件生成的字体如何应用到oled屏?

[复制链接]

22

主题

47

回帖

113

积分

初级会员

积分
113
发表于 2023-7-4 18:43:43 | 显示全部楼层 |阅读模式
FontCvtDemo软件生成的.c字体都是横向扫描,如下的0代码:
===============================================================================
static LCD_CONST_STORAGE unsigned char acLCD_FontCourier_New_20_0030[ 11] =   /* code 0030, DIGIT ZERO */
{
    _XXXX___,
    X____X__,
    X____X__,
    X____X__,
    X____X__,
    X____X__,
    X____X__,
    X____X__,
    X____X__,
    X____X__,
    _XXXX___
};
===============================================================================
但是诸如一些128*64的OLED屏驱动都是以页作为单位驱动,每写一个字节是对应一列的8个像素点,这跟生成的字体正好是相反的。可是emwin自带库里却也是支持像这一类OLED屏的,如果我想简单地把这一块内容移植到自己的工程里,应该如何应用?总不能一个像素像素根据mask倒置一遍吧。。。。那也效率太低了,求助各位大佬出出主意

回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106913
QQ
发表于 2023-7-5 09:21:57 | 显示全部楼层
OLED开显存了吧,你设置下你的字体显示API函数,就是旋转的方式显示即可,这样效率搞。

或者直接提前做好数组的旋转。
回复

使用道具 举报

22

主题

47

回帖

113

积分

初级会员

积分
113
 楼主| 发表于 2023-7-5 10:16:07 | 显示全部楼层
eric2013 发表于 2023-7-5 09:21
OLED开显存了吧,你设置下你的字体显示API函数,就是旋转的方式显示即可,这样效率搞。

或者直接提前做 ...

硬汉哥,旋转的方式显示,但实际数组里一个字节里存的还是横向的8个像素点,不还是得根据mask把每个字节的第一位拎出来,再第二位给拎出来,直到第八位

还是说我想岔了?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106913
QQ
发表于 2023-7-6 09:38:51 | 显示全部楼层
熊大 发表于 2023-7-5 10:16
硬汉哥,旋转的方式显示,但实际数组里一个字节里存的还是横向的8个像素点,不还是得根据mask把每个字节 ...


这个是我们的,做了个任意像素绘制OLED_PutPixel。

然后函数OLED_DispStr做的字体绘制。


[C] 纯文本查看 复制代码
/*
*********************************************************************************************************
*
*        模块名称 : OLED显示器驱动模块
*        文件名称 : bsp_oled.c
*        版    本 : V1.1
*        说    明 : OLED 屏(128x64)底层驱动程序,驱动芯片型号为 SSD1306.  本驱动程序适合于STM32-V5开发板.
*                                OLED模块挂在FSMC总线上。
*        修改记录 :
*                版本号  日期        作者    说明
*                V1.0    2013-02-01 armfly  正式发布
*                V1.1    2015-10-14 armfly  添加24点阵,32点阵汉字和ASCII支持
*
*        Copyright (C), 2015-2020, 安富莱电子 [url=http://www.armfly.com]www.armfly.com[/url]
*
*********************************************************************************************************
*/

#include "bsp.h"
#include "fonts.h"

/*
        安富莱STM32-V6开发板的OLED显示接口为FSMC总线模式。
*/

/* 下面2个宏任选 1个; 表示显示方向 */
#define DIR_NORMAL                        /* 此行表示正常显示方向 */
//#define DIR_180                                /* 此行表示翻转180度 */

#ifdef OLED_SPI3_EN
        /*
                SPI 模式接线定义 (只需要6根杜邦线连接)  本例子采用软件模拟SPI时序

           【OLED模块排针】 【开发板TFT接口(STM32口线)】
                VCC ----------- 3.3V
                GND ----------- GND
                 CS ----------- TP_NCS   (PI10)
                RST ----------- NRESET (也可以不连接)
             D0/SCK ----------- TP_SCK   (PB3)
            D1/SDIN ----------- TP_MOSI  (PB5)
        */
        #define RCC_OLED_PORT (RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOI)                /* GPIO端口时钟 */

        #define OLED_CS_PORT        GPIOI
        #define OLED_CS_PIN                GPIO_PIN_10

        #define OLED_SCK_PORT        GPIOB
        #define OLED_SCK_PIN        GPIO_PIN_3

        #define OLED_SDIN_PORT        GPIOB
        #define OLED_SDIN_PIN        GPIO_PIN_5


        /* 定义IO = 1和 0的代码 (不用更改) */
        #define SSD_CS_1()                OLED_CS_PORT->BSRRL = OLED_CS_PIN
        #define SSD_CS_0()                OLED_CS_PORT->BSRRH = OLED_CS_PIN

        #define SSD_SCK_1()                OLED_SCK_PORT->BSRRL = OLED_SCK_PIN
        #define SSD_SCK_0()                OLED_SCK_PORT->BSRRH = OLED_SCK_PIN

        #define SSD_SDIN_1()        OLED_SDIN_PORT->BSRRL = OLED_SDIN_PIN
        #define SSD_SDIN_0()        OLED_SDIN_PORT->BSRRH = OLED_SDIN_PIN

#else

        /* 定义LCD驱动器的访问地址
                TFT接口中的RS引脚连接FSMC_A0引脚,由于是16bit模式,RS对应A1地址线,因此
                OLED_RAM的地址是+2
        */
        #define OLED_BASE       ((uint32_t)(0x60000000))
        #define OLED_CMD                *(__IO uint16_t *)(OLED_BASE)
        #define OLED_DATA                *(__IO uint16_t *)(OLED_BASE + (1 << 2))                /* FSMC_A0接D/C, 总线配置为32bit(兼容74HC574端口) */

        /*
        1.安富莱OLED模块 80XX 模式接线定义 (需要15根杜邦线连接)
           【OLED模块排针】 【开发板TFT接口(STM32口线)】
                    VCC ----------- 3.3V
                    GND ----------- GND
                     CS ----------- NCS
                RST ----------- NRESET (也可以不连接)
                    D/C ----------- RS   (FSMC_A18)
                     WE ----------- NWE  (FSMC_NWE)
                     OE ----------- NOE  (FSMC_NOE)
             D0/SCK ----------- DB0  (FSMC_D0)
                D1/SDIN ----------- DB1  (FSMC_D1)
                     D2 ----------- DB2  (FSMC_D2)
                     D3 ----------- DB3  (FSMC_D3)
                     D4 ----------- DB4  (FSMC_D4)
                     D5 ----------- DB5  (FSMC_D5)
                     D6 ----------- DB6  (FSMC_D6)
                     D7 ----------- DB7  (FSMC_D7)
        */


#endif

/* 12864 OLED的显存镜像,占用1K字节. 共8行,每行128像素 */
static uint8_t s_ucGRAM[8][128];

/* 为了避免刷屏拉幕感太强,引入刷屏标志。
0 表示显示函数只改写缓冲区,不写屏。1 表示直接写屏(同时写缓冲区) */
static uint8_t s_ucUpdateEn = 1;

static void OLED_ConfigGPIO(void);
static void OLED_WriteCmd(uint8_t _ucCmd);
static void OLED_WriteData(uint8_t _ucData);
static void OLED_BufToPanel(void);

/*
*********************************************************************************************************
*        函 数 名: OLED_InitHard
*        功能说明: 初始化OLED屏
*        形    参:  无
*        返 回 值: 无
*********************************************************************************************************
*/
void OLED_InitHard(void)
{
        OLED_ConfigGPIO();

        /* 上电延迟 */
        bsp_DelayMS(50);

         /* 模块厂家提供初始化代码 */
        OLED_WriteCmd(0xAE);        /* 关闭OLED面板显示(休眠) */
        OLED_WriteCmd(0x00);        /* 设置列地址低4bit */
        OLED_WriteCmd(0x10);        /* 设置列地址高4bit */
        OLED_WriteCmd(0x40);        /* 设置起始行地址(低5bit 0-63), 硬件相关*/

        OLED_WriteCmd(0x81);        /* 设置对比度命令(双字节命令),第1个字节是命令,第2个字节是对比度参数0-255 */
        OLED_WriteCmd(0xCF);        /* 设置对比度参数,缺省CF */

#ifdef DIR_NORMAL
        OLED_WriteCmd(0xA0);        /* A0 :列地址0映射到SEG0; A1 :列地址127映射到SEG0 */
        OLED_WriteCmd(0xC0);        /* C0 :正常扫描,从COM0到COM63;  C8 : 反向扫描, 从 COM63至 COM0 */
#endif

#ifdef DIR_180
        OLED_WriteCmd(0xA1);        /* A0 :列地址0映射到SEG0; A1 :列地址127映射到SEG0 */
        OLED_WriteCmd(0xC8);        /* C0 :正常扫描,从COM0到COM63;  C8 : 反向扫描, 从 COM63至 COM0 */
#endif

        OLED_WriteCmd(0xA6);        /* A6 : 设置正常显示模式; A7 : 设置为反显模式 */

        OLED_WriteCmd(0xA8);        /* 设置COM路数 */
        OLED_WriteCmd(0x3F);        /* 1 ->(63+1)路 */

        OLED_WriteCmd(0xD3);        /* 设置显示偏移(双字节命令)*/
        OLED_WriteCmd(0x00);        /* 无偏移 */

        OLED_WriteCmd(0xD5);        /* 设置显示时钟分频系数/振荡频率 */
        OLED_WriteCmd(0x80);        /* 设置分频系数,高4bit是分频系数,低4bit是振荡频率 */

        OLED_WriteCmd(0xD9);        /* 设置预充电周期 */
        OLED_WriteCmd(0xF1);        /* [3:0],PHASE 1; [7:4],PHASE 2; */

        OLED_WriteCmd(0xDA);        /* 设置COM脚硬件接线方式 */
        OLED_WriteCmd(0x12);

        OLED_WriteCmd(0xDB);        /* 设置 vcomh 电压倍率 */
        OLED_WriteCmd(0x40);        /* [6:4] 000 = 0.65 x VCC; 0.77 x VCC (RESET); 0.83 x VCC  */

        OLED_WriteCmd(0x8D);        /* 设置充电泵(和下个命令结合使用) */
        OLED_WriteCmd(0x14);        /* 0x14 使能充电泵, 0x10 是关闭 */
        OLED_WriteCmd(0xAF);        /* 打开OLED面板 */
}

/*
*********************************************************************************************************
*        函 数 名: OLED_DispOn
*        功能说明: 打开显示
*        形    参:  无
*        返 回 值: 无
*********************************************************************************************************
*/
void OLED_DispOn(void)
{
        OLED_WriteCmd(0x8D);        /* 设置充电泵(和下个命令结合使用) */
        OLED_WriteCmd(0x14);        /* 0x14 使能充电泵, 0x10 是关闭 */
        OLED_WriteCmd(0xAF);        /* 打开OLED面板 */
}

/*
*********************************************************************************************************
*        函 数 名: OLED_DispOff
*        功能说明: 关闭显示
*        形    参:  无
*        返 回 值: 无
*********************************************************************************************************
*/
void OLED_DispOff(void)
{
        OLED_WriteCmd(0x8D);        /* 设置充电泵(和下个命令结合使用)*/
        OLED_WriteCmd(0x10);        /* 0x14 使能充电泵,0x10 是关闭 */
        OLED_WriteCmd(0xAE);        /* 打开OLED面板 */
}

/*
*********************************************************************************************************
*        函 数 名: OLED_SetDir
*        功能说明: 设置显示方向
*        形    参: _ucDir = 0 表示正常方向,1表示翻转180度
*        返 回 值: 无
*********************************************************************************************************
*/
void OLED_SetDir(uint8_t _ucDir)
{
        if (_ucDir == 0)
        {
               OLED_WriteCmd(0xA0);        /* A0 :列地址0映射到SEG0; A1 :列地址127映射到SEG0 */
                OLED_WriteCmd(0xC0);        /* C0 :正常扫描,从COM0到COM63;  C8 : 反向扫描, 从 COM63至 COM0 */
        }
        else
        {
                OLED_WriteCmd(0xA1);        /* A0 :列地址0映射到SEG0; A1 :列地址127映射到SEG0 */
                OLED_WriteCmd(0xC8);        /* C0 :正常扫描,从COM0到COM63;  C8 : 反向扫描, 从 COM63至 COM0 */
        }
}

/*
*********************************************************************************************************
*        函 数 名: OLED_SetContrast
*        功能说明: 设置对比度
*        形    参:  无
*        返 回 值: 无
*********************************************************************************************************
*/
void OLED_SetContrast(uint8_t ucValue)
{
        OLED_WriteCmd(0x81);        /* 设置对比度命令(双字节命令),第1个字节是命令,第2个字节是对比度参数0-255 */
        OLED_WriteCmd(ucValue);        /* 设置对比度参数,缺省CF */
}

/*
*********************************************************************************************************
*        函 数 名: OLED_StartDraw
*        功能说明: 开始绘图。以后绘图函数只改写缓冲区,不改写面板显存
*        形    参:  无
*        返 回 值: 无
*********************************************************************************************************
*/
void OLED_StartDraw(void)
{
        s_ucUpdateEn = 0;
}

/*
*********************************************************************************************************
*        函 数 名: OLED_EndDraw
*        功能说明: 结束绘图。缓冲区的数据刷新到面板显存。 OLED_StartDraw() 和 OLED_EndDraw() 必须成对使用
*        形    参:  无
*        返 回 值: 无
*********************************************************************************************************
*/
void OLED_EndDraw(void)
{
        s_ucUpdateEn = 1;
        OLED_BufToPanel();
}

/*
*********************************************************************************************************
*        函 数 名: OLED_ClrScr
*        功能说明: 清屏
*        形    参:  _ucMode : 0 表示全黑; 0xFF表示全亮
*        返 回 值: 无
*********************************************************************************************************
*/
void OLED_ClrScr(uint8_t _ucMode)
{
        uint8_t i,j;

        for (i = 0 ; i < 8; i++)
        {
                for (j = 0 ; j < 128; j++)
                {
                        s_ucGRAM[i][j] = _ucMode;
                }
        }

        if (s_ucUpdateEn == 1)
        {
                OLED_BufToPanel();
        }
}

/*
*********************************************************************************************************
*        函 数 名: OLED_BufToPanel
*        功能说明: 将缓冲区中的点阵数据写入面板
*        形    参:  无
*        返 回 值: 无
*********************************************************************************************************
*/
static void OLED_BufToPanel(void)
{
        uint8_t i,j;

        for (i = 0 ; i< 8; i++)
        {
                OLED_WriteCmd (0xB0 + i);        /* 设置页地址(0~7) */
                OLED_WriteCmd (0x00);                /* 设置列地址的低地址 */
                OLED_WriteCmd (0x10);                /* 设置列地址的高地址 */

                for (j = 0 ; j < 128; j++)
                {
                        OLED_WriteData(s_ucGRAM[i][j]);
                }
        }
}

/*
*********************************************************************************************************
*        函 数 名: OLED_DispStr
*        功能说明: 在屏幕指定坐标(左上角为0,0)显示一个字符串
*        形    参:
*                _usX : X坐标,对于12864屏,范围为【0 - 127】
*                _usY : Y坐标,对于12864屏,范围为【0 - 63】
*                _ptr  : 字符串指针
*                _tFont : 字体结构体,包含颜色、背景色(支持透明)、字体代码、文字间距等参数
*        返 回 值: 无
*********************************************************************************************************
*/
void OLED_DispStr(uint16_t _usX, uint16_t _usY, char *_ptr, FONT_T *_tFont)
{
        uint32_t i;
        uint8_t code1;
        uint8_t code2;
        uint32_t address = 0;
        uint8_t buf[32 * 32 / 8];        /* 最大支持32点阵汉字 */
        uint16_t m;
        uint8_t width;
        uint8_t font_width,font_height, font_bytes;
        uint16_t x, y;
        const uint8_t *pAscDot;
        uint8_t line_bytes;
        uint8_t asc_bytes;
        uint8_t hz_bytes;
        uint8_t fGT = 0;

#ifdef USE_SMALL_FONT                
        const uint8_t *pHzDot = g_Hz12;
#else        
        uint32_t AddrHZK;
#endif        

        if (_tFont->FontCode == FC_ST_12)
        {
                font_height = 12;
                font_width = 12;
                font_bytes = 24;
                hz_bytes = 2;
                asc_bytes = 1;
                fGT = 0;
                pAscDot = g_Ascii12;
        #ifdef USE_SMALL_FONT                
                pHzDot = g_Hz12;
        #else                
                AddrHZK = HZK12_ADDR;
        #endif                
        }
        else if (_tFont->FontCode == FC_ST_16)
        {
                /* 缺省是16点阵 */
                font_height = 16;
                font_width = 16;
                font_bytes = 32;
                hz_bytes = 2;
                asc_bytes = 1;
                fGT = 0;
                pAscDot = g_Ascii16;
        #ifdef USE_SMALL_FONT                
                pHzDot = g_Hz16;
        #else
                AddrHZK = HZK16_ADDR;
        #endif
        }
        else if (_tFont->FontCode == FC_ST_24)
        {
                font_height = 24;
                font_width = 24;
                font_bytes = 72;
                hz_bytes = 3;
                asc_bytes = 2;
                fGT = 1;
                pAscDot = g_Ascii24;
        #ifdef USE_SMALL_FONT                
                pHzDot = g_Hz24;
        #else
                AddrHZK = HZK24_ADDR;
        #endif
        }
        else        // if (_tFont->FontCode == FC_ST_32)
        {
                font_height = 32;
                font_width = 32;
                font_bytes = 128;
                hz_bytes = 4;
                asc_bytes = 2;
                fGT = 1;
                pAscDot = g_Ascii32;
        #ifdef USE_SMALL_FONT                
                pHzDot = g_Hz32;
        #else
                AddrHZK = HZK32_ADDR;
        #endif
        }

        /* 开始循环处理字符 */
        while (*_ptr != 0)
        {
                code1 = *_ptr;        /* 读取字符串数据, 该数据可能是ascii代码,也可能汉字代码的高字节 */
                if (code1 < 0x80)
                {
                        /* 将ascii字符点阵复制到buf */
                        if (fGT == 1)        /* 根据ASCII码搜索点阵 */
                        {
                                m = 0;
                                while(1)
                                {
                                        address = m * (asc_bytes * font_height + 1);
                                        m++;
                                        if (code1 == pAscDot[address + 0])
                                        {
                                                address += 1;
                                                memcpy(buf, &pAscDot[address], asc_bytes * font_height);
                                                break;
                                        }
                                        else if ((pAscDot[address + 0] == 0xFF) && (pAscDot[address + 1] == 0xFF))
                                        {
                                                /* 字库搜索完毕,未找到,则填充全FF */
                                                memset(buf, 0xFF, font_bytes);
                                                break;
                                        }
                                        
                                }
                        }
                        else        /* 全ASCII码点阵,直接计算地址 */
                        {
                                memcpy(buf, &pAscDot[code1 * (font_bytes / 2)], (font_bytes / 2));
                        }
                        width = font_width / 2;
                        line_bytes = asc_bytes;
                }
                else
                {
                        code2 = *++_ptr;
                        if (code2 == 0)
                        {
                                break;
                        }

                        /* 计算16点阵汉字点阵地址
                                ADDRESS = [(code1-0xa1) * 94 + (code2-0xa1)] * 32
                                ;
                        */
                        #ifdef USE_SMALL_FONT
                                m = 0;
                                while(1)
                                {
                                        address = m * (font_bytes + 2);
                                        m++;
                                        if ((code1 == pHzDot[address + 0]) && (code2 == pHzDot[address + 1]))
                                        {
                                                address += 2;
                                                memcpy(buf, &pHzDot[address], font_bytes);
                                                break;
                                        }
                                        else if ((pHzDot[address + 0] == 0xFF) && (pHzDot[address + 1] == 0xFF))
                                        {
                                                /* 字库搜索完毕,未找到,则填充全FF */
                                                memset(buf, 0xFF, font_bytes);
                                                break;
                                        }
                                }
                        #else        /* 用全字库 */
                                /* 此处需要根据字库文件存放位置进行修改 */
                                if (code1 >=0xA1 && code1 <= 0xA9 && code2 >=0xA1)
                                {
                                        address = ((code1 - 0xA1) * 94 + (code2 - 0xA1)) * font_bytes + AddrHZK;
                                }
                                else if (code1 >=0xB0 && code1 <= 0xF7 && code2 >=0xA1)
                                {
                                        address = ((code1 - 0xB0) * 94 + (code2 - 0xA1) + 846) * font_bytes + AddrHZK;
                                }
                                memcpy(buf, (const uint8_t *)address, font_bytes);
                        #endif

                                width = font_width;
                                line_bytes = hz_bytes;
                }

                y = _usY;
                /* 开始刷LCD */
                for (m = 0; m < font_height; m++)        /* 字符高度 */
                {
                        x = _usX;
                        for (i = 0; i < width; i++)        /* 字符宽度 */
                        {
                                if ((buf[m * line_bytes + i / 8] & (0x80 >> (i % 8 ))) != 0x00)
                                {
                                        OLED_PutPixel(x, y, _tFont->FrontColor);        /* 设置像素颜色为文字色 */
                                }
                                else
                                {
                                        OLED_PutPixel(x, y, _tFont->BackColor);        /* 设置像素颜色为文字背景色 */
                                }

                                x++;
                        }
                        y++;
                }

                if (_tFont->Space > 0)
                {
                        /* 如果文字底色按_tFont->usBackColor,并且字间距大于点阵的宽度,那么需要在文字之间填充(暂时未实现) */
                }
                _usX += width + _tFont->Space;        /* 列地址递增 */
                _ptr++;                        /* 指向下一个字符 */
        }
}

/*
*********************************************************************************************************
*        函 数 名: OLED_PutPixel
*        功能说明: 画1个像素
*        形    参:
*                        _usX,_usY : 像素坐标
*                        _ucColor  :像素颜色
*        返 回 值: 无
*********************************************************************************************************
*/
void OLED_PutPixel(uint16_t _usX, uint16_t _usY, uint8_t _ucColor)
{
        uint8_t ucValue;
        uint8_t ucPageAddr;
        uint8_t ucColAddr;

        const uint8_t aOrTab[8]  = {0x01, 0x02, 0x04, 0x08,0x10,0x20,0x40,0x80};
        const uint8_t aAndTab[8] = {0xFE, 0xFD, 0xFB, 0xF7,0xEF,0xDF,0xBF,0x7F};

        ucPageAddr = _usY / 8;
        ucColAddr = _usX;

        ucValue = s_ucGRAM[ucPageAddr][ucColAddr];
        if (_ucColor == 0)
        {
                ucValue &= aAndTab[_usY % 8];
        }
        else
        {
                ucValue |= aOrTab[_usY % 8];
        }
        s_ucGRAM[ucPageAddr][ucColAddr] = ucValue;

        if (s_ucUpdateEn == 1)
        {
                OLED_WriteCmd (0xB0 + ucPageAddr);                                        /* 设置页地址(0~7) */
                OLED_WriteCmd (0x00 + (ucColAddr & 0x0F));                        /* 设置列地址的低地址 */
                OLED_WriteCmd (0x10 + ((ucColAddr >> 4) & 0x0F));        /* 设置列地址的高地址 */
                OLED_WriteData(ucValue);
        }
}

/*
*********************************************************************************************************
*        函 数 名: OLED_GetPixel
*        功能说明: 读取1个像素
*        形    参:
*                        _usX,_usY : 像素坐标
*        返 回 值: 颜色值 (0, 1)
*********************************************************************************************************
*/
uint8_t OLED_GetPixel(uint16_t _usX, uint16_t _usY)
{
        uint8_t ucValue;
        uint8_t ucPageAddr;
        uint8_t ucColAddr;

        ucPageAddr = _usY / 8;
        ucColAddr = _usX;

        ucValue = s_ucGRAM[ucPageAddr][ucColAddr];
        if (ucValue & (_usY % 8))
        {
                return 1;
        }
        else
        {
                return 0;
        }
}

/*
*********************************************************************************************************
*        函 数 名: OLED_DrawLine
*        功能说明: 采用 Bresenham 算法,在2点间画一条直线。
*        形    参:
*                        _usX1, _usY1 :起始点坐标
*                        _usX2, _usY2 :终止点Y坐标
*                        _ucColor     :颜色
*        返 回 值: 无
*********************************************************************************************************
*/
void OLED_DrawLine(uint16_t _usX1 , uint16_t _usY1 , uint16_t _usX2 , uint16_t _usY2 , uint8_t _ucColor)
{
        int32_t dx , dy ;
        int32_t tx , ty ;
        int32_t inc1 , inc2 ;
        int32_t d , iTag ;
        int32_t x , y ;

        /* 采用 Bresenham 算法,在2点间画一条直线 */

        OLED_PutPixel(_usX1 , _usY1 , _ucColor);

        /* 如果两点重合,结束后面的动作。*/
        if ( _usX1 == _usX2 && _usY1 == _usY2 )
        {
                return;
        }

        iTag = 0 ;
        /* dx = abs ( _usX2 - _usX1 ); */
        if (_usX2 >= _usX1)
        {
                dx = _usX2 - _usX1;
        }
        else
        {
                dx = _usX1 - _usX2;
        }

        /* dy = abs ( _usY2 - _usY1 ); */
        if (_usY2 >= _usY1)
        {
                dy = _usY2 - _usY1;
        }
        else
        {
                dy = _usY1 - _usY2;
        }

        if ( dx < dy )   /*如果dy为计长方向,则交换纵横坐标。*/
        {
                uint16_t temp;

                iTag = 1 ;
                temp = _usX1; _usX1 = _usY1; _usY1 = temp;
                temp = _usX2; _usX2 = _usY2; _usY2 = temp;
                temp = dx; dx = dy; dy = temp;
        }
        tx = _usX2 > _usX1 ? 1 : -1 ;    /* 确定是增1还是减1 */
        ty = _usY2 > _usY1 ? 1 : -1 ;
        x = _usX1 ;
        y = _usY1 ;
        inc1 = 2 * dy ;
        inc2 = 2 * ( dy - dx );
        d = inc1 - dx ;
        while ( x != _usX2 )     /* 循环画点 */
        {
                if ( d < 0 )
                {
                        d += inc1 ;
                }
                else
                {
                        y += ty ;
                        d += inc2 ;
                }
                if ( iTag )
                {
                        OLED_PutPixel ( y , x , _ucColor) ;
                }
                else
                {
                        OLED_PutPixel ( x , y , _ucColor) ;
                }
                x += tx ;
        }
}

/*
*********************************************************************************************************
*        函 数 名: OLED_DrawPoints
*        功能说明: 采用 Bresenham 算法,绘制一组点,并将这些点连接起来。可用于波形显示。
*        形    参:
*                        x, y     :坐标数组
*                        _ucColor :颜色
*        返 回 值: 无
*********************************************************************************************************
*/
void OLED_DrawPoints(uint16_t *x, uint16_t *y, uint16_t _usSize, uint8_t _ucColor)
{
        uint16_t i;

        for (i = 0 ; i < _usSize - 1; i++)
        {
                OLED_DrawLine(x[i], y[i], x[i + 1], y[i + 1], _ucColor);
        }
}

/*
*********************************************************************************************************
*        函 数 名: OLED_DrawRect
*        功能说明: 绘制矩形。
*        形    参:
*                        _usX,_usY:矩形左上角的坐标
*                        _usHeight :矩形的高度
*                        _usWidth  :矩形的宽度
*        返 回 值: 无
*********************************************************************************************************
*/
void OLED_DrawRect(uint16_t _usX, uint16_t _usY, uint8_t _usHeight, uint16_t _usWidth, uint8_t _ucColor)
{
        /*
         ---------------->---
        |(_usX,_usY)        |
        V                    V  _usHeight
        |                    |
         ---------------->---
                  _usWidth
        */

        OLED_DrawLine(_usX, _usY, _usX + _usWidth - 1, _usY, _ucColor);        /* 顶 */
        OLED_DrawLine(_usX, _usY + _usHeight - 1, _usX + _usWidth - 1, _usY + _usHeight - 1, _ucColor);        /* 底 */

        OLED_DrawLine(_usX, _usY, _usX, _usY + _usHeight - 1, _ucColor);        /* 左 */
        OLED_DrawLine(_usX + _usWidth - 1, _usY, _usX + _usWidth - 1, _usY + _usHeight, _ucColor);        /* 右 */
}

/*
*********************************************************************************************************
*        函 数 名: OLED_DrawCircle
*        功能说明: 绘制一个圆,笔宽为1个像素
*        形    参:
*                        _usX,_usY  :圆心的坐标
*                        _usRadius  :圆的半径
*        返 回 值: 无
*********************************************************************************************************
*/
void OLED_DrawCircle(uint16_t _usX, uint16_t _usY, uint16_t _usRadius, uint8_t _ucColor)
{
        int32_t  D;                        /* Decision Variable */
        uint32_t  CurX;                /* 当前 X 值 */
        uint32_t  CurY;                /* 当前 Y 值 */

        D = 3 - (_usRadius << 1);
        CurX = 0;
        CurY = _usRadius;

        while (CurX <= CurY)
        {
                OLED_PutPixel(_usX + CurX, _usY + CurY, _ucColor);
                OLED_PutPixel(_usX + CurX, _usY - CurY, _ucColor);
                OLED_PutPixel(_usX - CurX, _usY + CurY, _ucColor);
                OLED_PutPixel(_usX - CurX, _usY - CurY, _ucColor);
                OLED_PutPixel(_usX + CurY, _usY + CurX, _ucColor);
                OLED_PutPixel(_usX + CurY, _usY - CurX, _ucColor);
                OLED_PutPixel(_usX - CurY, _usY + CurX, _ucColor);
                OLED_PutPixel(_usX - CurY, _usY - CurX, _ucColor);

                if (D < 0)
                {
                        D += (CurX << 2) + 6;
                }
                else
                {
                        D += ((CurX - CurY) << 2) + 10;
                        CurY--;
                }
                CurX++;
        }
}

/*
*********************************************************************************************************
*        函 数 名: OLED_DrawBMP
*        功能说明: 在LCD上显示一个BMP位图,位图点阵扫描次序:从左到右,从上到下
*        形    参:
*                        _usX, _usY : 图片的坐标
*                        _usHeight  :图片高度
*                        _usWidth   :图片宽度
*                        _ptr       :单色图片点阵指针,每个像素占用1个字节
*        返 回 值: 无
*********************************************************************************************************
*/
void OLED_DrawBMP(uint16_t _usX, uint16_t _usY, uint16_t _usHeight, uint16_t _usWidth, uint8_t *_ptr)
{
        uint16_t x, y;

        for (x = 0; x < _usWidth; x++)
        {
                for (y = 0; y < _usHeight; y++)
                {
                        OLED_PutPixel(_usX + x, _usY + y, *_ptr);
                }
        }
}

/*
*********************************************************************************************************
*        函 数 名: OLED_ConfigGPIO
*        功能说明: 配置OLED控制口线,设置为8位80XX总线控制模式或SPI模式
*        形    参:  无
*        返 回 值: 无
*********************************************************************************************************
*/
static void OLED_ConfigGPIO(void)
{
#ifdef OLED_SPI3_EN
        /* 1.配置GPIO,模拟SPI */
        {
                GPIO_InitTypeDef GPIO_InitStructure;

                RCC_AHB1PeriphClockCmd(RCC_OLED_PORT, ENABLE);        /* 打开GPIO时钟 */

                GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;                /* 设为输出口 */
                GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;                /* 设为推挽输出模式 */
                GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;        /* 上下拉电阻不使能 */
                GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;        /* IO口最大速度 */

                GPIO_InitStructure.GPIO_Pin = OLED_CS_PIN;
                GPIO_Init(OLED_CS_PORT, &GPIO_InitStructure);

                GPIO_InitStructure.GPIO_Pin = OLED_SCK_PIN;
                GPIO_Init(OLED_SCK_PORT, &GPIO_InitStructure);

                GPIO_InitStructure.GPIO_Pin = OLED_SDIN_PIN;
                GPIO_Init(OLED_SDIN_PORT, &GPIO_InitStructure);
        }
#else
        /* 1.配置GPIO, 设置为FSMC总线。 为了和32位接口兼容,本例子也配置为32位总线,实际只用了其中8位。 */
        {
                /* bsp_fm_io 已配置fmc。 此处不必重复配置 
                        bsp_InitExtIO();
                */
        }
#endif
}

/*
*********************************************************************************************************
*        函 数 名: OLED_WriteCmd
*        功能说明: 向SSD1306发送一字节命令
*        形    参:  命令字
*        返 回 值: 无
*********************************************************************************************************
*/
static void OLED_WriteCmd(uint8_t _ucCmd)
{
#ifdef OLED_SPI3_EN
        uint8_t i;

        SSD_CS_0();

        SSD_SCK_0();
        SSD_SDIN_0();        /* 0 表示后面传送的是命令 1表示后面传送的数据 */
        SSD_SCK_1();

        for (i = 0; i < 8; i++)
        {
                if (_ucCmd & 0x80)
                {
                        SSD_SDIN_1();
                }
                else
                {
                        SSD_SDIN_0();
                }
                SSD_SCK_0();
                _ucCmd <<= 1;
                SSD_SCK_1();
        }

        SSD_CS_1();
#else
        OLED_CMD = _ucCmd;
#endif
}

/*
*********************************************************************************************************
*        函 数 名: OLED_WriteData
*        功能说明: 向SSD1306发送一字节数据
*        形    参:  命令字
*        返 回 值: 无
*********************************************************************************************************
*/
static void OLED_WriteData(uint8_t _ucData)
{
#ifdef OLED_SPI3_EN
        uint8_t i;

        SSD_CS_0();

        SSD_SCK_0();
        SSD_SDIN_1();        /* 0 表示后面传送的是命令 1表示后面传送的数据 */
        SSD_SCK_1();

        for (i = 0; i < 8; i++)
        {
                if (_ucData & 0x80)
                {
                        SSD_SDIN_1();
                }
                else
                {
                        SSD_SDIN_0();
                }
                SSD_SCK_0();
                _ucData <<= 1;
                SSD_SCK_1();
        }

        SSD_CS_1();
#else
        OLED_DATA = _ucData;
#endif
}

/***************************** 安富莱电子 [url=http://www.armfly.com]www.armfly.com[/url] (END OF FILE) *********************************/

回复

使用道具 举报

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

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-10 03:26 , Processed in 0.231237 second(s), 26 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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