📄 mater.lst
字号:
_LCD_write_char:
data --> Y+4
Y --> R22
X --> R20
00F8 940E01E8 CALL push_gset2
00FA 2F62 MOV R22,R18
00FB 2F40 MOV R20,R16
(0138) }
(0139)
(0140) }
(0141)
(0142) void LCD_write_char(unsigned char X,unsigned char Y,unsigned char data) //列x=0~15,行y=0,1
(0143) {
(0144) LCD_set_xy( X, Y ); //写地址
00FC 2F26 MOV R18,R22
00FD 2F04 MOV R16,R20
00FE DFD3 RCALL _LCD_set_xy
(0145) LCD_write_data( data);
00FF 810C LDD R16,Y+4
0100 DFB3 RCALL _LCD_write_data
0101 940E01DC CALL pop_gset2
0103 9508 RET
FILE: F:\ChengXuCunFang\ChengXU\AVR单片机程序存放\max485多机通讯1\主机\main.c
(0001) /* 通讯规则:
(0002) 01:时钟7.3728 MHz/波特率9600/9个数据位/奇校验/1个停止位/硬件多机通讯功能/
(0003) 02:通讯连接采用硬件MAX485,双向单工
(0004) 03:MAX485的RE/DE并联接到单片机的PD2脚(高电平发送/低电平接收)
(0005) 04:所有MAX485的A脚并联/B脚并联/D脚接TXD/R脚接RXD
(0006) 05:每个上行/下行的数据包的字节个数都是一样的(通讯数据量)
(0007) 06:数据包格式: 地址_数据1_数据2_数据3_数据n_CRC8校验码
(0008) 07:所有单元的数据接收都是采用中断+查询的方式
(0009) 08:总是由主机向从机下发一个数据包,从机收到数据包并校验正确后向主机回复一个数据包
(0010) 09:不管是主机还是从机,如果收到的数据包有任何错误,都将丢弃该数据包,等效于没有接收
(0011) 10:通讯采用主机轮询方式,从机之间不能相互通讯,必须通过主机才能交换数据
(0012) 11:无效地址是0,主机地址是1,从机地址是11.12.13...广播地址是255
(0013) */
(0014)
(0015) #include<iom16v.h>
(0016) #include <macros.h>
(0017) #include "1602.h"
(0018) #include "delay.h"
(0019)
(0020) #define amount 10
(0021) #define address 1
(0022)
(0023) unsigned char send[amount];
(0024) unsigned char inbox[amount];
(0025) unsigned char n=0;//记忆叫断接收的次数
(0026)
(0027)
(0028)
(0029) //end
(0030)
(0031) //波特率9600/9个数据位/1个停止位/奇校验/收发开启/接收中断/地址过滤
(0032) void usart_init(void)
(0033) {
(0034) UCSRA=0x01;
_usart_init:
0104 E081 LDI R24,1
0105 B98B OUT 0x0B,R24
(0035) UCSRB=0x9C;
0106 E98C LDI R24,0x9C
0107 B98A OUT 0x0A,R24
(0036) UCSRC=0xB6;
0108 EB86 LDI R24,0xB6
0109 BD80 OUT 0x20,R24
(0037) UBRRH=0x00;
010A 2422 CLR R2
010B BC20 OUT 0x20,R2
(0038) UBRRL=47;
010C E28F LDI R24,0x2F
010D B989 OUT 0x09,R24
010E 9508 RET
_crc8:
crc --> R20
i --> R22
len --> R18
ptr --> R16
010F 940E01E8 CALL push_gset2
(0039) }
(0040)
(0041) unsigned char crc8(unsigned char *ptr, unsigned char len)
(0042) {
(0043) unsigned char i;
(0044) unsigned char crc=0;
0111 2744 CLR R20
0112 C020 RJMP 0x0133
(0045) while(len--!=0)
(0046) {
(0047) for(i=1; i!=0; i*=2)
0113 E061 LDI R22,1
0114 C01A RJMP 0x012F
(0048) {
(0049) if((crc&1)!=0) {crc/=2; crc^=0x8C;}
0115 FF40 SBRS R20,0
0116 C009 RJMP 0x0120
0117 9546 LSR R20
0118 E88C LDI R24,0x8C
0119 E090 LDI R25,0
011A 2E24 MOV R2,R20
011B 2433 CLR R3
011C 2628 EOR R2,R24
011D 2639 EOR R3,R25
011E 2D42 MOV R20,R2
011F C001 RJMP 0x0121
(0050) else crc/=2;
0120 9546 LSR R20
(0051) if((*ptr&i)!=0) crc^=0x8C;
0121 01F8 MOVW R30,R16
0122 8020 LDD R2,Z+0
0123 2226 AND R2,R22
0124 F039 BEQ 0x012C
0125 E88C LDI R24,0x8C
0126 E090 LDI R25,0
0127 2E24 MOV R2,R20
0128 2433 CLR R3
0129 2628 EOR R2,R24
012A 2639 EOR R3,R25
012B 2D42 MOV R20,R2
012C E082 LDI R24,2
012D 9F86 MUL R24,R22
012E 2D60 MOV R22,R0
012F 2366 TST R22
0130 F721 BNE 0x0115
(0052) }
(0053) ptr++;
0131 5F0F SUBI R16,0xFF
0132 4F1F SBCI R17,0xFF
0133 2E22 MOV R2,R18
0134 2433 CLR R3
0135 5021 SUBI R18,1
0136 2022 TST R2
0137 F6D9 BNE 0x0113
(0054) }
(0055) return(crc);
0138 2F04 MOV R16,R20
0139 940E01DC CALL pop_gset2
013B 9508 RET
_RXC_Int:
013C 922A ST R2,-Y
013D 938A ST R24,-Y
013E 939A ST R25,-Y
013F 93EA ST R30,-Y
0140 93FA ST R31,-Y
0141 B62F IN R2,0x3F
0142 922A ST R2,-Y
(0056) }
(0057)
(0058) #pragma interrupt_handler RXC_Int: 12
(0059) void RXC_Int(void)
(0060) {
(0061) if( UCSRA&28 ){ n=UDR; n=0; UCSRA|=0x01; } else //接收出错就重新打开地址帧筛选功能
0143 B18B IN R24,0x0B
0144 718C ANDI R24,0x1C
0145 F041 BEQ 0x014E
0146 B02C IN R2,0x0C
0147 92200060 STS n,R2
0149 2422 CLR R2
014A 92200060 STS n,R2
014C 9A58 SBI 0x0B,0
014D C01C RJMP 0x016A
(0062) {
(0063) if( UCSRB&2 ) n=0; //检测到地址信息时计数清零
014E 9B51 SBIS 0x0A,1
014F C003 RJMP 0x0153
0150 2422 CLR R2
0151 92200060 STS n,R2
(0064) inbox[n]=UDR; n++; //把接收到的数据保存到收件箱
0153 E68C LDI R24,0x6C
0154 E090 LDI R25,0
0155 91E00060 LDS R30,n
0157 27FF CLR R31
0158 0FE8 ADD R30,R24
0159 1FF9 ADC R31,R25
015A B02C IN R2,0x0C
015B 8220 STD Z+0,R2
015C 91800060 LDS R24,n
015E 5F8F SUBI R24,0xFF
015F 93800060 STS n,R24
(0065) if( inbox[0]==address ) UCSRA&=254; else UCSRA|=0x01; //地址筛选
0161 9180006C LDS R24,inbox
0163 3081 CPI R24,1
0164 F421 BNE 0x0169
0165 B18B IN R24,0x0B
0166 7F8E ANDI R24,0xFE
0167 B98B OUT 0x0B,R24
0168 C001 RJMP 0x016A
0169 9A58 SBI 0x0B,0
(0066) }
016A 9029 LD R2,Y+
016B BE2F OUT 0x3F,R2
016C 91F9 LD R31,Y+
016D 91E9 LD R30,Y+
016E 9199 LD R25,Y+
016F 9189 LD R24,Y+
0170 9029 LD R2,Y+
0171 9518 RETI
_usart_out:
i --> R20
n --> R18
datas --> R16
0172 940E01EA CALL push_gset1
(0067) }
(0068)
(0069) void usart_out(unsigned char *datas,unsigned char n)
(0070) {
(0071) unsigned char i=0;
0174 2744 CLR R20
(0072) PORTD |=(1<<PD4); //使MAX485处于发送状态
0175 9A94 SBI 0x12,4
0176 C011 RJMP 0x0188
(0073) while(i<n) //一共发送n个数据
(0074) {
(0075) if(i==0) UCSRB|=1; else UCSRB&=254;
0177 2344 TST R20
0178 F411 BNE 0x017B
0179 9A50 SBI 0x0A,0
017A C003 RJMP 0x017E
017B B18A IN R24,0x0A
017C 7F8E ANDI R24,0xFE
017D B98A OUT 0x0A,R24
(0076) UDR=*(datas+i); //装载数据开始发送
017E 2FE4 MOV R30,R20
017F 27FF CLR R31
0180 0FE0 ADD R30,R16
0181 1FF1 ADC R31,R17
0182 8020 LDD R2,Z+0
0183 B82C OUT 0x0C,R2
(0077) while((UCSRA&64)==0); //等待发送结束
0184 9B5E SBIS 0x0B,6
0185 CFFE RJMP 0x0184
(0078) UCSRA|=64; //清除发送结束标志
0186 9A5E SBI 0x0B,6
(0079) i++; //发送次数统计
0187 9543 INC R20
0188 1742 CP R20,R18
0189 F368 BCS 0x0177
(0080) }
(0081) PORTD&=~(1<<PD4); //使MAX485处于接收状态
018A 9894 CBI 0x12,4
018B 940E01ED CALL pop_gset1
018D 9508 RET
_main:
018E 9722 SBIW R28,2
(0082) }
(0083) void main()
(0084) {
(0085) usart_init();
018F DF74 RCALL _usart_init
(0086) LCD_init(); //液晶初始化
0190 DEEA RCALL _LCD_init
(0087) DDRD |=(1<<PD4);
0191 9A8C SBI 0x11,4
(0088) DDRA |=0x07;
0192 B38A IN R24,0x1A
0193 6087 ORI R24,7
0194 BB8A OUT 0x1A,R24
(0089) SEI(); //打开全局中断,需要macros.h支持
0195 9478 BSET 7
(0090) LCD_write_string(0,0,"Send:");
0196 E686 LDI R24,0x66
0197 E090 LDI R25,0
0198 8399 STD Y+1,R25
0199 8388 STD Y+0,R24
019A 2722 CLR R18
019B 2700 CLR R16
019C DF45 RCALL _LCD_write_string
(0091) LCD_write_string(0,1,"Rev:");
019D E681 LDI R24,0x61
019E E090 LDI R25,0
019F 8399 STD Y+1,R25
01A0 8388 STD Y+0,R24
01A1 E021 LDI R18,1
01A2 2700 CLR R16
01A3 DF3E RCALL _LCD_write_string
01A4 C034 RJMP 0x01D9
(0092) while(1){
(0093) send[3]=9; //更新发件箱的数据(测试代码)
01A5 E089 LDI R24,0x9
01A6 93800079 STS send+3,R24
(0094) send[0]=11; //指向从机地址
01A8 E08B LDI R24,0xB
01A9 93800076 STS send,R24
(0095) send[amount-1]=crc8(send,amount-1); //计算发件箱数据的crc8校验码
01AB E029 LDI R18,0x9
01AC E706 LDI R16,0x76
01AD E010 LDI R17,0
01AE DF60 RCALL _crc8
01AF 9300007F STS 0x7F,R16
(0096) usart_out(send,amount); //将发件箱的数据send[]发送出去;
01B1 E02A LDI R18,0xA
01B2 E706 LDI R16,0x76
01B3 E010 LDI R17,0
01B4 DFBD RCALL _usart_out
(0097) LCD_write_string(5,0,send);
01B5 E786 LDI R24,0x76
01B6 E090 LDI R25,0
01B7 8399 STD Y+1,R25
01B8 8388 STD Y+0,R24
01B9 2722 CLR R18
01BA E005 LDI R16,5
01BB DF26 RCALL _LCD_write_string
(0098) n=0; //计数复位,准备接收新数据
01BC 2422 CLR R2
01BD 92200060 STS n,R2
(0099) delay_nms(15); //等待从机回复数据,这个时间要计算好
01BF E00F LDI R16,0xF
01C0 E010 LDI R17,0
01C1 DEAA RCALL _delay_nms
(0100)
(0101) if(n==amount && inbox[amount-1]==crc8(inbox,amount-1)) //接收正确处理与测试
01C2 91800060 LDS R24,n
01C4 308A CPI R24,0xA
01C5 F471 BNE 0x01D4
01C6 E029 LDI R18,0x9
01C7 E60C LDI R16,0x6C
01C8 E010 LDI R17,0
01C9 DF45 RCALL _crc8
01CA 90200075 LDS R2,0x75
01CC 1620 CP R2,R16
01CD F431 BNE 0x01D4
(0102) {
(0103) PORTA|=(1<<PA1); delay_nms(10); PORTA&=~(1<<PA1);
01CE 9AD9 SBI 0x1B,1
01CF E00A LDI R16,0xA
01D0 E010 LDI R17,0
01D1 DE9A RCALL _delay_nms
01D2 98D9 CBI 0x1B,1
(0104) }
01D3 C005 RJMP 0x01D9
(0105) else //接收错误处理与测试
(0106) {
(0107) PORTA|=(1<<PA2); delay_nms(10); PORTA&=~(1<<PA2);
FILE: <library>
01D4 9ADA SBI 0x1B,2
01D5 E00A LDI R16,0xA
01D6 E010 LDI R17,0
01D7 DE94 RCALL _delay_nms
01D8 98DA CBI 0x1B,2
01D9 CFCB RJMP 0x01A5
01DA 9622 ADIW R28,2
01DB 9508 RET
pop_gset2:
01DC E0E2 LDI R30,2
01DD 940C01EE JMP pop
pop_gset3:
01DF E0E4 LDI R30,4
01E0 940C01EE JMP pop
push_gset5:
01E2 92FA ST R15,-Y
01E3 92EA ST R14,-Y
push_gset4:
01E4 92DA ST R13,-Y
01E5 92CA ST R12,-Y
push_gset3:
01E6 92BA ST R11,-Y
01E7 92AA ST R10,-Y
push_gset2:
01E8 937A ST R23,-Y
01E9 936A ST R22,-Y
push_gset1:
01EA 935A ST R21,-Y
01EB 934A ST R20,-Y
01EC 9508 RET
pop_gset1:
01ED E0E1 LDI R30,1
pop:
01EE 9149 LD R20,Y+
01EF 9159 LD R21,Y+
01F0 FDE0 SBRC R30,0
01F1 9508 RET
01F2 9169 LD R22,Y+
01F3 9179 LD R23,Y+
01F4 FDE1 SBRC R30,1
01F5 9508 RET
01F6 90A9 LD R10,Y+
01F7 90B9 LD R11,Y+
01F8 FDE2 SBRC R30,2
01F9 9508 RET
01FA 90C9 LD R12,Y+
01FB 90D9 LD R13,Y+
01FC FDE3 SBRC R30,3
01FD 9508 RET
01FE 90E9 LD R14,Y+
01FF 90F9 LD R15,Y+
0200 9508 RET
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -