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

📄 1602.lst

📁 AVR MEGA16 控制 LCD(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 + -