12864液晶驱动程序

12864液晶驱动程序,第1张

#include <reg51h>

#define uchar unsigned char

#define uint unsigned int

sbit SCLK = P3^1; //液晶时钟线

sbit SDAT = P3^0; //液晶数据线

void SEND_BYTE_LCD(uchar data_to_lcd);

void SEND_DATA_SER(bit codeordata, uchar SERIAL_DATA); //code 为1

void wrlcd(uchar HANG, uchar LIE, uchar SENTENCE);

void lcdinit(void);

//void delay(uchar deltime);

//

//延时程序

//

void delay(uint deltime)

{

uchar i;

uint j;

for (j = 0; j < deltime; j++)

for (i = 0; i < 255; i++)

;

}

/

液晶写命令子程序

/

void SEND_BYTE_LCD(uchar data_to_lcd)

{

uchar j;

for (j = 0; j < 8; j++)

{

SDAT = (bit) (data_to_lcd &0x80);

SCLK = 0;

SCLK = 0;

SCLK = 0;

SCLK = 0;

SCLK = 0;

SCLK = 1;

SCLK = 1;

SCLK = 1;

SCLK = 1;

SCLK = 1;

data_to_lcd <<= 1;

SCLK = 0;

SCLK = 0;

SCLK = 0;

SCLK = 0;

SCLK = 0;

}

}

void SEND_DATA_SER(bit codeordata, uchar SERIAL_DATA)

{

uchar first, second, third;

if (codeordata)

{

first = 0xf8;

}

else

{

first = 0xfa;

}

second = SERIAL_DATA &0xf0;

third = SERIAL_DATA << 4;

SEND_BYTE_LCD(first);

SEND_BYTE_LCD(second);

SEND_BYTE_LCD(third);

}

void wrlcd(uchar HANG, uchar LIE, uchar SENTENCE)

{

uchar position;

position = HANG + LIE;

SEND_DATA_SER(1, position);

delay(2);

while (SENTENCE)

{

SEND_DATA_SER(0, SENTENCE++);

}

}

void lcdinit(void)

{

delay(100);

SEND_DATA_SER(1, 0X30);

delay(4); //基本功能设置

//SEND_DATA_SER(1,0X06);delay(2);

SEND_DATA_SER(1, 0X0C);

delay(4);

SEND_DATA_SER(1, 0X01);

delay(40);

SEND_DATA_SER(1, 0X02);

delay(40);

// SEND_DATA_SER(1,0X80);delay(2);

delay(10);

}

/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液晶显示模块驱动

程序功能:显示字符 、汉字和

开发工具: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);//显示开

}

带字库的驱动

为什么不用TX中断发送数据?设置一个发送数据指针和需发送数据总量,由TX中断依次将数据传输完毕后关掉中断。

接收中断内也只做数据接收工作,不可在中断内做过多的处理工作,处理应该交由main()程序的while(1){}内进行。

给个例子:

//发送中断

//

#pragma vector=USART0TX_VECTOR

__interrupt void InterruptUsart0_TX

{

if(tx_point<tx_count){

TXBUF0=uart_buf[tx_point++];

}

else{

OpenU0Rx(); //开接收中断,同时关发送中断

flag_com &= ~FCOM_SENDING; //清发送标志

SetTB6(0); //开红外遥控接收

}

}

//--------------------------------

//接收中断

//

#pragma vector=USART0RX_VECTOR

__interrupt void InterruptUsart0_RX(void)

{

if(flag_com & FCOM_READING)

{

uart_buf[++rx_count]=RXBUF0;

}

else {

flag_com |=FCOM_READING; //新一帧数据首次中断

SetTB6(1); //关红外遥控中断

rx_count=0; //第一个数据

uart_buf[0]=RXBUF0;

}

TBCCR4=TBR;

free_time_count=uart_free_time; //空闲时间计数重置

}

//-------------

main()

{

while(1)

{

if(flag_com & FCOM_READ_OK)

{

}

}

}

以上就是关于12864液晶驱动程序全部的内容,包括:12864液晶驱动程序、用FPGA编写12864显示的程序,跪求。。。可以显示就行,内容可以是字母。。谢谢、关于单片机液晶屏LCD12864的程序等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zz/9300143.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-26
下一篇 2023-04-26

发表评论

登录后才能评论

评论列表(0条)

保存