这个驱动程序我耗了3天的时间,想想真够笨的!一开始一天半,没有一点收获,主要是液晶的硬件电路没有连好!却开始写程序,结果怎么调,液晶就是没有显示!以前的用过的液晶不需要接什么电位器来调节显示的亮度,这个液晶却需要,而我没有接!浪费了我这么长时间,真是郁闷!
头文件
#ifndef JM240_H
#define JM240_H
#include "main.h"
//define port
#define DB PORTD
#define DB_DIR TRISD
#define WR RA0
#define RD RA1
#define CE RA2
#define CD RA3
#define RST RA4
typedef struct JM240
{
uint graphic_add ;//only use graphic mode
uchar graphic_width ;//define graphic width
uint offset ;// offset address of currect page
uint cur_page ;//current page
uchar char_width ;//width of charactor
uchar chn_width ;//width of chn
} JM240 ;
//define the first address of seperative page
extern JM240 jm ;
enum state{} ;
//define basic function
void init_jm240() ;//init JM240 include initiating control port ,JM240 struct and iniatiating LCD
void send_byte(uchar data) ;//send data
void send_cmd(uchar cmd) ;//send a cmd
uchar ch_status() ;//get status word
void ch_busy(uchar flag) ;//check whether the current lcd is busy or not
void rst_lcd() ;//reset lcd
uchar rd_data() ;
//define high zone function
void wr_data(uchar dat) ;
void wr_cmd0(uchar cmd) ;//no para command
void wr_cmd1(uchar data,uchar cmd) ;//one para command
void wr_cmd2(uchar dat1,uchar dat2,uchar cmd) ;//two para command
void wr_cmd3(uint data,uchar cmd) ;//one para of int type command
void set_mode(uchar mode) ;
void enable_autowr(uchar flag) ;
void enable_autord(uchar flag) ;
void auto_wr(uchar dat) ;
uchar auto_rd() ;
//define higher zone function
void str_disp(const uchar *str,uchar x,uchar y) ;//display string through internal character library
void show_char(uchar data,uchar x,uchar y) ;
void show_chn(const uchar *chn,uchar x,uchar y) ;
void chns_disp(const uchar *chn,uchar x,uchar y,uchar count) ;
void show_img(uchar x,uchar y,uchar x1,uchar y1,const uchar *img) ;
void lcd_refresh(const uchar *img) ;
void clr_lcd(uchar x,uchar y,uchar x1,uchar y1) ;
void clr_ram() ;
void wr_img(uchar x,uchar y,uchar width,uchar height,const uchar *img) ;
void set_add(uint ad) ;
void add_xy(uchar x,uchar y) ;//move ram pointer
void add_add(uint x) ;
void set_graphic(uint add,uchar width) ;//set graphic par
//define draw
void draw_vline(uchar x,uchar y,uchar height) ;
void draw_hline(uchar x,uchar y,uchar width) ;
void draw_frame(uchar x,uchar y,uchar width,uchar height) ;
void draw_point(uchar x,uchar y) ;
void draw_page(uchar num) ;
#endif
子程序
#include "jm240.h"
#include "ascii0816.h"
const uint add[]={0x0000,0x0F00,0x1E00,0x2D00,0x3C00,0x4B00,0x5A00,0x6900,0x7800,0x9700,0xA600,0xB500,0xC400} ;
JM240 jm ;
void init_jm240()
{
//set the directio of port
DB_DIR=0 ;
ADCON1=0x06 ;
TRISA=TRISA&0xC0 ;
//init global variable
jm.graphic_add=0x0000 ;
jm.graphic_width=30 ;
jm.cur_page=0 ;
jm.offset=0x0000 ;
jm.char_width=8 ;
jm.chn_width=16 ;
//init
rst_lcd() ;
set_graphic(jm.graphic_add,jm.graphic_width) ;
wr_cmd0(0x80) ;// 或模式
wr_cmd0(0x98) ;//note here must start graphic display
clr_ram() ;
}
//restart lcd
void rst_lcd()
{
RST=0 ;
DelayUs(50) ;
RST=1 ;
DelayMs(50) ;
}
//get the currrent state of lcd
uchar ch_status()
{
uchar temp ;
CD=1 ;
WR=1 ;
CE=0 ;
DB_DIR=0x00 ;
DB=0xff ;
RD=0 ;
DB_DIR=0xFF ;
temp=DB ;
RD=1 ;
CE=1 ;
DB_DIR=0x00 ;
return temp ;
}
//check whether lcd is busy or not at present
void ch_busy(uchar flag)
{
uchar temp1,temp2 ;
if(!flag)//one write or read status flag
temp2=0x03 ;
else
{
if(flag==1)// auto write status flag check
temp2=0x08 ;
else//auto read state flag check
temp2=0x04 ;
}
do
{
temp1=ch_status() ;
temp1=temp1&temp2 ;
}while(temp1!=temp2) ;
}
//set graphic mode
void set_graphic(uint ad,uchar width)
{
jm.graphic_add=ad ;
jm.graphic_width=width ;
wr_cmd3(ad,0x42) ;
wr_cmd2(width,0x00,0x43) ;
}
//read a byte from lcd
uchar rd_data()
{
uchar temp ;
ch_busy(0) ;
CD=0 ;
DB=0 ;
CE=0 ;
DB_DIR=0x00 ;
DB=0xff ;
RD=0 ;
DB=0 ;
CE=0 ;
DB_DIR=0xFF ;
temp=DB ;
RD=1 ;
CD=1 ;
return temp ;
}
//send a byte to lcd ram
void send_byte(uchar dat)
{
RD=1 ;
DB_DIR=0x00 ;
CE=0 ;
CD=0 ;
WR=0 ;
DB=dat ;
// DelayUs(2) ;
CE=1 ;
CD=1 ;
WR=1 ;
}
//send a command word to lcd registor
void send_cmd(uchar cmd)
{
RD=1 ;
DB_DIR=0x00 ;
CE=0 ;
CD=1 ;
WR=0 ;
DB=cmd ;
// DelayUs(2) ;
CE=1 ;
CD=1 ;
WR=1 ;
}
//write a byte
void wr_data(uchar data)
{
ch_busy(0) ;
send_byte(data) ;
}
//write a command with no parameter
void wr_cmd0(uchar cmd)
{
ch_busy(0) ;
send_cmd(cmd) ;
}
//write a command with one parametre
void wr_cmd1(uchar para,uchar cmd)
{
ch_busy(0) ;
send_byte(para) ;
ch_busy(0) ;
send_cmd(cmd) ;
}
//write a cammand with two parameters
void wr_cmd2(uchar para1,uchar para2,uchar cmd)
{
ch_busy(0) ;
send_byte(para1) ;
ch_busy(0) ;
send_byte(para2) ;
ch_busy(0) ;
send_cmd(cmd) ;
}
//write a command with a uint parameter
void wr_cmd3(uint para,uchar cmd)
{
uchar temp,temp1 ;
temp=(uchar )para ;
temp1=(uchar)(para>>8) ;
wr_cmd2(temp,temp1,cmd) ;
}
//autowrite
void auto_wr(uchar dat)
{
ch_busy(1) ;
send_byte(dat) ;
}
//autoread
uchar auto_rd()
{
uchar temp ;
ch_busy(2) ;
CD=0 ;
DB=0 ;
CE=0 ;
DB_DIR=0x00 ;
DB=0xff ;
RD=0 ;
DB=0 ;
CE=0 ;
DB_DIR=0xFF ;
temp=DB ;
RD=1 ;
CD=1 ;
return temp ;
}
//enable auto write or not
void enable_autowr(uchar flag)
{
if(flag)
wr_cmd0(0xB0) ;
else
wr_cmd0(0xB2) ;
}
//enable autoread or not
void enable_autord(uchar flag)
{
if(flag)
wr_cmd0(0xB1) ;
else
wr_cmd0(0xB3) ;
}
//define higher function
//current display ram address add add
void add_add(uint ad)
{
uint temp ;
jm.offset+=ad ;
temp=jm.cur_page+jm.offset ;
wr_cmd3(temp,0x24) ;
}
//set addres s pointer
// had better not use this function
void set_add(uint ad)
{
jm.cur_page=ad ;
wr_cmd3(ad,0x24) ;
}
//move address pointer to y row and x column
void add_xy(uchar x,uchar y)
{
uint temp ;
temp=(uint)x+((uint)y)*jm.graphic_width ;
jm.offset=temp ;
temp=temp+jm.cur_page ;
wr_cmd3(temp,0x24) ;
}
void str_disp(const uchar *str,uchar x,uchar y)
{
uint temp1 ;
uchar temp,temp2,j,i ;
// wr_cmd0(0x9F) ;
// wr_cmd0(0x81) ;
// add_xy(1,x,y) ;
// while(*str!='/0')
// {
// temp=*(str++)-0x20 ;
// wr_cmd1(temp,0xC0) ;//address auto add 1
// }
// wr_cmd0(jm.disp_mode)
i=x ;
y=y*16 ;
while(*str!='/0')
{
add_xy(i++,y) ;
temp1=(*(str++)-0x20)*16 ;
for(j=0;j<16;j++)
{
temp2=ascii0816[temp1+j];
wr_cmd1(temp2,0xC4) ;
add_add(30) ;
}
}
}
//here as long as we understand how lcd scan screen,we can
//implement what function we want
//this lcd scan in horizon mode
void show_char( uchar dat ,uchar x,uchar y)
{
uint temp1 ;
uchar i ,j ,temp2;
y=y*16 ;
add_xy(x,y) ;
temp1=(dat-0x20)*16 ;
//for one char is composed of 16*8 dots ,so we need scan 16 times in horizontal way
for(j=0;j<16;j++)
{
temp2=ascii0816[temp1+j];
//one times we write in 8 dots
wr_cmd1(temp2,0xC4) ;
add_add(30) ;
}
}
void show_chn(const uchar *chn,uchar x,uchar y)
{
uchar i ;
// x=x*8;
y=y*16 ;
add_xy(x,y) ;
for(i=0;i<16;i++)
{
wr_cmd1(*chn++,0xC4) ;
add_add(1) ;
wr_cmd1(*chn++,0xC4) ;
add_add(29) ;
}
}
void chns_disp(const uchar *chn,uchar x,uchar y,uchar count)
{
uchar i,j ;
for(i=0;i {
add_xy(x+i*2,y) ;
for(j=0;j<16;j++)
{
wr_cmd1(*chn++,0xC4) ;
add_add(1) ;
wr_cmd1(*chn++,0xC4) ;
add_add(29) ;
}
// y=y+16 ;
}
}
void show_img(uchar x,uchar y,uchar width,uchar height,const uchar *img)
{
uchar i ,j,temp1,temp2 ;
// set_add(jm.cur_page) ;
// temp1=(x1-x)/8 ;
// temp2=(y1-y) ;
add_xy(0,y) ;
add_add(x) ;
for(i=0;i {
for(j=0;j {
wr_cmd1(*img++,0xC4) ;
add_add(1) ;
}
add_add(30-width) ;
}
}
void clr_lcd(uchar x,uchar y,uchar width,uchar height)
{
uchar i,j;
width=width/8 ;
// add_xy(0,x,y) ;
for(i=0;i {
add_xy(0,y+i) ;//move to the position where you want to clear
add_add(x) ;
enable_autowr(1) ;
for(j=0;j {
auto_wr(0x00) ;
}
enable_autowr(0) ;
}
}
void clr_ram()
{
uint i ;
set_add(jm.cur_page) ;
enable_autowr(1) ;
for(i=0;i<0xFFFE;i++)
{
auto_wr(0x00) ;
}
enable_autowr(0) ;
set_add(jm.cur_page) ;
}
//this function has some problems
void wr_img(uchar x,uchar y,uchar width,uchar height,const uchar *img)
{
uchar i,j,flag ;
if(jm.offset<0xF00)
flag=0 ;
else
flag=1 ;
width=width/8 ;
for(i=0;i {
add_xy(x,y+i) ;//move to the position where you want to clear
enable_autowr(1) ;
for(j=0;j {
auto_wr(*img++) ;
}
enable_autowr(0) ;
}
}
//draw picture
void draw_vline(uchar x,uchar y,uchar height)
{
uchar i ;
add_xy(x,y) ;
for(i=0;i {
wr_cmd0(0xF8) ;
add_add(30) ;
}
}
void draw_hline(uchar x,uchar y,uchar width)
{
uchar i;
add_xy(x,y) ;
width=width/8 ;
enable_autowr(1) ;
for(i=0;i auto_wr(0xff) ;
enable_autowr(0) ;
}
void draw_frame(uchar x,uchar y,uchar width,uchar height)
{
uchar i,j ;
width=width/8 ;
//draw two horizon line
add_xy(x,y) ;
enable_autowr(1) ;
for(i=0;i auto_wr(0xFF) ;
enable_autowr(0) ;
add_xy(x,y+height) ;
enable_autowr(1) ;
for(i=0;i auto_wr(0xFF) ;
enable_autowr(0) ;
//draw two vertical line
add_xy(x,y) ;
for(i=0;i {
wr_cmd0(0xFF) ;
add_add(29) ;
wr_cmd0(0xF8) ;
add_add(1) ;
}
}
void draw_point(uchar x,uchar y)
{
uchar temp ;
temp=x%8 ;
x=x/8 ;
add_xy(0,y) ;
add_add(x) ;
temp=7-temp+0xF8 ;
wr_cmd0(temp) ;
}
void draw_page(uchar num)
{
uint temp=jm.cur_page ;
set_add(add[num]) ;
clr_lcd(0,0,239,127) ;
draw_frame(0,0,240,126) ;
draw_hline(1,105,220) ;
draw_vline(1,20,90) ;
// chns_disp(str,8,3,6) ;
// chns_disp(str1,205,102,2) ;
// show_chn(str2,0,2) ;
// show_chn(str2+32,0,3) ;
draw_point(12,3) ;
set_add(temp) ;
}
测试程序
#include
#include
#include "main.h"
#include "jm240.h"
void interrupt main_int()
{
;
}
void init_all()
{
init_jm240() ;
}
const uchar str[]={
/*---------------实----------------*/
0x01,0x00,0x00,0x80,0x3F,0xFE,0x28,0x04,0x46,0x88,0x04,0x80,0x08,0x80,0x06,0x80,
0x04,0x80,0x7F,0xFE,0x00,0x80,0x01,0x40,0x02,0x20,0x04,0x10,0x18,0x18,0x60,0x10,
/*---------------时----------------*/
0x00,0x10,0x00,0x10,0x7C,0x10,0x44,0x10,0x47,0xFE,0x44,0x10,0x7C,0x10,0x45,0x10,
0x44,0x90,0x44,0x90,0x7C,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x50,0x00,0x20,
/*---------------温----------------*/
0x40,0x00,0x27,0xF0,0x24,0x10,0x07,0xF0,0x94,0x10,0x54,0x10,0x17,0xF0,0x20,0x00,
0x2F,0xFC,0xC9,0x24,0x49,0x24,0x49,0x24,0x49,0x24,0x49,0x24,0x5F,0xFE,0x40,0x00,
/*---------------度----------------*/
0x01,0x00,0x00,0x80,0x3F,0xFE,0x22,0x20,0x22,0x20,0x2F,0xFC,0x22,0x20,0x23,0xE0,
0x20,0x00,0x27,0xF8,0x22,0x10,0x21,0x20,0x20,0xC0,0x41,0x30,0x46,0x0E,0x98,0x04,
/*---------------曲----------------*/
0x04,0x40,0x04,0x40,0x04,0x40,0x3F,0xFC,0x24,0x44,0x24,0x44,0x24,0x44,0x24,0x44,
0x3F,0xFC,0x24,0x44,0x24,0x44,0x24,0x44,0x24,0x44,0x3F,0xFC,0x20,0x04,0x00,0x00,
/*---------------线----------------*/
0x10,0x40,0x18,0x50,0x10,0x4C,0x20,0x48,0x23,0xFC,0x48,0x40,0xF8,0x40,0x13,0xFE,
0x20,0x40,0x7C,0x48,0x00,0x30,0x00,0x22,0x1C,0xD2,0xE3,0x0A,0x00,0x06,0x00,0x02,
} ;
const uchar str1[]=
{
/*---------------时----------------*/
0x00,0x10,0x00,0x10,0x7C,0x10,0x44,0x10,0x47,0xFE,0x44,0x10,0x7C,0x10,0x45,0x10,
0x44,0x90,0x44,0x90,0x7C,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x50,0x00,0x20,
/*---------------间----------------*/
0x20,0x00,0x13,0xFC,0x10,0x04,0x40,0x04,0x47,0xE4,0x44,0x24,0x44,0x24,0x47,0xE4,
0x44,0x24,0x44,0x24,0x47,0xE4,0x40,0x04,0x40,0x04,0x40,0x04,0x40,0x14,0x40,0x08,
} ;
const uchar str2[]=
{
/*---------------温----------------*/
0x40,0x00,0x27,0xF0,0x24,0x10,0x07,0xF0,0x94,0x10,0x54,0x10,0x17,0xF0,0x20,0x00,
0x2F,0xFC,0xC9,0x24,0x49,0x24,0x49,0x24,0x49,0x24,0x49,0x24,0x5F,0xFE,0x40,0x00,
/*---------------度----------------*/
0x01,0x00,0x00,0x80,0x3F,0xFE,0x22,0x20,0x22,0x20,0x2F,0xFC,0x22,0x20,0x23,0xE0,
0x20,0x00,0x27,0xF8,0x22,0x10,0x21,0x20,0x20,0xC0,0x41,0x30,0x46,0x0E,0x98,0x04,
};
const char dat[]=
{
0,1,2,3,4,6,7,8,9,10,
11,12,13,14,15,16,17,18,19,20,
21,22,22,23,24,25,26,26,27,28,
28,29,30,30,31,31,32,32,33,33,
33,34,34,34,34,35,35,35,35,35,
35,35,35,35,35,35,34,34,34,34,
33,33,32,32,32,31,30,30,29,29,
28,27,27,26,25,24,24,23,22,21,
20,19,18,17,16,15,14,13,12,11,
10,9,8,7,6,5,4,3,2,1,
-1,-2,-3,-4,-5,-6,-7,-8,-9,-10,
-11,-12,-13,-14,-15,-16,-17,-18,-19,-20,
-21,-22,-23,-24,-24,-25,-26,-27,-27,-28,
-29,-29,-30,-30,-31,-32,-32,-32,-33,-33,
-34,-34,-34,-34,-35,-35,-35,-35,-35,-35,
-35,-35,-35,-35,-35,-34,-34,-34,-34,-33,
-33,-33,-32,-32,-31,-31,-30,-30,-29,-28,
-28,-27,-26,-26,-25,-24,-23,-22,-22,-21,
-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,
-10,-9,-8,-7,-6,-4,-3,-2,-1,0,
};
const char dat1[]=
{-3,-2,-1,0,
0,1,2,3,4,6,7,8,9,10,
11,12,13,14,15,16,17,18,19,20,
21,22,22,23,24,25,26,26,27,28,
28,29,30,30,31,31,32,32,33,33,
33,34,34,34,34,35,35,35,35,35,
35,35,35,35,35,35,34,34,34,34,
33,33,32,32,32,31,30,30,29,29,
28,27,27,26,25,24,24,23,22,21,
20,19,18,17,16,15,14,13,12,11,
10,9,8,7,6,5,4,3,2,1,
-1,-2,-3,-4,-5,-6,-7,-8,-9,-10,
-11,-12,-13,-14,-15,-16,-17,-18,-19,-20,
-21,-22,-23,-24,-24,-25,-26,-27,-27,-28,
-29,-29,-30,-30,-31,-32,-32,-32,-33,-33,
-34,-34,-34,-34,-35,-35,-35,-35,-35,-35,
-35,-35,-35,-35,-35,-34,-34,-34,-34,-33,
-33,-33,-32,-32,-31,-31,-30,-30,-29,-28,
-28,-27,-26,-26,-25,-24,-23,-22,-22,-21,
-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,
-10,-9,-8,-7,-6,-4,
};
bank1 uchar i,j,tmp1;
bank1 uint temp ;
void test()
{
set_graphic(0x0000,30) ;
set_add(0x0F00) ;
set_graphic(0x0000,30) ;
clr_lcd(2,18,220,80) ;
set_add(0x0F00) ;
for(i=0;i<200;i++)
{
// if(i+j<200)
// tmp1=dat[i+j]+55 ;
// else
// tmp1=dat[200-i-j]+55 ;
draw_point(16+i,20) ;
}
if(j>=200)
j=0 ;
else
j++ ;
DelayMs(255) ;
DelayMs(255) ;
set_graphic(0x0F00,30) ;
set_add(0x0000) ;
clr_lcd(2,18,220,80) ;
set_graphic(0x0F00,30) ;
set_add(0x0000) ;
for(i=0;i<200;i++)
{
// if(i+j<200)
// tmp1=dat[i+j]+55 ;
// else
// tmp1=dat[200-i-j]+55 ;
draw_point(16+i,j) ;
}
if(j>=200)
j=0 ;
else
j++ ;
}
void main()
{
// const uchar str1[]="hello world!" ;
init_all() ;
wr_cmd0(0x98) ;
clr_lcd(1,1,240,128) ;
draw_frame(0,0,240,126) ;
draw_hline(1,105,220) ;
draw_vline(1,20,90) ;
chns_disp(str,8,3,6) ;
chns_disp(str1,205,102,2) ;
show_chn(str2,0,2) ;
show_chn(str2+32,0,3) ;
draw_point(12,3) ;
// clr_lcd(0,0,240,128) ;
// show_img(0,0,240,128,img) ;
for(i=0;i<200;i++)
{
draw_point(16+i,dat[i]+55) ;
}
// clr_lcd(2,18,220,80) ;
temp=jm.cur_page ;
set_add(0x0F00) ;
clr_lcd(1,1,240,128) ;
draw_frame(0,0,240,126) ;
draw_hline(1,105,220) ;
draw_vline(1,20,90) ;
chns_disp(str,8,3,6) ;
chns_disp(str1,205,102,2) ;
show_chn(str2,0,2) ;
show_chn(str2+32,0,3) ;
draw_point(12,3) ;
// clr_lcd(0,0,240,128) ;
// show_img(0,0,240,128,img) ;
for(i=0;i<200;i++)
{
draw_point(16+i,dat1[i]+55) ;
}
set_add(temp) ;
j=0 ;
while(1)
{
// set_graphic(0x0000,30) ;
// set_add(0x0F00) ;
//// set_graphic(0x0000,30) ;
// clr_lcd(2,18,220,80) ;
// set_add(0x0F00) ;
// for(i=0;i<200;i++)
// {
//
// if(i+j<200)
// tmp1=dat[i+j]+55 ;
// else
// tmp1=dat[200-i-j]+55 ;
//
// draw_point(16+i,2) ;
// }
//// if(j>=200)
//// j=0 ;
//// else
// j++ ;
//// DelayMs(255) ;
//// DelayMs(255) ;
//
// set_graphic(0x0F00,30) ;
// set_add(0x0000) ;
// clr_lcd(2,18,220,80) ;
// set_graphic(0x0F00,30) ;
// set_add(0x0000) ;
// for(i=0;i<200;i++)
// {
// if(i+j<200)
// tmp1=dat[i+j]+55 ;
// else
// tmp1=dat[200-i-j]+55 ;
//
// draw_point(16+i,5) ;
// }
//// if(j>=200)
//// j=0 ;
//// else
// j++ ;
//// DelayMs(255) ;
//// DelayMs(255) ;
test() ;
}
}
本来想用来画动态曲线的,可是PIC16F877A的RAM空间太小,不能容下200字节的数组,所以也就没有做完,不过思路就有了,
就是建立两个缓冲区,一个缓冲区显示,一个缓冲区用于写数据,当一个缓冲区在显示时,向另一个缓冲区中写数据,然后移动显示指针,显示另一个缓冲区的数据,再重复上面的操作!这样显示比使用一个缓冲区效果要好!不会因刷屏而造成屏幕的闪烁!