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

📄 192x64液晶屏用avr驱动的汇编语言.asm.txt

📁 192X64液晶屏用AVR驱动的汇编语言 192X64液晶屏的MCS51汇编语言 192 64液晶片驱动程序 12232点阵信利液晶驱动
💻 TXT
📖 第 1 页 / 共 2 页
字号:
;		 TG19264A接口程序(AVR模拟方式)
;液晶模块供应商:广州市盛宝电子有限公司	Tel:020-87592491 Fax:87541571
;Email:	tinsharp@public.guangzhou.gd.cn
;这个连线图是因为原先的51试验电路改的,有些脚是将就着用的。
;************************************************************************
;连线图:								*
;*LCM------S8515*  *LCM----S8515*  *LCM-------S8515* *LCM------S8515*	*
;*DB0-------PA0*   *DB4-----PA4*   *D/I--------PC6*  *CS1-------PC5*	*
;*DB1-------PA1*   *DB5-----PA5*   *R/W--------PC7*  *CS2-------PC4*	*
;*DB2-------PA2*   *DB6-----PA6*   */RST-------VCC*  *CS3-------PD2*	* 
;*DB3-------PA3*   *DB7-----PA7*   *E----------PC3*			*
;注:AT90S8515的晶振频率为8MHz						*
;************************************************************************
.include"8515def.inc"		;器件配置文件
;接口引脚定义:
.equ	DI	=PC6		;数据/命令
.equ	RW	=PC7		;读/写
.equ	ELCM	=PC3		;操作允许,高电平有效(允许)
.equ	CS1	=PC4		;左区选中,低电平有效
.equ	CS2	=PC5		;中区选中,低电平有效
.equ	CS3	=PD2		;右区选中,低电平有效
.equ	Colend	= 0x40		;每一个分区宽64点

.def	status	= r1
.def	eeaddrl	= r5		;eeprom地址低8位
.def	eeaddrh	= r6		;eeprom地址高8位
.def	temp	= r3
.def	temp1	= r4
.def	rxpos	= r9		;X坐标备份
.def	rypos	= r10		;X坐标备份
.def	mode	= r15
.def	cbyte	= r16		;通用寄存器,主要在液晶显示数据
.def	count	= r17
.def	ioreg	= r18

.def	baud	= r20
.def	maxcol	= r21		;字符点阵宽度(8或16)
.def	col	= r22		;X坐标
.def	row	= r23		;Y坐标
.def	lbyte	= r24
.def	hbyte	= r25

.macro	Dptrinc				;AVR没有带进位立即数的加法,没办法
	subi	r30,low(-0x0001)	;才出此下策
	sbci	r31,high(-0x0001)
.endmacro

;主程序开始
.cseg
	.org	$000
	rjmp	RESET
	.org	URXCaddr
	
;*****************************************
;* Program starts here after power up.	 *
;*****************************************
.org	10				;保留空间给应用程序(中断向量区)
RESET:	cli				;关全局中断允许位(SREG.7)=I
	ldi	cbyte,low(RAMEND)	;堆栈顶部设定
	out	SPL,cbyte		;
	ldi	cbyte,high(RAMEND)	;
	out	SPH,cbyte		;
	clr	eeaddrl			;内部 EEPROM 指针清零
	clr	eeaddrh			;指向起始点
	clr	mode			;显示模式清零
	clr	cbyte			;显示内容清零
	out	GIMSK,cbyte		;通用屏蔽寄存器清零
	out	timsk,cbyte		;定时/计数器中断屏蔽寄存器清零
	out	wdtcr,cbyte		;看门狗定时控制寄存器清零

	clr	count			;程序软件计数器(R17)清零
	out	MCUCR,count		;MCU通用控制寄存器清零
	ser	ioreg			;置FF. (R18=0xFF)
	out	DDRD,ioreg		;定义端口D为输出
	out	DDRC,ioreg		;定义端口C为输出
	out	portb,ioreg		;端口B置FF
	out	portd,ioreg		;端口D置FF
	rjmp	Main			;初始化结束,进入主程序

;****************************************************************
; 主程序
;****************************************************************

Main:	ldi	cbyte, low(ramend)	;堆栈顶部设定
	out	SPL, cbyte		;keep our stack	healthy!!!
	ldi	cbyte, high(ramend)	;确认堆栈指针正确
	out	SPH,cbyte
	rcall	delay			;延时等待LCM复位好
	rcall	delay
	rcall	Initlcd			;液晶模块初始化
	ldi	col,0x00		; X = 0
	ldi	row,0x00		; Y = 0 (第一行)
	ldi	r30,low(STRING1*2)	; Z 指针指向第一个字符串
	ldi	r31,high(STRING1*2)
	rcall	Putstr			;显示输出这个字符串
	ldi	col,0x00		; X = 0
	ldi	row,0x02		; Y = 2 (第二行)
	ldi	r30,low(STRING2*2)	; Z 指针指向第二个字符串
	ldi	r31,high(STRING2*2)
	rcall	Putstr			;显示输出这个字符串
Main1:	wdr
	rjmp	Main1			;程序死循环,到此为止。

;****************************************************************
; LCM系统复位
;****************************************************************
InitLcd:
	ldi	cbyte,0x3e	;关显示
	rcall	WrCmd1
	rcall	WrCmd2
	rcall	WrCmd3
	ldi	cbyte,0x3F	;开显示
	rcall	WrCmd1
	rcall	WrCmd2
	rcall	WrCmd3
	ldi	cbyte,0xC0	;设定起始地址
	rcall	WrCmd1
	rcall	WrCmd2
	rcall	WrCmd3
	rcall	Cls		;清屏
	ret
;****************************************************************
; 延时程序
;****************************************************************
Delay:	push 	temp
	push 	temp1
	clr 	temp
  dt11:	clr 	temp1
  dt21:	nop
	dec temp1
	brne dt21
	dec temp
	brne dt11
	pop temp1
	pop temp
	ret

;****************************************************************
;获取字串内字符编码,C=0 显示结束,字符串以0FFH结尾作为结束标志
;以两字节组成一个字符:前一字节表示是全角(>=80H)还是半角(<80H)
;                      后一字节字符点阵表内偏移量“内码”
;****************************************************************
Getstrchar:
Gsc_pa:
	lpm			;先读取字头(字符属性或结束标志)
	mov	cbyte,r0	;保存字符属性
	Dptrinc			; Z++
	inc	r0
	clc			;置程序出口标志(表示已经结束)
	breq	Gsc_px		;如果是结束码(0ffh+1=00h)
	lpm			;真正读取“内码”
	Dptrinc
	sec			;编码有效标志
Gsc_px:
	ret

;************************************************************************
;一个长字符串数据输出,字符串以 0xFF 作结尾标志,入口 Z 指向该字符串
;显示位置的 XY 坐标由调用方确定
;************************************************************************
Putstr:	rcall	delay		;演示加上的延时,实际应用时去掉
	rcall	Getstrchar	;从字符串中取一个字
	push	r30		;push Z
	push	r31
	brcc	Psr_ax		; if c=0 输出结束
	sbrc	cbyte,0x07	; if cbyte^7=0 半角字符
	rjmp	Psr_pb
				; 半角字符
Psr_pa:	ldi	Maxcol,0x08	; 每字8列
	mov	cbyte,r0	; 取字符编码(内部码)
	rcall	Edotpos		; 字库实际指针换算,结果置入Z
	rjmp	Psr_pbx
;Chinese			; 全角字符
Psr_pb:	ldi	Maxcol,0x10	; 每字16列
	mov	cbyte,r0	; 取字符编码(内部码)
	rcall	Cdotpos		; 字库实际指针换算,结果置入Z
Psr_pbx:
	rcall	Putchardot	; 点阵码输出
	pop	r31
	pop	r30
	rjmp	Putstr		; 继续下一个字
Psr_ax:
	pop	r31
	pop	r30
	ret			; return
	
;****************************************************************
;半(全)角字符数据输出,Maxcol*16 点阵, Maxcol = 8 0r 16
;****************************************************************
Putchardot:
	push	col		;暂时保护X坐标,留给下半个字符用
	mov	count,Maxcol	;共Maxcol列
Pat_pa:
	lpm			;读取点阵码,放在r0
	mov	cbyte,r0	;给输出器存器
	rcall	Wrdata		;输出
	Dptrinc			;指针加1,指向下一位
	inc	col		;X=X+1
	dec	count		;计数器减1
	brne	Pat_pa		;判断如果未完成则继续
	inc	row		;Y=Y+1 指向下半个字符
	pop	col		;对齐左边起点
	mov	count,Maxcol	;也是Maxcol列
Pat_pb:
	lpm			;读取点阵码,放在r0
	mov	cbyte,r0	;给输出器存器
	rcall	Wrdata		;输出
	Dptrinc			;指针加1,指向下一位
	inc	col		;X=X+1
	dec	count		;计数器减1
	brne	Pat_pb		;判断如果未完成则继续
	dec	col		;回退1列
	rcall	Cusornext	;做边界判断
	cpi	col,0x01	;判断是否换行?
	brsh	Pat_pc		;没有换行,返回
	inc	row		;加一行(每个字符占用两行)
Pat_pc:
	dec	row		;指向上半部分
	ret			; return
	
;****************************************************************
;按给定的XY坐标定位,并写数据子程序
;****************************************************************
Wrdata:
	rcall	Locate
	rcall	LcdWd
	ret

;****************************************************************
;一字节数据输出,并根据坐标自动定位写入区域
;****************************************************************
LcdWd:	cpi	col,Colend		;分区判断,是否左区?
	brsh	LW1			;col>=Colend是中区或右区
	rcall	Wrdata1			;输出该(数据)字节
	rjmp	LW3			;返回
LW1:	cpi	col,Colend*2		;在中与右间区分
	brsh	LW2			;col>=2Colend 则为右区
	rcall	Wrdata2			;中区数据输出
	rjmp	LW3			;返回
LW2:	rcall	Wrdata3			;右区数据输出
LW3:	ret				;返回
	
;****************************************************************
;清屏,全屏幕清零
;****************************************************************
Cls:	ldi	row,0x00		;Y坐标起点
	ldi	cbyte,0x00		;填充数据 0x00
lflpb:	ldi	col,0x00		;X坐标起点
lflpa:	rcall	WrData			;数据写输出(分区自动判别)
	rcall	Cusornext		;计算下一个该填充位置
	cpi	col,0x00		;有否产生换行?
	brne	lflpa			;还未完成本行处理,继续
	cpi	row,0x00		;是否已结束?
	brne	lflpb			;没有结束,继续下一行处理
	ret

;****************************************************************
; 连续输出时的坐标指针换算,自动指向下一个可写入地址
;****************************************************************
Cusornext:
	andi	row,0x07	; 防止意外,确认只保留低3位
	inc	col		; X=X+1
	cpi	col,Colend*3	; 是否出界(右边界=3Colend)
	brlo	Cusret		; 未出界(col<Colend*3)
	clr	col		; 出界了,X=0x00 重新指向左边起点
	inc	row		; Y=Y+1 换行
	sbrc	row,0x03	; 行出界了吗?if (~row^3)
	clr	row		; 已出界,回到第0行
Cusret:	ret			; return

;****************************************************************
; BUSY状态等待,出口片选信号保持有效,elcm已关闭
;****************************************************************
StatusCS1:
	cbi	portc,CS1	; CS1 = 0
	sbi	portc,CS2	; CS2 = 1
	sbi	portd,CS3	; CS3 = 1
	rjmp	Statuscom	; 程序的公共部分
StatusCS2:
	sbi	portc,CS1	; CS1 = 1
	cbi	portc,CS2	; CS2 = 0
	sbi	portd,CS3	; CS3 = 1
	rjmp	Statuscom	; 程序的公共部分
StatusCS3:
	sbi	portc,CS1	; CS1 = 1
	sbi	portc,CS2	; CS2 = 1
	cbi	portd,CS3	; CS3 = 0
Statuscom:
	sbi	portc,RW	; R/W = 1
	cbi	portc,DI	; D/I = 0
	sbi	portc,elcm	; ELCM = 1 (ENABLE)
Stchk1:	
	clr	ioreg		;清零
	out	DDRA,ioreg	;定义A口作为输入
	ser	ioreg		;置FF
	out	porta,ioreg	;使A口成高阻状态
	nop			;等待书出到端口线上(一个指令周期)
	in	status,PINA	; 读a口数据给status
	sbrc	status,0x07	; 如果忙,再读状态,直到不忙为止(跳行)
	rjmp	Stchk1
	cbi	portc,elcm	; 关 Elcm
	ser	ioreg		; 置FF
	out	DDRA,ioreg	; 恢复A口为输出
	ret			;状态已允许,返回
;
;****************************************************************
;数据写输出(分为左中右3个程序)
;****************************************************************
WrData1:
	rcall	StatusCS1	;等待允许(片选保持)
	rjmp	Wrdatac
	WrData2:
	rcall	StatusCS2	;等待允许(片选保持)
	rjmp	Wrdatac
WrData3:
	rcall	StatusCS3	;等待允许(片选保持)
	
Wrdatac:
;	ldi	cbyte,0x55	;
	sbi	portc,DI	;D/I=1 R/W=0
	cbi	portc,RW
	out	porta,cbyte
	sbi	portc,elcm
	wdr			;看门狗复位
	cbi	portc,elcm
	ret
;
;****************************************************************
; 控制命令输出
;****************************************************************
WrCmd1:
	rcall	StatusCS1	; 等待允许(片选保持)
	rjmp	Wrcmdc
WrCmd2:
	rcall	StatusCS2	; 等待允许(片选保持)
	rjmp	Wrcmdc
WrCmd3:
	rcall	StatusCS3	; 等待允许(片选保持)
Wrcmdc:				; E=1 D/I=0 R/W=0 为指向命令口
	cbi	portc,DI	; D/I = 0
	cbi	portc,RW	; R/W = 0
	out	porta,cbyte	; 将控制指令放到数据线上
	sbi	portc,Elcm	; Elcm = 1
	wdr			; 看门狗复位(借以延时)
	cbi	portc,Elcm	; Elcm = 0
	ret
;****************************************************************
; 汉字库实际指针换算,结果置入Z(r31r30)
;****************************************************************
Cdotpos:
	ldi	count,0x05		;每个全角字符占用32字节
   	ldi	r31,high(HZKDOT*2)	;Z的高8位(指向汉字点阵码表)
  	ldi	r30,low(HZKDOT*2) 	;Z的低8位
	rjmp	Eps0			;转到公共程序入口
;
;****************************************************************
; 半角字符实际指针换算,结果置入 Z(r31r30)
;****************************************************************
Edotpos:
	ldi	count,0x04		;每个半角字符占用16字节
   	ldi	r31,high(EZKDOT*2)	;Z的高8位(指向半角点阵码表)
  	ldi	r30,low(EZKDOT*2)	;Z的低8位
 Eps0:	mov	temp,cbyte		;取字符编码
	clr	temp1			;高8位清零
	clc				;请进位标志C
 Eps1:	rol	temp		;带进位位的左循环
  	rol	temp1		;将标志移入高8位内
  	dec	count		;计数器减1
  	brne	Eps1		;如果计数器不为零继续
  	add	r30,temp
  	adc	r31,temp1	;指向表内制定字符
  	ret			;return

;****************************************************************
; X,Y坐标定位处理	,光标Y方向定位指令0xB8,X方向定位指令0x40
;****************************************************************

⌨️ 快捷键说明

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