📄 prj1.lst
字号:
(0039) void UART1_PutChar(unsigned char c) //字符输出函数
(0040) {
(0041) while (!(UCSR1A&(1 << UDRE1))); //判断上次发送有没有完成
_UART1_PutChar:
c --> R16
189 9020 009B LDS R2,0x009B
18B FE25 SBRS R2,5
18C CFFC RJMP _UART1_PutChar
(0042) UDR1 = c;
18D 9300 009C STS 0x009C,R16
18F 9508 RET
_UART1_Puts:
s --> R10
190 92AA ST R10,-Y
191 92BA ST R11,-Y
192 0158 MOVW R10,R16
(0043) }
(0044)
(0045) void UART1_Puts(unsigned char *s)
(0046) {
193 C004 RJMP 0x0198
(0047) while (*s)
(0048) {
(0049) UART1_PutChar(*s++);
194 01F5 MOVW R30,R10
195 9101 LD R16,Z+
196 015F MOVW R10,R30
197 DFF1 RCALL _UART1_PutChar
198 01F5 MOVW R30,R10
199 8020 LDD R2,Z+0
19A 2022 TST R2
19B F7C1 BNE 0x0194
19C 90B9 LD R11,Y+
19D 90A9 LD R10,Y+
19E 9508 RET
_UART1_PutBytes:
i --> R10
ilen --> R14
s --> R12
19F 940E 0349 CALL push_xgset00FC
1A1 2EE2 MOV R14,R18
1A2 0168 MOVW R12,R16
(0050) }
(0051) }
(0052)
(0053) //串口输出字节
(0054) void UART1_PutBytes(unsigned char *s, unsigned char ilen)
(0055) {
(0056) unsigned char i;
(0057)
(0058) for(i=0;i<ilen;i++)
1A3 24AA CLR R10
1A4 C005 RJMP 0x01AA
(0059) {
(0060) UART1_PutChar(*s++);
1A5 01F6 MOVW R30,R12
1A6 9101 LD R16,Z+
1A7 016F MOVW R12,R30
1A8 DFE0 RCALL _UART1_PutChar
1A9 94A3 INC R10
1AA 14AE CP R10,R14
1AB F3C8 BCS 0x01A5
1AC 940C 033E JMP pop_xgset00FC
FILE: E:\__test\_RTL8019_M128_struct_Test\Lcd7920.c
(0001) //本程序测试通过 --2007.11.27
(0002)
(0003) //本程序是7920的LM3037的液晶驱动程序
(0004) //汉字2x9
(0005) //可显示图形
(0006) //ATMEGA16, 内部晶振8M (也可用于外部7.3728MHz晶振)
(0007) //使用串行传输 (2线)
(0008)
(0009) #include "Lcd7920.h"
(0010)
(0011) #define LINEWIDTH 18 //行宽
(0012) #define LINES 2 //行数
(0013)
(0014) //LCD初始化
(0015) void LCD_Init(void)
(0016) {
(0017) Delay_nms(100);
_LCD_Init:
1AE E604 LDI R16,0x64
1AF E010 LDI R17,0
1B0 940E 02F1 CALL _Delay_nms
(0018)
(0019) //端口初始化
(0020) LCD_CONTROL_DDR=0xFF;
1B2 EF8F LDI R24,0xFF
1B3 BB84 OUT 0x14,R24
(0021)
(0022) CLRBIT(LCD_CONTROL_PORT,E);
1B4 98AB CBI 0x15,3
(0023) CLRBIT(LCD_CONTROL_PORT,RW);
1B5 98AA CBI 0x15,2
(0024) Delay_nms(1);
1B6 E001 LDI R16,1
1B7 E010 LDI R17,0
1B8 940E 02F1 CALL _Delay_nms
(0025)
(0026) LCD_WriteCmd(0x20); // 8bit I/F, basic command, graphic off
1BA E200 LDI R16,0x20
1BB D021 RCALL _LCD_WriteCmd
(0027) LCD_WriteCmd(0x20); // 8bit I/F, basic command, graphic off
1BC E200 LDI R16,0x20
1BD D01F RCALL _LCD_WriteCmd
(0028) LCD_WriteCmd(0x0C); // display on
1BE E00C LDI R16,0xC
1BF D01D RCALL _LCD_WriteCmd
(0029) LCD_WriteCmd(0x06); // cursor right shift
1C0 E006 LDI R16,6
1C1 D01B RCALL _LCD_WriteCmd
(0030)
(0031) LCD_Clear(); // cursor right shift
1C2 D001 RCALL _LCD_Clear
1C3 9508 RET
(0032) }
(0033)
(0034)
(0035) //LCD清屏
(0036) void LCD_Clear(void)
(0037) {
(0038) LCD_WriteCmd(0x01);
_LCD_Clear:
1C4 E001 LDI R16,1
1C5 D017 RCALL _LCD_WriteCmd
(0039) Delay_nms(1); //发清屏命令后,一定要加这个延时,不然后面马上写字符串到LCD会出现错误
1C6 E001 LDI R16,1
1C7 E010 LDI R17,0
1C8 940E 02F1 CALL _Delay_nms
1CA 9508 RET
(0040) }
(0041)
(0042)
(0043) //状态检查函数,判断是否处于忙状态 //--保留
(0044) void LCD_CheckState(void)
(0045) {
_LCD_CheckState:
1CB 9508 RET
_LCD_Send:
i --> R20
senddata --> R16
1CC 934A ST R20,-Y
(0046) /* unsigned char dat;
(0047) CLRBIT(LCD_CONTROL_PORT,RS); //RS=0
(0048) //SETBIT(LCD_CONTROL_PORT,RW); //RW=1
(0049) LCD_DATA_DDR=0x00; // portA as input
(0050) do
(0051) {
(0052) SETBIT(LCD_CONTROL_PORT,E);
(0053) NOP();
(0054) CLRBIT(LCD_CONTROL_PORT,E);
(0055) }
(0056) while (LCD_DATA_PIN&0x80);
(0057) */
(0058) }
(0059)
(0060)
(0061) //对LCD写入数据的时序协议处理
(0062) void LCD_Send(unsigned char senddata)
(0063) {
(0064) unsigned char i;
(0065)
(0066) for(i=0;i<8;i++)
1CD 2744 CLR R20
1CE C00A RJMP 0x01D9
(0067) {
(0068) if((senddata)&0x80)
1CF FF07 SBRS R16,7
1D0 C002 RJMP 0x01D3
(0069) {
(0070) //D_OUT=1 ;
(0071) SETBIT(LCD_CONTROL_PORT,RW);
1D1 9AAA SBI 0x15,2
(0072) }
1D2 C001 RJMP 0x01D4
(0073) else
(0074) {
(0075) //D_OUT=0;
(0076) CLRBIT(LCD_CONTROL_PORT,RW);
1D3 98AA CBI 0x15,2
(0077) }
(0078)
(0079) //SCK=1;
(0080) SETBIT(LCD_CONTROL_PORT,E);
1D4 9AAB SBI 0x15,3
(0081) NOP();
1D5 0000 NOP
(0082) //SCK=0;
(0083) CLRBIT(LCD_CONTROL_PORT,E);
1D6 98AB CBI 0x15,3
(0084)
(0085) senddata<<=1;
1D7 0F00 LSL R16
1D8 9543 INC R20
1D9 3048 CPI R20,0x8
1DA F3A0 BCS 0x01CF
1DB 9149 LD R20,Y+
1DC 9508 RET
_LCD_WriteCmd:
scmd --> R20
1DD 934A ST R20,-Y
1DE 2F40 MOV R20,R16
(0086) }
(0087) }
(0088)
(0089) //写一个命令到LCD
(0090) void LCD_WriteCmd(unsigned char scmd)
(0091) {
(0092) LCD_Send(0xf8);
1DF EF08 LDI R16,0xF8
1E0 DFEB RCALL _LCD_Send
(0093) LCD_Send(scmd&0xf0);
1E1 2F04 MOV R16,R20
1E2 7F00 ANDI R16,0xF0
1E3 DFE8 RCALL _LCD_Send
(0094) LCD_Send(scmd<<4);
1E4 2F04 MOV R16,R20
1E5 700F ANDI R16,0xF
1E6 9502 SWAP R16
1E7 DFE4 RCALL _LCD_Send
(0095) Delay_nus(20);
1E8 E104 LDI R16,0x14
1E9 E010 LDI R17,0
1EA 940E 02D0 CALL _Delay_nus
1EC 9149 LD R20,Y+
1ED 9508 RET
_LCD_WriteData:
DData --> R20
1EE 934A ST R20,-Y
1EF 2F40 MOV R20,R16
(0096) }
(0097)
(0098) ////写一个数据到LCD
(0099) void LCD_WriteData(unsigned char DData)
(0100) {
(0101) LCD_Send(0xfa);
1F0 EF0A LDI R16,0xFA
1F1 DFDA RCALL _LCD_Send
(0102) LCD_Send(DData&0xf0);
1F2 2F04 MOV R16,R20
1F3 7F00 ANDI R16,0xF0
1F4 DFD7 RCALL _LCD_Send
(0103) LCD_Send(DData<<4);
1F5 2F04 MOV R16,R20
1F6 700F ANDI R16,0xF
1F7 9502 SWAP R16
1F8 DFD3 RCALL _LCD_Send
(0104) Delay_nus(20);
1F9 E104 LDI R16,0x14
1FA E010 LDI R17,0
1FB 940E 02D0 CALL _Delay_nus
1FD 9149 LD R20,Y+
1FE 9508 RET
_LCD_Set_xy:
i --> R20
X --> R22
Y --> R10
1FF 940E 035A CALL push_xgsetF00C
201 2F62 MOV R22,R18
202 2EA0 MOV R10,R16
(0105) }
(0106)
(0107) //设置光标位置,先Y坐标后X坐标
(0108) void LCD_Set_xy(unsigned char Y, unsigned char X)
(0109) {
(0110) unsigned char i=0x00;
203 2744 CLR R20
(0111) switch(Y & 0x0f) //确定行号
204 2D8A MOV R24,R10
205 2799 CLR R25
206 708F ANDI R24,0xF
207 7090 ANDI R25,0
208 015C MOVW R10,R24
209 3080 CPI R24,0
20A 0789 CPC R24,R25
20B F069 BEQ 0x0219
20C 3081 CPI R24,1
20D E0E0 LDI R30,0
20E 079E CPC R25,R30
20F F059 BEQ 0x021B
210 3082 CPI R24,2
211 E0E0 LDI R30,0
212 079E CPC R25,R30
213 F049 BEQ 0x021D
214 3083 CPI R24,3
215 E0E0 LDI R30,0
216 079E CPC R25,R30
217 F039 BEQ 0x021F
218 C007 RJMP 0x0220
(0112) {
(0113) case 0x00:
(0114) i=0x80;
219 E840 LDI R20,0x80
(0115) break;
21A C005 RJMP 0x0220
(0116) case 0x01:
(0117) i=0x90;
21B E940 LDI R20,0x90
(0118) break;
21C C003 RJMP 0x0220
(0119) case 0x02:
(0120) i=0x88;
21D E848 LDI R20,0x88
(0121) break;
21E C001 RJMP 0x0220
(0122) case 0x03:
(0123) i=0x98;
21F E948 LDI R20,0x98
(0124) break;
(0125) default :
(0126) break;
(0127) }
(0128) i = (X & 0x0f)|i; //确定列号
220 2F86 MOV R24,R22
221 708F ANDI R24,0xF
222 2B48 OR R20,R24
(0129) LCD_WriteCmd(i);
223 2F04 MOV R16,R20
224 DFB8 RCALL _LCD_WriteCmd
225 940C 0361 JMP pop_xgsetF00C
_LCD_WriteChar:
c1 --> Y,+2
Y --> R12
X --> R10
227 92AA ST R10,-Y
228 92CA ST R12,-Y
229 2EC2 MOV R12,R18
22A 2EA0 MOV R10,R16
(0130)
(0131) }
(0132)
(0133) //写一个字符到LCD
(0134) void LCD_WriteChar(unsigned char X,unsigned char Y,unsigned char c1)
(0135) {
(0136) //从显示屏指定的行(Y),列(X)的位置写入字符
(0137)
(0138) LCD_WriteCmd(0x34); // 8bit I/F, basic command
22B E304 LDI R16,0x34
22C DFB0 RCALL _LCD_WriteCmd
(0139) LCD_WriteCmd(0x30); // 8bit I/F, basic command, graphic off
22D E300 LDI R16,0x30
22E DFAE RCALL _LCD_WriteCmd
(0140)
(0141) LCD_Set_xy(X,Y);
22F 2D2C MOV R18,R12
230 2D0A MOV R16,R10
231 DFCD RCALL _LCD_Set_xy
(0142) LCD_WriteData(c1);
232 810A LDD R16,Y+2
233 DFBA RCALL _LCD_WriteData
(0143)
(0144) Delay_nms(1); //2006.11.19
234 E001 LDI R16,1
235 E010 LDI R17,0
236 940E 02F1 CALL _Delay_nms
238 90C9 LD R12,Y+
239 90A9 LD R10,Y+
23A 9508 RET
_LCD_WriteStr:
pstr --> R22
j --> R20
pstr1 --> Y,+8
Y --> R12
X --> R10
23B 940E 0368 CALL push_xgsetF03C
23D 2EC2 MOV R12,R18
23E 2EA0 MOV R10,R16
(0145) }
(0146)
(0147) //指定光标位置,写字符串到LCD显示
(0148) void LCD_WriteStr(unsigned char X,unsigned char Y,unsigned char *pstr1)
(0149) {
(0150) //从显示屏指定的行(Y),列(X)的位置写入字符串
(0151) unsigned char j;
(0152) unsigned char *pstr = pstr1;
23F 8568 LDD R22,Y+8
240 8579 LDD R23,Y+9
(0153)
(0154) LCD_WriteCmd(0x34); // 8bit I/F, basic command
241 E304 LDI R16,0x34
242 DF9A RCALL _LCD_WriteCmd
(0155) LCD_WriteCmd(0x30); // 8bit I/F, basic command, graphic off
243 E300 LDI R16,0x30
244 DF98 RCALL _LCD_WriteCmd
(0156)
(0157) LCD_Set_xy(Y,X);
245 2D2A MOV R18,R10
246 2D0C MOV R16,R12
247 DFB7 RCALL _LCD_Set_xy
(0158)
(0159) j=Y * LINEWIDTH + X;
248 E182 LDI R24,0x12
249 9D8C MUL R24,R12
24A 2D40 MOV R20,R0
24B 0D4A ADD R20,R10
24C C025 RJMP 0x0272
(0160) while (*pstr && j< (LINEWIDTH * LINES))
(0161) {
(0162) if (j%LINEWIDTH==0) //判断是否换行
24D E112 LDI R17,0x12
24E 2F04 MOV R16,R20
24F 940E 0326 CALL mod8u
251 2300 TST R16
252 F431 BNE 0x0259
(0163) {
(0164) LCD_Set_xy(j/LINEWIDTH,0); //如换行, 则光标移动到行首
253 2722 CLR R18
254 E112 LDI R17,0x12
255 2F04 MOV R16,R20
256 940E 0328 CALL div8u
258 DFA6 RCALL _LCD_Set_xy
(0165) }
(0166)
(0167) //避免最后一格写半个汉字, 把汉字写到下一行
(0168) if (((j+1)%2==0) && *pstr>127 && *(pstr-1)<128)
259 E012 LDI R17,2
25A 2F04 MOV R16,R20
25B 5F0F SUBI R16,0xFF
25C 940E 0326 CALL mod8u
25E 2300 TST R16
25F F469 BNE 0x026D
260 E78F LDI R24,0x7F
261 01FB MOVW R30,R22
262 8020 LDD R2,Z+0
263 1582 CP R24,R2
264 F440 BCC 0x026D
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -