#include <ioavr.h> #include <ina90.h> #define uchar unsigned char #define LCD_PORT PORTA #define LCD_DDR DDRA #define LCD_PIN PINA #define LCD_DATA ((1<<0)|(1<<1)|(1<<2)|(1<<3)) #define EN_SET PORTC|=(1<<6);//en拉高 #define EN_CLR PORTC&=~(1<<6);//en拉低 #define RS_SET PORTC|=(1<<4); #define RS_CLR PORTC&=~(1<<4); #define RW_SET PORTC|=(1<<5); #define RW_CLR PORTC&=~(1<<5); #define SETBIT(x,y) (x|=(1<<y)) //set bit y in byte x #define CLRBIT(x,y) (x&=(~(1<<y))) //clear bit y in byte xx void DelayUs(unsigned char us)//delay us { unsigned char uscnt; uscnt=us>>1;/* Crystal frequency in 12MHz*/ while(--uscnt); } //<<<<<<<<<<<<<<<<<<<<LCD检查忙程序>>>>>>>>>>>>>>>>>>>>>> void LCD_Check_busy(void) { RS_CLR; RW_SET; LCD_DDR = 0x00; _NOP(); EN_SET; while(LCD_PIN & 0x08) { ; } EN_CLR; LCD_DDR = 0xff; } //-------------------------------------------------------------------------------- //-------------------------------------------------------------------------------- //设置所需函数 //写数据线命令(四线模式数据要分两次写) void out_dataline(uchar dat) { DelayUs(10000);// LCD_Check_busy(); LCD_PORT &= 0x0F; LCD_PORT |= dat&0xF0; //写高四位数据 EN_SET;//SETBIT(LCD_PORT, EN); //EN=1 _NOP(); EN_CLR;//CLRBIT(LCD_PORT, EN); //EN=0 _NOP(); LCD_PORT &= 0x0F; LCD_PORT |= (dat<<4)&0xF0; //写高四位数据 EN_SET;//SETBIT(LCD_PORT, EN); //EN=1 _NOP(); EN_CLR;//CLRBIT(LCD_PORT, EN); //EN=0 } //一、写指令函数 void write_command(unsigned char com) { DelayUs(10000);// LCD_Check_busy(); RS_CLR;//CLRBIT(LCD_PORT, RS); //RS=0 out_dataline(com); } //二、写数据函数(四线模式数据要分两次写) void write_data(unsigned char data) { DelayUs(10000);// LCD_Check_busy(); RS_SET;//SETBIT(LCD_PORT, RS); //RS=1 out_dataline(data); } //三、初始化LCD1602函数 void LCD_init(void) { LCD_DDR = 0xFF; //设为输出 DDRC=0XFF; RW_CLR;//CLRBIT(LCD_PORT, RW); //设为永远W状态 write_command(0x28); DelayUs(100000); write_command(0x0D); DelayUs(1000000); write_command(0x01); //显示开--对应开关显示控制指令 DelayUs(10000); write_command(0x06); //清屏--对应清屏指令 } //四、写地址函数 //-------------------------------------------------------------------------------- //要显示字符时要先输入显示字符地址,也就是告诉模块在哪里显示字符 //1602液晶内部显示地址 //比如第二行第一个字符的地址是40H,那么是否直接写入40H就可以将光标定位在第二行第一个字符的位置呢? //这样不行,因为写入显示地址时要求最高位D7恒定为高电平1所以实际写入的数据应该? //?1000000B(40H)+10000000B(80H)=11000000B(C0H) //-------------------------------------------------------------------------------- void LCD_set_addr(unsigned char x, unsigned char y) //x:0~15,y:0~1 { if(y) { write_command(0xc0 + x); //第二行显示 } else { write_command(0x80 + x); //第一行显示 } } //五、写字符函数 void LCD_write_char(unsigned char X, unsigned char Y, unsigned char data) //列x=0~15,行y=0,1 { LCD_set_addr(X, Y); //写地址 write_data(data); } //六、写字符串函数 void LCD_write_string(unsigned char X, unsigned char Y, unsigned char* s) //列x=0~15,行y=0,1 { LCD_set_addr(X, Y); //写地址 while(*s) // 写显示字符 { write_data(*s); s ++; } }