[应用方案] 【NuMaker-M471测评】+模拟SPI驱动lcd(ST7789)

[复制链接]
2554|3
 楼主| qjp1988113 发表于 2021-8-13 16:35 | 显示全部楼层 |阅读模式
今天在同事那,拿了个小屏幕,驱动芯片ST7780,分辨率240X240。就用M471驱动一下吧!其实也没啥好说的,都烂大街的驱动了~
M471有ARDUINO接口,我就直接插在某一排上了,电源直接用IO模拟。虽然不是很亮,但也
能正常驱动~
具体连接如下图:
Z1.png
新唐它的很多寄存器受保护,必须先解锁 才能操作~
Z2.png
我们定义一个宏,来解决这个问题:
  1. #define PROTECT_REG(__CODE) {SYS_UnlockReg();__CODE;SYS_LockReg();}
这样初始化这些受保护的寄存器,我们就可以直接写在里面了,如:
  1.     PROTECT_REG
  2.     (
  3.       /* Init System Clock*/
  4.       SYS_Init();
  5.       /* Init UART0 for printf */
  6.       UART0_Init(115200);
  7.       /* Init TIMER0 */
  8.       TM0_Init();
  9.     )
  10.    
废话不多说,我们着手模拟SPI驱动LCD的程序:
lcd.h
  1. #ifndef __LCD_240X240_H_
  2. #define __LCD_240X240_H_

  3. #include "NuMicro.h"


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


  6. #define LCD_W 240
  7. #define LCD_H 240

  8. //-----------------LCD端口定义----------------
  9. //LCD_GND   GND
  10. //LCD_VCC   PA2
  11. //LCD_SCL   PA1
  12. //LCD_SDA   PA0
  13. //LCD_RES   PA3
  14. //LCD_DC    PA4
  15. //LCD_BLK   PA5


  16. #define LCD_VCC_Clr()   PA2=0
  17. #define LCD_VCC_Set()   PA2=1

  18. #define LCD_SCLK_Clr()  PA1=0
  19. #define LCD_SCLK_Set()  PA1=1

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

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

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

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


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

  35. ////////////////应用操作

  36. //画笔颜色
  37. #define WHITE                  0xFFFF
  38. #define BLACK                  0x0000          
  39. #define BLUE                    0x001F  
  40. #define BRED             0XF81F
  41. #define GRED                          0XFFE0
  42. #define GBLUE                         0X07FF
  43. #define RED                    0xF800
  44. #define MAGENTA                0xF81F
  45. #define GREEN                  0x07E0
  46. #define CYAN                   0x7FFF
  47. #define YELLOW                 0xFFE0
  48. #define BROWN                          0XBC40 //棕色
  49. #define BRRED                          0XFC07 //棕红色
  50. #define GRAY                           0X8430 //灰色
  51. #define DARKBLUE               0X01CF        //深蓝色
  52. #define LIGHTBLUE               0X7D7C        //浅蓝色  
  53. #define GRAYBLUE                0X5458 //灰蓝色
  54. #define LIGHTGREEN              0X841F //浅绿色
  55. #define LGRAY                          0XC618 //浅灰色(PANNEL),窗体背景色
  56. #define LGRAYBLUE        0XA651 //浅灰蓝色(中间层颜色)
  57. #define LBBLUE           0X2B12 //浅棕蓝色(选择条目的反色)

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

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

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

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



  73. #endif

lcd.c
  1. #include "lcd_240x240.h"
  2. #include "lcdfont.h"
  3. #include "delay.h"

  4. ///////LCD基本操作///////////////////////////////
  5. //LCD_GND   GND
  6. //LCD_VCC   PA2
  7. //LCD_SCL   PA1
  8. //LCD_SDA   PA0
  9. //LCD_RES   PA3
  10. //LCD_DC    PA4
  11. //LCD_BLK   PA5
  12. void LCD_GPIO_Init(void)
  13. {
  14.     CLK->AHBCLK |= CLK_AHBCLK_GPACKEN_Msk;            //开启端口时钟
  15.    
  16.     GPIO_SetMode(PA, BIT2, GPIO_MODE_OUTPUT);        //输出模式
  17.     GPIO_SetSlewCtl(PA, BIT2,GPIO_SLEWCTL_NORMAL);   //选择速度
  18.     GPIO_SetPullCtl(PA, BIT2,GPIO_PUSEL_PULL_UP);    //选择上拉模式
  19.     PA2=0;//默认关
  20.    
  21.     GPIO_SetMode(PA, BIT1, GPIO_MODE_OUTPUT);        //输出模式
  22.     GPIO_SetSlewCtl(PA, BIT1,GPIO_SLEWCTL_NORMAL);   //选择速度
  23.     GPIO_SetPullCtl(PA, BIT1,GPIO_PUSEL_PULL_UP);    //选择上拉模式
  24.     PA1=0;//默认关
  25.    
  26.     GPIO_SetMode(PA, BIT0, GPIO_MODE_OUTPUT);        //输出模式
  27.     GPIO_SetSlewCtl(PA, BIT0,GPIO_SLEWCTL_NORMAL);   //选择速度
  28.     GPIO_SetPullCtl(PA, BIT0,GPIO_PUSEL_PULL_UP);    //选择上拉模式
  29.     PA0=0;//默认关
  30.    
  31.     GPIO_SetMode(PA, BIT3, GPIO_MODE_OUTPUT);        //输出模式
  32.     GPIO_SetSlewCtl(PA, BIT3,GPIO_SLEWCTL_NORMAL);   //选择速度
  33.     GPIO_SetPullCtl(PA, BIT3,GPIO_PUSEL_PULL_UP);    //选择上拉模式
  34.     PA3=0;//默认关
  35.    
  36.     GPIO_SetMode(PA, BIT4, GPIO_MODE_OUTPUT);        //输出模式
  37.     GPIO_SetSlewCtl(PA, BIT4,GPIO_SLEWCTL_NORMAL);   //选择速度
  38.     GPIO_SetPullCtl(PA, BIT4,GPIO_PUSEL_PULL_UP);    //选择上拉模式
  39.     PA4=0;//默认关
  40.    
  41.     GPIO_SetMode(PA, BIT5, GPIO_MODE_OUTPUT);        //输出模式
  42.     GPIO_SetSlewCtl(PA, BIT5,GPIO_SLEWCTL_NORMAL);   //选择速度
  43.     GPIO_SetPullCtl(PA, BIT5,GPIO_PUSEL_PULL_UP);    //选择上拉模式
  44.     PA5=0;//默认关
  45.         //其余全部置高
  46.         LCD_SCLK_Set();
  47.         LCD_MOSI_Set();
  48.         LCD_RES_Set();
  49.         LCD_DC_Set();
  50.         LCD_BLK_Set();
  51.         //初始化打开电源
  52.         LCD_VCC_Set();
  53.         //LCD_GND_Clr();
  54.         //延时,保证充分上电
  55.         delay_ms(1000);
  56. }


  57. /******************************************************************************
  58.       函数说明:LCD串行数据写入函数
  59.       入口数据:dat  要写入的串行数据
  60.       返回值:  无
  61. ******************************************************************************/
  62. void LCD_Writ_Bus(u8 dat)
  63. {       
  64.         u8 i;
  65.         for(i=0;i<8;i++)
  66.         {                          
  67.                 LCD_SCLK_Clr();
  68.                 if(dat&0x80)
  69.                 {
  70.                    LCD_MOSI_Set();
  71.                 }
  72.                 else
  73.                 {
  74.                    LCD_MOSI_Clr();
  75.                 }
  76.                 LCD_SCLK_Set();
  77.                 dat<<=1;
  78.         }       
  79. }


  80. /******************************************************************************
  81.       函数说明:LCD写入数据
  82.       入口数据:dat 写入的数据
  83.       返回值:  无
  84. ******************************************************************************/
  85. void LCD_WR_DATA8(u8 dat)
  86. {
  87.         LCD_Writ_Bus(dat);
  88. }


  89. /******************************************************************************
  90.       函数说明:LCD写入数据
  91.       入口数据:dat 写入的数据
  92.       返回值:  无
  93. ******************************************************************************/
  94. void LCD_WR_DATA(u16 dat)
  95. {
  96.         LCD_Writ_Bus(dat>>8);
  97.         LCD_Writ_Bus(dat);
  98. }


  99. /******************************************************************************
  100.       函数说明:LCD写入命令
  101.       入口数据:dat 写入的命令
  102.       返回值:  无
  103. ******************************************************************************/
  104. void LCD_WR_REG(u8 dat)
  105. {
  106.         LCD_DC_Clr();//写命令
  107.         LCD_Writ_Bus(dat);
  108.         LCD_DC_Set();//写数据
  109. }


  110. /******************************************************************************
  111.       函数说明:设置起始和结束地址
  112.       入口数据:x1,x2 设置列的起始和结束地址
  113.                 y1,y2 设置行的起始和结束地址
  114.       返回值:  无
  115. ******************************************************************************/
  116. void LCD_Address_Set(u16 x1,u16 y1,u16 x2,u16 y2)
  117. {
  118.         if(USE_HORIZONTAL==0)
  119.         {
  120.                 LCD_WR_REG(0x2a);//列地址设置
  121.                 LCD_WR_DATA(x1);
  122.                 LCD_WR_DATA(x2);
  123.                 LCD_WR_REG(0x2b);//行地址设置
  124.                 LCD_WR_DATA(y1);
  125.                 LCD_WR_DATA(y2);
  126.                 LCD_WR_REG(0x2c);//储存器写
  127.         }
  128.         else if(USE_HORIZONTAL==1)
  129.         {
  130.                 LCD_WR_REG(0x2a);//列地址设置
  131.                 LCD_WR_DATA(x1);
  132.                 LCD_WR_DATA(x2);
  133.                 LCD_WR_REG(0x2b);//行地址设置
  134.                 LCD_WR_DATA(y1+80);
  135.                 LCD_WR_DATA(y2+80);
  136.                 LCD_WR_REG(0x2c);//储存器写
  137.         }
  138.         else if(USE_HORIZONTAL==2)
  139.         {
  140.                 LCD_WR_REG(0x2a);//列地址设置
  141.                 LCD_WR_DATA(x1);
  142.                 LCD_WR_DATA(x2);
  143.                 LCD_WR_REG(0x2b);//行地址设置
  144.                 LCD_WR_DATA(y1);
  145.                 LCD_WR_DATA(y2);
  146.                 LCD_WR_REG(0x2c);//储存器写
  147.         }
  148.         else
  149.         {
  150.                 LCD_WR_REG(0x2a);//列地址设置
  151.                 LCD_WR_DATA(x1+80);
  152.                 LCD_WR_DATA(x2+80);
  153.                 LCD_WR_REG(0x2b);//行地址设置
  154.                 LCD_WR_DATA(y1);
  155.                 LCD_WR_DATA(y2);
  156.                 LCD_WR_REG(0x2c);//储存器写
  157.         }
  158. }

  159. void LCD_Init(void)
  160. {
  161.         LCD_GPIO_Init();//初始化GPIO
  162.        
  163.         LCD_RES_Clr();//复位
  164.         delay_ms(100);
  165.         LCD_RES_Set();
  166.         delay_ms(100);
  167.        
  168.         LCD_BLK_Set();//打开背光
  169.     delay_ms(100);
  170.        
  171.         //************* Start Initial Sequence **********//
  172.         LCD_WR_REG(0x11); //Sleep out
  173.         delay_ms(120);              //Delay 120ms
  174.         //************* Start Initial Sequence **********//
  175.         LCD_WR_REG(0x36);
  176.         if(USE_HORIZONTAL==0)LCD_WR_DATA8(0x00);
  177.         else if(USE_HORIZONTAL==1)LCD_WR_DATA8(0xC0);
  178.         else if(USE_HORIZONTAL==2)LCD_WR_DATA8(0x70);
  179.         else LCD_WR_DATA8(0xA0);

  180.         LCD_WR_REG(0x3A);
  181.         LCD_WR_DATA8(0x05);

  182.         LCD_WR_REG(0xB2);
  183.         LCD_WR_DATA8(0x0C);
  184.         LCD_WR_DATA8(0x0C);
  185.         LCD_WR_DATA8(0x00);
  186.         LCD_WR_DATA8(0x33);
  187.         LCD_WR_DATA8(0x33);

  188.         LCD_WR_REG(0xB7);
  189.         LCD_WR_DATA8(0x35);  

  190.         LCD_WR_REG(0xBB);
  191.         LCD_WR_DATA8(0x19);

  192.         LCD_WR_REG(0xC0);
  193.         LCD_WR_DATA8(0x2C);

  194.         LCD_WR_REG(0xC2);
  195.         LCD_WR_DATA8(0x01);

  196.         LCD_WR_REG(0xC3);
  197.         LCD_WR_DATA8(0x12);   

  198.         LCD_WR_REG(0xC4);
  199.         LCD_WR_DATA8(0x20);  

  200.         LCD_WR_REG(0xC6);
  201.         LCD_WR_DATA8(0x0F);   

  202.         LCD_WR_REG(0xD0);
  203.         LCD_WR_DATA8(0xA4);
  204.         LCD_WR_DATA8(0xA1);

  205.         LCD_WR_REG(0xE0);
  206.         LCD_WR_DATA8(0xD0);
  207.         LCD_WR_DATA8(0x04);
  208.         LCD_WR_DATA8(0x0D);
  209.         LCD_WR_DATA8(0x11);
  210.         LCD_WR_DATA8(0x13);
  211.         LCD_WR_DATA8(0x2B);
  212.         LCD_WR_DATA8(0x3F);
  213.         LCD_WR_DATA8(0x54);
  214.         LCD_WR_DATA8(0x4C);
  215.         LCD_WR_DATA8(0x18);
  216.         LCD_WR_DATA8(0x0D);
  217.         LCD_WR_DATA8(0x0B);
  218.         LCD_WR_DATA8(0x1F);
  219.         LCD_WR_DATA8(0x23);

  220.         LCD_WR_REG(0xE1);
  221.         LCD_WR_DATA8(0xD0);
  222.         LCD_WR_DATA8(0x04);
  223.         LCD_WR_DATA8(0x0C);
  224.         LCD_WR_DATA8(0x11);
  225.         LCD_WR_DATA8(0x13);
  226.         LCD_WR_DATA8(0x2C);
  227.         LCD_WR_DATA8(0x3F);
  228.         LCD_WR_DATA8(0x44);
  229.         LCD_WR_DATA8(0x51);
  230.         LCD_WR_DATA8(0x2F);
  231.         LCD_WR_DATA8(0x1F);
  232.         LCD_WR_DATA8(0x1F);
  233.         LCD_WR_DATA8(0x20);
  234.         LCD_WR_DATA8(0x23);
  235.         LCD_WR_REG(0x21);

  236.         LCD_WR_REG(0x29);
  237. }

  238. ///////////////////具体应用操作///////////////////
  239. /******************************************************************************
  240.       函数说明:在指定区域填充颜色
  241.       入口数据:xsta,ysta   起始坐标
  242.                 xend,yend   终止坐标
  243.                                                                 color       要填充的颜色
  244.       返回值:  无
  245. ******************************************************************************/
  246. void LCD_Fill(u16 xsta,u16 ysta,u16 xend,u16 yend,u16 color)
  247. {         
  248.         u16 i,j;
  249.         LCD_Address_Set(xsta,ysta,xend-1,yend-1);//设置显示范围
  250.         for(i=ysta;i<yend;i++)
  251.         {                                                                                                                           
  252.                 for(j=xsta;j<xend;j++)
  253.                 {
  254.                         LCD_WR_DATA(color);
  255.                 }
  256.         }                                                       
  257. }

  258. /******************************************************************************
  259.       函数说明:在指定位置画点
  260.       入口数据:x,y 画点坐标
  261.                 color 点的颜色
  262.       返回值:  无
  263. ******************************************************************************/
  264. void LCD_DrawPoint(u16 x,u16 y,u16 color)
  265. {
  266.         LCD_Address_Set(x,y,x,y);//设置光标位置
  267.         LCD_WR_DATA(color);
  268. }


  269. /******************************************************************************
  270.       函数说明:画线
  271.       入口数据:x1,y1   起始坐标
  272.                 x2,y2   终止坐标
  273.                 color   线的颜色
  274.       返回值:  无
  275. ******************************************************************************/
  276. void LCD_DrawLine(u16 x1,u16 y1,u16 x2,u16 y2,u16 color)
  277. {
  278.         u16 t;
  279.         int xerr=0,yerr=0,delta_x,delta_y,distance;
  280.         int incx,incy,uRow,uCol;
  281.         delta_x=x2-x1; //计算坐标增量
  282.         delta_y=y2-y1;
  283.         uRow=x1;//画线起点坐标
  284.         uCol=y1;
  285.         if(delta_x>0)incx=1; //设置单步方向
  286.         else if (delta_x==0)incx=0;//垂直线
  287.         else {incx=-1;delta_x=-delta_x;}
  288.         if(delta_y>0)incy=1;
  289.         else if (delta_y==0)incy=0;//水平线
  290.         else {incy=-1;delta_y=-delta_x;}
  291.         if(delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴
  292.         else distance=delta_y;
  293.         for(t=0;t<distance+1;t++)
  294.         {
  295.                 LCD_DrawPoint(uRow,uCol,color);//画点
  296.                 xerr+=delta_x;
  297.                 yerr+=delta_y;
  298.                 if(xerr>distance)
  299.                 {
  300.                         xerr-=distance;
  301.                         uRow+=incx;
  302.                 }
  303.                 if(yerr>distance)
  304.                 {
  305.                         yerr-=distance;
  306.                         uCol+=incy;
  307.                 }
  308.         }
  309. }


  310. /******************************************************************************
  311.       函数说明:画矩形
  312.       入口数据:x1,y1   起始坐标
  313.                 x2,y2   终止坐标
  314.                 color   矩形的颜色
  315.       返回值:  无
  316. ******************************************************************************/
  317. void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2,u16 color)
  318. {
  319.         LCD_DrawLine(x1,y1,x2,y1,color);
  320.         LCD_DrawLine(x1,y1,x1,y2,color);
  321.         LCD_DrawLine(x1,y2,x2,y2,color);
  322.         LCD_DrawLine(x2,y1,x2,y2,color);
  323. }


  324. /******************************************************************************
  325.       函数说明:画圆
  326.       入口数据:x0,y0   圆心坐标
  327.                 r       半径
  328.                 color   圆的颜色
  329.       返回值:  无
  330. ******************************************************************************/
  331. void Draw_Circle(u16 x0,u16 y0,u8 r,u16 color)
  332. {
  333.         int a,b;
  334.         a=0;b=r;          
  335.         while(a<=b)
  336.         {
  337.                 LCD_DrawPoint(x0-b,y0-a,color);             //3           
  338.                 LCD_DrawPoint(x0+b,y0-a,color);             //0           
  339.                 LCD_DrawPoint(x0-a,y0+b,color);             //1               
  340.                 LCD_DrawPoint(x0-a,y0-b,color);             //2            
  341.                 LCD_DrawPoint(x0+b,y0+a,color);             //4               
  342.                 LCD_DrawPoint(x0+a,y0-b,color);             //5
  343.                 LCD_DrawPoint(x0+a,y0+b,color);             //6
  344.                 LCD_DrawPoint(x0-b,y0+a,color);             //7
  345.                 a++;
  346.                 if((a*a+b*b)>(r*r))//判断要画的点是否过远
  347.                 {
  348.                         b--;
  349.                 }
  350.         }
  351. }

  352. /******************************************************************************
  353.       函数说明:显示汉字串
  354.       入口数据:x,y显示坐标
  355.                 *s 要显示的汉字串
  356.                 fc 字的颜色
  357.                 bc 字的背景色
  358.                 sizey 字号 可选 16 24 32
  359.                 mode:  0非叠加模式  1叠加模式
  360.       返回值:  无
  361. ******************************************************************************/
  362. void LCD_ShowChinese(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode)
  363. {
  364.         while(*s!=0)
  365.         {
  366.                 if(sizey==16) LCD_ShowChinese16x16(x,y,s,fc,bc,sizey,mode);
  367.                 else if(sizey==24) LCD_ShowChinese24x24(x,y,s,fc,bc,sizey,mode);
  368.                 else if(sizey==32) LCD_ShowChinese32x32(x,y,s,fc,bc,sizey,mode);
  369.                 else return;
  370.                 s+=2;
  371.                 x+=sizey;
  372.         }
  373. }

  374. /******************************************************************************
  375.       函数说明:显示单个16x16汉字
  376.       入口数据:x,y显示坐标
  377.                 *s 要显示的汉字
  378.                 fc 字的颜色
  379.                 bc 字的背景色
  380.                 sizey 字号
  381.                 mode:  0非叠加模式  1叠加模式
  382.       返回值:  无
  383. ******************************************************************************/
  384. void LCD_ShowChinese16x16(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode)
  385. {
  386.         u8 i,j;
  387.         u16 k;
  388.         u16 HZnum;//汉字数目
  389.         u16 TypefaceNum;//一个字符所占字节大小
  390.         u16 x0=x;
  391.         TypefaceNum=sizey/8*sizey;//此算法只适用于字宽等于字高,且字高是8的倍数的字,
  392.                                   //也建议用户使用这样大小的字,否则显示容易出问题!
  393.         HZnum=sizeof(tfont16)/sizeof(typFNT_GB16);        //统计汉字数目
  394.         for(k=0;k<HZnum;k++)
  395.         {
  396.                 if ((tfont16[k].Index[0]==*(s))&&(tfont16[k].Index[1]==*(s+1)))
  397.                 {        
  398.                         LCD_Address_Set(x,y,x+sizey-1,y+sizey-1);
  399.                         for(i=0;i<TypefaceNum;i++)
  400.                         {
  401.                                 for(j=0;j<8;j++)
  402.                                 {       
  403.                                         if(!mode)//非叠加方式
  404.                                         {
  405.                                                 if(tfont16[k].Msk[i]&(0x01<<j))LCD_WR_DATA(fc);
  406.                                                 else LCD_WR_DATA(bc);
  407.                                         }
  408.                                         else//叠加方式
  409.                                         {
  410.                                                 if(tfont16[k].Msk[i]&(0x01<<j))        LCD_DrawPoint(x,y,fc);//画一个点
  411.                                                 x++;
  412.                                                 if((x-x0)==sizey)
  413.                                                 {
  414.                                                         x=x0;
  415.                                                         y++;
  416.                                                         break;
  417.                                                 }
  418.                                         }
  419.                                 }
  420.                         }
  421.                 }                                         
  422.                 continue;  //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响
  423.         }
  424. }


  425. /******************************************************************************
  426.       函数说明:显示单个24x24汉字
  427.       入口数据:x,y显示坐标
  428.                 *s 要显示的汉字
  429.                 fc 字的颜色
  430.                 bc 字的背景色
  431.                 sizey 字号
  432.                 mode:  0非叠加模式  1叠加模式
  433.       返回值:  无
  434. ******************************************************************************/
  435. void LCD_ShowChinese24x24(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode)
  436. {
  437.         u8 i,j;
  438.         u16 k;
  439.         u16 HZnum;//汉字数目
  440.         u16 TypefaceNum;//一个字符所占字节大小
  441.         u16 x0=x;
  442.         TypefaceNum=sizey/8*sizey;//此算法只适用于字宽等于字高,且字高是8的倍数的字,
  443.                                   //也建议用户使用这样大小的字,否则显示容易出问题!
  444.         HZnum=sizeof(tfont24)/sizeof(typFNT_GB24);        //统计汉字数目
  445.         for(k=0;k<HZnum;k++)
  446.         {
  447.                 if ((tfont24[k].Index[0]==*(s))&&(tfont24[k].Index[1]==*(s+1)))
  448.                 {        
  449.                         LCD_Address_Set(x,y,x+sizey-1,y+sizey-1);
  450.                         for(i=0;i<TypefaceNum;i++)
  451.                         {
  452.                                 for(j=0;j<8;j++)
  453.                                 {       
  454.                                         if(!mode)//非叠加方式
  455.                                         {
  456.                                                 if(tfont24[k].Msk[i]&(0x01<<j))LCD_WR_DATA(fc);
  457.                                                 else LCD_WR_DATA(bc);
  458.                                         }
  459.                                         else//叠加方式
  460.                                         {
  461.                                                 if(tfont24[k].Msk[i]&(0x01<<j))        LCD_DrawPoint(x,y,fc);//画一个点
  462.                                                 x++;
  463.                                                 if((x-x0)==sizey)
  464.                                                 {
  465.                                                         x=x0;
  466.                                                         y++;
  467.                                                         break;
  468.                                                 }
  469.                                         }
  470.                                 }
  471.                         }
  472.                 }                                         
  473.                 continue;  //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响
  474.         }
  475. }

  476. /******************************************************************************
  477.       函数说明:显示单个32x32汉字
  478.       入口数据:x,y显示坐标
  479.                 *s 要显示的汉字
  480.                 fc 字的颜色
  481.                 bc 字的背景色
  482.                 sizey 字号
  483.                 mode:  0非叠加模式  1叠加模式
  484.       返回值:  无
  485. ******************************************************************************/
  486. void LCD_ShowChinese32x32(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode)
  487. {
  488.         u8 i,j;
  489.         u16 k;
  490.         u16 HZnum;//汉字数目
  491.         u16 TypefaceNum;//一个字符所占字节大小
  492.         u16 x0=x;
  493.         TypefaceNum=sizey/8*sizey;//此算法只适用于字宽等于字高,且字高是8的倍数的字,
  494.                                   //也建议用户使用这样大小的字,否则显示容易出问题!
  495.         HZnum=sizeof(tfont32)/sizeof(typFNT_GB32);        //统计汉字数目
  496.         for(k=0;k<HZnum;k++)
  497.         {
  498.                 if ((tfont32[k].Index[0]==*(s))&&(tfont32[k].Index[1]==*(s+1)))
  499.                 {        
  500.                         LCD_Address_Set(x,y,x+sizey-1,y+sizey-1);
  501.                         for(i=0;i<TypefaceNum;i++)
  502.                         {
  503.                                 for(j=0;j<8;j++)
  504.                                 {       
  505.                                         if(!mode)//非叠加方式
  506.                                         {
  507.                                                 if(tfont32[k].Msk[i]&(0x01<<j))LCD_WR_DATA(fc);
  508.                                                 else LCD_WR_DATA(bc);
  509.                                         }
  510.                                         else//叠加方式
  511.                                         {
  512.                                                 if(tfont32[k].Msk[i]&(0x01<<j))        LCD_DrawPoint(x,y,fc);//画一个点
  513.                                                 x++;
  514.                                                 if((x-x0)==sizey)
  515.                                                 {
  516.                                                         x=x0;
  517.                                                         y++;
  518.                                                         break;
  519.                                                 }
  520.                                         }
  521.                                 }
  522.                         }
  523.                 }                                         
  524.                 continue;  //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响
  525.         }
  526. }


  527. /******************************************************************************
  528.       函数说明:显示单个字符
  529.       入口数据:x,y显示坐标
  530.                 num 要显示的字符
  531.                 fc 字的颜色
  532.                 bc 字的背景色
  533.                 sizey 字号
  534.                 mode:  0非叠加模式  1叠加模式
  535.       返回值:  无
  536. ******************************************************************************/
  537. void LCD_ShowChar(u16 x,u16 y,u8 num,u16 fc,u16 bc,u8 sizey,u8 mode)
  538. {
  539.         u8 temp,sizex,t;
  540.         u16 i,TypefaceNum;//一个字符所占字节大小
  541.         u16 x0=x;
  542.         sizex=sizey/2;
  543.         TypefaceNum=sizex/8*sizey;
  544.         num=num-' ';    //得到偏移后的值
  545.         LCD_Address_Set(x,y,x+sizex-1,y+sizey-1);  //设置光标位置
  546.         for(i=0;i<TypefaceNum;i++)
  547.         {
  548.                 if(sizey==16)temp=ascii_1608[num][i];                       //调用8x16字体
  549.                 else if(sizey==32)temp=ascii_3216[num][i];                 //调用16x32字体
  550.                 else return;
  551.                 for(t=0;t<8;t++)
  552.                 {
  553.                         if(!mode)//非叠加模式
  554.                         {
  555.                                 if(temp&(0x01<<t))LCD_WR_DATA(fc);
  556.                                 else LCD_WR_DATA(bc);
  557.                         }
  558.                         else//叠加模式
  559.                         {
  560.                                 if(temp&(0x01<<t))LCD_DrawPoint(x,y,fc);//画一个点
  561.                                 x++;
  562.                                 if((x-x0)==sizex)
  563.                                 {
  564.                                         x=x0;
  565.                                         y++;
  566.                                         break;
  567.                                 }
  568.                         }
  569.                 }
  570.         }                      
  571. }


  572. /******************************************************************************
  573.       函数说明:显示字符串
  574.       入口数据:x,y显示坐标
  575.                 *p 要显示的字符串
  576.                 fc 字的颜色
  577.                 bc 字的背景色
  578.                 sizey 字号
  579.                 mode:  0非叠加模式  1叠加模式
  580.       返回值:  无
  581. ******************************************************************************/
  582. void LCD_ShowString(u16 x,u16 y,const u8 *p,u16 fc,u16 bc,u8 sizey,u8 mode)
  583. {         
  584.         while(*p!='\0')
  585.         {      
  586.                 LCD_ShowChar(x,y,*p,fc,bc,sizey,mode);
  587.                 x+=sizey/2;
  588.                 p++;
  589.         }  
  590. }


  591. /******************************************************************************
  592.       函数说明:显示数字
  593.       入口数据:m底数,n指数
  594.       返回值:  无
  595. ******************************************************************************/
  596. u32 mypow(u8 m,u8 n)
  597. {
  598.         u32 result=1;         
  599.         while(n--)result*=m;
  600.         return result;
  601. }


  602. /******************************************************************************
  603.       函数说明:显示整数变量
  604.       入口数据:x,y显示坐标
  605.                 num 要显示整数变量
  606.                 len 要显示的位数
  607.                 fc 字的颜色
  608.                 bc 字的背景色
  609.                 sizey 字号
  610.       返回值:  无
  611. ******************************************************************************/
  612. void LCD_ShowIntNum(u16 x,u16 y,u16 num,u8 len,u16 fc,u16 bc,u8 sizey)
  613. {                
  614.         u8 t,temp;
  615.         u8 enshow=0;
  616.         u8 sizex=sizey/2;
  617.         for(t=0;t<len;t++)
  618.         {
  619.                 temp=(num/mypow(10,len-t-1))%10;
  620.                 if(enshow==0&&t<(len-1))
  621.                 {
  622.                         if(temp==0)
  623.                         {
  624.                                 LCD_ShowChar(x+t*sizex,y,' ',fc,bc,sizey,0);
  625.                                 continue;
  626.                         }else enshow=1;
  627.                           
  628.                 }
  629.                  LCD_ShowChar(x+t*sizex,y,temp+48,fc,bc,sizey,0);
  630.         }
  631. }


  632. /******************************************************************************
  633.       函数说明:显示两位小数变量
  634.       入口数据:x,y显示坐标
  635.                 num 要显示小数变量
  636.                 len 要显示的位数
  637.                 fc 字的颜色
  638.                 bc 字的背景色
  639.                 sizey 字号
  640.       返回值:  无
  641. ******************************************************************************/
  642. void LCD_ShowFloatNum1(u16 x,u16 y,float num,u8 len,u16 fc,u16 bc,u8 sizey)
  643. {                
  644.         u8 t,temp,sizex;
  645.         u16 num1;
  646.         sizex=sizey/2;
  647.         num1=num*100;
  648.         for(t=0;t<len;t++)
  649.         {
  650.                 temp=(num1/mypow(10,len-t-1))%10;
  651.                 if(t==(len-2))
  652.                 {
  653.                         LCD_ShowChar(x+(len-2)*sizex,y,'.',fc,bc,sizey,0);
  654.                         t++;
  655.                         len+=1;
  656.                 }
  657.                  LCD_ShowChar(x+t*sizex,y,temp+48,fc,bc,sizey,0);
  658.         }
  659. }


  660. /******************************************************************************
  661.       函数说明:显示图片
  662.       入口数据:x,y起点坐标
  663.                 length 图片长度
  664.                 width  图片宽度
  665.                 pic[]  图片数组   
  666.       返回值:  无
  667. ******************************************************************************/
  668. void LCD_ShowPicture(u16 x,u16 y,u16 length,u16 width,const u8 pic[])
  669. {
  670.         u16 i,j,k=0;
  671.         LCD_Address_Set(x,y,x+length-1,y+width-1);
  672.         for(i=0;i<length;i++)
  673.         {
  674.                 for(j=0;j<width;j++)
  675.                 {
  676.                         LCD_WR_DATA8(pic[k*2]);
  677.                         LCD_WR_DATA8(pic[k*2+1]);
  678.                         k++;
  679.                 }
  680.         }                       
  681. }



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




  20. int main(void)
  21. {
  22.     u8 i,j;
  23.         float t=0;
  24.    
  25.     PROTECT_REG
  26.     (
  27.       /* Init System Clock*/
  28.       SYS_Init();
  29.       /* Init UART0 for printf */
  30.       UART0_Init(115200);
  31.       /* Init TIMER0 */
  32.       TM0_Init();
  33.     )
  34.    
  35.     LED_Init();
  36.     KEY_Init();
  37.     printf("\n\nCPU [url=home.php?mod=space&uid=72445]@[/url] %d Hz\n", SystemCoreClock);
  38.     printf("+-------------------------------------------------------+\n");
  39.     printf("|    GPIO Power-Down and Wake-up by PB.3 Sample Code    |\n");
  40.     printf("+-------------------------------------------------------+\n\n");

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

  57.                 LCD_ShowChinese(8,0,(u8*)"意法半导体社区",RED,WHITE,32,0);
  58.                 LCD_ShowString(0,40,(u8*)"LCD_W:",RED,WHITE,16,0);
  59.                 LCD_ShowIntNum(48,40,LCD_W,3,RED,WHITE,16);
  60.                 LCD_ShowString(80,40,(u8*)"LCD_H:",RED,WHITE,16,0);
  61.                 LCD_ShowIntNum(128,40,LCD_H,3,RED,WHITE,16);
  62.                 LCD_ShowString(80,40,(u8*)"LCD_H:",RED,WHITE,16,0);
  63.                 LCD_ShowString(0,70,(u8*)"Increaseing Nun:",RED,WHITE,16,0);
  64.                 LCD_ShowFloatNum1(128,70,t,4,RED,WHITE,16);
  65.                 LCD_ShowString(0,86+8,(u8*)"qjp1988113 @ 21 IC",RED,WHITE,16,0);//86+16=102
  66.                 t+=0.11f;
  67.                 for(j=0;j<3;j++)
  68.                 {
  69.                         for(i=0;i<6;i++)
  70.                         {
  71.                                 LCD_ShowPicture(40*i,120+j*40,40,40,gImage_1);
  72.                         }
  73.                 }
  74.                 delay_ms(2000);
  75.                 LCD_ShowPicture(0,0,240,240,gImage_2);
  76.                 delay_ms(2000);
  77.                 LCD_ShowPicture(0,0,240,240,gImage_3);
  78.                 delay_ms(2000);
  79.                 LCD_ShowPicture(0,0,240,240,gImage_4);
  80.                 delay_ms(2000);
  81.     }
  82. }
这里,我把官方例子给整理了一边,各个外设分离,方便移植之用:
Z4.png
下载,查看LCD显示:
XX1.gif

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

粉丝
快速回复 在线客服 返回列表 返回顶部