📄 1602.lst
字号:
__start:
__text_start:
0041 E5CF LDI R28,0x5F
0042 E0D4 LDI R29,4
0043 BFCD OUT P3D,R28
0044 BFDE OUT P3E,R29
0045 51C0 SUBI R28,0x10
0046 40D0 SBCI R29,0
0047 EA0A LDI R16,0xAA
0048 8308 STD R16,0+Y
0049 2400 CLR R0
004A E8E1 LDI R30,0x81
004B E0F0 LDI R31,0
004C E010 LDI R17,0
004D 38E1 CPI R30,0x81
004E 07F1 CPC R31,R17
004F F011 BEQ 0x0052
0050 9201 ST R0,Z+
0051 CFFB RJMP 0x004D
0052 8300 STD R16,0+Z
0053 E6E0 LDI R30,0x60
0054 E0F0 LDI R31,0
0055 E6A0 LDI R26,0x60
0056 E0B0 LDI R27,0
0057 E010 LDI R17,0
0058 38E1 CPI R30,0x81
0059 07F1 CPC R31,R17
005A F021 BEQ 0x005F
005B 95C8 LPM
005C 9631 ADIW R30,1
005D 920D ST R0,X+
005E CFF9 RJMP 0x0058
005F 940E0062 CALL _main
_exit:
0061 CFFF RJMP _exit
FILE: 1602.c
(0001) #include <iom16v.h>
(0002) #include <macros.h>
(0003)
(0004) #define lcd_data_port PORTD
(0005) #define lcd_data_ddr DDRD
(0006) #define lcd_busy_pin PIND
(0007) #define lcd_busy_ddr DDRD
(0008) #define lcd_control_port PORTA
(0009) #define lcd_control_ddr DDRA
(0010)
(0011) #define lcd_RS 0x01
(0012) //PORTA0
(0013) #define lcd_RW 0x02
(0014) //PORTA1
(0015) #define lcd_EN 0x04
(0016) //PORTA2
(0017) #define busy 0x80
(0018) //LCD_DB7
(0019)
(0020)
(0021)
(0022)
(0023)
(0024)
(0025)
(0026) /*----------------------------------函数声明------------------------------------------*/
(0027) void lcd_init(void);
(0028) void lcd_write_command(unsigned char command,unsigned char wait_en);
(0029) void lcd_write_data(unsigned char char_data);
(0030) void wait_enable(void);
(0031) void display_a_char(unsigned char position,unsigned char char_data);
(0032) void display_a_string(unsigned char col,unsigned char *ptr);
(0033) void delay_1ms(void);
(0034) void delay_nms(unsigned int n);
(0035)
(0036)
(0037)
(0038)
(0039)
(0040)
(0041)
(0042) //显示的两行字符
(0043) unsigned char str1[]=" I love you ";
(0044) unsigned char str2[]=" www.ouravr.com ";
(0045)
(0046)
(0047)
(0048)
(0049)
(0050)
(0051)
(0052) /*------------------------------------主函数-------------------------------------------*/
(0053) void main(void)
(0054) {
(0055) lcd_data_port=0xff;
_main:
0062 EF8F LDI R24,0xFF
0063 BB82 OUT P12,R24
(0056) lcd_data_ddr=0xff;
0064 BB81 OUT P11,R24
(0057) lcd_control_port=0x07;
0065 E087 LDI R24,7
0066 BB8B OUT P1B,R24
(0058) lcd_control_ddr=0x07;
0067 BB8A OUT P1A,R24
(0059) lcd_init();
0068 D00A RCALL _lcd_init
(0060) display_a_string(0,str1);
0069 E620 LDI R18,0x60
006A E030 LDI R19,0
006B 2700 CLR R16
006C D067 RCALL _display_a_string
(0061) display_a_string(1,str2);
006D E720 LDI R18,0x70
006E E030 LDI R19,0
006F E001 LDI R16,1
0070 D063 RCALL _display_a_string
(0062) while(1);
0071 CFFF RJMP 0x0071
(0063) }
0072 9508 RET
(0064)
(0065)
(0066)
(0067)
(0068)
(0069)
(0070)
(0071)
(0072)
(0073)
(0074) /*------------------------------------液晶驱动函数-------------------------------------*/
(0075) //液晶初始化
(0076) void lcd_init(void)
(0077) {
(0078) delay_nms(15);
_lcd_init:
0073 E00F LDI R16,0xF
0074 E010 LDI R17,0
0075 D081 RCALL _delay_nms
(0079) lcd_write_command(0x38,0);//显示模式设置三次(此时不管lcd空闲与否)
0076 2722 CLR R18
0077 E308 LDI R16,0x38
0078 D01E RCALL _lcd_write_command
(0080) delay_nms(5);
0079 E005 LDI R16,5
007A E010 LDI R17,0
007B D07B RCALL _delay_nms
(0081) lcd_write_command(0x38,0);
007C 2722 CLR R18
007D E308 LDI R16,0x38
007E D018 RCALL _lcd_write_command
(0082) delay_nms(5);
007F E005 LDI R16,5
0080 E010 LDI R17,0
0081 D075 RCALL _delay_nms
(0083) lcd_write_command(0x38,0);
0082 2722 CLR R18
0083 E308 LDI R16,0x38
0084 D012 RCALL _lcd_write_command
(0084) delay_nms(5);
0085 E005 LDI R16,5
0086 E010 LDI R17,0
0087 D06F RCALL _delay_nms
(0085)
(0086) lcd_write_command(0x38,1);//显示模式设置(从此之后均需lcd空闲)
0088 E021 LDI R18,1
0089 E308 LDI R16,0x38
008A D00C RCALL _lcd_write_command
(0087) lcd_write_command(0x08,1);//显示关闭
008B E021 LDI R18,1
008C E008 LDI R16,0x8
008D D009 RCALL _lcd_write_command
(0088) lcd_write_command(0x01,1);//显示清屏
008E E021 LDI R18,1
008F E001 LDI R16,1
0090 D006 RCALL _lcd_write_command
(0089) lcd_write_command(0x06,1);//显示光标移动设置
0091 E021 LDI R18,1
0092 E006 LDI R16,6
0093 D003 RCALL _lcd_write_command
(0090) lcd_write_command(0x0c,1);//显示开及光标设置
0094 E021 LDI R18,1
0095 E00C LDI R16,0xC
(0091) }
0096 C000 RJMP _lcd_write_command
0097 940E011D CALL push_gset2
0099 2F62 MOV R22,R18
009A 2F40 MOV R20,R16
(0092)
(0093)
(0094)
(0095)
(0096)
(0097)
(0098)
(0099)
(0100) //写指令函数: E=高脉冲 RS=0 RW=0
(0101) void lcd_write_command(unsigned char command,unsigned char wait_en)//command为指令,wait_en指定是否要检测LCD忙信号
(0102) {
(0103) if(wait_en)wait_enable();//若wait_en为1,则要检测LCD忙信号,等待其空闲
009B 2366 TST R22
009C F009 BEQ 0x009E
009D D018 RCALL _wait_enable
(0104) lcd_control_port&=~lcd_RS;//RS=0
009E 98D8 CBI P1B,0
(0105) lcd_control_port&=~lcd_RW;//RW=0
009F 98D9 CBI P1B,1
(0106) lcd_control_port&=~lcd_EN;//E=0,下面给LCD一个高脉冲
00A0 98DA CBI P1B,2
(0107) NOP();
00A1 0000 NOP
(0108) lcd_control_port|=lcd_EN;//E=1
00A2 9ADA SBI P1B,2
(0109) lcd_data_port=command;
00A3 BB42 OUT P12,R20
(0110) lcd_control_port&=~lcd_EN;//重设E=0
00A4 98DA CBI P1B,2
(0111) }
00A5 940E0125 CALL pop_gset2
00A7 9508 RET
_lcd_write_data:
char_data --> R20
00A8 940E0106 CALL push_gset1
00AA 2F40 MOV R20,R16
(0112)
(0113)
(0114)
(0115)
(0116)
(0117)
(0118)
(0119)
(0120)
(0121) //写数据函数: E =高脉冲 RS=1 RW=0
(0122) void lcd_write_data(unsigned char char_data)
(0123) {
(0124) wait_enable();//等待LCD空闲
00AB D00A RCALL _wait_enable
(0125) lcd_control_port|=lcd_RS;//RS=1
00AC 9AD8 SBI P1B,0
(0126) lcd_control_port&=~lcd_RW;//RW=0
00AD 98D9 CBI P1B,1
(0127) lcd_control_port&=~lcd_EN;//E=0,下面给LCD一个高脉冲
00AE 98DA CBI P1B,2
(0128) NOP();
00AF 0000 NOP
(0129) lcd_control_port|=lcd_EN;//E=1
00B0 9ADA SBI P1B,2
(0130) lcd_data_port=char_data;
00B1 BB42 OUT P12,R20
(0131) lcd_control_port&=~lcd_EN;//重设E=0
00B2 98DA CBI P1B,2
(0132) }
00B3 940E0109 CALL pop_gset1
00B5 9508 RET
(0133)
(0134)
(0135)
(0136)
(0137)
(0138)
(0139)
(0140)
(0141)
(0142)
(0143) //正常读写操作之前必须检测LCD控制器状态:E=1 RS=0 RW=1;DB7: 0 LCD控制器空闲,1 LCD控制器忙。
(0144) //检测忙信号,等待LCD空闲函数
(0145) void wait_enable(void)
(0146) {
(0147) lcd_busy_ddr&=~busy;//设置busy口为输入
_wait_enable:
00B6 988F CBI P11,7
(0148) lcd_control_port&=~lcd_RS;//RS=0
00B7 98D8 CBI P1B,0
(0149) lcd_control_port|=lcd_RW;//RW=1
00B8 9AD9 SBI P1B,1
(0150) NOP();
00B9 0000 NOP
(0151) lcd_control_port|=lcd_EN;//E=1
00BA 9ADA SBI P1B,2
(0152) while(lcd_busy_pin&busy);//等待LCD_DB7为0
00BB 9987 SBIC P10,7
00BC CFFE RJMP 0x00BB
(0153) lcd_control_port&=~lcd_EN;//重设E=0
00BD 98DA CBI P1B,2
(0154) lcd_busy_ddr|=busy;//设置busy口为输出
00BE 9A8F SBI P11,7
(0155) }
00BF 9508 RET
_display_a_char:
position_tem --> R22
char_data --> R20
position --> R10
00C0 940E0121 CALL push_gset3
00C2 2F42 MOV R20,R18
00C3 2EA0 MOV R10,R16
(0156)
(0157)
(0158)
(0159)
(0160)
(0161)
(0162)
(0163) //指定位置显示一个字符:第一行位置0~15,第二行16~31
(0164) //显示一个字符函数
(0165) //LCD显示字符的位置,我是按附图的坐标安排的,参数position就是指图中的0~31,比如你要在第二行第三个位置显示“s”,你只要display_a_char(18,s)就可以了。
(0166)
(0167) // lcd_writecommand是用来指定显示寄存器地址亦即显示的地址的
(0168) void display_a_char(unsigned char position,unsigned char char_data)//参数position指定位置0~31,char_data为要显示的字符
(0169) {
(0170) unsigned char position_tem;
(0171) if(position>=0x10)
00C4 2D8A MOV R24,R10
00C5 3180 CPI R24,0x10
00C6 F018 BCS 0x00CA
(0172) position_tem=position+0xb0;//因为LCD第一行显示寄存器地址0X80-0X8F,第二行显示寄存器地址:0XC0-0XCF,所以你的position〉=16位置时,即要写显示寄存器地址position+0xC0-16即是position+0xB0。
00C7 2D6A MOV R22,R10
00C8 5560 SUBI R22,0x50
00C9 C002 RJMP 0x00CC
(0173) else
(0174) position_tem=position+0x80;//第一行显示
00CA 2D6A MOV R22,R10
00CB 5860 SUBI R22,0x80
(0175) lcd_write_command(position_tem,1);
00CC E021 LDI R18,1
00CD 2F06 MOV R16,R22
00CE DFC8 RCALL _lcd_write_command
(0176) lcd_write_data(char_data);
00CF 2F04 MOV R16,R20
00D0 DFD7 RCALL _lcd_write_data
(0177) }
00D1 940E0128 CALL pop_gset3
00D3 9508 RET
_display_a_string:
col_tem --> R20
i --> R22
ptr --> R10
col --> R20
00D4 940E0121 CALL push_gset3
00D6 0159 MOVW R10,R18
00D7 2F40 MOV R20,R16
(0178)
(0179)
(0180)
(0181)
(0182)
(0183)
(0184)
(0185) //指定一行显示连续字符串:0显示在第一行,1显示在第二行,注字符串不能长于16个字符
(0186) //显示一行连续字符串函数
(0187) void display_a_string(unsigned char col,unsigned char *ptr)//参数col指定行,*ptr指字符串数组的首指针
(0188) {
(0189) unsigned char col_tem,i;
(0190) col_tem=col<<4;//若col为1(即在LCD第二行显示字符串),先把col左移4位,使显示字符的首位置改到第二行首位,即位置16
00D8 2F84 MOV R24,R20
00D9 708F ANDI R24,0xF
00DA 9582 SWAP R24
00DB 2F48 MOV R20,R24
(0191) for(i=0;i<16;i++)
00DC 2766 CLR R22
00DD C00A RJMP 0x00E8
(0192) display_a_char(col_tem++,*(ptr+i));
00DE 2FE6 MOV R30,R22
00DF 27FF CLR R31
00E0 0DEA ADD R30,R10
00E1 1DFB ADC R31,R11
00E2 8120 LDD R18,0+Z
00E3 2E24 MOV R2,R20
00E4 5F4F SUBI R20,0xFF
00E5 2D02 MOV R16,R2
00E6 DFD9 RCALL _display_a_char
00E7 9563 INC R22
00E8 3160 CPI R22,0x10
00E9 F3A0 BCS 0x00DE
(0193) }
00EA 940E0128 CALL pop_gset3
00EC 9508 RET
(0194)
(0195)
(0196)
(0197)
(0198)
(0199)
(0200)
(0201)
(0202) /*---------------------------------------延时函数-------------------------------------*/
(0203) //1ms延时函数
(0204) void delay_1ms(void)
(0205) {
(0206) unsigned int i;
(0207) for(i=0;i<600;i++);
_delay_1ms:
i --> R16
00ED 2700 CLR R16
00EE 2711 CLR R17
00EF C002 RJMP 0x00F2
00F0 5F0F SUBI R16,0xFF
00F1 4F1F SBCI R17,0xFF
00F2 3508 CPI R16,0x58
00F3 E0E2 LDI R30,2
00F4 071E CPC R17,R30
00F5 F3D0 BCS 0x00F0
(0208) }
00F6 9508 RET
_delay_nms:
i --> R20
n --> R22
00F7 940E011D CALL push_gset2
00F9 01B8 MOVW R22,R16
(0209)
(0210) //n ms延时函数
(0211) void delay_nms(unsigned int n)
(0212) {
(0213) unsigned int i;
(0214) for(i=0;i<n;i++)delay_1ms();
00FA 2744 CLR R20
00FB 2755 CLR R21
00FC C003 RJMP 0x0100
00FD DFEF RCALL _delay_1ms
00FE 5F4F SUBI R20,0xFF
00FF 4F5F SBCI R21,0xFF
0100 1746 CP R20,R22
0101 0757 CPC R21,R23
0102 F3D0 BCS 0x00FD
(0215) }
FILE: <library>
0103 940E0125 CALL pop_gset2
0105 9508 RET
push_gset1:
0106 935A ST R21,-Y
0107 934A ST R20,-Y
0108 9508 RET
pop_gset1:
0109 E0E1 LDI R30,1
pop:
010A 9149 LD R20,Y+
010B 9159 LD R21,Y+
010C FDE0 SBRC R30,0
010D 9508 RET
010E 9169 LD R22,Y+
010F 9179 LD R23,Y+
0110 FDE1 SBRC R30,1
0111 9508 RET
0112 90A9 LD R10,Y+
0113 90B9 LD R11,Y+
0114 FDE2 SBRC R30,2
0115 9508 RET
0116 90C9 LD R12,Y+
0117 90D9 LD R13,Y+
0118 FDE3 SBRC R30,3
0119 9508 RET
011A 90E9 LD R14,Y+
011B 90F9 LD R15,Y+
011C 9508 RET
push_gset2:
011D 937A ST R23,-Y
011E 936A ST R22,-Y
011F 940C0106 JMP push_gset1
push_gset3:
0121 92BA ST R11,-Y
0122 92AA ST R10,-Y
0123 940C011D JMP push_gset2
pop_gset2:
0125 E0E2 LDI R30,2
0126 940C010A JMP pop
pop_gset3:
0128 E0E4 LDI R30,4
0129 940C010A JMP pop
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -