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

📄 scr.c

📁 这个rt12864的驱动是我自己摸索了很久才做出来的,因为这块液晶的真正权威的能参考的绘图资料真的是太少了,所以我上传上来,算是做点贡献吧
💻 C
字号:
#include <avr/io.h>
#include <util/delay.h>

//宏定义*********************************************************************************************

//端口A,只用低四位,根据需要改
#define Set_RData() DDRA=0xFB     //读(输入)
#define Set_WData() DDRA=0xFF     //写(输出)

#define LCD PORTA

//PA3  模组片选端 :高电平有效
#define cS_0() LCD&=0xF7            //PA3=1111-0111  模组片选端 :高电平有效
#define cS_1() LCD|=~0xF7

//PA2 串行数据端
#define SID_0() LCD&=0xFB           //PA2=1111-1011 串行数据输入端
#define SID_1() LCD|=~0xFB

//PA1 串行同步时钟,上升沿时读取SID数据
#define CLK_0() LCD&=0xFD           //PA1=1111-1101 串行同步时钟,上升沿时读取SID数据
#define CLK_1() LCD|=~0xFD

//PA0,液晶复位,低电平有效
#define RET_0() LCD&=0xFE           //PA0=1111-1110 低电平有效
#define RET_1() LCD|=~0xFE

//串行数据传送的第一个字节 ____ 串口控制
#define busy		0x80  //忙
#define _rdata_		0xFE  //读数据
#define _rcomm_		0xFC  //读指令 
#define _wdata_		0xFA  //写数据
#define _wcomm_		0xF8  //写指令

#define disp_star_line	0xc0		//显示起始行(后6位表示0-63行)
#define page_addr_set	0xB8		//页地址设置(后3位表示0~7页)
#define	col_addr_set	0x40		//列地址设置(后6位表示0-63列)	

//全局变量*****************************************************************************************
unsigned int count =0 ;

//向LCD发送一个字节******************************************************************************
 
 void sendbyte(unsigned char senddata)
  {
    int i=0,j=0;
	Set_WData();     //数据输出,DDRA=0XFF; 设置端口A为写(输出)
    cS_1();                   //模组片选端有效
    CLK_0();                  //时钟设低电平,以便产生上升沿
  
      for(i=0;i<8;i++)  //八位
      {
	     if(senddata&0x80)   //从高到低将数据传送到LCD,如果该位是1则SID置1,否则SID置0
		    SID_1();
	     else
		    SID_0();		
	     _delay_ms(0.0001);         //延时
	     CLK_1();            //上升沿读取SID数据写到LCD
	     senddata<<=1;       //数据左移一位
	     CLK_0();            //时钟设低电平
		  _delay_ms(0.0001);
      }
    cS_0();                  //片选无效
  }

//从LCD读一个字节**********************************************************************************
//参数 readtype 指明所要读的数据是"指令数据"还是"显示数据"

 unsigned char readByte(unsigned char readtype)
 {
  int i=0;
  Set_WData();                 //数据输出
  sendbyte(readtype);          //告诉LCD读什么样的数据
  cS_1();                      //模组片选端有效
  CLK_0();                     //低电平,以便产生上升沿
  //DDRA&=0xFB;                  // set SID(PA2) input,others ouput
  Set_RData();

  unsigned char temph=0,templ=0,temp=0;
  
  for(i=0;i<7;i++)       //读高四位
  {
	    CLK_1();              //上升沿,读一位
         _delay_ms(1);
	    if(PINA&0x04)
			temph=temph|1;
	    temph<<=1;            //存到temph中
		CLK_0();
		 _delay_ms(1);
  }
  CLK_1();              //上升沿,读一位
  CLK_0();
  
  for(i=0;i<7;i++)      //读低四位
  {
	   CLK_1();
        _delay_ms(1);
	   if(PINA&0x04)
		    templ=templ|1;
	   templ<<=1;            //存到templ中
	   CLK_0();
	    _delay_ms(1);
  }
  CLK_1();              //上升沿,读一位
  
  temp=(temph&0xf0)|((templ&0xf0)>>4);     //存到temp中
  Set_WData();                     // GPDIR 的CS,SID,SCLK为输出 
  cS_0();                                   //模组片选无效
  return(temp);
 }

//判断忙否,直到不忙才往下运行***********************************************************************

void busywait(void)
{
  unsigned char bf;
  do
  {
	bf=readByte(_rcomm_);      //读指令
  }
  while(bf&0x80);
}


//写入一个字节的命令******************************************************************************
//参数 command 指明所要写入LCD的命令

void wr_comm_lcd(unsigned char command)
{
  //busywait();                      //忙否
  sendbyte(_wcomm_);               //告诉LCD要写指令了
  sendbyte(command&0xf0);          //写指令的高四位
  sendbyte((command&0x0f)<<4);     //写指令的低四位
}

//写入一个字节的数据*****************************************************************************
//参数 wdata 指明所要发送的显示数据

void wr_data_lcd(unsigned char wdata)
{
  //busywait();                     //忙否
  sendbyte(_wdata_);              //告诉LCD要写数据了
  sendbyte(wdata&0xF0);           //写数据的高四位
  sendbyte((wdata&0x0F)<<4);     //写数据的低四位
}

//液晶屏幕初始化************************************************************************************

void init_lcd(void)
{
  RET_0();                      //复位 低电平有效
  _delay_ms(1);                //延时
  RET_1(); 
  Set_WData();                  //写(输出)
  wr_comm_lcd(0x30);            //功能设置,基本指令集动作
  _delay_ms(1);                //延时
  wr_comm_lcd(0x0c);            //显示状态ON,游标OFF,反白OFF
  _delay_ms(1);
  wr_comm_lcd(0x01);            //清除显示
  _delay_ms(1);
}


//清屏********************************************************************************************

void clear_lcd(void)
{
  wr_comm_lcd(0x01);            //清除显示
}

//光标定位************************************************************?************************
//x表示列,y表示行,(x<=8,y<=4)

void locate_xy(unsigned int x,unsigned int y)
{
  unsigned char addr;
  switch(y)
	{ 
	  /*水平方向X,以字节单位 垂直方向Y—以位为单位*/
	  case 0:addr=0x80+x%8;break; 
	  case 1:addr=0x90+x%8;break;
	  case 2:addr=0x88+x%8;break;
	  case 3:addr=0x98+x%8;break;
	  default:break;
	}
	wr_comm_lcd(addr);
}

//写一个字节到LCD******************************************************************************
//参数 word 指明要写的数据

void w_Char(unsigned char word)
{
    int x=0,y=0;
	y =count/8; 
	y= y%4;                  //得到行号
	x = count%8;             //得到列号
	
	if(y==0 && x==0)
    {    
	   clear_lcd();         //满屏则需清屏
	} 
    locate_xy(x,y);         //定光标位置
	wr_data_lcd(word);      //写数据到LCD
	//count++;
}

//显示一个中文字,进行两次写一字节的操作*******************************************************
//x是列号,y是行号,word1/word1是要发送中文的前/后一字节

void w_Word(unsigned int x,unsigned int y,unsigned char word1,unsigned char word2)
{
   locate_xy(x,y);            //定光标位置
   wr_data_lcd(word1);        //写前一字节
   wr_data_lcd(word2);        //写后一字节
}

//显示整个中文字符数组里的文字********************************************************************
//x,y为定位坐标,pstr为操作数组

void w_strword(unsigned int x,unsigned int y,unsigned char *pstr)
 {
    int i=0,j=0;
    unsigned int t=0;
    busywait();                         //忙否
    while(pstr[t]!='\0')t++;
  
    for(i=0;i<(t-1);i++)
	{  j=i;
	   i++;
	   w_Word(x,y,pstr[j],pstr[i]);
	   x++;
	   if(x==8)
		{
		    y+=1;                   //换行
	  	    x=0;                    //回车
		    if(y==4)
			{
			  y=0;           //已满屏
			}
		}
	}
 } 
 
void clear_panel()
{
  unsigned char yaddr=0x80;
  wr_comm_lcd(0x30);
  wr_comm_lcd(0x34);               
  for(int y=0;y<32;y++)
  {
    wr_comm_lcd(yaddr++);
	wr_comm_lcd(0x80);
	for(int x=0;x<16;x++)
	{
	  wr_data_lcd(0x00);
	}
  }
  yaddr=0x80;
  for(int y=0;y<32;y++)
  {
    wr_comm_lcd(yaddr++);
	wr_comm_lcd(0x88);
	for(int x=0;x<16;x++)
	{
	  wr_data_lcd(0x00);
	}
  }
  wr_comm_lcd(0x32);
  wr_comm_lcd(0x36);
  
}

//************---画点---******************************************** 
//图形点阵起始数组的地址
//画点(在液晶屏上任意一点)
//横坐标x0:0~127
//纵坐标y0:0~63
void draw_point(unsigned char x0,unsigned char y0)
{
	unsigned char c;//point_data;
	unsigned char page,colume,screen;
	wr_comm_lcd(0x30);
    wr_comm_lcd(0x34);
	if(y0>=32)
	   screen=0x88;
	else
	   screen=0x80;
	page=y0%32;
	wr_comm_lcd(page|0x80);
	wr_comm_lcd(screen); 
	//point_data=0;
	//point_data=readByte(_rdata_);
	if((page+1)%10==0) wr_data_lcd(0x2b);
	else wr_data_lcd(0x2a);
	wr_comm_lcd(0x32);
  wr_comm_lcd(0x36);
}
unsigned char templetrue=0;
void pixy()
{ 
  unsigned int count=5;
  wr_comm_lcd(0x30);
  wr_comm_lcd(0x34); 
  wr_comm_lcd(0x80|0);
  wr_comm_lcd(0x80); 
  wr_data_lcd(0x3f);
  wr_data_lcd(0x77);
   for(int i=1;i<32;i++)
   {  
      wr_comm_lcd(0x80|i);
      wr_comm_lcd(0x80);
	  if(i%10==0)
	  {
	     wr_data_lcd(0x23);
	  }
	  else
         wr_data_lcd(0x22);
	  switch(i)
		{
		  case 1: wr_data_lcd(0x45);break;
		  case 2: wr_data_lcd(0x75);break;
		  case 3: wr_data_lcd(0x55);break;
		  case 4: wr_data_lcd(0x77);break;
		  case 10: wr_data_lcd(0x77);break;
		  case 11: wr_data_lcd(0x45);break;
		  case 12: wr_data_lcd(0x75);break;
		  case 13: wr_data_lcd(0x15);break;
		  case 14: wr_data_lcd(0x77);break;
		  case 20: wr_data_lcd(0x57);break;
		  case 21: wr_data_lcd(0x55);break;
		  case 22: wr_data_lcd(0x55);break;
		  case 23: wr_data_lcd(0x75);break;
		  case 24: wr_data_lcd(0x17);break;
		  case 30: wr_data_lcd(0x77);break;
		  case 31: wr_data_lcd(0x15);break;
		  default: break;
		}
   }
   for(int i=0;i<31;i++)
   {  
      wr_comm_lcd(0x80|i);
      wr_comm_lcd(0x88);
      if((i+1)%10==0)
	     wr_data_lcd(0x23);
	  else if(i>29) wr_data_lcd(0x3e);
	  else
         wr_data_lcd(0x22);
	  switch(i)
		{
		  case 0: wr_data_lcd(0x75);break;
		  case 1: wr_data_lcd(0x15);break;
		  case 2: wr_data_lcd(0x77);break;
		  case 8: wr_data_lcd(0x77);break;
		  case 9: wr_data_lcd(0x15);break;
		  case 10: wr_data_lcd(0x75);break;
		  case 11: wr_data_lcd(0x45);break;
		  case 12: wr_data_lcd(0x77);break;
		  case 18: wr_data_lcd(0x17);break;
		  case 19: wr_data_lcd(0x15);break;
		  case 20: wr_data_lcd(0x15);break;
		  case 21: wr_data_lcd(0x15);break;
		  case 22: wr_data_lcd(0x17);break;
		  case 27: wr_data_lcd(0x07);break;
		  case 28: wr_data_lcd(0x05);break;
		  case 29: wr_data_lcd(0x05);break;
		  case 30: wr_data_lcd(0x05);break;
		  default: break;
		}
   }
   wr_comm_lcd(0x80|31);
   wr_comm_lcd(0x88);
   wr_data_lcd(0x3e);
   wr_data_lcd(0x07);
   wr_comm_lcd(0x32);
  wr_comm_lcd(0x36);
}

void write_Int(unsigned char t)
{
   if(t/10!=0)
      wr_data_lcd(t/10+48);
   wr_data_lcd(t%10+48);
}

void disp_lcd()
{ int j;
  pixy();                   //
wr_comm_lcd(0x02);
if(templetrue<=29)
{
   for(j=29;j>=29-templetrue;j--)
   {
      draw_point(0,j+32);
   }
}
else
{  
   for(j=29;j>=0;j--)
   {
      draw_point(0,j+32);
   }
   for(j=31;j>=29-templetrue+31;j--)
   {
      draw_point(0,j);
   }
}
wr_comm_lcd(0x30);
w_strword(2,0,"单位:摄氏度");
w_strword(2,1,"版本号");
wr_data_lcd(':');
wr_data_lcd('1');
w_strword(2,3,"温度");
write_Int(templetrue);
wr_comm_lcd(0x36);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -