|
楼主 |
发表于 2009-7-31 12:20:23
|
显示全部楼层
下面是全部源程序,我现在是画一条竖线就会出现三条竖线,这到底是什么原因啊???也参看了论坛里的好多程序,看起来我的程序和他们的都一样,一直找不出错误....
#include<avr/io.h>
#include<delay.h>
#include<math.h>
#include <string.h>
#define uchar unsigned char
#define uint unsigned int
#define CTRL_PORT PORTA
#define CTRL_DDR DDRA
#define CTRL_PIN PINA
#define RS 5 //CS 第四引脚
#define RW 6 //SIO 第五引脚
#define E 7 //SCK 第六引脚
#define DATA_DDR DDRD
#define DATA_PIN PIND
#define DATA_PORT PORTD
#define CTRL_OUT() CTRL_DDR |= (1<<(RS))|(1<<(RW))|(1<<(E))
#define CLR_RS() CTRL_PORT &= ~(1<<RS)
#define SET_RS() CTRL_PORT |= (1<<RS)
#define CLR_RW() CTRL_PORT &= ~(1<<RW)
#define SET_RW() CTRL_PORT |= (1<<RW)
#define CLR_E() CTRL_PORT &= ~(1<<E)
#define SET_E() CTRL_PORT |= (1<<E)
#define DATA_IN() DATA_DDR &= ~0xFF
#define DATA_OUT() DATA_DDR |= 0xFF
#define DATA_GET() DATA_PIN
//液晶基本参数
#define X_MAX 127
#define Y_MAX 63
//每行的首地址
#define ONE 0x80
#define TWO 0x90
#define THREE 0x88
#define FOUR 0x98
//基本指令集预定义
#define DATA 1 //数据位
#define COMMAND 0 //命令位
#define CLEAR_SCREEN 0x01 //清屏
#define ADDRESS_RESET 0x02 //地址归零
#define BASIC_FUNCTION 0x30 //基本指令集
#define EXTEND_FUNCTION 0x34 //扩充指令集
//扩展指令集预定义
#define AWAIT_MODE 0x01 //待命模式
#define ROLLADDRESS_ON 0x03 //允许输入垂直卷动地址
#define IRAMADDRESS_ON 0x02 //允许输入IRAM地址
#define SLEEP_MODE 0x08 //进入睡眠模式
#define NO_SLEEP_MODE 0x0c //脱离睡眠模式
#define GRAPH_ON 0x36 //打开绘图模式
#define GRAPH_OFF 0x34 //关闭绘图模式
#ifndef COLOR
#define BLACK 1
#define WHITE 0
#endif
void Init(); //液晶屏初始化
void ClearRam(); //清除显示存储区内的内容
void DisplayCLR(); //清除显示的内容
void GraphModeSet(uchar Select); //开关画图功能
void DisplayStrings_WithAddress(uchar ucAdd,const char *p); //显示汉字/字符串,地址:80H~87H,90H~97H,88H~8FH,98H~9FH
void DisplayChinese(uchar x,uchar y,const char *p); //在x,y处显示汉字或字符,地址:x<8, y<4
void DisplayStrings(uchar x,uchar y,const char *p); //在x,y处显示汉字或字符,地址: x<16, y<4
void ImgDisplay(unsigned char *img); //全屏显示128*64个象素的图形
void ImgDisplayCharacter(uchar x,uchar y,uchar *img); //在(x,y)处画一个16*16点阵的图案,也可以是字符
void draw_xy(uchar x,uchar y,uchar colour); //画127*63上的任意一个点
void SendByte(unsigned char a)
{
unsigned char i,d;
SET_RS();
CLR_RW();
for(i=0;i<8;i++)
{
CLR_E(); //clrbit(LCD_CTRL,E);
d = a&0x80;
if(d)
SET_RW(); //setbit(LCD_CTRL,RW);
else
CLR_RW(); //clrbit(LCD_CTRL,RW);
a<<=1;
SET_E(); //setbit(LCD_CTRL,E); //上升弦发送
}
CLR_RS();
}
//*******************************************
//*函数名称:void LCD_CheckBusy(void) *
//*函数功能:并行方式查忙 *
//*形式参数:无 *
//*形参说明:无 *
//*返回参数:无 *
//*使用说明:无 *
//*******************************************
void CheckBusy(void)
{
unsigned char temp;
DATA_IN();
CLR_RS(); //RS = 0;指令
SET_RW(); //RW = 1;读模式
delay3us(); //延时
delay3us(); //延时
SET_E(); //E = 1,使能
do
{
temp = DATA_GET(); //temp = BUSY;
}
while( 0x80==(temp&0x80) ); //等待不忙,temp=0x00时不忙
CLR_E(); //E = 0;
//_delay_ms(20);
}
//************************************************************************************
//*函数名称:void LCD_Write(unsigned char Data_Command , unsigned char uc_Content ) *
//*函数功能:并行模式向LCD发送数据或指令 *
//*形式参数:unsigned char Data_Command , unsigned char uc_Content *
//*形参说明:数据或指令的标志位,指令或数据的内容 *
//*返回参数:无 *
//*使用说明:无 *
//************************************************************************************
void Write( unsigned char Data_Command , unsigned char uc_Content )
{
CheckBusy();
DATA_OUT();
if(Data_Command==COMMAND)
{
CLR_RS(); //RS = 0;指令
}
else
{
SET_RS(); //RS = 1; 数据
}
CLR_RW(); //RW = 0; //写模式
DATA_PORT = uc_Content;
SET_E(); //E = 1;
delay3us(); //延时
CLR_E(); //E = 0;
}
//********************************************
//*函数名称:LCD_ReadData *
//*函数功能:并行读LCD数据 *
//*形式参数:无 *
//*形参说明:无 *
//*返回参数:读回的数据 *
//*使用说明:无 *
//********************************************
unsigned char ReadData(void)
{
unsigned char uc_Content;
CheckBusy();
//_delay_us(2);
DATA_PORT = 0xff ;
DATA_IN(); //P1 = 0xff;//输入前置1
SET_RS(); //RS = 1; //数据
SET_RW(); //RW = 1; //读模式
SET_E(); //E = 1; //使能
delay3us(); //延时很重要
uc_Content = DATA_GET(); //uc_Content = P1; //P1口的内容放到变量中
CLR_E(); //E = 0;
delay3us(); //延时很重要
return uc_Content;
}
//*************************************************************
//*函数名称:void LCD_DDRAM_AddressSet(unsigned char ucDDramAdd) *
//*函数功能:设定DDRAM(文本区)地址到地址计数器AC *
//*形式参数:unsigned char ucDDramAdd *
//*行参说明:具体地址 *
//*格式说明: *
//* RS RW DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 *
//* 0 0 1 AC6 AC5 AC4 AC3 AC2 AC1 AC0 *
//*返回参数:无 *
//*使用说明: *
//* 第一行地址:80H~8FH *
//* 第二行地址:90H~9FH *
//* 第三行地址:A0H~AFH *
//* 第四行地址:B0H~BFH *
//*************************************************************
void DDRAM_AddressSet(unsigned char ucDDramAdd)
{
Write(COMMAND,BASIC_FUNCTION); //基本指令集
Write(COMMAND,ucDDramAdd); //设定DDRAM地址到地址计数器AC
}
//*************************************************************
//*函数名称:void LCD_CGRAM_AddressSet(unsigned char ucCGramAdd) *
//*函数功能:设定CGRAM(自定义字库区)地址到地址计数器AC *
//*形式参数:unsigned char ucCGramAdd *
//*形参说明:具体地址 *
//*格式说明: *
//* RS RW DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 *
//* 0 0 0 1 AC5 AC4 AC3 AC2 AC1 AC0 *
//*返回参数:无 *
//*使用说明:地址范围为40H~3FH *
//*************************************************************
void CGRAM_AddressSet(unsigned char ucCGramAdd)
{
Write(COMMAND,BASIC_FUNCTION); //基本指令集
Write(COMMAND,ucCGramAdd); //设定CGRAM地址到地址计数器AC
}
//*******************************************************************************
//*函数名称:void LCD_GDRAM_AddressSet(unsigned char ucGDramAdd) *
//*函数功能:设定GDRAM(图形区)地址到地址计数器AC *
//*形式参数:unsigned char ucGDramAdd *
//*形参说明:具体地址值 *
//* RS RW DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 *
//* 0 0 1 AC6 AC5 AC4 AC3 AC2 AC1 AC0 *
//* 先设定垂直位置再设定水平位置(连续写入两个字节完成垂直和水平位置的设置) *
//* 垂直地址范围:AC6~AC0 *
//* 水平地址范围:AC3~AC0 *
//*返回参数:无 *
//*使用说明:必须在扩展指令集的情况下使用 *
//*******************************************************************************
void GDRAM_AddressSet(unsigned char ucGDramAdd)
{
Write(COMMAND,EXTEND_FUNCTION); //扩展指令集
Write(COMMAND,ucGDramAdd);
}
//*******************************************
//*函数名称:void LCD_Init(void) *
//*函数功能:并行初始化LCD *
//*形式参数:无 *
//*形参说明:无 *
//*返回参数:无 *
//*使用说明:无 *
//*******************************************
void Init(void)
{
CTRL_OUT();
Write(COMMAND,BASIC_FUNCTION); //基本指令动作
delay50us();
Write(COMMAND,CLEAR_SCREEN); //清屏,地址指针指向00H
delay50us();
Write(COMMAND,0x06); //光标的移动方向
delay50us();
Write(COMMAND,0x0C); //开显示,关游标
}
//********************************************************
//*函数名称:void LCD_ClearRam(void) *
//*函数功能:并行清屏函数 *
//*形式参数:无 *
//*形参说明:无 *
//*返回参数:无 *
//*使用说明:DDRAM填满20H,并设定DDRAM AC到00H *
//*格式说明: *
//* RS RW DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 *
//* 0 0 0 0 0 0 0 0 0 1 *
//********************************************************
void ClearRam(void)
{
Write(COMMAND,BASIC_FUNCTION); //基本指令集
Write(COMMAND,CLEAR_SCREEN); //清屏
}
//*****************************************************
//*函数名称:void LCD_GraphModeSet(unsigned char bSelect) *
//*函数功能:打开或关闭绘图显示 *
//*形式参数:unsigned char Select *
//*形参说明:打开或关闭绘图显示的标志位,1打开,0关闭 *
//*格式说明: *
//* RS RW DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 *
//* 0 0 0 0 1 1 X RE G X *
//* *
//* RE:0,基本指令集 *
//* RE:1,扩充指令集 *
//* G :0,绘图显示OFF *
//* G :1,绘图显示ON *
//*返回参数:无 *
//*使用说明:无 *
//*****************************************************
void GraphModeSet(unsigned char Select)
{
Write(COMMAND,EXTEND_FUNCTION); //扩展指令集
if(Select==1)
{
Write(COMMAND,GRAPH_ON); //打开绘图模式
}
else
{
Write(COMMAND,GRAPH_OFF); //关闭绘图模式
}
}
//*********************************************************************************
//*函数名称:void LCD_DisplayStrings_WithAddress(unsigned char ucAdd,unsigned char code *p) *
//*函数功能:在(文本区)ucAdd指定的位置显示一串字符(或是汉字或是ASCII或是两者混合) *
//*形式参数:unsigned char ucAdd,unsigned char code *p *
//*形参说明:指定的位置,要显示的字符串 *
//*地址必须是:80H~87H,90H~97H,88H~8FH,98H~8FH *
//*返回参数:无 *
//*使用说明:使用之前要初始化液晶 *
//*********************************************************************************
void DisplayStrings_WithAddress(unsigned char ucAdd,const char *p)
{
unsigned char length;
length = strlen(p);
Write(COMMAND,BASIC_FUNCTION); //基本指令动作
DDRAM_AddressSet(ucAdd);
for( ; length ; length -- )
Write(DATA, *(p++));
}
//*********************************************************************************
//*函数名称:void LCD_DisplayChinese(unsigned char x,unsigned char y,unsigned char code *p) *
//*函数功能:在(文本区)ucAdd指定的位置显示一串字符(或是汉字或是ASCII或是两者混合) *
//*形式参数:unsigned char x,unsigned char y,const char *p *
//*形参说明:指定的位置,要显示的字符串 *
//*地址必须是: x<8, y<4 *
//*返回参数:无 *
//*使用说明:使用之前要初始化液晶 *
//*********************************************************************************
void DisplayChinese(unsigned char x,unsigned char y,const char *p)
{
unsigned char length,addr;
y &= 0x03; //y < 4
x &= 0x07; //x < 8
switch( y )
{
case 0:
addr = 0x80;
break;
case 1:
addr = 0x90;
break;
case 2:
addr = 0x88;
break;
case 3:
addr = 0x98;
break;
}
addr += x;
length = strlen(p);
Write(COMMAND,BASIC_FUNCTION); //基本指令动作
DDRAM_AddressSet(addr);
for( ; length ; length -- )
Write(DATA, *(p++));
}
//*********************************************************************************
//*函数名称:void LCD_DisplayStrings(unsigned char x,unsigned char y,unsigned char code *p) *
//*函数功能:在(文本区)ucAdd指定的位置显示一串ASCII *
//*形式参数:unsigned char x,unsigned char y,const char *p *
//*形参说明:指定的位置,要显示的字符串 *
//*地址必须是: x<16, y<4 *
//*返回参数:无 *
//*使用说明:使用之前要初始化液晶 *
//*********************************************************************************
void DisplayStrings(unsigned char x,unsigned char y,const char *p)
{
unsigned char length,addr;
unsigned char AddrEO; //x地址是奇偶
unsigned char Data1;
y &= 0x03; //y < 4
x &= 0x0F; //x < 16
switch( y )
{
case 0:
addr = 0x80;
break;
case 1:
addr = 0x90;
break;
case 2:
addr = 0x88;
break;
case 3:
addr = 0x98;
break;
}
addr += x/2;
AddrEO = x&0x01;
length = strlen(p);
Write(COMMAND,BASIC_FUNCTION); //基本指令动作
DDRAM_AddressSet(addr);
if(AddrEO == 0x01)
{
Data1 = ReadData();
DDRAM_AddressSet(addr);
Write(DATA, Data1);
}
for( ; length ; length -- )
Write(DATA, *(p++));
}
//*********************************************************************
//*函数名称:void LCD_ImgDisplay(unsigned char code *img) *
//*函数功能:全屏显示128*64个象素的图形 *
//*形式参数:unsigned char code *img *
//*形参说明:要显示的图形 *
//*液晶屏坐标说明: *
//* ________________128个像素______________________ *
//* |(0,0) (7,0)| *
//* | | *
//* 64 | | *
//* 个 |(0,31) (7,31)| *
//* 像 |(8,0) (15,0)| *
//* 素 | | *
//* | | *
//* |(8,31) (15,31)| *
//* |______________________________________________| *
//* *
//返回参数:无 *
//使用说明:此函数适用于CM12864-12型液晶 *
//*********************************************************************
void ImgDisplay(unsigned char *img)
{
unsigned char i,j;
GraphModeSet(0); //先关闭图形显示功能
for(j=0;j<32;j++)
{
for(i=0;i<8;i++)
{
Write(COMMAND,0x80+j); //设定垂直坐标
Write(COMMAND,0x80+i); //设定水平坐标
Write(DATA,img[j*16+i*2]); //放入数据高字节
Write(DATA,img[j*16+i*2+1]); //放入数据低字节
}
}
for(j=32;j<64;j++)
{
for(i=0;i<8;i++)
{
Write(COMMAND,0x80+j-32);
Write(COMMAND,0x88+i);
Write(DATA,img[j*16+i*2]);
Write(DATA,img[j*16+i*2+1]);
}
}
GraphModeSet(1);//最后打开图形显示功能
}
//*******************************************
//*函数名称:LCD_DisplayCLR *
//*函数功能:清除显示的内容 *
//*形式参数:无 *
//*形参说明:无 *
//*返回参数:无 *
//*使用说明:无 *
//*******************************************
void DisplayCLR()
{
unsigned char i,j;
GraphModeSet(0); //先关闭图形显示功能
for(j=0;j<32;j++)
{
for(i=0;i<8;i++)
{
Write(COMMAND,0x80+j); //设定垂直坐标
Write(COMMAND,0x80+i); //设定水平坐标
Write(DATA,0x00); //放入数据高字节
Write(DATA,0x00); //放入数据低字节
}
}
for(j=32;j<64;j++)
{
for(i=0;i<8;i++)
{
Write(COMMAND,0x80+j-32);
Write(COMMAND,0x88+i);
Write(DATA,0x00);
Write(DATA,0x00);
}
}
GraphModeSet(1);//最后打开图形显示功能
}
//******************************************************************************
//*函数名称:void LCD_ImgDisplayCharacter(unsigned char x,unsigned char y,unsigned char code *img) *
//*函数功能:使用绘图的方法,在(x,y)处画一个16*16点阵的图案,也可以是字符 *
//*形式参数:unsigned char x,unsigned char y,unsigned char code *img *
//* x取值范围:0~7 *
//* y取值范围:0~31 (针对CM12864-12型液晶) *
//*形参说明:坐标水平位置,坐标垂直位置,要显示的图形 *
//*液晶屏坐标说明: *
//* ________________128个像素______________________ *
//* |(0,0) (7,0)| *
//* | | *
//* 64 | | *
//* 个 |(0,31) (7,31)| *
//* 像 |(8,0) (15,0)| *
//* 素 | | *
//* | | *
//* |(8,31) (15,31)| *
//* |______________________________________________| *
//* *
//*返回参数:无 *
//*使用说明:此函数适用于CM12864-12型液晶 *
//******************************************************************************
void ImgDisplayCharacter(unsigned char x,unsigned char y,unsigned char *img)
{
unsigned char i;
GraphModeSet(0); //先关闭图形显示功能
Write(COMMAND,EXTEND_FUNCTION);
for(i=0;i<16;i++)
{
GDRAM_AddressSet(0x80+y+i);
GDRAM_AddressSet(0x80+x);
Write(DATA,img[i*2]);
Write(DATA,img[i*2+1]);
}
GraphModeSet(1); //最后打开图形显示功能
}
//******************************************************************************
//*函数名称:set_xy12864(unsigned char y,unsigned char x,unsigned colour) *
//*函数功能:在指定位置上画点。 *
//*形式参数:unsigned char x,unsigned char y,unsigned char color *
//* x取值范围:0~127 *
//* y取值范围:0~63 (针对CM12864-12型液晶) *
//*形参说明:坐标水平位置,坐标垂直位置 *
//*液晶屏坐标说明: *
//* ________________128个像素______________________ *
//* |(0,0) (7,0)| *
//* | | *
//* 64 | | *
//* 个 |(0,31) (7,31)| *
//* 像 |(8,0) (15,0)| *
//* 素 | | *
//* | | *
//* |(8,31) (15,31)| *
//* |______________________________________________| *
//* *
//*返回参数:无 *
//*使用说明:此函数适用于CM12864-12型液晶 *
//******************************************************************************
void set_xy12864(unsigned char x,unsigned char y ) //在任意位置画点 输入范围x 0-127
{
unsigned char row,tier,tier_y,Gram_old_1,Gram_old_2; // y 0-63
Write(COMMAND,0x34);
Write(COMMAND,0x36);
tier= x>>16; ///16
tier_y=x&0x0f; //%16
if(y<32)
{
row=y;
}
else
{
row=y-32;
tier+=8;
}
Write(COMMAND,row+0x80); //写行地址
Write(COMMAND,tier+0x80); //写列地址
ReadData(); //当前地址读,第一次虚读
Gram_old_1=ReadData(); //连续读两次
Gram_old_2=ReadData();
Write(COMMAND,row+0x80); //写行地址
Write(COMMAND,tier+0x80); //写列地址
if(tier_y<8)
{
Write(DATA,Gram_old_1|(0x01<<(7-tier_y)));
Write(DATA,Gram_old_2);
}
else
{
Write(DATA,Gram_old_1);
Write(DATA,Gram_old_2|(0x01<<(15-tier_y)));
}
Write(COMMAND,0x30);
}
int main()
{
uchar i;
Init(); //液晶屏初始化
ClearRam(); //清除显示存储区内的内容
DisplayCLR();
for(i=0;i<50;i++)
{
set_xy12864(i,20,1);
}
} |
|