STM32 驱动12864液晶显示汉字、图片、画点、横线、竖线、斜线
我做本实验的软件平台为MDK软件,选用STM32VET6,12864液晶屏5v供电采用并行接法。之前本来想网上找一个现成的程序实验一下,但都没找到合适的,于是就自己编写了一个,最终可在12864液晶屏上面任意位置显示任意内容。在此贴出整个工程文件,希望对大家有帮助!
本实验的整个工程文件可在此处下载:http://download.csdn.net/detail/u010173859/5908815
/********************************************************************************** * 文件名 :main.c * 描述 :利用12864液晶屏显示汉字和图片,且可在任意位置画点、横线、竖线、斜线。 * 实验平台:THE_ONE_1 STM32开发板 * 库版本 :ST 3.5.0 * 硬件连接:并行接法 * -------------------------------------------- * | | * | DB0~7 -- GPIOE0~7 | * | RS -- GPIOE8 | * | RW -- GPIOE9 | * | E -- GPIOE10 | * | PSB -- GPIOE11 | * | | * -------------------------------------------- * * 作者 :ZXL * 日期 :2013.8 * 备注 :无 **********************************************************************************/ #include "stm32f10x.h" #include "12864.h" __IO u8 hang0[] = "别人笑我太疯癫, "; __IO u8 hang1[] = "我笑他人看不穿;"; __IO u8 hang2[] = "不见武陵豪杰墓,"; __IO u8 hang3[] = "无花无酒锄作田。"; /* * 函数名:main * 描述 : 主函数 * 输入 :无 * 输出 : 无 */ int main(void) { u8 i; LCD_Init(); //液晶屏初始化 LCD_Clear_Screen(); //清屏操作 LCD_Draw_Point(2,3,24); //画小点,在X列的第xx个小列的第y行中画一个小点 LCD_Draw_Point(2,3,25); //画小点,在X列的第xx个小列的第y行中画一个小点 LCD_Draw_Point(2,4,24); //画小点,在X列的第xx个小列的第y行中画一个小点 LCD_Draw_Point(2,4,25); //画小点,在X列的第xx个小列的第y行中画一个小点 LCD_Draw_Horizontal(1,0,8,12); //画横线,在y行的x列中画一条从x1小列到x2小列的横线 LCD_Draw_Horizontal(1,0,8,20); //画横线,在y行的x列中画一条从x1小列到x2小列的横线 LCD_Draw_Column(1,0,12,20); //画竖线,在X列的第xx个小列中画一条从y1到y2的竖线 LCD_Draw_Column(1,8,12,20); //画竖线,在X列的第xx个小列中画一条从y1到y2的竖线 LCD_Draw_Column(1,10,8,24); //画竖线,在X列的第xx个小列中画一条从y1到y2的竖线 LCD_Draw_Oblique(1,10,16,15,21);//画斜线,在X列中画一条(x1,y1)到(x2,y2)的斜线 LCD_Draw_Oblique(1,10,16,15,11);//画斜线,在X列中画一条(x1,y1)到(x2,y2)的斜线 LCD_Display(1); //显示x1 LCD_Display(2); //显示x7 /* LCD_Position(0,0); //第0行第0个位置显示 i = 0; while(hang0[i] != '\0') { LCD_Write_Data(hang0[i]); i ++; } LCD_Position(1,0); //第1行第0个位置显示 i = 0; while(hang1[i] != '\0') { LCD_Write_Data(hang1[i]); i ++; } */ LCD_Position(2,0); //第2行第0个位置显示 i = 0; while(hang2[i] != '\0') { LCD_Write_Data(hang2[i]); i ++; } LCD_Position(3,0); //第3行第0个位置显示 i = 0; while(hang3[i] != '\0') { LCD_Write_Data(hang3[i]); i ++; } // LCD_Draw_Picture(); //此函数用来画一幅十六进制的monkey1图片 while(1); // add your code here ^_^。 }
/********************************************************************************** * 文件名 :12864.c * 描述 :利用12864液晶屏显示汉字和图片,且可在任意位置画点、横线、竖线、斜线。 * 实验平台:THE_ONE_1 STM32开发板 * 库版本 :ST 3.5.0 * 硬件连接:并行接法 * -------------------------------------------- * | | * | DB0~7 -- GPIOE0~7 | * | RS -- GPIOE8 | * | RW -- GPIOE9 | * | E -- GPIOE10 | * | PSB -- GPIOE11 | * | | * -------------------------------------------- * * 作者 :ZXL * 日期 :2013.8 * 备注 :无 **********************************************************************************/ #include "12864.h" #include "monkey.h" u16 data[512]; //定义一个16*32大小的数组来存放X[0~15]共16组的Y[0~31]数据 #define RS GPIO_Pin_8 // 数据/命令选择端 #define RS_H GPIO_SetBits(GPIOE,GPIO_Pin_8) #define RS_L GPIO_ResetBits(GPIOE,GPIO_Pin_8) #define RW GPIO_Pin_9 // 读/写选择端 #define RW_H GPIO_SetBits(GPIOE,GPIO_Pin_9) #define RW_L GPIO_ResetBits(GPIOE,GPIO_Pin_9) #define E GPIO_Pin_10 // 使能信号 #define E_H GPIO_SetBits(GPIOE,GPIO_Pin_10) #define E_L GPIO_ResetBits(GPIOE,GPIO_Pin_10) #define PSB_H GPIO_SetBits(GPIOE,GPIO_Pin_11) // 并/串行选择端 #define DATA GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 void delay(u16 x ) //延时 { u16 i,j; for(i=0;i<x;i++) for(j=0;j<1000;j++); } void LCD_Write_Cmd(u8 cmd) //写命令 { RS_L; RW_L; E_L; GPIOE->ODR = (GPIOE->ODR & 0xFF00) | cmd; delay(5); E_H; delay(5); E_L; } void LCD_Write_Data(u16 data) //写数据 { RS_H; RW_L; E_L; GPIOE->ODR = (GPIOE->ODR & 0xFF00) | data; delay(5); E_H; delay(5); E_L; } void LCD_Init(void) { GPIO_InitTypeDef GPIO_InitStructure;//定义一个GPIO_InitTypeDef类型的结构体 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE); //开启GPIOE的外设时钟 GPIO_InitStructure.GPIO_Pin = RS | RW | E | DATA;//选择要控制的GPIOE引脚 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//设置引脚模式为推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置引脚速率为50MHZ GPIO_Init(GPIOE,&GPIO_InitStructure); //调用库函数,初始化GPIOE delay(10); PSB_H; //并行方式 LCD_Write_Cmd(0x30);delay(5);//基本指令集 LCD_Write_Cmd(0x0c);delay(5);//整体显示打开,关光标 LCD_Write_Cmd(0x01);delay(5);//清除LCD的显示内容 LCD_Write_Cmd(0x02);delay(5);// 地址归位 LCD_Write_Cmd(0x06);delay(5);//游标右移 LCD_Write_Cmd(0x80);delay(5);//设定显示的起始地址 } void LCD_Clear_Screen(void) //清屏操作 { u8 i,j; LCD_Write_Cmd(0x34);//打开拓展指令集,绘图指令关 for(j=0;j<8;j++) //清除第一行 { for(i=0;i<32;i++) { LCD_Write_Cmd(0x80+i);//行 LCD_Write_Cmd(0x80+j);//列 LCD_Write_Data(0x00);//写高八位数据 LCD_Write_Data(0x00);//写低八位数据 } } for(j=0;j<8;j++) //清除第二行 { for(i=0;i<32;i++) { LCD_Write_Cmd(0x80+i); LCD_Write_Cmd(0x88+j); LCD_Write_Data(0x00); LCD_Write_Data(0x00); } } LCD_Write_Cmd(0x30);//打开基本指令集 } void LCD_Position(u8 x,u8 y) //定位在第几行第y个位置显示 { u8 position; if(x==0) x=0x80; //第一行 else if(x==1) x=0x90; //第二行 else if(x==2) x=0x88; //第三行 else if(x==3) x=0x98; //第四行 position = x + y; LCD_Write_Cmd(position); } u16 Exchange(u8 xx) //自定义一个转换函数 { u16 data; if(xx==0) data=0x8000; if(xx==1) data=0x4000; if(xx==2) data=0x2000; if(xx==3) data=0x1000; if(xx==4) data=0x0800; if(xx==5) data=0x0400; if(xx==6) data=0x0200; if(xx==7) data=0x0100; if(xx==8) data=0x0080; if(xx==9) data=0x0040; if(xx==10) data=0x0020; if(xx==11) data=0x0010; if(xx==12) data=0x0008; if(xx==13) data=0x0004; if(xx==14) data=0x0002; if(xx==15) data=0x0001; return data; } void LCD_Draw_Point(u8 x,u8 xx,u8 y) //画小点,在X列的第xx个小列的第y行中画一个小点 { data[y+x*32] |= Exchange(xx); } void LCD_Draw_Column(u8 x,u8 xx,u8 y1,u8 y2) //画竖线,在X列的第xx个小列中画一条从y1到y2的竖线 { u8 i; for(i=y1;i<=y2;i++) { data[i+x*32] |= Exchange(xx); //数据转换 } } void LCD_Draw_Horizontal(u8 x,u8 x1,u8 x2,u8 y) //画横线,在y行的x列中画一条从x1小列到x2小列的横线 { u8 i; u16 temp; for(i=x1;i<=x2;i++) { temp=Exchange(i); //数据转换 data[y+x*32] |= temp; } } void LCD_Draw_Oblique (u8 x,u8 x1,u8 y1,u8 x2,u8 y2)//画斜线,在X列中画一条(x1,y1)到(x2,y2)的斜线 { u8 i,yy; if(y1<=y2) { for(i=y1;i<=y2;i++) { data[i+x*32] |= Exchange(x1); //数据转换 x1 ++; } } else if(y1>y2) { yy=y1; y1=y2; y2=yy; for(i=y1;i<=y2;i++) { data[i+x*32] |= Exchange(x2); //数据转换 x2 --; } } } void LCD_Display(u8 x) //画点、横线、竖线、斜线的显示函数 { u8 i; LCD_Write_Cmd(0x34); //打开拓展指令集,绘图指令关闭 for(i=0;i<32;i++) { LCD_Write_Cmd(0x80+i); //写Y值坐标 LCD_Write_Cmd(0x80+x); //写X值坐标 LCD_Write_Data( (data[i+x*32] >> 8)& 0xff ); //D0-D7, 写低八位 LCD_Write_Data( data[i+x*32] & 0xff ); //D8-D15,写高八位 } LCD_Write_Cmd(0x36); //打开绘图显示 LCD_Write_Cmd(0x30); //打开基本指令集 } void LCD_Draw_Picture(void) //画图片函数 { u8 i,j; u16 add=0; LCD_Write_Cmd(0x34);//打开拓展指令集,绘图指令关 for(i=0;i<32;i++) //写第一行,先写完一行再写下一行 { for(j=0;j<8;j++) { LCD_Write_Cmd(0x80+i); LCD_Write_Cmd(0x80+j); LCD_Write_Data( monkey1[add++] ); //D0-D7 LCD_Write_Data( monkey1[add++] ); //D8-D15 } } for(i=0;i<32;i++) //写第二行,先写完一行再写下一行 { for(j=0;j<8;j++) { LCD_Write_Cmd(0x80+i); LCD_Write_Cmd(0x88+j); LCD_Write_Data( monkey1[add++] ); //D0-D7 LCD_Write_Data( monkey1[add++] ); //D8-D15 } } LCD_Write_Cmd(0x36);//打开绘图显示 LCD_Write_Cmd(0x30);//打开基本指令集 }