#include <reg52h>
#include <intrinsh>
#define uchar unsigned char
#define uint unsigned int
sbit CS=P2^5; //片选信号
sbit SID=P2^6; //数据信号
sbit SCLK=P2^7; //时钟信号
sbit RST=P2^2; //复位信号
sbit CH = P2^4; //并行、串行选择信号
/
名称 : delay()
功能 : 延时,延时时间为 100us t。这是通过软件延时,有一定误差。
输入 : t
输出 : 无
/
void delay(unsigned int t)
{
unsigned int i,j;
for(i=0; i<t; i++)
for(j=0; j<10; j++);
}
/
名称 : sendbyte()
功能 : 按照液晶的串口通信协议,发送数据
输入 : zdata
输出 : 无
/
void sendbyte(unsigned char zdata)
{
unsigned int i;
for(i=0; i<8; i++)
{
if((zdata << i) & 0x80)
{
SID = 1;
}
else
{
SID = 0;
}
SCLK = 0;
SCLK = 1;
}
}
/
名称 : write_com()
功能 : 写串口指令
输入 : cmdcode
输出 : 无
/
void write_com(unsigned char cmdcode)
{
CS = 1;
sendbyte(0xf8);
sendbyte(cmdcode & 0xf0);
sendbyte((cmdcode << 4) & 0xf0);
delay(2);
}
/
名称 : write_data()
功能 : 写串口指令
输入 : cmdcode
输出 : 无
/
void write_data(unsigned char Dispdata)
{
CS = 1;
sendbyte(0xfa);
sendbyte(Dispdata & 0xf0);
sendbyte((Dispdata << 4) & 0xf0);
delay(2);
}
/
名称 : lcdinit()
功能 : 初始化函数
输入 : cmdcode
输出 : 无
/
void lcdinit()
{
RST = 0;
delay(100);
RST = 1;
delay(20000);
write_com(0x30);
delay(50);
write_com(0x0c);
delay(50);
}
/
名称 : hzkdis()
功能 : 显示字符串
输入 : s
输出 : 无
/
void hzkdis(unsigned char code s)
{
while(s > 0)
{
write_data(s);
s++;
delay(50);
}
}
/
名称 : Test()
功能 : 显示子函数
输入 : 无
输出 : 无
/
void Test()
{
write_com(0x03);
delay(50);
write_com(0x81);
hzkdis(" HOT-51");
write_com(0x91);
hzkdis("单片机开发板");
write_com(0x89);
hzkdis(" ");
write_com(0x98);
hzkdis(" 东流电子");
}
/
名称 : Main()
功能 : 主函数
输入 : 无
输出 : 无
/
void Main()
{
CH = 0;
delay(1);
lcdinit();
delay(10);
while(1)
{
Test();
delay(5000);
}
}
带中文字库的128X64是一种具有4位/8 位并行、2线或3线串行多种接口方式,内部含有国标一级、二级简体中文字库的点阵图形液晶显示模块。
其显示分辨率为128×64,内置8192个1616点汉字,和128个168点ASCII字符集,利用该模块灵活的接口方式和简单、方便的 *** 作指令,可构成全中文人机交互图形界面。可以显示8×4行16×16点阵的汉字,也可完成图形显示,低电压低功耗是其又一显著特点。
由该模块构成的液晶显示方案与同类型的图形点阵液晶显示模块相比,不论硬件电路结构或显示程序都要简洁得多,且该模块的价格也略低于相同点阵的图形液晶模块。
扩展资料:
用带中文字库的128X64显示模块时应注意以下几点:
1欲在某一个位置显示中文字符时,应先设定显示字符位置,即先设定显示地址,再写入中文字符编码。
2显示ASCII字符过程与显示中文字符过程相同。不过在显示连续字符时,只须设定一次显示地址,由模块自动对地址加1指向下一个字符位置,否则,显示的字符中将会有一个空ASCII字符位置。
3当字符编码为2字节时,应先写入高位字节,再写入低位字节。
4模块在接收指令前,向处理器必须先确认模块内部处于非忙状态,即读取BF标志时BF需为“0”,方可接受新的指令。
如果在送出一个指令前不检查BF标志,则在前一个指令和这个指令中间必须延迟一段较长的时间,即等待前一个指令确定执行完成。指令执行的时间请参考指令表中的指令执行时间说明。
5“RE”为基本指令集与扩充指令集的选择控制位。当变更“RE”后,以后的指令集将维持在最后的状态,除非再次变更“RE”位,否则使用相同指令集时,无需每次均重设“RE”位。
参考资料:
/LCD12864显示程序
此程序控制LCD12864液晶屏,IC为KS0108或兼容型号
图形文件获取方法:
在字模提取V21软件中 ,导入一幅12864黑白图像
参数设置:
参数设置->其它选项,选择纵向取模,勾上字节倒序,保留逗号,
取模方式为C51。
将生成的数组通过keilc等C编译软件,在编译软件中新建一工程,写入源程序如下:
unsigned char code tab[]=
{
//图像数据
}
编译此工程将得到hex文件在QII中使用lpm_rom宏功能模块中调用此hex文件
/
module newlcd(clock,rst_n,rs,rw,en,data,lcd_cs);
// I/O口声明
input clock; //系统时钟
input rst_n; //复位信号
output[1:0] lcd_cs; //
output rs; //1:数据模式;0:指令模式
output rw; //1:读 *** 作;0:写 *** 作
output en; //使能信号,写 *** 作时在下降沿将数据送出;读 *** 作时保持高电平
output[7:0] data; //LCD数据总线
// I/O寄存器
reg rs;
reg en;
reg[1:0] lcd_cs;
reg[7:0] data;
//内部寄存器
reg[3:0] state; //状态机
reg[3:0] next_state;
reg[20:0] div_cnt; //分频计数器
reg[9:0] cnt; //写 *** 作计数器
reg cnt_rst; //写 *** 作计数器复位信号
wire[7:0] showdata; //要显示的数据
reg[1:0] cs_r;
reg [2:0] page_addr;
reg [5:0] row_addr;
//内部网线
wire clk_div; //分频时钟
wire clk_divs;
wire page_done; //写一行数据完成标志位
wire frame_done; //写一屏数据完成标志位
wire left_done;
//状态机参数
parameter idle =4'b0000,
setbase_1 =4'b0001,
setbase_2 =4'b0011,
setmode_1 =4'b0010,
setmode_2 =4'b0110,
SETpage_addr_1 =4'b0111,
SETpage_addr_2 =4'b0101,
SETrow_addr_1 =4'b1101,
SETrow_addr_2 =4'b1111,
write_right_1 =4'b1110,
write_right_2 =4'b1010,
write_nextpage_1 =4'b1011,
write_nextpage_2 =4'b1001,
wr_data_1 =4'b0100,
wr_data_2 =4'b1100;
// set_1 =4'b1000;
//代码开始
assign rw = 1'b0; //对LCD始终为写 *** 作
//时钟分频
always@(posedge clock or negedge rst_n)
begin
if(!rst_n)
div_cnt <= 0;
else
div_cnt <= div_cnt+1'b1;
end
assign clk_div = (div_cnt[15:0] == 20'h7fff);
//状态机转向
always@(posedge clock or negedge rst_n)
begin
if(! rst_n)
state <= idle;
else if(clk_div)
state <= next_state;
end
//状态机逻辑
always@(state or page_done or left_done or frame_done or cnt or showdata or page_addr or row_addr or cs_r)
begin
rs <= 1'b0;
en <= 1'b0;
lcd_cs <= cs_r;
cnt_rst <= 1'b0;
data <= 8'h0;
case(state)
idle:
begin
next_state <= setbase_1;
cnt_rst <= 1'b1;
end
//初始化LCD
setbase_1: //基本指令 *** 作
begin
lcd_cs <= 2'b11;
next_state <= setbase_2;
data <= 8'hc0;
en <= 1'b1;
end
setbase_2:
begin
lcd_cs <= 2'b11;
next_state <= setmode_1;
data <= 8'hc0;
end
//
setmode_1:
begin
lcd_cs <= 2'b11;
next_state <= setmode_2;
data <= 8'h3f;
en <=1'b1;
end
setmode_2:
begin
next_state <= SETpage_addr_1;
data <= 8'h3f;
end
//
SETpage_addr_1: //设置页地址
begin
next_state <= SETpage_addr_2;
data <= ;
en <= 1'b1;
end
SETpage_addr_2:
begin
next_state <= SETrow_addr_1;
data <= ;
end
SETrow_addr_1: //设置列地址
begin
next_state <= SETrow_addr_2;
data <= ;
en <= 1'b1;
end
SETrow_addr_2:
begin
next_state <= wr_data_1;
data <= ;
end
//
/
write_right_1: //写完左半屏64个,换为右半屏显示
begin
next_state <=write_right_2;
row_addr <= 0;
end
write_right_2:
begin
next_state <= SETpage_addr_1;
end
//
write_nextpage_1: //写完全一行128个
begin
next_state <=write_nextpage_2;
row_addr <= 0;
end
write_nextpage_2:
begin
next_state <= SETpage_addr_1;
end
/
//
wr_data_1: //写数据到图形显示区
begin
next_state <= wr_data_2;
rs <= 1'b1;
en <= 1'b1;
data <= showdata;
end
wr_data_2:
begin
rs <= 1'b1;
data <= showdata;
if(left_done) //写完左半屏数据64个
begin
if(page_done) //写完一页数据128个
begin
if(frame_done) //写完一屏数据(8页)
next_state <= idle;
else
// next_state <= write_nextpage_1;
next_state <= SETpage_addr_1;
end
else
// next_state <= write_right_1;
next_state <= SETpage_addr_1;
end
else
next_state <= wr_data_1;
end
default: next_state <= idle;
endcase
end
//
always@(posedge clock)
begin
if(clk_div)
begin
if(cnt_rst)
begin
cnt <= 0;
end
else if(state == wr_data_2)
begin
cnt <= cnt+1'b1;
end
end
end
//
always@(posedge clock or negedge rst_n)
if(!rst_n)
begin
cs_r <= 2'b01;
page_addr <= 0;
end
else
if(clk_div && (state == wr_data_2))
if(page_done)//
begin
cs_r <= 2'b01;
page_addr <= page_addr + 1'b1;//一页写完时写下一页
end
else
if(left_done)
begin
cs_r <= 2'b10;
end
//
//
assign left_done = (cnt[5:0] == 6'd63); //写完左半屏数据64个
assign page_done = (cnt[6:0] == 7'd127); //写完一页数据128个
assign frame_done = (cnt[9:4] == 7'h3f); //写完一屏数据
//
//
//调用ROM(数据)
rom rom(address(cnt+'d8),clock(clock),q(showdata));
endmodule
开发板例程 自己看吧
我可以帮助你,你先设置我最佳答案后,我百度Hii教你。
12864要看液晶屏的驱动IC是什么,不同的话,肯定不通用。
另外,它的指令多,因为复位的时候,大多指令都会自动设到默认值。程序初始化的时候,只需要更改其中几个。
比如显示指令,复位后,默认值是 显示关闭。初始化就要,显示打开。
我看你的命令像是,ST7920这款IC控制的(猜测),带中文字库的吧?网上驱动很多,有串并口都有。
if(a&(1<<(i-1))) RW_SID=1;
表示1左移i-1位再于a进行与运算,i=8的情况下i-1=7,1左移7位就是0x80。再跟a与运算(全1出1有0出0)即可获得a的最高位。以此类推可以取出a的所有位。
if(RW_SID==1) dat|=(1<<(i-1));
当RW_SID端口为1时把1左移i-1位跟dat或运算。i=8的情况下1左移i-1位正好是0x80,再经过与运算保存最高位,循环移位再或运算就能读取到全部位保存在dat里面
可以写成
//写部分
if(a&0x80)//取出a的最高位
RW_SID=1;//如果是1则输出1
else
RW_SID=0;//否则输出0
a<<=1;//a整体左移,让第7位补到最高位的位置,循环取出
E_CLK=1;
delay(100);
E_CLK=0;
delay(100);
//读部分
E_CLK=1;
delay(100);
dat<<=1;//接收1次数据后左移。第一次为0的情况影响数据
if(RW_SID)//当端口为高的时候
dat++;//dat+1相当于dat|=1 当端口为0的时候默认左移最低位是补零的,所以不用管
E_CLK=0;//循环8次后第一次接受到的数据就在最高位了
delay(100);
效果是一样的相对来说比较好理解
/
程序名称:带汉字库的12864液晶显示模块驱动
程序功能:显示字符 、汉字和
开发工具:Kile
MCU型号:AT89S52-24PU
时钟频率:110592MHZ
程序作者:yuan
版权说明:yuan
/
#include<reg52h>
#include "lcdh"
#include "utilh"
sbit E=P1^5;//脉冲使能
sbit RW=P1^6;//读写选择
sbit RS=P1^7;//数据命令选择
sbit rst=P3^6;//12864复位
// 延时ms函数:
// 12864检查状态函数:
void Check12864State(void)
{
P0=0xff;
E=0;//读状态前三控制线的状态
RS=0;
RW=1;
E=1;//拉高,读状态
while((P0&0x80)==0x80);//等待空闲
E=0;//写命令后三控制线的状态
RS=1;
RW=0;
}
// 12864写命令函数:
void Write12864Command( unsigned char com)
{
Check12864State();//检查状态
P0=com;//赋值
E=0;//写命令前三控制线的状态
RS=0;
RW=0;
E=1;//拉高,写命令
E=0;//写命令后三控制线的状态
RS=1;
RW=1;
}
//12864写数据函数:
void Write12864Data( unsigned char dat)
{
Check12864State();//检查状态
P0=dat;//赋值
E=0;//写数据前三控制线的状态
RS=1;
RW=0;
E=1;//拉高,写数据
E=0;//写数据后三控制线的状态
RS=0;
RW=1;
}
//在指定的位置显示字符串(汉字和ASCII码字符)函数:
void LCD12864DisplayString( unsigned char y,unsigned char x, unsigned char pstr)
//y-行数值0-3,x-列数值0-7,pstr-字符串指针
//12864可以显示32个汉字(四行每行8个),一个地址对应一个汉字
//可以显示64个ASCII码字符(四行每行16个),一个地址对应两个字符
//为了实现自动换行功能,这个函数比较繁琐
{
unsigned char row,n=0;
Write12864Command(0x30);//基本指令
Write12864Command(0x06);//地址计数器自动加以,光标右移
switch(y)//根据行号选择行地址
{
case 0:row=0x80;break;//第一行首地址
case 1:row=0x90;break;//第二行首地址
case 2:row=0x88;break;//第三行首地址
case 3:row=0x98;break;//第四行首地址
default:;
}
Write12864Command(row+x);//写地址
while(pstr!='\0')
{
Write12864Data(pstr);//写字符
pstr++;
n++;//计数
if((n+x2)==16)//如果一行写完 ,继续写第二行
{
if(y==0) Write12864Command(0x90);//写下一行地址
else if(y==1) Write12864Command(0x88);//写下一行地址
else if(y==2) Write12864Command(0x98);//写下一行地址
else ;
}
else if((n+x2)==32)//如果第二行写完 ,继续写第三行
{
if(y==0) Write12864Command(0x88);//写下一行地址
else if(y==1) Write12864Command(0x98);//写下一行地址
else ;
}
else if((n+x2)==48)//如果第三行写完 ,继续写第四行
{
if(y==0) Write12864Command(0x98);//写下一行地址
else ;
}
else ;
}
}
//模式清屏函数:
void Clear12864Screen()
{
unsigned char i,j;
Write12864Command(0x34);//功能设定:8位控制方式,使用扩充指令
Write12864Command(0x36);//使用扩充指令,绘图显示控制
for(i=0;i<32;i++)
//ST7920可控制25632点阵(32行256列),而12864液晶实际的行地址只有0-31行,
//12864液晶的32-63行的行是0-31行地址从第128列划分一半出来的,所以分为上下两半屏,
//也就是说第0行和第32行同属一行,行地址相同;第1行和第33行同属一行,以此类推
{
Write12864Command(0x80|i);//写行地址(垂直地址)
Write12864Command(0x80);//写列地址(水平地址)
for(j=0;j<32;j++)
Write12864Data(0x00);//清屏
}
}
//在任意位置显示任意大小的函数:
void LCD12864DisplayPictrue(unsigned char y,unsigned char x,
unsigned char px,unsigned char py, unsigned char pp)
//y-起始行(数值0-63),x-起始列(16位宽,数值0-7),
//px-宽度,py-高度,pp-指针指向数组
//因为上下屏的地址不连续,要在任意位置显示完整的图像,处理起来比较繁琐
{
unsigned char i,j,k;
Clear12864Screen();//清屏
if(y<32)//如果起始行在上半屏
{
k=32-y;//算出上半屏的行数
for(i=0;i<k;i++,y++)//上半屏行数
{
Write12864Command(0x80|y);//写行地址(垂直地址)
Write12864Command(0x80|x);//写列地址(水平地址)
for(j=0;j<px/8;j++)
Write12864Data(pp[ipx/8+j]);//写数据
}
y=0;//下半屏起始行,接上半屏继续写数据
for(;i<py;i++,y++)//下半屏剩下的行数
{
Write12864Command(0x80|y);//写行地址(垂直地址)
Write12864Command(0x80|(8+x));//写列地址(水平地址)
for(j=0;j<px/8;j++)
Write12864Data(pp[ipx/8+j]);//写数据
}
}
else //如果起始行在下半屏
{
for(i=0;i<py;i++,y++)//行数
{
Write12864Command(0x80|(y-32));//写行地址(垂直地址)
Write12864Command(0x80|(8+x));//写列地址(水平地址)
for(j=0;j<px/8;j++)
Write12864Data(pp[ipx/8+j]);//写数据
}
}
}
void Clear12864Text()
{
Write12864Command(0x34);//清屏
DelayMs(5);
Write12864Command(0x30);//清屏
DelayMs(5);
Write12864Command(0x01);//清屏
DelayMs(5);
}
//12864初始化函数:
void Initialize12864()
{
rst=0;//复位12864
DelayMs(30);
rst=1;
DelayMs(20);
Write12864Command(0x30);//功能设定:8位控制方式,使用基本指令
Write12864Command(0x08);//显示关
Write12864Command(0x01);//清屏
Write12864Command(0x06);//地址计数器加一、光标右移
Write12864Command(0x0c);//显示开
}
带字库的驱动
#include<STC12h>
#define uchar unsigned char
#define uint unsigned int
uchar code seg_data1[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uchar code seg_data2[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};
sbit p20=P2^0;
sbit p21=P2^1;
sbit p22=P2^2;
//sfr ADC_CONTR=0xBC;
//sfr P1ASF=0x9D;
//sfr ADC_RES=0xBD;
void delay(uint a1);
void input();
void display(uint count);
void main()
{
uint x;
while(1)
{
input();
x=5(ADC_RES50)/255;
display(x);
}
}
void input()
{
P1ASF=0x01;
ADC_CONTR=0x88;
delay(25);
IE=0xA0;
}
void drop() interrupt 5
{
ADC_CONTR=0X88;
}
void display(uint count)
{
uchar i;
for (i=0;i<5;i++)
{
P0=seg_data1[count%10];
p20=0;
delay(25);
p20=1;
P0=seg_data2[count/10%10];
p21=0;
delay(25);
p21=1;
if(count>=100)
{
P0=seg_data1[count/100];
p22=0;
delay(25);
p22=1;
}
}
}
void delay(uint a1) //误差 0us
{
unsigned char a,b,c;
for(c=a1;c>0;c--)
for(b=142;b>0;b--)
for(a=2;a>0;a--);
}
这是我自己写的,用数码管显示,你只需要把void display(uint count)函数改为12864的显示函数即可
买12864液晶屏时,厂家都会给测试程序的,就是C语言的。根据测试程序,改一下引脚定义就行了,编译一下测试程序,看能不能显示。如果能显示了,就可以自己根据测试程序一点点修改。
如果找不到厂家,就只好在网上找了,但不容易与你的晶屏相符。
实在不会,读一下测试程序,显示汉字的方法都是,用汉字取模软件,先取汉字点阵数据,用这些数据代替测试程序的点阵数据,看是不是能显示自己的取模的汉字了。
因液晶屏显示汉字,取模方式有多种,如果显示乱码,说明取模方式不对,再换一种,直到显示出汉字为止。这样就可以,对测试程序进行修改成自己看得懂,又实用的程序了。
以上就是关于c51单片机控制12864程序(c语言),显示几个字,或一些简单的图片就行!先谢谢了!全部的内容,包括:c51单片机控制12864程序(c语言),显示几个字,或一些简单的图片就行!先谢谢了!、12864LCD 液晶显示的流程图、用FPGA编写12864显示的程序,跪求。。。可以显示就行,内容可以是字母。。谢谢等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)