📄 lcd.c
字号:
//ICC-AVR application builder : 2007-7-25 上午 11:46:23
// Target : M16
// Crystal: 1.0000Mhz
//PORTD为数据输出端,PORTB2,3, 4为指令端口
#include <iom16v.h>
#include <macros.h>
#define SET_LCD_E PORTB|=0x04 // LCD: E = 1,PB2
#define CLR_LCD_E PORTB&=~0x04 // LCD: E = 0,PB2
#define SET_LCD_RW PORTB|=0x08 // LCD: R/W = 1 (read),PB3
#define CLR_LCD_RW PORTB&=~0x08 // LCD: R/W = 0 (write),PB3
#define SET_LCD_RS PORTB|=0x16 // LCD: R/S = 1 (data reg),PB4
#define CLR_LCD_RS PORTB&=~0x16 // LCD: R/S = 0 (status reg),PB4
#define uchar unsigned char
#define uint unsigned int
#define DataPortfx DDRD //方向
#define Busy 0x80
#define LCM_Dataout PORTD // 输出数据,可以根据需要来改变端口设置
#define LCM_Datain PIND // 读入数据,可以根据需要来改变端口设置
unsigned char zifu;//全局变量,待显示字符编码
unsigned char huancun[16]={0};//显存数组
void ReadStatusLCM(void);//声明一边以后调用
void WriteDataLCM(unsigned char WDLCM);
void WriteCommandLCM(unsigned char WCLCM,unsigned char BuysC);
void delay5ms(void);
void delayms(unsigned int n);
void delay40us(void);
void port_init(void)
{
PORTA = 0x00;
DDRA = 0x00;
PORTB = 0x00;
DDRB = 0x00;
PORTC = 0x00; //m103 output only
DDRC = 0x00;
PORTD = 0x00;
DDRD = 0x00;
}
//call this routine to initialize all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
port_init();
MCUCR = 0x00;
GICR = 0x00;
TIMSK = 0x00; //timer interrupt sources
SEI(); //re-enable interrupts
//all peripherals are now initialized
}
#pragma data:code
unsigned char const dxzm[]={"@ABCDEFGHIJKLMNOPQRSTUVWXYZ"};//0x40-0x5a
unsigned char const dxzm1[]={0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,
0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0x53,
0x54,0x55,0x56,0x57,0x58,0x59,0x5a};
unsigned char const xxzm[]={"abcdefghijklmnopqrstuvwxyz"}; //0x61-0x7a
unsigned char const xxzm1[]={0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,
0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,
0x75,0x76,0x77,0x78,0x79,0x7a};
unsigned char const shuzi[]={"0123456789:;<=>?"};//0x30-0x3f,,,//0x21-0x2f
unsigned char const shuzi1[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,
0x3a,0x3b,0x3c,0x3d,0x3e,0x3f};
//unsigned char const kongzhizf[]={'!','"','#','$','%',''','(',')','*','+',',','-','.','/'};
//unsigned char const kongzhizf1[]={0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,
// 0x2a,0x2b,0x2c,0x2d,0x2e,0x2f};
unsigned char const cgramzf[]={
0x08,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02, //年,代码 0x00
0x0f,0x09,0x0f,0x09,0x0f,0x09,0x11,0x00, //月,代码 0x01
0x1f,0x11,0x11,0x1f,0x11,0x11,0x1f,0x00, //日,代码 0x02
0x11,0x0a,0x04,0x1f,0x04,0x1f,0x04,0x00, //$,代码 0x03
0x0e,0x00,0x1f,0x0a,0x0a,0x0a,0x13,0x00, //元,代码 0x04
0x18,0x18,0x07,0x08,0x08,0x08,0x07,0x00, //C,代码 0x05
0x04,0x0a,0x15,0x04,0x04,0x04,0x04,0x00, //^, 代码 0x06
0x17,0x15,0x15,0x15,0x15,0x15,0x17,0x00 //10, 代码 0x07
};
#pragma data:data
void CgramWrite(void)//装载自定义字符
{
uint i;
WriteCommandLCM(0x06,1); // 指针自动加1
WriteCommandLCM(0x40,1); // CGRAM地址设置:从零地址开始
for(i=0;i<64;i++)
{
WriteDataLCM(cgramzf[i]);
}
}
void zhonechar(uchar k)//k表示任意字符,此程序实现将字符转换为cgram地质马
{
uint i,j;
// if(k==0x32)
// {
// zifu=0x20;
//}
// else
// {
for(i=0;dxzm[i]!=0;i++)//chazhaodxzm
{
if(k==dxzm[i])
{
zifu=dxzm1[i];
break;
}
else
;
}
for(i=0;xxzm[i]!=0;i++)//chazhaoxxzm
{
if(k==xxzm[i])
{
zifu=xxzm1[i];
break;
}
else
;
}
for(i=0;shuzi[i]!=0;i++)//chazhaoshuji
{
if(k==shuzi[i])
{
zifu=shuzi1[i];
break;
}
else
;
}
/* for(i=0;kongzhizf[i]!='';i++)//chazhaokongzhizifu
{
if(k==kongzhizf[i])
{
zifu=kongzhizf1[i];
break;
}
else
;
}*/
//}
}
void zhlistchar(uchar *p) //转换一组数据
{
uint i=0;
if(*p)
{
zhonechar(*p);
huancun[i++]=zifu;//将转换后的编码放入显存
p++;
}
}
//写数据
void WriteDataLCM(unsigned char WDLCM)
{
DDRD=0xff;
ReadStatusLCM(); //检测忙
LCM_Dataout = WDLCM;
SET_LCD_RS;
CLR_LCD_RW;
asm("nop");
asm("nop");
CLR_LCD_E; //若晶振速度太高可以在这后加小的延时
asm("nop");
asm("nop");
SET_LCD_E;
asm("nop");//写函数下降元有效
asm("nop");
asm("nop");
CLR_LCD_E;
asm("nop");
//DDRA=0x00;
}
//写指令
void WriteCommandLCM(unsigned char WCLCM,unsigned char BuysC) //BuysC为0时忽略忙检测
{
DDRD=0xff;
if (BuysC)
ReadStatusLCM(); //根据需要检测忙
LCM_Dataout=WCLCM;
CLR_LCD_RS;
CLR_LCD_RW;
CLR_LCD_E;
asm("nop");
asm("nop");
SET_LCD_E;
asm("nop");
asm("nop");
asm("nop");
CLR_LCD_E;
asm("nop");
//DDRA=0x00;
delay40us();
}
//读数据
unsigned char ReadDataLCM(void)
{
unsigned char t;
DDRD=0x00;
SET_LCD_RS;
SET_LCD_RW;
asm("nop");
asm("nop");
CLR_LCD_E;
asm("nop");
asm("nop");
asm("nop");
SET_LCD_E;
asm("nop");
asm("nop");
asm("nop");
t=LCM_Datain;
CLR_LCD_E;
return(t);
}
//读状态
void ReadStatusLCM(void)
{
DDRD=0x00; //输入
CLR_LCD_RS;//为低读指令
SET_LCD_RW;
asm("nop");
asm("nop");
CLR_LCD_E;
asm("nop");
asm("nop");
SET_LCD_E;
asm("nop");
asm("nop");
asm("nop");
asm("nop");
while (LCM_Datain & Busy); //检测忙信号
CLR_LCD_E;
DDRD=0xff;
//变回输出
}
void LCMInit(void) //LCM初始化
{
LCM_Dataout = 0;
WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号
delay5ms();asm("nop");asm("nop");
WriteCommandLCM(0x38,0);//两行显示,5乘以7自付点阵;0x39则是一行显示5乘以10点阵
delay5ms();asm("nop");asm("nop");
WriteCommandLCM(0x38,0);
delay5ms();asm("nop");asm("nop");
WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号
asm("nop");
WriteCommandLCM(0x08,1); //关闭显示,光标,闪烁
asm("nop");
WriteCommandLCM(0x01,1); //显示清屏,即清ddram和ac值;0x02光标,画面回到初始位置
asm("nop");
WriteCommandLCM(0x06,1); // 显示光标移动设置,ac加1,画面不动
asm("nop");
WriteCommandLCM(0x0C,1); // 显示开及光标设置,显示开,光标,闪烁关
}
/*=======================================================
显示光标定位,ddram位置
=======================================================*/
void LocateXY( uchar posx,uchar posy)
{
uchar temp;
temp=posx&0xf;
posy&=0x1;
if(posy)temp|=0x40;
temp|=0x80;
WriteCommandLCM(temp,0);
}
/*=======================================================
按指定位置显示数出一个字符
=======================================================*/
/*void DisplayOneChar(uchar x,uchar y,uchar Wdata)
{
LocateXY(x,y); // 定位显示地址
WriteDataLCM(Wdata); // 写字符
}*/
//按指定位置显示一个字符
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
{
zhonechar(DData);
Y &= 0x1;
X &= 0xF; //限制X不能大于15,Y不能大于1
if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;
X |= 0x80; //算出指令码,指令最高位必须是1;
WriteCommandLCM(X, 0); //这里不检测忙信号,发送地址码
WriteDataLCM(zifu);
// WriteCommandLCM(X, 0); //光标返回,调节时很重要
}
/*=======================================================
显示字符串
=======================================================*/
void DisplayListChar(uchar x,uchar y,uchar *ptr )
{
uchar i,l=0;
y&=0x1;
x&=0xF;
while (ptr[l]>31)
{l++;}//统计字符串长度
for (i=0;i<l;i++)
{
DisplayOneChar(x++,y,ptr[i]);
if (x==16)
{
x=0;
y^=1;
}
}
}
//按指定位置显示一串字符
/*void DisplayListChar(unsigned char X, unsigned char Y, unsigned char const *DData)
{
unsigned char ListLength;
ListLength = 0;
Y &= 0x1;
X &= 0xF; //限制X不能大于15,Y不能大于1
while (DData[ListLength]>0x20) //若到达字串尾则退出
{
if (X <= 0xF) //X坐标应小于0xF
{
DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符
ListLength++;
X++;
}
}
}
*/
//5ms延时
void delay5ms(void)
{
unsigned int i=0;
while(i<8)
{
asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
i++;
}
}
//n ms延时
void delayms(unsigned int n)
{
unsigned int i;
for(i=0;i<n;i++)
delay5ms();
}
void delay40us(void)
{
asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
}
/*=======================================================
演示一行连续zifu
=======================================================*/
void Display( uchar dd )
{
uchar i;
for(i=0;i<16;i++)
{
DisplayOneChar(i,1,dd++);
dd&=0x7f;
if(dd<32)dd=32;
}
}
void main(void)
{
unsigned char i;
uchar j=0;
uchar char1[16]={"ILoveyou!"};
port_init();
DDRD=0XFF;//PA设为输出
DDRB=0XFF;//PB设为输出
delayms(95); //启动等待,等LCM讲入工作状态
LCMInit(); //LCM初始化
delay5ms(); //延时片刻(可不要)
WriteCommandLCM(0x38,1);//2 显示,5乘以7点阵
WriteCommandLCM(0x80,1); // 显示光标移动设置
//DisplayOneChar(0,0,'T');
//DisplayOneChar(1,0,'t');
//char1={"I Love you!"};
//DisplayListChar(3,0,char1);
CgramWrite(); //传送自定义字符
while(1)
{
DisplayOneChar(1,0,'2');
DisplayOneChar(2,0,'0');
DisplayOneChar(3,0,'0');
DisplayOneChar(4,0,'7');
LocateXY(5,0);
WriteDataLCM(0x00);
// delayms(300);
DisplayOneChar(7,0,'7');
LocateXY(8,0);
WriteDataLCM(0x01);
DisplayOneChar(9,0,'2');
DisplayOneChar(10,0,'6');
LocateXY(11,0);
WriteDataLCM(0x02);
LocateXY(6,1);
WriteDataLCM(0x32);
LocateXY(7,1);
WriteDataLCM(0x33);
DisplayOneChar(10,1,'2');
delayms(100);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -