打印
[应用方案]

【NuMaker-M471测评】+模拟SPI驱动lcd(ST7789)

[复制链接]
2027|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
今天在同事那,拿了个小屏幕,驱动芯片ST7780,分辨率240X240。就用M471驱动一下吧!其实也没啥好说的,都烂大街的驱动了~
M471有ARDUINO接口,我就直接插在某一排上了,电源直接用IO模拟。虽然不是很亮,但也
能正常驱动~
具体连接如下图:

新唐它的很多寄存器受保护,必须先解锁 才能操作~

我们定义一个宏,来解决这个问题:
#define PROTECT_REG(__CODE) {SYS_UnlockReg();__CODE;SYS_LockReg();}
这样初始化这些受保护的寄存器,我们就可以直接写在里面了,如:
    PROTECT_REG
    (
      /* Init System Clock*/
      SYS_Init();
      /* Init UART0 for printf */
      UART0_Init(115200);
      /* Init TIMER0 */
      TM0_Init();
    )
   
废话不多说,我们着手模拟SPI驱动LCD的程序:
lcd.h
#ifndef __LCD_240X240_H_
#define __LCD_240X240_H_

#include "NuMicro.h"


//GPIO INIT  基本操作
#define USE_HORIZONTAL 0  //设置横屏或者竖屏显示 0或1为竖屏 2或3为横屏


#define LCD_W 240
#define LCD_H 240

//-----------------LCD端口定义----------------
//LCD_GND   GND
//LCD_VCC   PA2
//LCD_SCL   PA1
//LCD_SDA   PA0
//LCD_RES   PA3
//LCD_DC    PA4
//LCD_BLK   PA5


#define LCD_VCC_Clr()   PA2=0
#define LCD_VCC_Set()   PA2=1

#define LCD_SCLK_Clr()  PA1=0
#define LCD_SCLK_Set()  PA1=1

#define LCD_MOSI_Clr()  PA0=0//SDA=MOSI
#define LCD_MOSI_Set()  PA0=1

#define LCD_RES_Clr()   PA3=0//RES
#define LCD_RES_Set()   PA3=1

#define LCD_DC_Clr()    PA4=0//DC
#define LCD_DC_Set()    PA4=1

#define LCD_BLK_Clr()   PA5=0//BLK
#define LCD_BLK_Set()   PA5=1


void LCD_GPIO_Init(void);//初始化GPIO
void LCD_Writ_Bus(u8 dat);//模拟SPI时序
void LCD_WR_DATA8(u8 dat);//写入一个字节
void LCD_WR_DATA(u16 dat);//写入两个字节
void LCD_WR_REG(u8 dat);//写入一个指令
void LCD_Address_Set(u16 x1,u16 y1,u16 x2,u16 y2);//设置坐标函数
void LCD_Init(void);//LCD初始化

////////////////应用操作

//画笔颜色
#define WHITE                  0xFFFF
#define BLACK                  0x0000          
#define BLUE                    0x001F  
#define BRED             0XF81F
#define GRED                          0XFFE0
#define GBLUE                         0X07FF
#define RED                    0xF800
#define MAGENTA                0xF81F
#define GREEN                  0x07E0
#define CYAN                   0x7FFF
#define YELLOW                 0xFFE0
#define BROWN                          0XBC40 //棕色
#define BRRED                          0XFC07 //棕红色
#define GRAY                           0X8430 //灰色
#define DARKBLUE               0X01CF        //深蓝色
#define LIGHTBLUE               0X7D7C        //浅蓝色  
#define GRAYBLUE                0X5458 //灰蓝色
#define LIGHTGREEN              0X841F //浅绿色
#define LGRAY                          0XC618 //浅灰色(PANNEL),窗体背景色
#define LGRAYBLUE        0XA651 //浅灰蓝色(中间层颜色)
#define LBBLUE           0X2B12 //浅棕蓝色(选择条目的反色)

void LCD_Fill(u16 xsta,u16 ysta,u16 xend,u16 yend,u16 color);//指定区域填充颜色
void LCD_DrawPoint(u16 x,u16 y,u16 color);//在指定位置画一个点
void LCD_DrawLine(u16 x1,u16 y1,u16 x2,u16 y2,u16 color);//在指定位置画一条线
void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2,u16 color);//在指定位置画一个矩形
void Draw_Circle(u16 x0,u16 y0,u8 r,u16 color);//在指定位置画一个圆

void LCD_ShowChinese(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode);//显示汉字串
void LCD_ShowChinese16x16(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode);//显示单个16x16汉字
void LCD_ShowChinese24x24(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode);//显示单个24x24汉字
void LCD_ShowChinese32x32(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode);//显示单个32x32汉字

void LCD_ShowChar(u16 x,u16 y,u8 num,u16 fc,u16 bc,u8 sizey,u8 mode);//显示一个字符
void LCD_ShowString(u16 x,u16 y,const u8 *p,u16 fc,u16 bc,u8 sizey,u8 mode);//显示字符串
u32 mypow(u8 m,u8 n);//求幂
void LCD_ShowIntNum(u16 x,u16 y,u16 num,u8 len,u16 fc,u16 bc,u8 sizey);//显示整数变量
void LCD_ShowFloatNum1(u16 x,u16 y,float num,u8 len,u16 fc,u16 bc,u8 sizey);//显示两位小数变量

void LCD_ShowPicture(u16 x,u16 y,u16 length,u16 width,const u8 pic[]);//显示图片



#endif

lcd.c
#include "lcd_240x240.h"
#include "lcdfont.h"
#include "delay.h"

///////LCD基本操作///////////////////////////////
//LCD_GND   GND
//LCD_VCC   PA2
//LCD_SCL   PA1
//LCD_SDA   PA0
//LCD_RES   PA3
//LCD_DC    PA4
//LCD_BLK   PA5
void LCD_GPIO_Init(void)
{
    CLK->AHBCLK |= CLK_AHBCLK_GPACKEN_Msk;            //开启端口时钟
   
    GPIO_SetMode(PA, BIT2, GPIO_MODE_OUTPUT);        //输出模式
    GPIO_SetSlewCtl(PA, BIT2,GPIO_SLEWCTL_NORMAL);   //选择速度
    GPIO_SetPullCtl(PA, BIT2,GPIO_PUSEL_PULL_UP);    //选择上拉模式
    PA2=0;//默认关
   
    GPIO_SetMode(PA, BIT1, GPIO_MODE_OUTPUT);        //输出模式
    GPIO_SetSlewCtl(PA, BIT1,GPIO_SLEWCTL_NORMAL);   //选择速度
    GPIO_SetPullCtl(PA, BIT1,GPIO_PUSEL_PULL_UP);    //选择上拉模式
    PA1=0;//默认关
   
    GPIO_SetMode(PA, BIT0, GPIO_MODE_OUTPUT);        //输出模式
    GPIO_SetSlewCtl(PA, BIT0,GPIO_SLEWCTL_NORMAL);   //选择速度
    GPIO_SetPullCtl(PA, BIT0,GPIO_PUSEL_PULL_UP);    //选择上拉模式
    PA0=0;//默认关
   
    GPIO_SetMode(PA, BIT3, GPIO_MODE_OUTPUT);        //输出模式
    GPIO_SetSlewCtl(PA, BIT3,GPIO_SLEWCTL_NORMAL);   //选择速度
    GPIO_SetPullCtl(PA, BIT3,GPIO_PUSEL_PULL_UP);    //选择上拉模式
    PA3=0;//默认关
   
    GPIO_SetMode(PA, BIT4, GPIO_MODE_OUTPUT);        //输出模式
    GPIO_SetSlewCtl(PA, BIT4,GPIO_SLEWCTL_NORMAL);   //选择速度
    GPIO_SetPullCtl(PA, BIT4,GPIO_PUSEL_PULL_UP);    //选择上拉模式
    PA4=0;//默认关
   
    GPIO_SetMode(PA, BIT5, GPIO_MODE_OUTPUT);        //输出模式
    GPIO_SetSlewCtl(PA, BIT5,GPIO_SLEWCTL_NORMAL);   //选择速度
    GPIO_SetPullCtl(PA, BIT5,GPIO_PUSEL_PULL_UP);    //选择上拉模式
    PA5=0;//默认关
        //其余全部置高
        LCD_SCLK_Set();
        LCD_MOSI_Set();
        LCD_RES_Set();
        LCD_DC_Set();
        LCD_BLK_Set();
        //初始化打开电源
        LCD_VCC_Set();
        //LCD_GND_Clr();
        //延时,保证充分上电
        delay_ms(1000);
}


/******************************************************************************
      函数说明:LCD串行数据写入函数
      入口数据:dat  要写入的串行数据
      返回值:  无
******************************************************************************/
void LCD_Writ_Bus(u8 dat)
{       
        u8 i;
        for(i=0;i<8;i++)
        {                          
                LCD_SCLK_Clr();
                if(dat&0x80)
                {
                   LCD_MOSI_Set();
                }
                else
                {
                   LCD_MOSI_Clr();
                }
                LCD_SCLK_Set();
                dat<<=1;
        }       
}


/******************************************************************************
      函数说明:LCD写入数据
      入口数据:dat 写入的数据
      返回值:  无
******************************************************************************/
void LCD_WR_DATA8(u8 dat)
{
        LCD_Writ_Bus(dat);
}


/******************************************************************************
      函数说明:LCD写入数据
      入口数据:dat 写入的数据
      返回值:  无
******************************************************************************/
void LCD_WR_DATA(u16 dat)
{
        LCD_Writ_Bus(dat>>8);
        LCD_Writ_Bus(dat);
}


/******************************************************************************
      函数说明:LCD写入命令
      入口数据:dat 写入的命令
      返回值:  无
******************************************************************************/
void LCD_WR_REG(u8 dat)
{
        LCD_DC_Clr();//写命令
        LCD_Writ_Bus(dat);
        LCD_DC_Set();//写数据
}


/******************************************************************************
      函数说明:设置起始和结束地址
      入口数据:x1,x2 设置列的起始和结束地址
                y1,y2 设置行的起始和结束地址
      返回值:  无
******************************************************************************/
void LCD_Address_Set(u16 x1,u16 y1,u16 x2,u16 y2)
{
        if(USE_HORIZONTAL==0)
        {
                LCD_WR_REG(0x2a);//列地址设置
                LCD_WR_DATA(x1);
                LCD_WR_DATA(x2);
                LCD_WR_REG(0x2b);//行地址设置
                LCD_WR_DATA(y1);
                LCD_WR_DATA(y2);
                LCD_WR_REG(0x2c);//储存器写
        }
        else if(USE_HORIZONTAL==1)
        {
                LCD_WR_REG(0x2a);//列地址设置
                LCD_WR_DATA(x1);
                LCD_WR_DATA(x2);
                LCD_WR_REG(0x2b);//行地址设置
                LCD_WR_DATA(y1+80);
                LCD_WR_DATA(y2+80);
                LCD_WR_REG(0x2c);//储存器写
        }
        else if(USE_HORIZONTAL==2)
        {
                LCD_WR_REG(0x2a);//列地址设置
                LCD_WR_DATA(x1);
                LCD_WR_DATA(x2);
                LCD_WR_REG(0x2b);//行地址设置
                LCD_WR_DATA(y1);
                LCD_WR_DATA(y2);
                LCD_WR_REG(0x2c);//储存器写
        }
        else
        {
                LCD_WR_REG(0x2a);//列地址设置
                LCD_WR_DATA(x1+80);
                LCD_WR_DATA(x2+80);
                LCD_WR_REG(0x2b);//行地址设置
                LCD_WR_DATA(y1);
                LCD_WR_DATA(y2);
                LCD_WR_REG(0x2c);//储存器写
        }
}

void LCD_Init(void)
{
        LCD_GPIO_Init();//初始化GPIO
       
        LCD_RES_Clr();//复位
        delay_ms(100);
        LCD_RES_Set();
        delay_ms(100);
       
        LCD_BLK_Set();//打开背光
    delay_ms(100);
       
        //************* Start Initial Sequence **********//
        LCD_WR_REG(0x11); //Sleep out
        delay_ms(120);              //Delay 120ms
        //************* Start Initial Sequence **********//
        LCD_WR_REG(0x36);
        if(USE_HORIZONTAL==0)LCD_WR_DATA8(0x00);
        else if(USE_HORIZONTAL==1)LCD_WR_DATA8(0xC0);
        else if(USE_HORIZONTAL==2)LCD_WR_DATA8(0x70);
        else LCD_WR_DATA8(0xA0);

        LCD_WR_REG(0x3A);
        LCD_WR_DATA8(0x05);

        LCD_WR_REG(0xB2);
        LCD_WR_DATA8(0x0C);
        LCD_WR_DATA8(0x0C);
        LCD_WR_DATA8(0x00);
        LCD_WR_DATA8(0x33);
        LCD_WR_DATA8(0x33);

        LCD_WR_REG(0xB7);
        LCD_WR_DATA8(0x35);  

        LCD_WR_REG(0xBB);
        LCD_WR_DATA8(0x19);

        LCD_WR_REG(0xC0);
        LCD_WR_DATA8(0x2C);

        LCD_WR_REG(0xC2);
        LCD_WR_DATA8(0x01);

        LCD_WR_REG(0xC3);
        LCD_WR_DATA8(0x12);   

        LCD_WR_REG(0xC4);
        LCD_WR_DATA8(0x20);  

        LCD_WR_REG(0xC6);
        LCD_WR_DATA8(0x0F);   

        LCD_WR_REG(0xD0);
        LCD_WR_DATA8(0xA4);
        LCD_WR_DATA8(0xA1);

        LCD_WR_REG(0xE0);
        LCD_WR_DATA8(0xD0);
        LCD_WR_DATA8(0x04);
        LCD_WR_DATA8(0x0D);
        LCD_WR_DATA8(0x11);
        LCD_WR_DATA8(0x13);
        LCD_WR_DATA8(0x2B);
        LCD_WR_DATA8(0x3F);
        LCD_WR_DATA8(0x54);
        LCD_WR_DATA8(0x4C);
        LCD_WR_DATA8(0x18);
        LCD_WR_DATA8(0x0D);
        LCD_WR_DATA8(0x0B);
        LCD_WR_DATA8(0x1F);
        LCD_WR_DATA8(0x23);

        LCD_WR_REG(0xE1);
        LCD_WR_DATA8(0xD0);
        LCD_WR_DATA8(0x04);
        LCD_WR_DATA8(0x0C);
        LCD_WR_DATA8(0x11);
        LCD_WR_DATA8(0x13);
        LCD_WR_DATA8(0x2C);
        LCD_WR_DATA8(0x3F);
        LCD_WR_DATA8(0x44);
        LCD_WR_DATA8(0x51);
        LCD_WR_DATA8(0x2F);
        LCD_WR_DATA8(0x1F);
        LCD_WR_DATA8(0x1F);
        LCD_WR_DATA8(0x20);
        LCD_WR_DATA8(0x23);
        LCD_WR_REG(0x21);

        LCD_WR_REG(0x29);
}

///////////////////具体应用操作///////////////////
/******************************************************************************
      函数说明:在指定区域填充颜色
      入口数据:xsta,ysta   起始坐标
                xend,yend   终止坐标
                                                                color       要填充的颜色
      返回值:  无
******************************************************************************/
void LCD_Fill(u16 xsta,u16 ysta,u16 xend,u16 yend,u16 color)
{         
        u16 i,j;
        LCD_Address_Set(xsta,ysta,xend-1,yend-1);//设置显示范围
        for(i=ysta;i<yend;i++)
        {                                                                                                                           
                for(j=xsta;j<xend;j++)
                {
                        LCD_WR_DATA(color);
                }
        }                                                       
}

/******************************************************************************
      函数说明:在指定位置画点
      入口数据:x,y 画点坐标
                color 点的颜色
      返回值:  无
******************************************************************************/
void LCD_DrawPoint(u16 x,u16 y,u16 color)
{
        LCD_Address_Set(x,y,x,y);//设置光标位置
        LCD_WR_DATA(color);
}


/******************************************************************************
      函数说明:画线
      入口数据:x1,y1   起始坐标
                x2,y2   终止坐标
                color   线的颜色
      返回值:  无
******************************************************************************/
void LCD_DrawLine(u16 x1,u16 y1,u16 x2,u16 y2,u16 color)
{
        u16 t;
        int xerr=0,yerr=0,delta_x,delta_y,distance;
        int incx,incy,uRow,uCol;
        delta_x=x2-x1; //计算坐标增量
        delta_y=y2-y1;
        uRow=x1;//画线起点坐标
        uCol=y1;
        if(delta_x>0)incx=1; //设置单步方向
        else if (delta_x==0)incx=0;//垂直线
        else {incx=-1;delta_x=-delta_x;}
        if(delta_y>0)incy=1;
        else if (delta_y==0)incy=0;//水平线
        else {incy=-1;delta_y=-delta_x;}
        if(delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴
        else distance=delta_y;
        for(t=0;t<distance+1;t++)
        {
                LCD_DrawPoint(uRow,uCol,color);//画点
                xerr+=delta_x;
                yerr+=delta_y;
                if(xerr>distance)
                {
                        xerr-=distance;
                        uRow+=incx;
                }
                if(yerr>distance)
                {
                        yerr-=distance;
                        uCol+=incy;
                }
        }
}


/******************************************************************************
      函数说明:画矩形
      入口数据:x1,y1   起始坐标
                x2,y2   终止坐标
                color   矩形的颜色
      返回值:  无
******************************************************************************/
void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2,u16 color)
{
        LCD_DrawLine(x1,y1,x2,y1,color);
        LCD_DrawLine(x1,y1,x1,y2,color);
        LCD_DrawLine(x1,y2,x2,y2,color);
        LCD_DrawLine(x2,y1,x2,y2,color);
}


/******************************************************************************
      函数说明:画圆
      入口数据:x0,y0   圆心坐标
                r       半径
                color   圆的颜色
      返回值:  无
******************************************************************************/
void Draw_Circle(u16 x0,u16 y0,u8 r,u16 color)
{
        int a,b;
        a=0;b=r;          
        while(a<=b)
        {
                LCD_DrawPoint(x0-b,y0-a,color);             //3           
                LCD_DrawPoint(x0+b,y0-a,color);             //0           
                LCD_DrawPoint(x0-a,y0+b,color);             //1               
                LCD_DrawPoint(x0-a,y0-b,color);             //2            
                LCD_DrawPoint(x0+b,y0+a,color);             //4               
                LCD_DrawPoint(x0+a,y0-b,color);             //5
                LCD_DrawPoint(x0+a,y0+b,color);             //6
                LCD_DrawPoint(x0-b,y0+a,color);             //7
                a++;
                if((a*a+b*b)>(r*r))//判断要画的点是否过远
                {
                        b--;
                }
        }
}

/******************************************************************************
      函数说明:显示汉字串
      入口数据:x,y显示坐标
                *s 要显示的汉字串
                fc 字的颜色
                bc 字的背景色
                sizey 字号 可选 16 24 32
                mode:  0非叠加模式  1叠加模式
      返回值:  无
******************************************************************************/
void LCD_ShowChinese(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode)
{
        while(*s!=0)
        {
                if(sizey==16) LCD_ShowChinese16x16(x,y,s,fc,bc,sizey,mode);
                else if(sizey==24) LCD_ShowChinese24x24(x,y,s,fc,bc,sizey,mode);
                else if(sizey==32) LCD_ShowChinese32x32(x,y,s,fc,bc,sizey,mode);
                else return;
                s+=2;
                x+=sizey;
        }
}

/******************************************************************************
      函数说明:显示单个16x16汉字
      入口数据:x,y显示坐标
                *s 要显示的汉字
                fc 字的颜色
                bc 字的背景色
                sizey 字号
                mode:  0非叠加模式  1叠加模式
      返回值:  无
******************************************************************************/
void LCD_ShowChinese16x16(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode)
{
        u8 i,j;
        u16 k;
        u16 HZnum;//汉字数目
        u16 TypefaceNum;//一个字符所占字节大小
        u16 x0=x;
        TypefaceNum=sizey/8*sizey;//此算法只适用于字宽等于字高,且字高是8的倍数的字,
                                  //也建议用户使用这样大小的字,否则显示容易出问题!
        HZnum=sizeof(tfont16)/sizeof(typFNT_GB16);        //统计汉字数目
        for(k=0;k<HZnum;k++)
        {
                if ((tfont16[k].Index[0]==*(s))&&(tfont16[k].Index[1]==*(s+1)))
                {        
                        LCD_Address_Set(x,y,x+sizey-1,y+sizey-1);
                        for(i=0;i<TypefaceNum;i++)
                        {
                                for(j=0;j<8;j++)
                                {       
                                        if(!mode)//非叠加方式
                                        {
                                                if(tfont16[k].Msk[i]&(0x01<<j))LCD_WR_DATA(fc);
                                                else LCD_WR_DATA(bc);
                                        }
                                        else//叠加方式
                                        {
                                                if(tfont16[k].Msk[i]&(0x01<<j))        LCD_DrawPoint(x,y,fc);//画一个点
                                                x++;
                                                if((x-x0)==sizey)
                                                {
                                                        x=x0;
                                                        y++;
                                                        break;
                                                }
                                        }
                                }
                        }
                }                                         
                continue;  //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响
        }
}


/******************************************************************************
      函数说明:显示单个24x24汉字
      入口数据:x,y显示坐标
                *s 要显示的汉字
                fc 字的颜色
                bc 字的背景色
                sizey 字号
                mode:  0非叠加模式  1叠加模式
      返回值:  无
******************************************************************************/
void LCD_ShowChinese24x24(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode)
{
        u8 i,j;
        u16 k;
        u16 HZnum;//汉字数目
        u16 TypefaceNum;//一个字符所占字节大小
        u16 x0=x;
        TypefaceNum=sizey/8*sizey;//此算法只适用于字宽等于字高,且字高是8的倍数的字,
                                  //也建议用户使用这样大小的字,否则显示容易出问题!
        HZnum=sizeof(tfont24)/sizeof(typFNT_GB24);        //统计汉字数目
        for(k=0;k<HZnum;k++)
        {
                if ((tfont24[k].Index[0]==*(s))&&(tfont24[k].Index[1]==*(s+1)))
                {        
                        LCD_Address_Set(x,y,x+sizey-1,y+sizey-1);
                        for(i=0;i<TypefaceNum;i++)
                        {
                                for(j=0;j<8;j++)
                                {       
                                        if(!mode)//非叠加方式
                                        {
                                                if(tfont24[k].Msk[i]&(0x01<<j))LCD_WR_DATA(fc);
                                                else LCD_WR_DATA(bc);
                                        }
                                        else//叠加方式
                                        {
                                                if(tfont24[k].Msk[i]&(0x01<<j))        LCD_DrawPoint(x,y,fc);//画一个点
                                                x++;
                                                if((x-x0)==sizey)
                                                {
                                                        x=x0;
                                                        y++;
                                                        break;
                                                }
                                        }
                                }
                        }
                }                                         
                continue;  //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响
        }
}

/******************************************************************************
      函数说明:显示单个32x32汉字
      入口数据:x,y显示坐标
                *s 要显示的汉字
                fc 字的颜色
                bc 字的背景色
                sizey 字号
                mode:  0非叠加模式  1叠加模式
      返回值:  无
******************************************************************************/
void LCD_ShowChinese32x32(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode)
{
        u8 i,j;
        u16 k;
        u16 HZnum;//汉字数目
        u16 TypefaceNum;//一个字符所占字节大小
        u16 x0=x;
        TypefaceNum=sizey/8*sizey;//此算法只适用于字宽等于字高,且字高是8的倍数的字,
                                  //也建议用户使用这样大小的字,否则显示容易出问题!
        HZnum=sizeof(tfont32)/sizeof(typFNT_GB32);        //统计汉字数目
        for(k=0;k<HZnum;k++)
        {
                if ((tfont32[k].Index[0]==*(s))&&(tfont32[k].Index[1]==*(s+1)))
                {        
                        LCD_Address_Set(x,y,x+sizey-1,y+sizey-1);
                        for(i=0;i<TypefaceNum;i++)
                        {
                                for(j=0;j<8;j++)
                                {       
                                        if(!mode)//非叠加方式
                                        {
                                                if(tfont32[k].Msk[i]&(0x01<<j))LCD_WR_DATA(fc);
                                                else LCD_WR_DATA(bc);
                                        }
                                        else//叠加方式
                                        {
                                                if(tfont32[k].Msk[i]&(0x01<<j))        LCD_DrawPoint(x,y,fc);//画一个点
                                                x++;
                                                if((x-x0)==sizey)
                                                {
                                                        x=x0;
                                                        y++;
                                                        break;
                                                }
                                        }
                                }
                        }
                }                                         
                continue;  //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响
        }
}


/******************************************************************************
      函数说明:显示单个字符
      入口数据:x,y显示坐标
                num 要显示的字符
                fc 字的颜色
                bc 字的背景色
                sizey 字号
                mode:  0非叠加模式  1叠加模式
      返回值:  无
******************************************************************************/
void LCD_ShowChar(u16 x,u16 y,u8 num,u16 fc,u16 bc,u8 sizey,u8 mode)
{
        u8 temp,sizex,t;
        u16 i,TypefaceNum;//一个字符所占字节大小
        u16 x0=x;
        sizex=sizey/2;
        TypefaceNum=sizex/8*sizey;
        num=num-' ';    //得到偏移后的值
        LCD_Address_Set(x,y,x+sizex-1,y+sizey-1);  //设置光标位置
        for(i=0;i<TypefaceNum;i++)
        {
                if(sizey==16)temp=ascii_1608[num][i];                       //调用8x16字体
                else if(sizey==32)temp=ascii_3216[num][i];                 //调用16x32字体
                else return;
                for(t=0;t<8;t++)
                {
                        if(!mode)//非叠加模式
                        {
                                if(temp&(0x01<<t))LCD_WR_DATA(fc);
                                else LCD_WR_DATA(bc);
                        }
                        else//叠加模式
                        {
                                if(temp&(0x01<<t))LCD_DrawPoint(x,y,fc);//画一个点
                                x++;
                                if((x-x0)==sizex)
                                {
                                        x=x0;
                                        y++;
                                        break;
                                }
                        }
                }
        }                      
}


/******************************************************************************
      函数说明:显示字符串
      入口数据:x,y显示坐标
                *p 要显示的字符串
                fc 字的颜色
                bc 字的背景色
                sizey 字号
                mode:  0非叠加模式  1叠加模式
      返回值:  无
******************************************************************************/
void LCD_ShowString(u16 x,u16 y,const u8 *p,u16 fc,u16 bc,u8 sizey,u8 mode)
{         
        while(*p!='\0')
        {      
                LCD_ShowChar(x,y,*p,fc,bc,sizey,mode);
                x+=sizey/2;
                p++;
        }  
}


/******************************************************************************
      函数说明:显示数字
      入口数据:m底数,n指数
      返回值:  无
******************************************************************************/
u32 mypow(u8 m,u8 n)
{
        u32 result=1;         
        while(n--)result*=m;
        return result;
}


/******************************************************************************
      函数说明:显示整数变量
      入口数据:x,y显示坐标
                num 要显示整数变量
                len 要显示的位数
                fc 字的颜色
                bc 字的背景色
                sizey 字号
      返回值:  无
******************************************************************************/
void LCD_ShowIntNum(u16 x,u16 y,u16 num,u8 len,u16 fc,u16 bc,u8 sizey)
{                
        u8 t,temp;
        u8 enshow=0;
        u8 sizex=sizey/2;
        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+t*sizex,y,' ',fc,bc,sizey,0);
                                continue;
                        }else enshow=1;
                          
                }
                 LCD_ShowChar(x+t*sizex,y,temp+48,fc,bc,sizey,0);
        }
}


/******************************************************************************
      函数说明:显示两位小数变量
      入口数据:x,y显示坐标
                num 要显示小数变量
                len 要显示的位数
                fc 字的颜色
                bc 字的背景色
                sizey 字号
      返回值:  无
******************************************************************************/
void LCD_ShowFloatNum1(u16 x,u16 y,float num,u8 len,u16 fc,u16 bc,u8 sizey)
{                
        u8 t,temp,sizex;
        u16 num1;
        sizex=sizey/2;
        num1=num*100;
        for(t=0;t<len;t++)
        {
                temp=(num1/mypow(10,len-t-1))%10;
                if(t==(len-2))
                {
                        LCD_ShowChar(x+(len-2)*sizex,y,'.',fc,bc,sizey,0);
                        t++;
                        len+=1;
                }
                 LCD_ShowChar(x+t*sizex,y,temp+48,fc,bc,sizey,0);
        }
}


/******************************************************************************
      函数说明:显示图片
      入口数据:x,y起点坐标
                length 图片长度
                width  图片宽度
                pic[]  图片数组   
      返回值:  无
******************************************************************************/
void LCD_ShowPicture(u16 x,u16 y,u16 length,u16 width,const u8 pic[])
{
        u16 i,j,k=0;
        LCD_Address_Set(x,y,x+length-1,y+width-1);
        for(i=0;i<length;i++)
        {
                for(j=0;j<width;j++)
                {
                        LCD_WR_DATA8(pic[k*2]);
                        LCD_WR_DATA8(pic[k*2+1]);
                        k++;
                }
        }                       
}



然后main函数中调用:
/**************************************************************************//**
* [url=home.php?mod=space&uid=288409]@file[/url]     main.c
* [url=home.php?mod=space&uid=895143]@version[/url]  V3.00
* [url=home.php?mod=space&uid=247401]@brief[/url]    Show how to wake up system from Power-down mode by GPIO interrupt.
*
* SPDX-License-Identifier: Apache-2.0
* [url=home.php?mod=space&uid=17282]@CopyRight[/url] (C) 2020 Nuvoton Technology Corp. All rights reserved.
******************************************************************************/
#include <stdio.h>
#include "NuMicro.h"
#include "system.h"
#include "delay.h"
#include "uart0.h"
#include "led.h"
#include "key.h"
#include "tm0.h"
//LCD
#include "LCD_240X240.h"
#include "pic.h"




int main(void)
{
    u8 i,j;
        float t=0;
   
    PROTECT_REG
    (
      /* Init System Clock*/
      SYS_Init();
      /* Init UART0 for printf */
      UART0_Init(115200);
      /* Init TIMER0 */
      TM0_Init();
    )
   
    LED_Init();
    KEY_Init();
    printf("\n\nCPU [url=home.php?mod=space&uid=72445]@[/url] %d Hz\n", SystemCoreClock);
    printf("+-------------------------------------------------------+\n");
    printf("|    GPIO Power-Down and Wake-up by PB.3 Sample Code    |\n");
    printf("+-------------------------------------------------------+\n\n");

    //进入低功耗模式 PH4引脚中断可唤醒
    //printf("Enter to Power-Down. Wait PH.4 falling edge interrupt to wake up ...\n");
    //PowerDownFunction();
    //printf("System waken-up done.\n\n");
    /* Waiting for PB.3 rising-edge interrupt event */
   
    //LCD
    LCD_Init();//LCD初始化
        LCD_Fill(0,0,LCD_W,LCD_H,WHITE);
   
    while(1)
    {  
//        printf("Hello NUVOTON_M471_EVK!\r\n");
//        delay_ms(500);
        
        LCD_Fill(0,0,LCD_W,LCD_H,WHITE);

                LCD_ShowChinese(8,0,(u8*)"意法半导体社区",RED,WHITE,32,0);
                LCD_ShowString(0,40,(u8*)"LCD_W:",RED,WHITE,16,0);
                LCD_ShowIntNum(48,40,LCD_W,3,RED,WHITE,16);
                LCD_ShowString(80,40,(u8*)"LCD_H:",RED,WHITE,16,0);
                LCD_ShowIntNum(128,40,LCD_H,3,RED,WHITE,16);
                LCD_ShowString(80,40,(u8*)"LCD_H:",RED,WHITE,16,0);
                LCD_ShowString(0,70,(u8*)"Increaseing Nun:",RED,WHITE,16,0);
                LCD_ShowFloatNum1(128,70,t,4,RED,WHITE,16);
                LCD_ShowString(0,86+8,(u8*)"qjp1988113 @ 21 IC",RED,WHITE,16,0);//86+16=102
                t+=0.11f;
                for(j=0;j<3;j++)
                {
                        for(i=0;i<6;i++)
                        {
                                LCD_ShowPicture(40*i,120+j*40,40,40,gImage_1);
                        }
                }
                delay_ms(2000);
                LCD_ShowPicture(0,0,240,240,gImage_2);
                delay_ms(2000);
                LCD_ShowPicture(0,0,240,240,gImage_3);
                delay_ms(2000);
                LCD_ShowPicture(0,0,240,240,gImage_4);
                delay_ms(2000);
    }
}
这里,我把官方例子给整理了一边,各个外设分离,方便移植之用:

下载,查看LCD显示:


使用特权

评论回复
沙发
643757107| | 2021-8-13 17:45 | 只看该作者
说明IO的驱动能力很强啊。

使用特权

评论回复
板凳
643757107| | 2021-8-13 17:47 | 只看该作者
楼主屏幕上怎么还给ST打广告,代码里也给St广告,不走心啊。

使用特权

评论回复
地板
twjiang| | 2021-8-13 17:51 | 只看该作者
643757107 发表于 2021-8-13 17:47
楼主屏幕上怎么还给ST打广告,代码里也给St广告,不走心啊。

就是就是!

使用特权

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

本版积分规则

111

主题

627

帖子

2

粉丝