📄 1602lcd.lst
字号:
__text_start:
__start:
4C E5CF LDI R28,0x5F
4D E0D4 LDI R29,4
4E BFCD OUT 0x3D,R28
4F BFDE OUT 0x3E,R29
50 51C0 SUBI R28,0x10
51 40D0 SBCI R29,0
52 EA0A LDI R16,0xAA
53 8308 STD Y+0,R16
54 2400 CLR R0
55 EAE4 LDI R30,0xA4
56 E0F0 LDI R31,0
57 E010 LDI R17,0
58 3AE7 CPI R30,0xA7
59 07F1 CPC R31,R17
5A F011 BEQ 0x005D
5B 9201 ST R0,Z+
5C CFFB RJMP 0x0058
5D 8300 STD Z+0,R16
5E E5E4 LDI R30,0x54
5F E0F0 LDI R31,0
60 E6A0 LDI R26,0x60
61 E0B0 LDI R27,0
62 E010 LDI R17,0
63 E000 LDI R16,0
64 BF0B OUT 0x3B,R16
65 39E8 CPI R30,0x98
66 07F1 CPC R31,R17
67 F021 BEQ 0x006C
68 95C8 LPM
69 9631 ADIW R30,1
6A 920D ST R0,X+
6B CFF9 RJMP 0x0065
6C 940E 00FA CALL _main
_exit:
6E CFFF RJMP _exit
FILE: F:\avr单片机学习\我自编程序\1602lcd\1602lcd.c
(0001)
(0002) /*---------------------------------------------------------------*/
(0003) #include <iom16v.h>
(0004) #include <macros.h>
(0005) #include "lcd1602.h"
(0006) /*------------------------------------主函数-------------------------------------------*/
(0007)
(0008) /*------------------------------------液晶驱动函数-------------------------------------*/
(0009) //液晶初始化
(0010) void lcd_init(void)
(0011) {
(0012) delay_nms(15);
_lcd_init:
6F E00F LDI R16,0xF
70 E010 LDI R17,0
71 D07A RCALL _delay_nms
(0013) lcd_write_command(0x38,0);//显示模式设置三次(此时不管lcd空闲与否)
72 2722 CLR R18
73 E308 LDI R16,0x38
74 D01F RCALL _lcd_write_command
(0014) delay_nms(5);
75 E005 LDI R16,5
76 E010 LDI R17,0
77 D074 RCALL _delay_nms
(0015) lcd_write_command(0x38,0);
78 2722 CLR R18
79 E308 LDI R16,0x38
7A D019 RCALL _lcd_write_command
(0016) delay_nms(5);
7B E005 LDI R16,5
7C E010 LDI R17,0
7D D06E RCALL _delay_nms
(0017) lcd_write_command(0x38,0);
7E 2722 CLR R18
7F E308 LDI R16,0x38
80 D013 RCALL _lcd_write_command
(0018) delay_nms(5);
81 E005 LDI R16,5
82 E010 LDI R17,0
83 D068 RCALL _delay_nms
(0019)
(0020) lcd_write_command(0x38,1);//显示模式设置(从此之后均需lcd空闲)
84 E021 LDI R18,1
85 E308 LDI R16,0x38
86 D00D RCALL _lcd_write_command
(0021) lcd_write_command(0x08,1);//显示关闭
87 E021 LDI R18,1
88 E008 LDI R16,0x8
89 D00A RCALL _lcd_write_command
(0022) lcd_write_command(0x01,1);//显示清屏
8A E021 LDI R18,1
8B E001 LDI R16,1
8C D007 RCALL _lcd_write_command
(0023) lcd_write_command(0x06,1);//显示光标移动设置
8D E021 LDI R18,1
8E E006 LDI R16,6
8F D004 RCALL _lcd_write_command
(0024) lcd_write_command(0x0c,1);//显示开及光标设置
90 E021 LDI R18,1
91 E00C LDI R16,0xC
92 D001 RCALL _lcd_write_command
93 9508 RET
_lcd_write_command:
wait_en --> R12
command --> R10
94 92AA ST R10,-Y
95 92CA ST R12,-Y
96 2EC2 MOV R12,R18
97 2EA0 MOV R10,R16
(0025) }
(0026)
(0027) //写指令函数: E=高脉冲 RS=0 RW=0
(0028) void lcd_write_command(unsigned char command,unsigned char wait_en)//command为指令,wait_en指定是否要检测LCD忙信号
(0029) {
(0030) if(wait_en)wait_enable();//若wait_en为1,则要检测LCD忙信号,等待其空闲
98 20CC TST R12
99 F009 BEQ 0x009B
9A D016 RCALL _wait_enable
(0031) lcd_control_port&=~lcd_RS;//RS=0
9B 98D8 CBI 0x1B,0
(0032) lcd_control_port&=~lcd_RW;//RW=0
9C 98D9 CBI 0x1B,1
(0033) lcd_control_port&=~lcd_EN;//E=0,下面给LCD一个高脉冲
9D 98DA CBI 0x1B,2
(0034) NOP();
9E 0000 NOP
(0035) lcd_control_port|=lcd_EN;//E=1
9F 9ADA SBI 0x1B,2
(0036) lcd_data_port=command;
A0 BAA2 OUT 0x12,R10
(0037) lcd_control_port&=~lcd_EN;//重设E=0
A1 98DA CBI 0x1B,2
A2 90C9 LD R12,Y+
A3 90A9 LD R10,Y+
A4 9508 RET
_lcd_write_data:
char_data --> R10
A5 92AA ST R10,-Y
A6 2EA0 MOV R10,R16
(0038) }
(0039)
(0040) //写数据函数: E =高脉冲 RS=1 RW=0
(0041) void lcd_write_data(unsigned char char_data)
(0042) {
(0043) wait_enable();//等待LCD空闲
A7 D009 RCALL _wait_enable
(0044) lcd_control_port|=lcd_RS;//RS=1
A8 9AD8 SBI 0x1B,0
(0045) lcd_control_port&=~lcd_RW;//RW=0
A9 98D9 CBI 0x1B,1
(0046) lcd_control_port&=~lcd_EN;//E=0,下面给LCD一个高脉冲
AA 98DA CBI 0x1B,2
(0047) NOP();
AB 0000 NOP
(0048) lcd_control_port|=lcd_EN;//E=1
AC 9ADA SBI 0x1B,2
(0049) lcd_data_port=char_data;
AD BAA2 OUT 0x12,R10
(0050) lcd_control_port&=~lcd_EN;//重设E=0
AE 98DA CBI 0x1B,2
AF 90A9 LD R10,Y+
B0 9508 RET
(0051) }
(0052)
(0053) //正常读写操作之前必须检测LCD控制器状态:E=1 RS=0 RW=1;DB7: 0 LCD控制器空闲,1 LCD控制器忙。
(0054) //检测忙信号,等待LCD空闲函数
(0055) void wait_enable(void)
(0056) {
(0057) lcd_busy_ddr&=~busy;//设置busy口为输入
_wait_enable:
B1 988F CBI 0x11,7
(0058) lcd_control_port&=~lcd_RS;//RS=0
B2 98D8 CBI 0x1B,0
(0059) lcd_control_port|=lcd_RW;//RW=1
B3 9AD9 SBI 0x1B,1
(0060) NOP();
B4 0000 NOP
(0061) lcd_control_port|=lcd_EN;//E=1
B5 9ADA SBI 0x1B,2
(0062) //while(lcd_busy_pin&busy);//等待LCD_DB7为0/////////////////////////
(0063) lcd_control_port&=~lcd_EN;//重设E=0
B6 98DA CBI 0x1B,2
(0064) lcd_busy_ddr|=busy;//设置busy口为输出
B7 9A8F SBI 0x11,7
B8 9508 RET
_display_a_char:
position_tem --> R20
char_data --> R10
position --> R22
B9 940E 0215 CALL push_xgsetF00C
BB 2EA2 MOV R10,R18
BC 2F60 MOV R22,R16
(0065) }
(0066)
(0067) //指定位置显示一个字符:第一行位置0~15,第二行16~31
(0068) //显示一个字符函数
(0069) void display_a_char(unsigned char position,unsigned char char_data)//参数position指定位置0~31,char_data为要显示的字符
(0070) {
(0071) unsigned char position_tem;
(0072) if(position>=0x10)
BD 3160 CPI R22,0x10
BE F018 BCS 0x00C2
(0073) position_tem=position+0xb0;///////////
BF 2F46 MOV R20,R22
C0 5540 SUBI R20,0x50
C1 C002 RJMP 0x00C4
(0074) else
(0075) position_tem=position+0x80;
C2 2F46 MOV R20,R22
C3 5840 SUBI R20,0x80
(0076) lcd_write_command(position_tem,1);
C4 E021 LDI R18,1
C5 2F04 MOV R16,R20
C6 DFCD RCALL _lcd_write_command
(0077) lcd_write_data(char_data);
C7 2D0A MOV R16,R10
C8 DFDC RCALL _lcd_write_data
C9 940C 021C JMP pop_xgsetF00C
_display_a_string:
col_tem --> R22
i --> R20
ptr --> R10
col --> R20
CB 940E 0215 CALL push_xgsetF00C
CD 0159 MOVW R10,R18
CE 2F40 MOV R20,R16
(0078) }
(0079)
(0080) //指定一行显示连续字符串:0显示在第一行,1显示在第二行,注字符串不能长于16个字符
(0081) //显示一行连续字符串函数
(0082) void display_a_string(unsigned char col,unsigned char *ptr)//参数col指定行,*ptr指字符串数组的首指针
(0083) {
(0084) unsigned char col_tem,i;
(0085) col_tem=col<<4;//若col为1(即在LCD第二行显示字符串),先把col左移4位,使显示字符的首位置改到第二行首位,即位置16
CF 2F64 MOV R22,R20
D0 706F ANDI R22,0xF
D1 9562 SWAP R22
(0086) for(i=0;i<16;i++)
D2 2744 CLR R20
D3 C00A RJMP 0x00DE
(0087) display_a_char(col_tem++,*(ptr+i));
D4 2FE4 MOV R30,R20
D5 27FF CLR R31
D6 0DEA ADD R30,R10
D7 1DFB ADC R31,R11
D8 8120 LDD R18,Z+0
D9 2E26 MOV R2,R22
DA 5F6F SUBI R22,0xFF
DB 2D02 MOV R16,R2
DC DFDC RCALL _display_a_char
DD 9543 INC R20
DE 3140 CPI R20,0x10
DF F3A0 BCS 0x00D4
E0 940C 021C JMP pop_xgsetF00C
(0088) }
(0089)
(0090) /*---------------------------------------延时函数-------------------------------------*/
(0091) //1ms延时函数
(0092) void delay_1ms(void)
(0093) {
(0094) unsigned int i;
(0095) for(i=0;i<600;i++);
_delay_1ms:
i --> R16
E2 2700 CLR R16
E3 2711 CLR R17
E4 C002 RJMP 0x00E7
E5 5F0F SUBI R16,0xFF
E6 4F1F SBCI R17,0xFF
E7 3508 CPI R16,0x58
E8 E0E2 LDI R30,2
E9 071E CPC R17,R30
EA F3D0 BCS 0x00E5
EB 9508 RET
_delay_nms:
i --> R20
n --> R10
EC 940E 020B CALL push_xgset300C
EE 0158 MOVW R10,R16
(0096) }
(0097)
(0098) //n ms延时函数
(0099) void delay_nms(unsigned int n)
(0100) {
(0101) unsigned int i;
(0102) for(i=0;i<n;i++)delay_1ms();
EF 2744 CLR R20
F0 2755 CLR R21
F1 C003 RJMP 0x00F5
F2 DFEF RCALL _delay_1ms
F3 5F4F SUBI R20,0xFF
F4 4F5F SBCI R21,0xFF
F5 154A CP R20,R10
F6 055B CPC R21,R11
F7 F3D0 BCS 0x00F2
F8 940C 0210 JMP pop_xgset300C
FILE: F:\avr单片机学习\我自编程序\1602lcd\main.c
(0001) /*---------------------------------------------------------------
(0002) 工程名称:1602液晶演示频率计
(0003) 编译器类型及版本:ICCAVR 6.9
(0004) 设计者:余威明
(0005) 设计日期:2007.08.09
(0006)
(0007) 芯片类型:ATmega16L
(0008) 时钟频率:4M外部时钟
(0009) 硬件接口说明:MCU ~ LCD
(0010) PORTD ~ dataport对应1602的d0~d7
(0011) PA1 ~ RS
(0012) PA2 ~ RW
(0013) PA3 ~ E
(0014) ---------------------------------------------------------------*/
(0015) #include <iom16v.h>
(0016) #include <macros.h>
(0017) #include "lcd1602.h"
(0018)
(0019)
(0020) void hextoasc(void); //十六进制转ASCII码
(0021) void timer1_init(void); //定时器1初始化
(0022) void port_init(void); //端口初始化
(0023) void init_devices(void);
(0024)
(0025) //显示的两行字符
(0026) unsigned char str00[]=" author:ancient"; //液晶屏初始显示内容
(0027) unsigned char str01[]=" time:2008/08/09";
(0028) unsigned char str1[]=" frequency meter";
(0029) unsigned char str2[]=" F:000HZ "; //频率显示形式
(0030) unsigned int count; //外部脉冲计数值
(0031) unsigned char tim0_ovf_count; //t0溢出次数
(0032) //在LCD上显示两行字符
(0033)
(0034)
(0035) void main(void)
(0036) {
(0037) init_devices(); //初始化
_main:
FA D08B RCALL _init_devices
(0038) display_a_string(0,str00); //开机界面
FB E620 LDI R18,0x60
FC E030 LDI R19,0
FD 2700 CLR R16
FE 940E 00CB CALL _display_a_string
(0039) delay_nms(500);
100 EF04 LDI R16,0xF4
101 E011 LDI R17,1
102 940E 00EC CALL _delay_nms
(0040) display_a_string(1,str01);
104 E721 LDI R18,0x71
105 E030 LDI R19,0
106 E001 LDI R16,1
107 940E 00CB CALL _display_a_string
(0041) delay_nms(1000);
109 EE08 LDI R16,0xE8
10A E013 LDI R17,3
10B 940E 00EC CALL _delay_nms
(0042) lcd_write_command(0x01,1);//显示清屏
10D E021 LDI R18,1
10E E001 LDI R16,1
10F 940E 0094 CALL _lcd_write_command
(0043) delay_nms(200);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -