12864串行驱动

12864串行
/*************************************
** start51 study board test software
** test 12864LCD
** using serial interface
** author:bluehacker
** QQ:282074921
** Date:2007-11-18
**************************************/
#ifndef _LZP_START51_12864LCDS_H
#define _LZP_START51_12864LCDS_H
#include "reg52.h"
//12864串行口定义
sbit LCD_CS=P2^3;
sbit LCD_CLK=P2^5;
sbit LCD_SID=P2^4;

//12864LCD指令定义
#define CMD_CLEAR 0x01
#define CMD_RESET 0x02
//设置波特率
#define OSC_FREQ 11059200L

#define BAUD_115200 256 - (OSC_FREQ/192L)/115200L // 255
#define BAUD_57600 256 - (OSC_FREQ/192L)/57600L // 254
#define BAUD_38400 256 - (OSC_FREQ/192L)/38400L // 253
#define BAUD_28800 256 - (OSC_FREQ/192L)/28800L // 252
#define BAUD_19200 256 - (OSC_FREQ/192L)/19200L // 250
#define BAUD_14400 256 - (OSC_FREQ/192L)/14400L // 248
#define BAUD_9600 256 - (OSC_FREQ/192L)/9600L // 244
void Delay_us(unsigned char nUs);
void Delay_ms(unsigned int nMs);

bit lcd_busy(void);
void write_command(unsigned char cmd);
unsigned char read_data(void);
void write_data(unsigned char dat);
void clear_lcd();
void lcd_init();
void lcd_setxy(unsigned char x,unsigned char y);
void lcd_display_str(unsigned char x, unsigned char y,unsigned char *str);
#endif
我的是ST7920控制的.接了RS(CS),与WR(SID)两个至单片机,节约了串口.

另外PSB(串行为0,并行接1)跟LED-接GND,RS与LED+接VCC.

这个程序可能还有点问题,接上背光(LED+,LED-)显示就不很清晰了,关了之后很清晰.

显示最后三个汉字"李正平"错误,为"李掌"

可笑.查查程序哪里有问题了






//FileName:12864lcds.c
/*************************************
** start51 study board test software
** test 12864LCD
** using serial interface
** author:bluehacker
** QQ:282074921
** Date:2007-11-18
**************************************/

#include "12864.h"
void Delay_us(unsigned char nUs)
{unsigned char i;
while(nUs--)
for(i=0;i<10;i++);
}

void Delay_ms(unsigned int nMs)
{ unsigned char i;
while(nMs--)
for(i=0;i<120;i++);
}


bit lcd_busy()
{
unsigned char i;
bit dat;
//先产生连续5个'1'
LCD_CS=1;
for(i=0;i<5;i++)
{
LCD_CLK=0;
LCD_SID=1;
LCD_CLK=1;
}
//再发送一个'1',表示读操作
LCD_CLK=0;
LCD_SID=1;
LCD_CLK=1;
//再发送一个'0',表示写命令操作
LCD_CLK=0;
LCD_SID=0;
LCD_CLK=1;
//再发送一个'0',这是表示第一个字节结束
LCD_CLK=0;
LCD_SID=0;
LCD_CLK=1;

//Delay_us(1);
dat=0;
LCD_CLK=0;
dat=LCD_SID;
LCD_CLK=1;
LCD_CS=0;
return dat;
}

void write_command(unsigned char cmd)
{
unsigned char i;


while(lcd_busy());
//先产生连续5个'1'
LCD_CS=1;
for(i=0;i<5;i++)
{
LCD_CLK=0;
LCD_SID=1;
LCD_CLK=1;
}
//再发送一个'0',表示写操作
LCD_CLK=0;
LCD_SID=0;
LCD_CLK=1;
//再发送一个'0',表示写命令操作
LCD_CLK=0;
LCD_SID=0;
LCD_CLK=1;
//再发送一个'0',这是表示第一个字节结束
LCD_CLK=0;
LCD_SID=0;
LCD_CLK=1;
//下面发送具体指令,先发送高4位
for(i=0;i<4;i++)
{
LCD_CLK=0;
if(cmd&0x80)
LCD_SID=1;
else
LCD_SID=0;
LCD_CLK=1;
cmd<<=1;
}
//发送连续4个'0'
for(i=0;i<4;i++)
{
LCD_CLK=0;
LCD_SID=0;
LCD_CLK=1;
}
//下面发送指令的低4位
for(i=0;i<4;i++)
{
LCD_CLK=0;
if(cmd&0x80)
LCD_SID=1;
else
LCD_SID=0;
LCD_CLK=1;
cmd<<=1;
}
//发送连续4个'0'
for(i=0;i<4;i++)
{
LCD_CLK=0;
LCD_SID=0;
LCD_CLK=1;
}
LCD_CS=0;//结束
}


void write_data(unsigned char dat)
{
unsigned char i;
while(lcd_busy());
//先产生连续5个'1'
LCD_CS=1;
for(i=0;i<5;i++)
{
LCD_CLK=0;
LCD_SID=1;
LCD_CLK=1;
}
//再发送一个'0',表示写操作
LCD_CLK=0;
LCD_SID=0;
LCD_CLK=1;
//再发送一个'1',表示写数据操作
LCD_CLK=0;
LCD_SID=1;
LCD_CLK=1;
//再发送一个'0',这是表示第一个字节结束
LCD_CLK=0;
LCD_SID=0;
LCD_CLK=1;
//下面发送具体数据,先发送高4位
for(i=0;i<4;i++)
{
LCD_CLK=0;
if(dat&0x80)
LCD_SID=1;
else
LCD_SID=0;
LCD_CLK=1;
dat<<=1;
}
//发送连续4个'0'
for(i=0;i<4;i++)
{
LCD_CLK=0;
LCD_SID=0;
LCD_CLK=1;
}
//下面发送数据的低4位
for(i=0;i<4;i++)
{
LCD_CLK=0;
if(dat&0x80)
LCD_SID=1;
else
LCD_SID=0;
LCD_CLK=1;
dat<<=1;
}
//发送连续4个'0'
for(i=0;i<4;i++)
{
LCD_CLK=0;
LCD_SID=0;
LCD_CLK=1;
}
LCD_CS=0;//结束
}


unsigned char read_data()
{
unsigned char i,dat;
while(lcd_busy());
//先产生连续5个'1'
LCD_CS=1;
for(i=0;i<5;i++)
{
LCD_CLK=0;
LCD_SID=1;
LCD_CLK=1;
}
//再发送一个'1',表示读操作
LCD_CLK=0;
LCD_SID=0;
LCD_CLK=1;
//再发送一个'1',表示数据操作
LCD_CLK=0;
LCD_SID=1;
LCD_CLK=1;
//再发送一个'0',这是表示第一个字节结束
LCD_CLK=0;
LCD_SID=0;
LCD_CLK=1;

//下面读具体数据
//先读高4位

dat=0;
for(i=0;i<4;i++)
{
LCD_CLK=0;
dat<<=1;
LCD_CLK=1;
dat|=LCD_SID;
}
//再接受4个连续'0',没什么意义,直接丢掉
for(i=0;i<4;i++)
{
LCD_CLK=0;
Delay_us(1);
LCD_CLK=1;
Delay_us(1);
}
//接受低4位
for(i=0;i<4;i++)
{
LCD_CLK=0;
dat<<=1;
LCD_CLK=1;

dat|=LCD_SID;
}
//再接受4个连续'0',没什么意义,直接丢掉
for(i=0;i<4;i++)
{
LCD_CLK=0;
Delay_us(1);
LCD_CLK=1;
Delay_us(1);
}
LCD_CS=0;
return dat;
}

void clear_lcd()
{
write_command(CMD_CLEAR);
}

void lcd_setxy(unsigned char x,unsigned char y)
{
unsigned char addr;
switch(y)
{
case 0:
addr=0x80+x;
break;
case 1:
addr=0x90+x;
break;
case 2:
addr=0x88+x;
break;
case 3:
addr=0x98+x;
break;
}
write_command(addr);
}

void lcd_display_str(unsigned char x, unsigned char y,unsigned char *str)
{
unsigned char i;
lcd_setxy(x,y);
for(i=0;str[i]!='\0';i++)
{
write_data(str[i]);
}
}


void lcd_init()
{
write_command(CMD_RESET);
write_command(0x0d);//设置显示状态,整体显示ON,游标与游标位置ON
write_command(0x30);//功能设置,基本指令
write_command(0x18);//游标与显示移位控制
clear_lcd();
//write_command(0x80);//设置DDRAM位址,并不必须
}

void main()
{
TCON=0;
SCON=0x50;/*mode 1,1 start bit ,8 data bit ,1 stop bit,enable receive*/
PCON=0x80;/*SMOD=1, Baud Rate twice*/
TMOD=0x21;/*timer 0--mode 1 and timer 1 ---mode2*/
//set baud rate,use timer 1 as baud rate generator
TH1=BAUD_19200;
TL1=TH1;
TR1=1;
// ET1=0;//disable timer 1 interrupt
EA=0;
lcd_init();
Delay_ms(100);
//显示武林外传

lcd_setxy(1,2);
write_data(0xce);
write_data(0xe4);
lcd_setxy(2,2);
write_data(0xc1);
write_data(0xd6);
lcd_setxy(3,2);
write_data(0xcd);
write_data(0xe2);
lcd_setxy(4,2);
write_data(0xb4);
write_data(0xab);
Delay_ms(5000);
clear_lcd();
write_command(CMD_RESET);
Delay_ms(5000);
lcd_display_str(2,0,"bluehacker");
lcd_display_str(1,1,"QQ:282074921");
lcd_display_str(3,2,"李正平");




























LCD12864(ST7920)串行驱动程序

作者:L_jeary 文章来源:L_jeary 点击数:286 更新时间:2011-6-23

/*====================================================================
LCD12864对应的C文件,定义了相关的LCD驱动函数
主要有:串行驱动LCD12864,内置的控制器为ST7920和ST7921
LCD初始化函数
读写函数

0xf8为写命令的命令字;0x

fa为写数据的命令字,这里用的是TI_F28027

在编写和调试过程中借鉴了一些网上的程序,在此表示感谢,

这里是已经调好的,在移植过程中,调试时注意先要通过示波器对函数

void send_data(Uint16 D_Ctrl,Uint16 D_data)
的时序检测一下,是否满足要求,不行的话可改一下延时值或者查看硬件是否连好
====================================================================*/
#include "LCD12864.h" //LCD12864的头文件
typedef unsigned int Uint16;

/*=====================================================================
管脚的初始化,主要定义复用管脚功能 方向等
======================================================================*/
void Init_guanjiao(void)
{
EALLOW;
GpioCtrlRegs.GPAMUX2.bit.GPIO16=0;//通用IO 片选CS管脚
GpioCtrlRegs.GPADIR.bit.GPIO16=1;//输出
GpioCtrlRegs.GPAPUD.bit.GPIO16=1;//禁止上拉电阻

GpioCtrlRegs.GPBMUX1.bit.GPIO33=0; //数据管脚SID
GpioCtrlRegs.GPBDIR.bit.GPIO33=1;
GpioCtrlRegs.GPBPUD.bit.GPIO33=1;

GpioCtrlRegs.GPAMUX1.bit.GPIO2=0;//时钟CLK管脚
GpioCtrlRegs.GPADIR.bit.GPIO2=1;
GpioCtrlRegs.GPAPUD.bit.GPIO2=1;

EDIS;
}
/*=====================================================================
LCD串行数据传送程序
函数名:void send_data(Uint16 D_Ctrl,Uint16 D_data)
功能:
串行数据传送共分三个字节完成:
第一字节:串口控制-格式 11111ABC
A为数据传送方向控制:H表示数据从LCD到MCU,L表示数据从MCU到LCD
B为数据类型选择:H表示数据是显示数据,L表示数据是控制指令
C固定为0
第二字节分两次传送
第一次:(并行)8位数据的高4位-格式 DDDD0000 放在一个字节中的高四位
第二次:(并行)8位数据的低4位-格式 0000DDDD 放在一个字节中的高四位

======================================================================*/
void send_data(Uint16 D_Ctrl,Uint16 D_data)
//LCD_CLK一个脉冲写一位
{
Uint16 i,j;
Uint16 temp;
//LCD_CS=1; //片选使能
GpioDataRegs.GPADAT.bit.GPIO16=1;

for(i=0;i<3;i++) // 串行数据的传送
{
if(i==0) //写第一个字节 格式1111 1ABC
{
temp=D_Ctrl;
}
if(i==1) //写第二个字节 第一次写 高四位放在第一次传送的高四位
{
temp=(D_data&0xf0);
}
if(i==2) //写第二个字节 第二次写 低四位放在第二次传送的高四位
{
temp=(D_data&0x0f);
temp=temp<<4;
}

for(j=0;j<8;j++) //串行写8位二进制数据
{
//LCD_CLK=0; //时钟输入置低
GpioDataRegs.GPADAT.bit.GPIO2=0;
F_delay(3);
if((temp&0x80)==0)
{
//LCD_SID=0; //数据SID
GpioDataRegs.GPBDAT.bit.GPIO33=0;
}
else
{
//LCD_SID=1; //数据SID
GpioDataRegs.GPBDAT.bit.GPIO33=1;
}
//LCD_CLK=1; //时钟输入置高
GpioDataRegs.GPADAT.bit.GPIO2=1;
temp=temp<<1;
F_delay(5);
}
}
//LCD_CLK=0; //时钟输入置低
GpioDataRegs.GPADAT.bit.GPIO2=0;
//LCD_CS=0; //片选禁止
GpioDataRegs.GPADAT.bit.

GPIO16=0;
}
/*=======================================================================
LCD初始化程序
函数名:void lcd_initial()
功能:
========================================================================*/
void lcd_initial(void)//写命令第一字节为0xf8,表示写的是命令
//0xfa则表示写数据
{
Init_guanjiao();

send_data(0xf8,0x30); //功能设定
//F_delay(10);
send_data(0xf8,0x0C); //显示状态开/关
//F_delay(10);
send_data(0xf8,0x01); //清屏显示
//F_delay(10);
//send_data(0xf8,0x06); //进如点设定,整体显示设定
//F_delay(10);
send_data(0xf8,0x02); //地址归位
//F_delay(10);
//send_data(0xf8,0x40); //设定CGRAM
//F_delay(10);
send_data(0xf8,0x80); //设定DDRAM
//F_delay(10);
}
/*=========================================================================
函数名:void write_one_word(Uint16 x,Uint16 y,Uint16 word0, Uint16 word1)
功能:
实现在任意坐标写一个字
X列;Y行
===========================================================================*/
void write_one_word(Uint16 x,Uint16 y,Uint16 word0, Uint16 word1)
{
x &= 0x0f;
y &= 0x0f;
switch(y)
{
case 0:x+=0x80;
break;
case 1:x+=0x90;
break;
case 2:x+=0x88;
break;
case 3:x+=0x98;
break;
default:break;
}
send_data(0xf8,x);
//F_delay(80L);
send_data(0xfa,word0);
//F_delay(80L);
send_data(0xfa,word1);
}
/*============================================================================
函数名:void write_list_word(Uint16 x,Uint16 y,Uint16 flash *hanzi)
功能:
实现从任一坐标开始写字
=============================================================================*/
//void write_list_word(Uint16 x,Uint16 y,Uint16 flash *hanzi)
void write_list_word(Uint16 x,Uint16 y,char *hanzi)
{
Uint16 i,j;
for(i=0;i<16;i+=2)//这里8是等于*hanzi指针所指字符串的汉字个数,如有删减要将8改成相应的数
{
j=x;
write_one_word(x,y,hanzi[i],hanzi[i+1]);
//F_delay(80L);
x=j+1;
}
}
/*================================================
//显示点阵
//经过调试发现显示点阵是非常有意思的,
//最主要的在于data1,data2上的两组数据的取值,
//不同的取值对应着不同的点阵效果。-
==================================================*/
void lat_disp (Uint16 data1,Uint16 data2)
{
Uint16 i,j,k,x,y;
x=0x80;
y=0x80;
//x1=0x80;
//x2=0x88;

for(k=0;k<2;k++)
{
for(j=0;j<16;j++)
{
for(i=0;i<8;i++)
{
send_data (0xf8,0x34); //扩充指令操作。
send_data (0xf8,y+j*2);
send_data (0xf8,x+i);
send_data (0xf8,0x30);
send_data (0xfa,data1);
send_data (0xfa,data1);
}
for(i=0;i<8;i++)
{
send_data (0xf8,0x34);
send_data (0xf8,y+j*2+1);
send_data (0xf8,x+i);
send_data (0xf8,0x30);
send_data (0xfa,data2);
send_data (0xfa,data2);
}
}
x=0x88;
}
send_data (0xf8,0x36);
}
//===============================================================================
void F_delay(Uint16 D_time)
{
Uint16 i;
f

or(i=0;i}

//===========================================================================
// End of file.
//===========================================================================


while(1)
{
}
}


相关文档
最新文档