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

📄 keylcd.c

📁 我学习AVR的代码例子
💻 C
字号:
/*
硬件连接
PS/2  1-----INT1   数据
PS/2  5-----INT0   时钟
PS/2  3-----GND
PS/2  4-----VCC
      
     4 。
   2。   6 。
   1。   5 。
      3。
*/
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/signal.h>
#include <avr/interrupt.h>

//#include "t1.h"
#include "keycode.h"          //PS/2键盘译码表
#include "ASC.h"
#include "GB16.h"
#include "GB24.h"
#include "scancodes.h"

#define PIN_DIR DDRD 
#define PIN_KB  PIND
#define PORT_KB PORTD
#define CLOCK   2
#define DATAPIN 3
#define LOBYTE(a) ((BYTE)(a))
#define HIBYTE(a) ((BYTE)((a)>>8))

typedef unsigned char BYTE;
typedef unsigned int WORD;
typedef unsigned long DWORD;
//#define SEI() asm volatile("sei"::)
//#define XTAL 6

volatile BYTE count=0,num=9,shu=0;  
volatile BYTE Int_Number;            //中断计数器;
volatile BYTE Key_Value,Key_Value1;             //键盘编码值;
volatile BYTE Key_Up;               //键盘被释放标志;
volatile BYTE Byte_Flag=0;           //键盘编码接收完成标志;
volatile BYTE tmp[2];
volatile unsigned char shift=0,up=0,shiftup,E0=0;
volatile char cur_x=20,cur_y=15;


void delay_us(int time)//微秒级延时程序
 {     
   do
   {
       time--;
   }	
   while (time>1);
 }	   
void delay_ms(unsigned int time)//毫秒级延时程序
 {
   while(time!=0)
	 {
	   delay_us(1000);
	   time--;
	 }
 }

//***************************外部中断1初试化***************//
void INT_Init(void)
{
  MCUCR=MCUCR&0xfc;       //INT0低电平中断
  GICR=GICR|0x40;       //INT0中断使能
  SREG=SREG|0x40;         //全局中断使能
}
/*
void WC(BYTE comm)  //write command
{
  PORTB|=(1<<PB7); //A0
  PORTB|=(1<<PB5); //RD
  PORTA=comm;
  PORTB&=~(1<<PB4); //WD
  
  PORTB|=(1<<PB4); //WD
}
*/
void W_comm(BYTE COMMAND)
{
  PORTB|=(1<<PB5); //RD
  PORTA=COMMAND;
  PORTB|=(1<<PB7); //A0
  PORTB&=~(1<<PB4);//WD
  asm volatile("nop"::);
  PORTB|=(1<<PB4); //WD
  PORTB&=~(1<<PB7); //A0
}
/*
void WD_WC(BYTE code) //write data and command paramete
{
  PORTB&=~(1<<PB7); //A0
  PORTB|=(1<<PB5); //RD
  PORTA=code;
  PORTB&=~(1<<PB4); //WD
  
  PORTB|=(1<<PB4); //WD
}
*/
void W_code(BYTE code)
{
  PORTA=code;
  PORTB&=~(1<<PB7); //A0
  PORTB|=(1<<PB5); //RD
  PORTB&=~(1<<PB4); //WD
  asm volatile("nop"::);
  PORTB|=(1<<PB4); //WD
}

void init_devices(void)
{
 PORTB = 0x00;
 DDRB  = 0xFF; 
 PORTA = 0xFF;//FB
 DDRA  = 0xFF;
 DDRD=0x00;
 PORTD=0xFF;
}

void initLCD(void)
{
  init_devices();     
  PORTB&=~(1<<6);     //   /cs -> 0
  W_comm(0x40);//SYSTEM SET
  W_code(0x30);//P1
  W_code(0x87);//P2
  W_code(0x07);//P3
  W_code(0x27);//p4  
  W_code(0x49);//p5
  W_code(0xf0);//P6 
  W_code(0x28);//p7
  W_code(0x00);//p8
  
  W_comm(0x44);//SCROLL
  W_code(0x00);//P1
  W_code(0x00);//P2
  W_code(0xf1);//P3
  W_code(0xB0);//P4
  W_code(0x04);//P5
  W_code(0xf1);//P6
  W_code(0x00);//P7
  W_code(0x00);//P8
  //W_code(0x00);//P9
  //W_code(0x00);//P10
  
  W_comm(0x5d);//CSR FORM
  W_code(0x07);
  W_code(0x07);                              
  W_comm(0x5a);//HDOT SCR
  W_code(0x00);              
  W_comm(0x5b);//OVLAY
  W_code(0x00);
  //W_code(0x18);
  W_comm(0x59);//DISP ON 
  //W_code(0x54);//无光标 
  W_code(0x56); //有光标                     
}

void clear1(void)
{
 unsigned int i;
  i=0x4b0;
  W_comm(0x4c);
  W_comm(0x46);
  W_code(0x00);
  W_code(0x00);
  W_comm(0x42);
  do{ 
    W_code(0xa0);
    i--;
	}
  while(i>0);
}

void clear2(void)
{
 unsigned int j;
  j=0x2580;
  W_comm(0x4c);
  W_comm(0x46);
  W_code(0xB0);
  W_code(0x04);
  W_comm(0x42);
  do{ 
    W_code(0x00);
    j--;
    }
  while(j>0);
}/*
void clear3(void)
{
 unsigned int j;
  j=0x2580;
  W_comm(0x4c);
  W_comm(0x46);
  W_code(0x30);
  W_code(0x2a);
  W_comm(0x42);
  do{ 
    W_code(0x00);
    j--;
    }
  while(j>0);
}*/
void W_data(BYTE z)
{
  W_comm(0X42);
  W_code(z);
}

BYTE r_data(void)
{
  BYTE a;
  W_comm(0X43);
  DDRA=0x00;
  PORTB|=(1<<PB7); //A0
  PORTA=0xff;
  PORTB|=(1<<PB4); //WD
  PORTA=0xff;
  PORTB&=~(1<<PB5); //RD
  asm volatile("nop"::);
  a=PINA;
  PORTB|=(1<<PB5); //RD
  PORTA=0x00;
  DDRA=0xff;
  return(a);
}

void set_csr(void)//(char x,char y)
{
  WORD addr;
  if(cur_x<0 ||cur_x>41)
	{
		cur_x=39;
		cur_y-=1;
	}
	if(cur_y<0)
	{
		cur_y=0;
	}
	if(cur_x>=40)
	{ 
		cur_x-=40;
		cur_y+=1;
	}
	if(cur_y>=30)
	{
		//cur_y-=30;
		cur_y=0;
	}
  addr=cur_x+cur_y*40;//+0x4b0
  W_comm(0x4c);
  W_comm(0x46);
  W_code(LOBYTE(addr));
  W_code(HIBYTE(addr));
}

void set_pos(BYTE pos_x,BYTE pos_y)
{
  WORD addr;
  addr=pos_x+pos_y*40+0x4b0;
  W_comm(0x4c);
  W_comm(0x46);
  W_code(LOBYTE(addr));
  W_code(HIBYTE(addr));
}

WORD r_pos(void)
{
  BYTE tp=0;
  WORD ad=0;
  W_comm(0x4c);
  W_comm(0x47);
  DDRA=0x00;
  PORTB|=(1<<PB7); //A0
  PORTA=0xff;
  PORTB|=(1<<PB4); //WD
  PORTA=0xff;
  PORTB&=~(1<<PB5); //RD
  asm volatile("nop"::);
  tp=PINA;
  PORTB|=(1<<PB5); //RD
  
  PORTB&=~(1<<PB5); //RD
  asm volatile("nop"::);
  ad = (WORD)(PINA);
  ad<<=8;
  ad|=tp;
  PORTB|=(1<<PB5); //RD
  
  PORTA=0x00;
  DDRA=0xff;
  return(ad);
}

unsigned char printf_16(unsigned char x,unsigned char y, char *ptr)
{
    unsigned char c1,c2,i=0,j,k,uLen=0;
    while (ptr[uLen]!=0) //探测字串长度
    {
        uLen++;
    }	
    while(i<uLen)
    {
	    set_pos(x++,y);
		if(x>39) {x=0;y+=16;set_pos(x,y);}
    	c1 = ptr[i];
    	c2 = ptr[i+1];
        //ascii字符与汉字内码的区别在于128做分界,大于界线的为汉字码
    	if(c1 <=128)	// ASCII
      	{
            for(j=0;j<16;j++) //写16行
            {
				W_comm(0X42);    			// 写数据(命令)
				if (c1 >= 0x20)
				{
            	    W_code(pgm_read_byte(ASC+(c1-0x20)*16+j)); 
				}
				else
				{
					W_code(0);
				}
				set_pos(x,y+1+j);
            }	
        }
    	else    	// 中文
      	{
            for(j=0;j<sizeof(GB16_Index)/sizeof(GB16_Index[0]);j++)  	// 查找定位
            {
                if(c1 ==pgm_read_byte(GB16_Index+j*2) && c2 == pgm_read_byte(GB16_Index+j*2+1))
                {
                    break;
                }        				
            }
            for(k=0;k<16;k++)
            {
                set_pos(x,y+k);
				if(x>38) {x=0;y+=16;set_pos(x,y);}
				W_comm(0X42);      		// 写数据
				if(j < sizeof(GB16_Index)/sizeof(GB16_Index[0]))
				{
					W_code(pgm_read_byte(GB16_Msk+j*32+k*2));
					W_code(pgm_read_byte(GB16_Msk+j*32+k*2+1));
				}
				else   		// 未找到该字
				{
					if(k < 8)
            	    {
                        W_code(0x00);
						W_code(0x00);
            	     }
					else
            	    {
						W_code(0xff);
						W_code(0xff);
            	    }
                }
			}
			x++;
			i++;
      	};
    	i++;
    }
    return uLen;        //返回字串长度,汉字按2字节计算
} 

unsigned char printf_24(unsigned char x,unsigned char y, char *ptr)
{
    unsigned char c1,c2,i=0,j,k,uLen=0;
    while (ptr[uLen]!=0) //探测字串长度
    {
        uLen++;
    }	
    while(i<uLen)
    {
	    set_pos(x++,y);
		if(x>39) {x=0;y+=16;set_pos(x,y);}
    	c1 = ptr[i];
    	c2 = ptr[i+1];
        //ascii字符与汉字内码的区别在于128做分界,大于界线的为汉字码
    	if(c1 <=128)	// ASCII
      	{
            for(j=0;j<24;j++) //写16行
            {
				W_comm(0X42);    			// 写数据(命令)
				if (c1 >= 0x20)
				{
            	    W_code(pgm_read_byte(ASC+(c1-0x20)*16+j)); 
				}
				else
				{
					W_code(0);
				}
				set_pos(x,y+1+j);
            }	
        }
    	else    	// 中文
      	{
            for(j=0;j<sizeof(GB24_Index)/sizeof(GB24_Index[0]);j++)  	// 查找定位
            {
                if(c1 ==pgm_read_byte(GB24_Index+j*2) && c2 == pgm_read_byte(GB24_Index+j*2+1))
                {
                    break;
                }        				
            }
            for(k=0;k<24;k++)
            {
                set_pos(x,y+k);
				if(x>37) {x=0;y+=24;set_pos(x,y);}
				W_comm(0X42);      		// 写数据
				if(j < sizeof(GB24_Index)/sizeof(GB24_Index[0]))
				{
					W_code(pgm_read_byte(GB24_Msk+j*72+k*3));
					W_code(pgm_read_byte(GB24_Msk+j*72+k*3+1));
					W_code(pgm_read_byte(GB24_Msk+j*72+k*3+2));
				}
				else   		// 未找到该字
				{
					if(k < 8)
            	    {
                        W_code(0x00);
						W_code(0x00);
            	     }
					else
            	    {
						W_code(0xff);
						W_code(0xff);
            	    }
                }
			}
			x++;
			x++;
			i++;
      	};
    	i++;
    }
    return uLen;        //返回字串长度,汉字按2字节计算
} 

//再指定坐标(x,y)画点
void point(WORD px,WORD py,BYTE dshow)
{
  BYTE px1;
  volatile BYTE temp,temp1;
  px1=px/8;
  px=px & 0x0007;
  temp =(BYTE)(7-px);
  temp = 1<<temp;
  set_pos(px1,py);
  temp1=r_data();
  if(dshow)
    temp|=temp1;
  else
    temp=(~temp)&temp1;
  set_pos(px1,py);
  W_comm(0X42);
  W_code(temp);  //在屏上写一点
}

void Line(int x1, int y1, int x2, int y2, BYTE show) 
{
  int dy = y2 - y1;
  int dx = x2 - x1;
  int stepx, stepy, fraction;
  if (dy < 0) 
  {
    dy = -dy;
    stepy = -1;
  }
  else 
  {
    stepy = 1;
  }
  if (dx < 0)
  {
    dx = -dx;
    stepx = -1;
  }
  else
  {
    stepx = 1;
  }
  dy <<= 1;
  dx <<= 1;
  point(x1,y1,show);
  if (dx > dy)
  {
    fraction = dy - (dx >> 1); 
    while (x1 != x2)
    {
      if (fraction >= 0)
      {
        y1 += stepy;
        fraction -= dx;
      }
	  x1 += stepx;
      fraction += dy;
	  point(x1,y1,show);
    }
  }
  else
  {
    fraction = dx - (dy >> 1);
    while (y1 != y2)
    {
      if (fraction >= 0)
      {
        x1 += stepx;
        fraction -= dy;
      }
	  y1 += stepy;
      fraction += dx;
	  point(x1,y1,show);
    }
  }
}

void Circle(int x, int y, int radius, BYTE  show)
{
  int xc = 0;
  int yc = radius;
  int p = 3 - (radius<<1);
  while (xc <= yc)  
  {
    point(x + xc, y + yc, show);
    point(x + xc, y - yc, show);
    point(x - xc, y + yc, show);
    point(x - xc, y - yc, show);
    point(x + yc, y + xc, show);
    point(x + yc, y - xc, show);
    point(x - yc, y + xc, show);
    point(x - yc, y - xc, show);
    if (p < 0)
      p += (xc++ << 2) + 6;
    else
      p += ((xc++ - yc--)<<2) + 10;
  }
}

//***************************PS/2键盘译码******************//
void decode(unsigned char sc)
{
      unsigned char i;
	  if (sc==0xf0)
	      {
		   up=1;
		   E0=0;
		   return;
		  }
	  if (up==1)
	  	  {
		   up=0;
		   if ((sc==0x12)|(sc==0x59)) shift=0;
		   return;
		  }	/**/ 
	  if(sc==0xe1)
	  {
		printf_16(17,160,"PAUSE");	
	  }
	  if(sc==0xe0)
	  {
		E0=1;
		return;
	  }
	  if(E0==1)
	  {
		E0=0;
		switch (sc)
		{
			case 0x4A:
			{
				Key_Value1='/';
				break;
			}
			case 0x5a://KPEN
			{
				Key_Value1=13;
				break;
			}
			case 0x75:
			{
				cur_y-=1;
				set_csr();//(cur_x,cur_y)
				return;
			}
			case 0x7a:
			{
				cur_y+=10;
				set_csr();//(cur_x,cur_y)
				return;
			}
			default:
				return;
		}
		Byte_Flag=1;
		return;
	  }
	  switch (sc)
	    {
		 case 0x12:
		 {
			shift=1;
			//shiftup=1;
		 }		           
		 case 0x59:
		 {
			shift=1;
			//shiftup=1;
		 }		           
		 default:
		 {
		          if (shift==0)
				  {
					 for(i = 0;pgm_read_byte(unshifted+i*2)!=sc && pgm_read_byte(unshifted+i*2); i++);
                     if (pgm_read_byte(unshifted+i*2) == sc)
					 {
						  Key_Value1=pgm_read_byte(unshifted+i*2+1);
						  Byte_Flag=1;
					}
				  }
				  else
				     {
					 for(i = 0;pgm_read_byte(shifted+i*2)!=sc && pgm_read_byte(shifted+i*2); i++);
                     if (pgm_read_byte(shifted+i*2) == sc)
                         {
							Key_Value1=pgm_read_byte(shifted+i*2+1);
							Byte_Flag=1;	  
						 }	 	 						 
					 } 
		}		         
	} 		
}

//*****************************中断服务程序****************// 
/*#pragma interrupt_handler INT0_Handler:2
void INT0_Handler(void)*/
SIGNAL(SIG_INTERRUPT0)
{
  if (Int_Number==0)
	{
	   if (PIND&0x08)
	   {
	     Int_Number= 0;
		 while (!(PIND&0x04)); //等待PS/2CLK拉高
		 return;
	   }
	}
    if ((Int_Number > 0) && (Int_Number < 9))  //接受只有一字节通码字符
	{
	  Key_Value = Key_Value >> 1; //因键盘数据是低>>高,结合上一句所以右移一位
	  if (PIND&0x08) Key_Value = Key_Value|0x80;
	} //当键盘数据线为1时为1到最高位
	if(Int_Number==10)//收到第10个脉冲表示一字节传送完成
	{
	   if (!(PIND&0x08))
	   {
	     Int_Number= 0;
		 while (!(PIND&0x04)); //等待PS/2CLK拉高
		 return;
	   }
	   else
	   {
	     
		 Int_Number=0;
		 decode(Key_Value);
		 return;
	   }
	}
    while (!(PIND&0x04)); //等待PS/2CLK拉高
    Int_Number++;
}

int main(void)
{
	volatile WORD ii=0;
	BYTE tmp=10;                
	initLCD();
	clear1();
	clear2();
	//clear3();
	INT_Init();                //中断初始化
	sei();/*
	set_csr();//(0,0)
	W_data('3');
	W_data('5');
	W_data('6');
	W_data('7');
	printf_16(36,8,"ok中文yes测试");
	printf_16(1,1,"武 中");
	printf_16(36,24,"E_mail:qianwei_518@163.com");*/
	
	point(30,100,1);
	point(31,101,1);
	point(31,100,1);
	point(32,100,1);
	point(31,100,0);
	set_pos(10,5);
	printf_24(10,32,"电压");
	set_pos(10,8);
	W_comm(0x42);
	W_code(0x22);
	
	set_pos(10,8);
	ii=r_data();
	ii=r_data();
	cur_x=10;
	cur_y=10;
	set_csr();//(cur_x,cur_y)
	ii=r_pos();
	ii=r_pos();
	Line(10,10,50,80,1);
	Line(10,10,10,80,1);
	Line(10,10,50,10,1);
	Line(10,10,50,210,1);
	Line(10,20,10,30,0);
	//Circle(160, 120, 40,1);
	W_comm(0x4c);
    W_comm(0x46);
    W_code(0xff);
    W_code(0x2f);
	W_data(0xff);
	while(1)
	{
	    set_csr();
		if(Byte_Flag)            //检测到键盘输入
		{
		    //set_csr();
			Byte_Flag=0;            //清除检测标志
			if(Key_Value1==8)
			{
			    cur_x--;
				set_csr();//(--cur_x,cur_y);
				W_data(' ');
			}
			else if(Key_Value1==13)
			{
				cur_y+=1;
			}
			else
			{
				W_data(Key_Value1);
				cur_x++;
			}
		}
		if(tmp==50)
		{
		   tmp=10;
		   Circle(160, 120, 49,0);
		}
		else
		{
		   Circle(160, 120, tmp-1,0);
		   Circle(160, 120, tmp,1);
		   tmp++;
		}
		delay_ms(100);
	}
}


⌨️ 快捷键说明

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