⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lcd.c

📁 该程序实现了LCD1602在AVR单片机上控制
💻 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 + -