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

📄 lcd.c~

📁 UCOS-II ATMEGA128 移殖
💻 C~
📖 第 1 页 / 共 2 页
字号:
#include <delay.h>
#include <ctype.h>
#include "lcd.h"
//#include "hz_db.h"
//#include "ascii_db.h"


/******************************************************************************************
 note : (for ACM12864I)
	
 XY地址计数器:
	九位计数器,头三位为X地址(页地址),后六位为Y地址
	地址X没有自动计数功能必须通过指令来设置	-	DDRAM的页指针  
	地址Y有自动计数功能数据写入后指针自动加1	-	DDRAM的Y地址指针
	
 显示数据RAM(DDRAM):
	存储图形显示数据,1 - 显示选择,0 - 显示非选择
	
 DDRAM地址与显示位置对照表:
		CS = 1			CS = 2
	Y=0  Y=1 ... Y=6  Y=7  Y=0  Y=1 ... Y=6  Y=7
	DB0  DB0     DB0  DB0  DB0  DB0     DB0  DB0
 X=0 	DB1  DB1     DB1  DB1  DB1  DB1     DB1  DB1
 		.....................
	DB7  DB7     DB7  DB7  DB7  DB7     DB7  DB7
 ...
 	DB0  DB0     DB0  DB0  DB0  DB0     DB0  DB0
 X=7 	DB1  DB1     DB1  DB1  DB1  DB1     DB1  DB1
 		.....................
	DB7  DB7     DB7  DB7  DB7  DB7     DB7  DB7

 Z地址记数器:
 	显示行扫描同步,显示屏幕的起始行(0~64)
 	
 指令集:
 	格式:R/W,D/I,DB7~DB0
 1.显示开关控制
 	00 0011-111x,x=1开,x=0关
 2.设置显示起始行
 	00 11xx-xxxx,xxxxxx自动送入Z地址记数器	-	0xc0~0xff
 3.设置页地址
 	00 1011-1xxx,复位后页地址为0		-	0xb8~0xbf
 4.设置Y地址
 	00 01xx-xxxx,自动增量			-	0x40~0x7f
 5.读状态(E信号此时为H状态)
 	10 B0DR-0000,B - 1:忙,0:空闲    D - 1:开显示,0:关显示   R - 1:初始化中,系统忙
 6.写显示数据
 	01 xxxx-xxxx
 7.读显示数据
 	11 xxxx-xxxx      	      
 硬件接口:
	A15---E  A14--- D/I  A13---CS1  A12---CS2  A11---R/W
	
 note	:	1.ACM12864的坐标系统定义如下:
 		  以平面直角坐标系的原点为圆心,逆时针旋转90度构成。从12864液晶平面的正面看,左上角
 		  为坐标原点,纵轴为横坐标(X),横轴为纵坐标(Y),范围:X - 0~64,Y - 0~128。实际上,
 		  X/8对应于页地址,Y/2对应于y地址。
 		2.从12864液晶平面的正面看,cs=1对应其右半部分平面,cs=2对应其左半部分平面
	
******************************************************************************************/

/******************************************************************************************
				全局宏定义
******************************************************************************************/
#define TRUE			1
#define FALSE			0

/*
	PC0		PC1		PC2		PC3		PC4		PC5		PC6		PC7
	 -		 -		 -		R/W		CS1		CS2		RS		 -
*/
#define LCD_DATA_WADDR		*(unsigned char *) 0xf000	//1111 0000,数据写地址-cs12
#define	LCD_DATA_WADDR1		*(unsigned char *) 0xd000	//1101 0000,数据写地址-cs1
#define LCD_DATA_RADDR1		*(unsigned char *) 0xd800	//1101 1000,数据读地址-cs1
#define LCD_DATA_WADDR2		*(unsigned char *) 0xe000	//1110 0000,数据写地址-cs2
#define LCD_DATA_RADDR2		*(unsigned char *) 0xe800	//1110 1000,数据读地址-cs2
#define LCD_INST_ADDR		*(unsigned char *) 0xb000	//1011 0000,指令写地址-cs12
#define	LCD_INST_ADDR1		*(unsigned char *) 0x9000	//1001 0000,指令写地址-cs1
#define	LCD_INST_ADDR2		*(unsigned char *) 0xa000	//1010 0000,指令写地址-cs2
#define LCD_STATE_R_ADDR	*(unsigned char *) 0xb800	//1011 1000,状态读地址-cs12
#define LCD_STATE_R_ADDR1	*(unsigned char *) 0x9800	//1001 1000,状态读地址-cs1
#define LCD_STATE_R_ADDR2	*(unsigned char *) 0xa800	//1010 1000,状态读地址-cs2
#define	LCD_OFF_COM		0x3e				//0011 1110,关显示
#define LCD_ON_COM		0x3f				//0011 1111,开显示
#define LCD_D_S_LINE		0xc0				//1100 0000,显示起始行
#define LCD_SET_D_LINE_COM(x)	LCD_D_S_LINE |(x)		//设置显示起始行
#define LCD_PAGE_ADDR		0xb8				//1011 1000,页地址
#define LCD_SET_PAGE_COM(x)	LCD_PAGE_ADDR|(x)		//设置页地址
#define LCD_Y_ADDR		0x40				//0100 0000,Y地址
#define LCD_SET_Y_COM(x)	LCD_Y_ADDR|(x)			//设置Y地址
#define detect_busy(x)	((((x)&0x80)||((x)&0x10))?1:0)		//1 - busy,0 - idle
#define detect_disp(x)	(((x)&0x20)?1:0)			//1 - disp,0 - off
#define chkbit(x,y)	((x)&(1<<y))				//位检测
#define setbit(x,y)	((x)|(1<<y))				//位设置
#define clrbit(x,y)	((x)&(~(1<<y)))				//位清除

/******************************************************************************************
				全局变量定义
******************************************************************************************/
//内部专用
//unsigned char Disp_buf[8][128];				//显示缓存
//bit Disp_buf_chg=0;						//标志显示是否需要刷新1-Y,0-N
typedef struct flash_data
{
	unsigned char x;					//坐标值(bit7活动位)
	unsigned char y;					//坐标值
	unsigned int code;					//汉字内码
	unsigned char mode;					//显示模式
}LCD_FLASH_DATA;
LCD_FLASH_DATA	Flash_data_buf[32];				//元素空间0~31
bit Flash_state;						//标志闪烁状态标志
bit Flash_state_ascii;

typedef struct flash_data_ascii
{
	unsigned char x; 					/*x bit7活动位,bit4~bit5显示模式*/
	unsigned char y;
	unsigned char code;
	unsigned char mode;
}LCD_FLASH_DATA_ASCII;
LCD_FLASH_DATA_ASCII Flash_data_buf_ascii[64];

//外部
unsigned char Lcd_flash_timer;					//闪烁频率

/******************************************************************************************
				绝对值
******************************************************************************************/
unsigned char abs_c(unsigned char x)
{
	if(x>0)
		return x;
	else	return -x;
}



/******************************************************************************************
				检测LCD忙状态
				
 return : TRUE - 忙,FALSE - 空闲
******************************************************************************************/
char Lcd_detect_busy(void)
{
	unsigned char state;
	
	state = LCD_STATE_R_ADDR;
//	putchar(state);
	return detect_busy(state);
}

/******************************************************************************************
				检测LCD显示是否已经打开
				
 return : TRUE - 打开状态,FALSE - 关闭状态
******************************************************************************************/
char Lcd_detect_disp(void)
{
	unsigned char state;
	
	state = LCD_STATE_R_ADDR;
	return detect_disp(state);
}

/******************************************************************************************
				开关LCD显示功能
******************************************************************************************/
void Lcd_turn_on(void)
{
	while(Lcd_detect_busy());
	LCD_INST_ADDR = LCD_ON_COM;	
}

void Lcd_turn_off(void)
{
	while(Lcd_detect_busy());
	LCD_INST_ADDR = LCD_OFF_COM;
}

/******************************************************************************************
				设置显示起始行
				
 in : line_num 显示起始行行号 0~63
******************************************************************************************/
void Lcd_set_start_line(unsigned char line_num)
{
	while(Lcd_detect_busy());
	LCD_INST_ADDR = LCD_SET_D_LINE_COM(line_num);
}

/******************************************************************************************
				设置页地址和Y地址
				
 in : addr_num		-	页地址 0~7,Y地址 0~63
      chip_num		-	芯片编号 1~2
      addr_type		-	地址类型 0 - 页地址,1 - Y地址, 2 - 行地址
******************************************************************************************/
void Lcd_set_addr(unsigned char addr_num,unsigned char chip_num,unsigned char addr_type)
{
	unsigned char op_code;
	
	if(addr_type == 0)
		op_code = LCD_SET_PAGE_COM(addr_num);
	else if(addr_type == 1)
		op_code = LCD_SET_Y_COM(addr_num);
	delay_us(10);
	if(chip_num == 1)
		LCD_INST_ADDR1 = op_code;
	else if(chip_num == 2)
		LCD_INST_ADDR2 = op_code;
}

/******************************************************************************************
				写入显示数据

 in : data	-	显示数据 0x00~0xff
      chip_num	-	芯片编号 1~2
******************************************************************************************/
void Lcd_write_data(unsigned char data,unsigned char chip_num)
{
	delay_us(10);
	if(chip_num == 1)
		LCD_DATA_WADDR1 = data;
	else if(chip_num ==2)
		LCD_DATA_WADDR2 = data;
}

/******************************************************************************************
				读显示数据
				
 in : chip_num	-	芯片编号
******************************************************************************************/
unsigned char Lcd_read_data(unsigned char chip_num)
{
	unsigned char data;
	
	delay_us(10);
	if(chip_num == 1)
		data = LCD_DATA_RADDR1;
	else if(chip_num ==2)
		data = LCD_DATA_RADDR2;
	return data;
}

/******************************************************************************************
				填充屏幕函数

 note : 1.以指定的数据填充整个屏幕
 	2.当data=0x00时,相当于清屏指令
 	  当data=0xff时,相当于黑屏指令
 in   : data	-	填充的数据
******************************************************************************************/
void Lcd_fill_scr(unsigned char data)
{
	unsigned char i,j;
	
	for(i=0;i<8;i++)
	{
		while(Lcd_detect_busy());
		LCD_INST_ADDR = LCD_SET_PAGE_COM(i);
		while(Lcd_detect_busy());
		LCD_INST_ADDR = LCD_SET_Y_COM(0);
		for(j=0;j<65;j++)
		{
			while(Lcd_detect_busy());
			LCD_DATA_WADDR = data;
		}
	}
}

/******************************************************************************************
				初始化
******************************************************************************************/
void Lcd_init(void)
{
	Lcd_turn_on();
	Lcd_fill_scr(0x00);	
} 

/******************************************************************************************
				显示汉字

 note	:	显示一个16X16大小的字符,详细说明参考Lcd_putsf()
 
 in	:	disp_data	-	显示汉字的内码
 		x		-	显示位置的横坐标0~7
 		y		-	显示位置的纵坐标0~127
 		mode		-	显示模式
 						0x0 : 正常模式
 						0x1 : 反显模式
 						0x4 :闪烁模式
 					注:显示模式可以组合 eg:0x00|0x01|0x04
******************************************************************************************/
void Lcd_disp_hz(unsigned int disp_data,unsigned char x,unsigned char y,unsigned char mode)
{
	unsigned char i,j,hz_pos,k=0;
	unsigned char tempc;
	unsigned char cs;
	unsigned char cs_bck=1;
	unsigned char draw_y;
        unsigned char xx,yy;
        
        xx = x;
        yy = y;
	
	for(hz_pos=0;hz_pos<Db_len;hz_pos++)
	{
		if(disp_data == Hz_16[hz_pos].index)
			break;
	}		
	if(hz_pos == Db_len)
		return;
	if(y>127)
		return;
	if(chkbit(x,7) == 0)
	{
		Lcd_flash_preproc(disp_data,x,y,mode);
		if(chkbit(mode,2))
			return;
	}
	else
	{
		x = clrbit(x,7);
	}
	if(y>63)
	{
		y -= 64;
		cs_bck = 2;
	}	
	for(i=0;i<2;i++)
	{
		draw_y = y;
		cs = cs_bck;
		x += i;
		if(x>7)
			break;
		Lcd_set_addr(x,cs,0);
		Lcd_set_addr(y,cs,1);
		for(j=0;j<16;j++)
		{
			tempc = Hz_16[hz_pos].data[k++];			
			if(chkbit(mode,0))
				tempc = ~tempc;
			Lcd_write_data(tempc,cs);
			draw_y++;
			if((draw_y > 63)&&(cs == 1))
			{
				cs = 2;
				Lcd_set_addr(x,cs,0);
				Lcd_set_addr(draw_y-64,cs,1);
			}
			else if((draw_y >63)&&(cs == 2)&&(cs_bck == 2))
			{
				k = 16;
				break;
			}
		}
	}
	
} 


/******************************************************************************************
				显示ASCII

 note	:	显示一个16X8大小的字符,详细说明参考Lcd_putsf()
 
 in	:	disp_data	-	ASCII码
 		x		-	显示位置的横坐标0~7
 		y		-	显示位置的纵坐标0~127
 		mode		-	显示模式
 						0x0 : 正常模式
 						0x1 : 反显模式
 						0x4 :闪烁模式
 					注:显示模式可以组合 eg:0x00|0x01|0x04
******************************************************************************************/
void Lcd_disp_ascii(unsigned char disp_data,unsigned char x,unsigned char y,unsigned char mode)
{
	unsigned char i,j,ascii_pos,k=0;
	unsigned char tempc;
	unsigned char cs;
	unsigned char cs_bck=1;
	unsigned char draw_y;
 	unsigned char xx,yy;
        
        xx = x;
        yy = y;

	if(y>127)
		return;
 	if(chkbit(x,7) == 0)
	{
		Lcd_flash_preproc_ascii(disp_data,x,y,mode);
		if(chkbit(mode,2))
			return;
	}
	else
	{
		x = clrbit(x,7);
	}
	if(y>63)
	{
		y -= 64;
		cs_bck = 2;
	}	
	for(i=0;i<2;i++)
	{
		draw_y = y;
		cs = cs_bck;
		x += i;
		if(x>7)
			break;
		Lcd_set_addr(x,cs,0);
		Lcd_set_addr(y,cs,1);
		for(j=0;j<8;j++)
		{
			tempc = Ascii_16[disp_data][k++];			
			if(chkbit(mode,0))
				tempc = ~tempc;
			Lcd_write_data(tempc,cs);
			draw_y++;
			if((draw_y > 63)&&(cs == 1))
			{
				cs = 2;
				Lcd_set_addr(x,cs,0);
				Lcd_set_addr(draw_y-64,cs,1);
			}
			else if((draw_y >63)&&(cs == 2)&&(cs_bck == 2))
			{
				k = 8;
				break;
			}
		}
	}
	
}

void Lcd_putsf_ascii(unsigned char flash *data_str,unsigned char x,unsigned char y,unsigned char mode)
{
	unsigned char data;
	while(*data_str)
	{
		data = toascii(*data_str++);
		if(y>120)
		{
			y = 0;
			x += 2;
		}
		if(x>6)
			continue;
		Lcd_disp_ascii(data,x,y,mode);
		y += 8;	
	}
}

void Lcd_puts_ascii(unsigned char *data_str,unsigned char x,unsigned char y,unsigned char mode)
{
	unsigned char data;
	while(*data_str)
	{
		data = toascii(*data_str++);
		if(y>120)
		{
			y = 0;
			x += 2;
		}
		if(x>6)
			continue;
		Lcd_disp_ascii(data,x,y,mode);
		y += 8;	
	}
}
  

/******************************************************************************************
				显示汉字字符串
 note	:	1.ACM12864的坐标系统定义如下:
 		  以平面直角坐标系的原点为圆心,逆时针旋转90度构成。从12864液晶平面的正面看,左上角
 		  为坐标原点,纵轴为横坐标(X),横轴为纵坐标(Y),范围:X - 0~64,Y - 0~128。实际上,
 		  X/8对应于页地址,\\main.cof
 		  Y/2对应于y地址。
 		2.从12864液晶平面的正面看,cs=1对应其右半部分平面,cs=2对应其左半部分平面
 		3.本函数显示的是16X16点阵字库
 		4.本函数保证显示出的是个完整的字型,当位置不足以显示一个完整的字型时,做换行处理。当
 		  连换行也不能显示一个完整的字型时,做空白处理
 		5.当字型位置处于cs1和cs2之间时,函数自动完成字型的拼接
 		6.12864显示16X16点阵字型时,范围为8X4,即满屏4行,每行8个字
 		
 in	:	data_str	-	要显示的汉字内码字符串
 		x		-	字串显示位置的横坐标,0~6
 		y		-	字串显示位置的纵坐标,0~128
 		mode		-	显示模式
						0正常模式
						1反显模式
						4闪烁模式
					注:显示模式可以组合 eg:0x00|0x01|0x02|0x04
******************************************************************************************/
void Lcd_putsf(unsigned char flash *data_str,unsigned char x,unsigned char y,unsigned char mode)
{
	unsigned int data;
	
	while(*data_str)
	{		
		data = *data_str++;
		data = (data<<8)|*data_str++;
		if(y>112)
		{
			y = 0;
			x += 2;
		}
		if(x>6)
			continue;
		Lcd_disp_hz(data,x,y,mode);
		y += 16;
	}
}

void Lcd_puts(unsigned char *data_str,unsigned char x,unsigned char y,unsigned char mode)
{
	unsigned int data;
	
	while(*data_str)
	{		
		if(*data_str > 0xa0)
		{
			data = *data_str++;
			data = (data<<8)|*data_str++;
		}
		else
			data = *data_str++;
		if(y>112)
		{
			y = 0;
			x += 2;
		}
		if(x>6)
			continue;
		Lcd_disp_hz(data,x,y,mode);
		y += 16;
	}
}


⌨️ 快捷键说明

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