STM32:FSMC驱动TFTLCD(2)

上一篇文章写了ST7789的基本驱动代码,但是没有实现具体的绘图代码。

这里加上。

1.代码

头文件

#ifndef __BSP_LCD_H
#define __BSP_LCD_H
#include "lcd_drv.h"

/*
    RGB565:
    高位至低位排列, RRRR RGGG GGGB BBBB
*/
#define RGB(R,G,B)    (((R >> 3) << 11) | ((G >> 2) << 5) | (B >> 3)) //24位RGB转化为 16位RGB565格式
#define RGB565_R(x)  ((x >> 8) & 0xF8)
#define RGB565_G(x)  ((x >> 3) & 0xFC)
#define RGB565_B(x)  ((x << 3) & 0xF8)
enum
{
    CL_WHITE        = RGB(255, 255, 255),   /* 白 */
    CL_BLACK        = RGB(  0,  0,  0),     /* 黑 */
    CL_RED          = RGB(255,    0,  0),   /* 红 */
    CL_GREEN        = RGB(  0, 255,  0),    /* 绿 */
    CL_BLUE         = RGB(  0,    0, 255),  /* 蓝 */
    CL_YELLOW       = RGB(255, 255,  0),    /* 黄 */
    CL_GREY         = RGB( 98, 98, 98),     /* 深灰 */
    CL_BUTTON_GREY  = RGB( 220, 220, 220),  /* 按钮灰*/
};

/* 可供外部模块调用的函数 */
void LCD_Init(void);


#define  LCD_GetHeight() LCD_HEIGHT
#define  LCD_GetWidth() LCD_WIDTH
//#define  LCD_FillColorPre lcddrv_FillColorPre

void LCD_PutPixel(uint16_t _usX, uint16_t _usY, uint16_t _usColor);
void LCD_DrawHLine(uint16_t _usX , uint16_t _usY , uint16_t _uslen , uint16_t _usColor);
void LCD_DrawHColorLine(uint16_t _usX , uint16_t _usY, uint16_t _uslen, const uint16_t *_pColor);
void LCD_Fill_Rect(uint16_t _usX,   uint16_t _usY, uint16_t _usWidth, uint16_t  _usHeight, uint16_t _usColor);
void LCD_Fill_ColorRect(uint16_t _usX,   uint16_t _usY, uint16_t _usWidth, uint16_t  _usHeight, const uint16_t *_pColor);

#define  LCD_ClrScr(_usColor)       LCD_Fill_Rect(0,0,LCD_WIDTH,LCD_HEIGHT,_usColor);
#define  LCD_DrawVLine(_usX,_usY,len,_usColor)      LCD_Fill_Rect(_usX,_usY,1,len,_usColor)

void LCD_DrawLine(uint16_t _usX1 , uint16_t _usY1 , uint16_t _usX2 , uint16_t _usY2 , uint16_t _usColor);
void LCD_DrawPolyline(uint16_t *x, uint16_t *y, uint16_t _usSize, uint16_t _usColor);
void LCD_DrawRect(uint16_t _usX, uint16_t _usY, uint16_t _usWidth,uint16_t _usHeight,  uint16_t _usColor);
void LCD_DrawCircle(uint16_t _usX, uint16_t _usY, uint16_t _usRadius, uint16_t _usColor);

void LCD_DrawBinBMP(uint16_t _usX, uint16_t _usY, const char * pPath);

void LCD_DispOn(void);
void LCD_DispOff(void);
void LCD_SetBackLight(uint8_t _ucBright);
uint8_t LCD_GetBackLight(void);

#endif

C文件

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

//#define LCD_GetWidth() LCD_WIDTH
//#define LCD_GetHeight() LCD_HEIGHT

static uint8_t s_ucBright;                    /* 背光亮度参数 */

/*
*************************************************************************************************
*    函 数 名: LCD_DispOn
*    功能说明: 打开显示
*    形    参: 无
*    返 回 值: 无
*************************************************************************************************
*/
void LCD_DispOn(void)
{
    lcddrv_DispOn();
}

/*
************************************************************************************************
*    函 数 名: LCD_DispOff
*    功能说明: 关闭显示
*    形    参: 无
*    返 回 值: 无
************************************************************************************************
*/
void LCD_DispOff(void)
{
    lcddrv_DispOff();
}

/*
*************************************************************************************************
*    函 数 名:  LCD_PutPixel
*    功能说明: 打点函数
*    形    参:
*             _usX,_usY : 像素坐标
*             _usColor  :像素颜色
*    返 回 值: 无
*************************************************************************************************
*/
void LCD_PutPixel(uint16_t _usX, uint16_t _usY, uint16_t _usColor)
{
    lcddrv_FillColorPre(_usX, _usY,LCD_WIDTH,LCD_HEIGHT);    /* 设置光标位置 */

    /* Write 16-bit GRAM Reg */
    LCDDRV_RAM = _usColor;
}
/*
*************************************************************************************************
*    函 数 名:  _DrawHLine
*    功能说明:  绘制水平线
*    形    参:  _usX ,_usY : 起始点坐标
*               _usLen     :长度
*               _usColor   : 颜色
*    返 回 值: 无
*************************************************************************************************
*/
void LCD_DrawHLine(uint16_t _usX , uint16_t _usY , uint16_t _usLen , uint16_t _usColor)
{
    uint16_t i;

    lcddrv_FillColorPre(_usX, _usY,LCD_WIDTH,LCD_HEIGHT);

    for (i = 0; i < _usLen; i++)
    {
        LCDDRV_RAM = _usColor;
    }
}
/*
*************************************************************************************************
*    函 数 名:  _DrawHColorLine
*    功能说明: 绘制一条彩色水平线
*    形    参:  _usX ,_usY :起始点坐标
*              _usLen       :直线的长度
*              _pColor      : 颜色缓冲区
*    返 回 值: 无
*************************************************************************************************
*/
void LCD_DrawHColorLine(uint16_t _usX , uint16_t _usY, uint16_t _usLen, const uint16_t *_pColor)
{
    uint16_t i;

    lcddrv_FillColorPre(_usX, _usY,LCD_WIDTH,LCD_HEIGHT);

    for (i = 0; i < _usLen; i++)
    {
        LCDDRV_RAM = *_pColor++;
    }
}
/*
*************************************************************************************************
*    函 数 名: LCD_Fill_Rect
*    功能说明: 绘制单色矩形区域
*    形    参:
*            _usX,_usY :  矩形左上角的坐标
*            _usHeight :  矩形的高度
*            _usWidth  :  矩形的宽度
*            _usColor  :  颜色
*    返 回 值: 无
*************************************************************************************************
*/
void LCD_Fill_Rect(uint16_t _usX,   uint16_t _usY, uint16_t _usWidth, uint16_t  _usHeight, uint16_t _usColor)
{
    uint32_t i;
    uint32_t len = (uint32_t)_usWidth * _usHeight;

    lcddrv_FillColorPre(_usX, _usY, _usWidth, _usHeight);
 
    for (i = 0; i < len; i++)
    {
        LCDDRV_RAM = _usColor;
    }

}
/*
*************************************************************************************************
*    函 数 名: LCD_Fill_ColorRect
*    功能说明: 绘制矩形区域,颜色填充数据
*    形    参:
*            _usX,_usY :  矩形左上角的坐标
*            _usHeight :  矩形的高度
*            _usWidth  :  矩形的宽度
*            _pColor   :  颜色缓冲区
*    返 回 值: 无
*************************************************************************************************
*/
void LCD_Fill_ColorRect(uint16_t _usX,   uint16_t _usY, uint16_t _usWidth, uint16_t  _usHeight, const uint16_t *_pColor)
{
    uint32_t i;
    uint32_t len = (uint32_t)_usWidth * _usHeight;

    lcddrv_FillColorPre(_usX, _usY, _usWidth, _usHeight);
 
    for (i = 0; i < len; i++)
    {
        ST7789_RAM = *_pColor++;
    }
}
/*
*************************************************************************************************
*    函 数 名: LCD_DrawRect
*    功能说明: 绘制矩形边。
*    形    参:
*            _usX,_usY: 矩形左上角的坐标
*            _usWidth  : 矩形的宽度
*            _usHeight : 矩形的高度
*    返 回 值: 无
*************************************************************************************************
*/
void LCD_DrawRect(uint16_t _usX, uint16_t _usY, uint16_t _usWidth, uint16_t _usHeight, uint16_t _usColor)
{
    LCD_DrawHLine(  _usX ,  _usY ,                  _usWidth ,  _usColor);
    LCD_DrawHLine(  _usX ,  _usY + _usHeight - 1 ,     _usWidth ,  _usColor);

    LCD_DrawVLine(  _usX ,              _usY ,    _usHeight,  _usColor);
    LCD_DrawVLine(  _usX + _usWidth - 1 ,  _usY ,    _usHeight,  _usColor);
}
/*
*************************************************************************************************
*    函 数 名: LCD_DrawLine
*    功能说明: Bresenham 算法绘制2点间的直线。
*    形    参:
*            _usX1, _usY1 : 起始点坐标
*            _usX2, _usY2 : 终止点Y坐标
*            _usColor     : 颜色
*    返 回 值: 无
*************************************************************************************************
*/
void LCD_DrawLine(uint16_t _usX1 , uint16_t _usY1 , uint16_t _usX2 , uint16_t _usY2 , uint16_t _usColor)
{
    int32_t dx , dy ;
    int32_t tx , ty ;
    int32_t inc1 , inc2 ;
    int32_t d , iTag ;
    int32_t x , y ;

    LCD_PutPixel(_usX1 , _usY1 , _usColor);

    if ( _usX1 == _usX2 && _usY1 == _usY2 )
    {
        LCD_PutPixel(  _usX1,  _usY2,   _usColor);
        return;
    }

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

    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 )
        {
            LCD_PutPixel ( y , x , _usColor) ;
        }
        else
        {
            LCD_PutPixel ( x , y , _usColor) ;
        }
        x += tx ;
    }
}


/*
*************************************************************************************************
*    函 数 名: LCD_DrawCircle
*    功能说明: 画空心圆
*    形    参:
*            _usX,_usY  : 圆心坐标
*            _usRadius  : 半径
*            _usColor   : 颜色
*    返 回 值: 无
*************************************************************************************************
*/
void LCD_DrawCircle(uint16_t _usX, uint16_t _usY, uint16_t _usRadius, uint16_t _usColor)
{
    int32_t  D;            /* Decision Variable */
    uint32_t  CurX;        /* 当前 X 值 */
    uint32_t  CurY;        /* 当前 Y 值 */

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

    while (CurX <= CurY)
    {
        LCD_PutPixel(_usX + CurX, _usY + CurY, _usColor);
        LCD_PutPixel(_usX + CurX, _usY - CurY, _usColor);
        LCD_PutPixel(_usX - CurX, _usY + CurY, _usColor);
        LCD_PutPixel(_usX - CurX, _usY - CurY, _usColor);
        LCD_PutPixel(_usX + CurY, _usY + CurX, _usColor);
        LCD_PutPixel(_usX + CurY, _usY - CurX, _usColor);
        LCD_PutPixel(_usX - CurY, _usY + CurX, _usColor);
        LCD_PutPixel(_usX - CurY, _usY - CurX, _usColor);

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

#define ONESIZE (2048)      //从SD卡单次读取的数据大小
__inline static uint16_t turn332to565( uint16_t c)  //RGB332转RGB565
{
    uint16_t r= (c&0x00E0)<<8;
    uint16_t g= (c&0x001C)<<6;
    uint16_t b= (c&0x0003)<<3;
    return r+g+b;
}
/*
*************************************************************************************************
*    函 数 名: LCD_DrawBinBMP
*    功能说明: 在LCD上显示一个SD卡的BMP-BIN格式位图,使用Img2Lcd将BMP转BIN;支持1BIT,8BIT,16BIT。
*              位图点阵扫描次序: 从左到右,从上到下.测试全幅图(16bit/RGB565),速度如下:
*              ONESIZE =512->180ms,1024->135ms,=2048->110ms,=4096->110ms
*    形    参:
*            _usX, _usY : 图片的坐标
*            path       : 路径,比如"0:/bmp/001.bin"
*            _ptr       : 图片点阵指针
*    返 回 值: 无
*************************************************************************************************
*/
void LCD_DrawBinBMP(uint16_t _usX, uint16_t _usY, const char * path)
{
    PICBIN_HEADCOLOR_T head;
    FRESULT  fres;
    FIL xfile;
    u32 br=0,pos=0;
    u16 *const buf= mymalloc(SRAMCCM,ONESIZE);
    u8 *p;
    if(buf==NULL){  printf(" mymalloc err !\r\n");return;}

    fres=f_open(&xfile,path,FA_OPEN_EXISTING|FA_READ);
    if(fres == FR_OK)
    {
        f_lseek(&xfile,0);
        p=(u8*)buf;
        fres = f_read(&xfile,p,ONESIZE,&br);

        if( fres==FR_OK )
        {
            memcpy(&head,p,sizeof(head));
            lcddrv_FillColorPre( _usX,_usY,head.w,head.h);
            if(head.gray==1) //1bit图
            {
                p+=6;
                u16 i=6;
                for(;i>j) )?0:0xffff;
                        }
                    }else
                    {
                        //TODO. 处理多余的0
                        printf(" bit err\r\n");
                    }
                    p++;
                }
            
                pos=ONESIZE;
                while(pos>j) )?0:0xffff;
                                }
                            }else
                            {
                                //TODO. 处理多余的0
                                printf(" bit err\r\n");
                            }
                            p++;
                        }
                    }
                    pos+=ONESIZE;
                }
            }
            else if(head.gray==8) //8bit图
            {
                p+=6;
                u16 i=6;
                for(;i

如果编译错误,试试勾选C99模式,因为我把一些变量放在语句后面定义了。

即使更换了其他驱动芯片的LCD,也只需要修改上篇文章的lcd_drv.c的底层驱动,和lcd_drv.h的LCD_RAM地址即可。本文件是中间层代码,隔离逻辑业务层与底层驱动层。

如果屏幕IC不使用FSMC驱动,则应该将画点函数,单色填充函数,颜色数据填充函数等几个基本画图函数放在底层lcd_drv.c文件实现。而为了追求速度,我设计了lcddrv_FillColorPre函数,导致不是很通用。

你可能感兴趣的:(stm32)