[MM32硬件] 【MM32 eMiniBoard测评报告】+ 基于SPI接口的显示屏驱动

[复制链接]
 楼主| jinglixixi 发表于 2020-5-26 14:51 | 显示全部楼层 |阅读模式
本帖最后由 jinglixixi 于 2020-5-26 15:04 编辑

熟练地掌握GPIO口的使用,既是基本功的训炼,也为其他的应用提供了方便,这里就模拟SPI接口来实现2种显示屏的显示功能。

1. LCD5510显示屏
该显示屏与GPIO口的连接情况如下:
PB3 -- LED+
PA15 -- D0   (SCL)
PB12 -- D1   (SDI)
PB15 -- D/C
PB14 -- RST
PB13 -- CS

为实现显示功能相应的定义如下:
#define X_Col_Addr     0x80               
#define Y_Page_Addr    0x40        

#define LCD_reset_hard            LCD_RST_L; LCD_RST_H        
#define LCD_reset_soft            LCD_reset_5510()                        
#define LCD_write_cmd(cmd)        LCD_write_byte(cmd, 0)        
#define LCD_write_dat(dat)        LCD_write_byte(dat, 1)

#define LCD_LED_High()      GPIO_SetBits(GPIOB,GPIO_Pin_3)

#define  LCD_CLK_H          GPIO_SetBits(GPIOA,GPIO_Pin_15);  // CLK PA15
#define  LCD_CLK_L          GPIO_ResetBits(GPIOA,GPIO_Pin_15);

#define  LCD_DIN_H          GPIO_SetBits(GPIOB,GPIO_Pin_12);  // DIN PB12
#define  LCD_DIN_L          GPIO_ResetBits(GPIOB,GPIO_Pin_12);

#define  LCD_DC_H                  GPIO_SetBits(GPIOB,GPIO_Pin_15);   //DC PB15
#define  LCD_DC_L                  GPIO_ResetBits(GPIOB,GPIO_Pin_15);

#define  LCD_CS_H                  GPIO_SetBits(GPIOB,GPIO_Pin_13);   //SCE PB13
#define  LCD_CS_L                  GPIO_ResetBits(GPIOB,GPIO_Pin_13);

#define  LCD_RST_H          GPIO_SetBits(GPIOB,GPIO_Pin_14);   //RST PB14
#define  LCD_RST_L          GPIO_ResetBits(GPIOB,GPIO_Pin_14);

对相关引脚的配置函数为:
  1. void LCD_GPIO_Cogfig(void)
  2. {
  3.   GPIO_InitTypeDef  GPIO_InitStructure;
  4.   RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA|RCC_AHBPeriph_GPIOB, ENABLE);
  5.   GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_15;
  6.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  7.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  8.   GPIO_Init(GPIOA, &GPIO_InitStructure);
  9.   GPIO_InitStructure.GPIO_Pin  =   GPIO_Pin_3|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
  10.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  11.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  12.   GPIO_Init(GPIOB, &GPIO_InitStructure);
  13.   LCD_LED_High();
  14. }


实现 LCD5510显示屏的初始化函数为:
  1. void LCD5510_Init(void)
  2. {
  3. LCD_GPIO_Cogfig();
  4. LCD_reset_hard;
  5. LCD_write_cmd(0x21);
  6. LCD_write_cmd(0x06);
  7. LCD_write_cmd(0x13);
  8. LCD_write_cmd(0xc8);
  9. LCD_write_cmd(0x20);
  10. LCD_write_cmd(0x0c);
  11. LCD_write_cmd(Y_Page_Addr);
  12. LCD_write_cmd(X_Col_Addr);
  13. LCD_clr_scr();
  14. }

相关的显示函数有:
  1. void LCD_printc(unsigned char x, unsigned char y, unsigned char c_dat)
  2. {
  3. unsigned char i, j;
  4. c_dat -= 32;
  5. x <<= 3;        //8
  6. y <<= 1;        //16
  7. for(j = 0; j < 2; j++)
  8. {
  9. LCD_pos_byte(x, (y + j));
  10. for(i = 0; i < 8; i++)
  11. LCD_write_dat(Font_code[c_dat][8 * j + i]);
  12. }
  13. }

  14. void LCD_prints(unsigned char x, unsigned char y, unsigned char *s_dat)
  15. {
  16. while(*s_dat && x < 10)
  17. {LCD_printc(x++, y, *s_dat); s_dat++;}
  18. }


  19. void LCD_printch(unsigned char x, unsigned char y, unsigned char  *h_dat)
  20. {
  21. unsigned char i, j;
  22. x <<= 4;
  23. y <<= 1;
  24. for(j = 0; j < 2; j++)
  25. {
  26. LCD_pos_byte(x, (y + j));
  27. for(i = 0; i < 16; i++) LCD_write_dat(h_dat[16 * j + i]);
  28. }
  29. }

  30. void LCD_showch(unsigned char x, unsigned char y, unsigned char  *dat)
  31. {
  32. unsigned char i;
  33. for(i = 0; i < 20; i++)
  34. {
  35. if((GB_16[i].Index[0] == dat[0]) && (GB_16[i].Index[1] == dat[1])) break;
  36. }
  37. LCD_printch(x, y, GB_16[i].Msk);
  38. }


  39. void LCD_showsh(unsigned char x, unsigned char y, unsigned char  *dat)
  40. {
  41. while(*dat) {LCD_showch(x++, y, dat); dat += 2;}
  42. }


实现图1显示效果的主程序为:
  1. int main(void)   
  2. {
  3.   delay_init();
  4.   delay_ms(300);
  5.   LCD5510_Init();
  6.   LCD_prints(0,0,"MM32L073PF");   
  7.   LCD_prints(0,1,"LCD5510 ");
  8.   LCD_prints(0,2,"JINGLIXIXI");
  9.   while(1);
  10. }


IMG_20200524_153214_resized_20200526_012917602.jpg
图1显示效果



2. TFT2.4’彩色显示屏
该显示屏对GPIO口的使用情况与前一个显示屏相近,其设置相关引脚输出高低电平的定义如下:

#define LCD_LED_High()      GPIO_SetBits(GPIOB,GPIO_Pin_3)

#define LCD_CS_High()        GPIO_SetBits(GPIOB,GPIO_Pin_13);   //SC PB13
#define LCD_CS_Low()         GPIO_ResetBits(GPIOB,GPIO_Pin_13);
#define LCD_SCK_High()      GPIO_SetBits(GPIOA,GPIO_Pin_15);  // CLK PA15
#define LCD_SCK_Low()       GPIO_ResetBits(GPIOA,GPIO_Pin_15);
#define LCD_SDI_High()       GPIO_SetBits(GPIOB,GPIO_Pin_12);  // SDI PB12
#define LCD_SDI_Low()        GPIO_ResetBits(GPIOB,GPIO_Pin_12);
#define LCD_DC_High()        GPIO_SetBits(GPIOB,GPIO_Pin_15);   //DC PB15
#define LCD_DC_Low()         GPIO_ResetBits(GPIOB,GPIO_Pin_15);
#define LCD_REST_High()     GPIO_SetBits(GPIOB,GPIO_Pin_14);   //RST PB14
#define LCD_REST_Low()     GPIO_ResetBits(GPIOB,GPIO_Pin_14);


定义相关引脚的函数如下:
  1. void GPIO_Configuration(void)
  2. {
  3. GPIO_InitTypeDef  GPIO_InitStructure;
  4. RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA|RCC_AHBPeriph_GPIOB, ENABLE);  
  5. GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_15;
  6. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  7. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  8. GPIO_Init(GPIOA, &GPIO_InitStructure);
  9. GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_3|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
  10. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  11. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  12. GPIO_Init(GPIOB, &GPIO_InitStructure);
  13. LCD_LED_High();
  14. }


其TFT显示屏的初始化函数为:
  1. void Lcd_Init(void)
  2. {
  3.     LCD_REST_Low();
  4.     delay_ms(20);
  5.     LCD_REST_High();
  6.     delay_ms(20);
  7.     LCD_CS_Low();
  8.     LCD_WR_REG(0xCB);
  9.     LCD_WR_DATA8(0x39);
  10.     LCD_WR_DATA8(0x2C);
  11.     LCD_WR_DATA8(0x00);
  12.     LCD_WR_DATA8(0x34);
  13.     LCD_WR_DATA8(0x02);
  14.     LCD_WR_REG(0xCF);
  15.     LCD_WR_DATA8(0x00);
  16.     LCD_WR_DATA8(0XC1);
  17.     LCD_WR_DATA8(0X30);
  18.     LCD_WR_REG(0xE8);
  19.     LCD_WR_DATA8(0x85);
  20.     LCD_WR_DATA8(0x00);
  21.     LCD_WR_DATA8(0x78);
  22.     LCD_WR_REG(0xEA);  
  23.     LCD_WR_DATA8(0x00);
  24.     LCD_WR_DATA8(0x00);
  25.     LCD_WR_REG(0xED);  
  26.     LCD_WR_DATA8(0x64);
  27.     LCD_WR_DATA8(0x03);
  28.     LCD_WR_DATA8(0X12);
  29.     LCD_WR_DATA8(0X81);
  30.     LCD_WR_REG(0xF7);
  31.     LCD_WR_DATA8(0x20);
  32.     LCD_WR_REG(0xC0);     //Power control
  33.     LCD_WR_DATA8(0x23);   //VRH[5:0]
  34.     LCD_WR_REG(0xC1);     //Power control
  35.     LCD_WR_DATA8(0x10);   //SAP[2:0];BT[3:0]
  36.     LCD_WR_REG(0xC5);     //VCM control
  37.     LCD_WR_DATA8(0x3e);  
  38.     LCD_WR_DATA8(0x28);
  39.     LCD_WR_REG(0xC7);     // VCM control2
  40.     LCD_WR_DATA8(0x86);
  41.     LCD_WR_REG(0x36);     // Memory Access Control
  42.     LCD_WR_DATA8(0x48);   // C8
  43.     LCD_WR_REG(0x3A);   
  44.     LCD_WR_DATA8(0x55);
  45.     LCD_WR_REG(0xB1);   
  46.     LCD_WR_DATA8(0x00);
  47.     LCD_WR_DATA8(0x18);
  48.     LCD_WR_REG(0xB6);    // Display Function Control
  49.     LCD_WR_DATA8(0x08);
  50.     LCD_WR_DATA8(0x82);
  51.     LCD_WR_DATA8(0x27);  
  52.     LCD_WR_REG(0xF2);    // 3Gamma Function Disable
  53.     LCD_WR_DATA8(0x00);
  54.     LCD_WR_REG(0x26);    // Gamma curve selected
  55.     LCD_WR_DATA8(0x01);
  56.     LCD_WR_REG(0xE0);    // Set Gamma
  57.     LCD_WR_DATA8(0x0F);
  58.     LCD_WR_DATA8(0x31);
  59.     LCD_WR_DATA8(0x2B);
  60.     LCD_WR_DATA8(0x0C);
  61.     LCD_WR_DATA8(0x0E);
  62.     LCD_WR_DATA8(0x08);
  63.     LCD_WR_DATA8(0x4E);
  64.     LCD_WR_DATA8(0xF1);
  65.     LCD_WR_DATA8(0x37);
  66.     LCD_WR_DATA8(0x07);
  67.     LCD_WR_DATA8(0x10);
  68.     LCD_WR_DATA8(0x03);
  69.     LCD_WR_DATA8(0x0E);
  70.     LCD_WR_DATA8(0x09);
  71.     LCD_WR_DATA8(0x00);
  72.     LCD_WR_REG(0XE1);    //Set Gamma
  73.     LCD_WR_DATA8(0x00);
  74.     LCD_WR_DATA8(0x0E);
  75.     LCD_WR_DATA8(0x14);
  76.     LCD_WR_DATA8(0x03);
  77.     LCD_WR_DATA8(0x11);
  78.     LCD_WR_DATA8(0x07);
  79.     LCD_WR_DATA8(0x31);
  80.     LCD_WR_DATA8(0xC1);
  81.     LCD_WR_DATA8(0x48);
  82.     LCD_WR_DATA8(0x08);
  83.     LCD_WR_DATA8(0x0F);
  84.     LCD_WR_DATA8(0x0C);
  85.     LCD_WR_DATA8(0x31);
  86.     LCD_WR_DATA8(0x36);
  87.     LCD_WR_DATA8(0x0F);
  88.     LCD_WR_REG(0x11);    //Exit Sleep
  89.     delay_ms(120);
  90.     LCD_WR_REG(0x29);    //Display on
  91.     LCD_WR_REG(0x2c);
  92. }

为实现汉字的显示,特定义了2种汉字显示字模,即16*16汉字字模和32*32汉字字模。

32*32汉字字模的结构为:
unsigned char hanzi32[]={
// 标(0) 准(1) 化(2) 考(3) 试(4) 进(5) 程(6) 语(7) 音(8) 提(9) 示(10) 器(11)
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x03,0x00,0x00,
0x80,0x00,0x00,0x04,0x80,0xC0,0xFF,0x0F,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x00,
0x80,0x00,0x00,0x00,0x80,0x08,0x00,0x00,0xFC,0x1F,0x00,0x00,0x80,0x00,0x00,0x18,
0xC0,0xF0,0xFF,0x3F,0xC0,0x00,0x30,0x00,0xC0,0x01,0x30,0x00,0xE0,0x06,0x30,0x00,
0xE0,0x0C,0x30,0x00,0xA0,0x8C,0x33,0x01,0xB0,0x88,0x31,0x03,0x90,0x80,0x31,0x06,
0x98,0xC0,0x30,0x0C,0x88,0x40,0x30,0x0C,0x84,0x60,0x30,0x18,0x84,0x20,0x30,0x18,
0x80,0x10,0x30,0x38,0x80,0x18,0x30,0x10,0x80,0x08,0x30,0x10,0x80,0x84,0x30,0x00,
0x80,0x00,0x3F,0x00,0x80,0x00,0x1C,0x00,0x80,0x00,0x08,0x00,0x00,0x00,0x00,0x00,/*"标",0*/
};

//16*16汉字字模的结构为:
unsigned char hanzi16[]={
//入(0) 场(1) 开(2) 考(3) 写(4) 作(5) 听(6) 力(7) 答(8) 题(9) 结(10) 束(11)
0x20,0x00,0x40,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x40,0x01,0x40,0x01,0x40,0x01,
0x20,0x02,0x20,0x02,0x10,0x04,0x10,0x04,0x08,0x08,0x04,0x08,0x02,0x10,0x01,0x60,/*"入",0*/
};

实现汉字显示的函数有:
  1. void showhanzi16(unsigned int x,unsigned int y,unsigned char index)
  2. {  
  3. unsigned char i,j,k;
  4. const unsigned char *temp=hanzi16;   
  5. temp+=index*32;
  6. for(j=0;j<16;j++)
  7. {
  8. LCD_SetCursor(x,y+j);
  9. LCD_WriteRAM_Prepare();
  10. for(k=0;k<2;k++)
  11. {
  12. for(i=0;i<8;i++)
  13. {      
  14.          if((*temp&(1<<i))!=0)
  15. {
  16. LCD_WR_DATA(POINT_COLOR);
  17. }
  18. else
  19. {
  20. LCD_WR_DATA(BACK_COLOR);
  21. }   
  22. }
  23. temp++;
  24. }
  25. }
  26. }

  27. void showhanzi32(unsigned int x,unsigned int y,unsigned char index)
  28. {  
  29. unsigned char i,j,k;
  30. const unsigned char *temp=hanzi32;   
  31. temp+=index*128;
  32. for(j=0;j<32;j++)
  33. {
  34. LCD_SetCursor(x,y+j);
  35. LCD_WriteRAM_Prepare();        //GRAM
  36. for(k=0;k<4;k++)
  37. {
  38. for(i=0;i<8;i++)
  39. {      
  40.         if((*temp&(1<<i))!=0)
  41. {
  42. LCD_WR_DATA(POINT_COLOR);
  43. }
  44. else
  45. {
  46. LCD_WR_DATA(BACK_COLOR);
  47. }   
  48. }
  49. temp++;
  50. }
  51. }
  52. }


显示图2显示效果的函数为:
  1. void xianshi()  
  2. {
  3. LCD_Clear(RED);  
  4. BACK_COLOR=RED;
  5. POINT_COLOR=WHITE;   
  6. //32*32
  7. showhanzi32(20,10,0);         
  8. showhanzi32(60,10,1);         
  9. showhanzi32(100,10,2);   
  10. showhanzi32(140,10,3);         
  11. showhanzi32(180,10,4);
  12. //16*16


对应的主程序为:
  1. int main(void)   
  2. {
  3.     delay_init();
  4.     delay_ms(300);
  5.     GPIO_Configuration();
  6.     Lcd_Init();           
  7.     xianshi();
  8.     while(1);
  9. }

IMG_20200526_104822_resized_20200526_012903670.jpg
图2显示效果

zhu^zhu 发表于 2020-5-26 15:11 | 显示全部楼层
请问一下大侠,用仿真器调试了吗?谢谢!
 楼主| jinglixixi 发表于 2020-5-26 15:14 | 显示全部楼层
zhu^zhu 发表于 2020-5-26 15:11
请问一下大侠,用仿真器调试了吗?谢谢!

没有用仿真器直接在硬件上完成的。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

515

主题

2929

帖子

39

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