[MM32硬件]

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

[复制链接]
622|2
手机看帖
扫描二维码
随时随地手机跟帖
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);

对相关引脚的配置函数为:
void LCD_GPIO_Cogfig(void)
{
  GPIO_InitTypeDef  GPIO_InitStructure;
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA|RCC_AHBPeriph_GPIOB, ENABLE);
  GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_15;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin  =   GPIO_Pin_3|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
  LCD_LED_High();
}


实现 LCD5510显示屏的初始化函数为:
void LCD5510_Init(void)
{
LCD_GPIO_Cogfig();
LCD_reset_hard;
LCD_write_cmd(0x21);
LCD_write_cmd(0x06);
LCD_write_cmd(0x13);
LCD_write_cmd(0xc8);
LCD_write_cmd(0x20);
LCD_write_cmd(0x0c);
LCD_write_cmd(Y_Page_Addr);
LCD_write_cmd(X_Col_Addr);
LCD_clr_scr();
}

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

void LCD_prints(unsigned char x, unsigned char y, unsigned char *s_dat)
{
while(*s_dat && x < 10)
{LCD_printc(x++, y, *s_dat); s_dat++;}
}


void LCD_printch(unsigned char x, unsigned char y, unsigned char  *h_dat)
{
unsigned char i, j;
x <<= 4;
y <<= 1;
for(j = 0; j < 2; j++)
{
LCD_pos_byte(x, (y + j));
for(i = 0; i < 16; i++) LCD_write_dat(h_dat[16 * j + i]);
}
}

void LCD_showch(unsigned char x, unsigned char y, unsigned char  *dat)
{
unsigned char i;
for(i = 0; i < 20; i++)
{
if((GB_16[i].Index[0] == dat[0]) && (GB_16[i].Index[1] == dat[1])) break;
}
LCD_printch(x, y, GB_16[i].Msk);
}


void LCD_showsh(unsigned char x, unsigned char y, unsigned char  *dat)
{
while(*dat) {LCD_showch(x++, y, dat); dat += 2;}
}


实现图1显示效果的主程序为:
int main(void)    
{
  delay_init();
  delay_ms(300);
  LCD5510_Init();
  LCD_prints(0,0,"MM32L073PF");   
  LCD_prints(0,1,"LCD5510 ");
  LCD_prints(0,2,"JINGLIXIXI");
  while(1);
}


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);


定义相关引脚的函数如下:
void GPIO_Configuration(void)
{
GPIO_InitTypeDef  GPIO_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA|RCC_AHBPeriph_GPIOB, ENABLE);  
GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_3|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
LCD_LED_High();
}


其TFT显示屏的初始化函数为:
void Lcd_Init(void)
{
    LCD_REST_Low();
    delay_ms(20);
    LCD_REST_High();
    delay_ms(20);
    LCD_CS_Low();
    LCD_WR_REG(0xCB);
    LCD_WR_DATA8(0x39);
    LCD_WR_DATA8(0x2C);
    LCD_WR_DATA8(0x00);
    LCD_WR_DATA8(0x34);
    LCD_WR_DATA8(0x02);
    LCD_WR_REG(0xCF);
    LCD_WR_DATA8(0x00);
    LCD_WR_DATA8(0XC1);
    LCD_WR_DATA8(0X30);
    LCD_WR_REG(0xE8);
    LCD_WR_DATA8(0x85);
    LCD_WR_DATA8(0x00);
    LCD_WR_DATA8(0x78);
    LCD_WR_REG(0xEA);  
    LCD_WR_DATA8(0x00);
    LCD_WR_DATA8(0x00);
    LCD_WR_REG(0xED);  
    LCD_WR_DATA8(0x64);
    LCD_WR_DATA8(0x03);
    LCD_WR_DATA8(0X12);
    LCD_WR_DATA8(0X81);
    LCD_WR_REG(0xF7);
    LCD_WR_DATA8(0x20);
    LCD_WR_REG(0xC0);     //Power control
    LCD_WR_DATA8(0x23);   //VRH[5:0]
    LCD_WR_REG(0xC1);     //Power control
    LCD_WR_DATA8(0x10);   //SAP[2:0];BT[3:0]
    LCD_WR_REG(0xC5);     //VCM control
    LCD_WR_DATA8(0x3e);  
    LCD_WR_DATA8(0x28);
    LCD_WR_REG(0xC7);     // VCM control2
    LCD_WR_DATA8(0x86);
    LCD_WR_REG(0x36);     // Memory Access Control
    LCD_WR_DATA8(0x48);   // C8
    LCD_WR_REG(0x3A);   
    LCD_WR_DATA8(0x55);
    LCD_WR_REG(0xB1);   
    LCD_WR_DATA8(0x00);
    LCD_WR_DATA8(0x18);
    LCD_WR_REG(0xB6);    // Display Function Control
    LCD_WR_DATA8(0x08);
    LCD_WR_DATA8(0x82);
    LCD_WR_DATA8(0x27);  
    LCD_WR_REG(0xF2);    // 3Gamma Function Disable
    LCD_WR_DATA8(0x00);
    LCD_WR_REG(0x26);    // Gamma curve selected
    LCD_WR_DATA8(0x01);
    LCD_WR_REG(0xE0);    // Set Gamma
    LCD_WR_DATA8(0x0F);
    LCD_WR_DATA8(0x31);
    LCD_WR_DATA8(0x2B);
    LCD_WR_DATA8(0x0C);
    LCD_WR_DATA8(0x0E);
    LCD_WR_DATA8(0x08);
    LCD_WR_DATA8(0x4E);
    LCD_WR_DATA8(0xF1);
    LCD_WR_DATA8(0x37);
    LCD_WR_DATA8(0x07);
    LCD_WR_DATA8(0x10);
    LCD_WR_DATA8(0x03);
    LCD_WR_DATA8(0x0E);
    LCD_WR_DATA8(0x09);
    LCD_WR_DATA8(0x00);
    LCD_WR_REG(0XE1);    //Set Gamma
    LCD_WR_DATA8(0x00);
    LCD_WR_DATA8(0x0E);
    LCD_WR_DATA8(0x14);
    LCD_WR_DATA8(0x03);
    LCD_WR_DATA8(0x11);
    LCD_WR_DATA8(0x07);
    LCD_WR_DATA8(0x31);
    LCD_WR_DATA8(0xC1);
    LCD_WR_DATA8(0x48);
    LCD_WR_DATA8(0x08);
    LCD_WR_DATA8(0x0F);
    LCD_WR_DATA8(0x0C);
    LCD_WR_DATA8(0x31);
    LCD_WR_DATA8(0x36);
    LCD_WR_DATA8(0x0F);
    LCD_WR_REG(0x11);    //Exit Sleep
    delay_ms(120);
    LCD_WR_REG(0x29);    //Display on
    LCD_WR_REG(0x2c);
}

为实现汉字的显示,特定义了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*/
};

实现汉字显示的函数有:
void showhanzi16(unsigned int x,unsigned int y,unsigned char index)
{  
unsigned char i,j,k;
const unsigned char *temp=hanzi16;   
temp+=index*32;
for(j=0;j<16;j++)
{
LCD_SetCursor(x,y+j);
LCD_WriteRAM_Prepare();
for(k=0;k<2;k++)
{
for(i=0;i<8;i++)
{      
         if((*temp&(1<<i))!=0)
{
LCD_WR_DATA(POINT_COLOR);
}
else
{
LCD_WR_DATA(BACK_COLOR);
}   
}
temp++;
}
}
}

void showhanzi32(unsigned int x,unsigned int y,unsigned char index)
{  
unsigned char i,j,k;
const unsigned char *temp=hanzi32;   
temp+=index*128;
for(j=0;j<32;j++)
{
LCD_SetCursor(x,y+j);
LCD_WriteRAM_Prepare();        //GRAM
for(k=0;k<4;k++)
{
for(i=0;i<8;i++)
{      
        if((*temp&(1<<i))!=0)
{
LCD_WR_DATA(POINT_COLOR);
}
else
{
LCD_WR_DATA(BACK_COLOR);
}   
}
temp++;
}
}
}


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


对应的主程序为:
int main(void)    
{
    delay_init();
    delay_ms(300);
    GPIO_Configuration();
    Lcd_Init();           
    xianshi();
    while(1);
}

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
请问一下大侠,用仿真器调试了吗?谢谢!

没有用仿真器直接在硬件上完成的。

使用特权

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

本版积分规则

446

主题

2675

帖子

37

粉丝