📄 485.lst
字号:
011D C011 RJMP 0x012F
(0020) while(i<n) //一共发送amount个数据
(0021) {
(0022) if(i==0) UCSRB|=0x01;
011E 2344 TST R20
011F F411 BNE 0x0122
0120 9A50 SBI 0x0A,0
0121 C003 RJMP 0x0125
(0023) else UCSRB&=0xfe;
0122 B18A IN R24,0x0A
0123 7F8E ANDI R24,0xFE
0124 B98A OUT 0x0A,R24
(0024) UDR=*(datas+i); //装载数据开始发送
0125 2FE4 MOV R30,R20
0126 27FF CLR R31
0127 0FE0 ADD R30,R16
0128 1FF1 ADC R31,R17
0129 8020 LDD R2,Z+0
012A B82C OUT 0x0C,R2
(0025) while((UCSRA&0x40)==0); //等待发送结束
012B 9B5E SBIS 0x0B,6
012C CFFE RJMP 0x012B
(0026) UCSRA|=0x40; //清除发送结束标志
012D 9A5E SBI 0x0B,6
(0027) i++; //发送次数统计
012E 9543 INC R20
012F 1742 CP R20,R18
0130 F368 BCS 0x011E
(0028) }
(0029) PORTD&=~0x08; //使MAX485处于接收状态
0131 9893 CBI 0x12,3
0132 940E021D CALL pop_gset1
0134 9508 RET
_crc8:
crc --> R20
i --> R22
len --> R18
ptr --> R16
0135 940E0218 CALL push_gset2
FILE: D:\avr\+++精华+++\485\485_slave3\crc8.h
(0001) //---------------------------------------------------------------------------------
(0002) //crc8校验程序
(0003) //---------------------------------------------------------------------------------
(0004) unsigned char crc8(unsigned char *ptr, unsigned char len)
(0005) {
(0006) unsigned char i;
(0007) unsigned char crc=0;
0137 2744 CLR R20
0138 C020 RJMP 0x0159
(0008) while(len--!=0)
(0009) {
(0010) for(i=1; i!=0; i*=2)
0139 E061 LDI R22,1
013A C01A RJMP 0x0155
(0011) {
(0012) if((crc&1)!=0) {crc/=2; crc^=0x8C;}
013B FF40 SBRS R20,0
013C C009 RJMP 0x0146
013D 9546 LSR R20
013E E88C LDI R24,0x8C
013F E090 LDI R25,0
0140 2E24 MOV R2,R20
0141 2433 CLR R3
0142 2628 EOR R2,R24
0143 2639 EOR R3,R25
0144 2D42 MOV R20,R2
0145 C001 RJMP 0x0147
(0013) else crc/=2;
0146 9546 LSR R20
(0014) if((*ptr&i)!=0) crc^=0x8C;
0147 01F8 MOVW R30,R16
0148 8020 LDD R2,Z+0
0149 2226 AND R2,R22
014A F039 BEQ 0x0152
014B E88C LDI R24,0x8C
014C E090 LDI R25,0
014D 2E24 MOV R2,R20
014E 2433 CLR R3
014F 2628 EOR R2,R24
0150 2639 EOR R3,R25
0151 2D42 MOV R20,R2
0152 E082 LDI R24,2
0153 9F86 MUL R24,R22
0154 2D60 MOV R22,R0
0155 2366 TST R22
0156 F721 BNE 0x013B
(0015) }
(0016) ptr++;
0157 5F0F SUBI R16,0xFF
0158 4F1F SBCI R17,0xFF
0159 2E22 MOV R2,R18
015A 2433 CLR R3
015B 5021 SUBI R18,1
015C 2022 TST R2
015D F6D9 BNE 0x0139
(0017) }
(0018) return(crc);
015E 2F04 MOV R16,R20
015F 940E020C CALL pop_gset2
0161 9508 RET
_RXC_Int:
ERROR --> R20
0162 940E0231 CALL push_lset
0164 940E021A CALL push_gset1
FILE: D:\avr\+++精华+++\485\485_slave3\main.c
(0001) /*******************************************************************************
(0002) 485多机通讯
(0003) --------------------------------------------------------------------------------
(0004) 通讯规则:
(0005) 1:时钟7.3728 MHz/波特率9600/9个数据位/奇校验/1个停止位/硬件多机通讯功能/
(0006) 2:通讯连接采用硬件MAX485,双向单工
(0007) 3:每个上行/下行的数据包的字节个数都是一样的(通讯数据量)
(0008) 4:每个上行/下行的数据包都采用CRC8校验
(0009) 5:数据接收采用中断+查询的方式
(0010) 6:总是由主机向从机发送一个数据包,从机收到数据包后向主机回复一个数据包
(0011) 7:不管是主机还是从机,如果收到的数据包有任何错误,都将丢弃该数据包,等效于没有接收
(0012) 8:从机之间不能相互通讯,必须通过主机才能交换数据
(0013) 9:无效地址是0,主机地址是1,从机地址是2.3.4......广播地址是255
(0014) ********************************************************************************/
(0015)
(0016) #include <iom16v.h>
(0017) #include <macros.h>
(0018) #include "1602.h"
(0019) #include "delay.h"
(0020) #include "usart.h"
(0021) #include "crc8.h" //CRC校验函数就在这个文件里面
(0022)
(0023) #define amount 10 //设定通讯数据量(包括1个地址帧,n个数据帧,1个校验帧)
(0024) #define address 3 //请在这里设定本机地址
(0025)
(0026) unsigned char send[amount]; //发件箱
(0027) unsigned char inbox[amount]; //收件箱
(0028) unsigned char n=0; //记忆中断次数
(0029) unsigned char flag_me=0; //个人数据标志
(0030) unsigned char flag_all=0; //广播数据标志
(0031)
(0032) //-------------------从机接收子程序--------------------------------
(0033) #pragma interrupt_handler RXC_Int: 12
(0034) void RXC_Int(void) //接收中断
(0035) {
(0036) unsigned char ERROR=0;
0166 2744 CLR R20
(0037)
(0038) if( UCSRA&0x04 || UCSRA&0x10 ) ERROR=1; //记录奇偶效验错误或者帧错误
0167 995A SBIC 0x0B,2
0168 C002 RJMP 0x016B
0169 9B5C SBIS 0x0B,4
016A C001 RJMP 0x016C
016B E041 LDI R20,1
(0039) inbox[n]=UDR; //把接收到的数据保存到收件箱
016C E78C LDI R24,0x7C
016D E090 LDI R25,0
016E 91E00060 LDS R30,n
0170 27FF CLR R31
0171 0FE8 ADD R30,R24
0172 1FF9 ADC R31,R25
0173 B02C IN R2,0x0C
0174 8220 STD Z+0,R2
(0040) n++;
0175 91800060 LDS R24,n
0177 5F8F SUBI R24,0xFF
0178 93800060 STS n,R24
(0041) //记忆接收的次数
(0042)
(0043) if(ERROR) //如果通讯有错....
017A 2344 TST R20
017B F021 BEQ 0x0180
(0044) {
(0045) //n=0; //接收计数清0
(0046) inbox[0]=0; //把地址改为无效地址0
017C 2422 CLR R2
017D 9220007C STS inbox,R2
(0047) UCSRA|=0x01; //重新打开接收器的地址帧筛选功能
017F 9A58 SBI 0x0B,0
(0048) }
(0049) //如果地址匹配本机或者是广播地址就关闭地址筛选(多机通讯)功能 (关闭是为了保证后面的数据全部接收到)
(0050) if(inbox[0]==address ||inbox[0]==0xff) {UCSRA&=~0x01; }
0180 9180007C LDS R24,inbox
0182 3083 CPI R24,3
0183 F011 BEQ 0x0186
0184 3F8F CPI R24,0xFF
0185 F409 BNE 0x0187
0186 9858 CBI 0x0B,0
(0051) if(n==amount) //接收到amount个数据以后...
0187 91800060 LDS R24,n
0189 308A CPI R24,0xA
018A F4D1 BNE 0x01A5
(0052) {
(0053) n=0; //接收计数清0
018B 2422 CLR R2
018C 92200060 STS n,R2
(0054) UCSRA|=0x01; //重新打开接收器的地址帧筛选功能
018E 9A58 SBI 0x0B,0
(0055)
(0056)
(0057)
(0058)
(0059) if(inbox[amount-1]==crc8(inbox,amount-1)) //如果crc8校验正确就...
018F E029 LDI R18,0x9
0190 E70C LDI R16,0x7C
0191 E010 LDI R17,0
0192 DFA2 RCALL _crc8
0193 90200085 LDS R2,0x85
0195 1620 CP R2,R16
0196 F471 BNE 0x01A5
(0060) {
(0061) if(inbox[0]==address)flag_me=1; //本机地址
0197 9180007C LDS R24,inbox
0199 3083 CPI R24,3
019A F419 BNE 0x019E
019B E081 LDI R24,1
019C 93800061 STS flag_me,R24
(0062) //接收完数据后会置标志位,在读取数据后要把标志位置零
(0063) if(inbox[0]==255) flag_me=1; //广播地址,接收后不要回复
019E 9180007C LDS R24,inbox
01A0 3F8F CPI R24,0xFF
01A1 F419 BNE 0x01A5
01A2 E081 LDI R24,1
01A3 93800061 STS flag_me,R24
(0064) //接收完数据后会置标志位,在读取数据后要把标志位置零
(0065) }
(0066) }
01A5 940E021D CALL pop_gset1
01A7 940E0248 CALL pop_lset
01A9 9518 RETI
_out_485:
i --> R20
ptr --> R22
01AA 940E0218 CALL push_gset2
01AC 01B8 MOVW R22,R16
(0067)
(0068) }
(0069)
(0070)
(0071) void out_485(unsigned char *ptr)
(0072) {unsigned char i;
(0073)
(0074) send[0]=1; //发件箱地址指向主机
01AD E081 LDI R24,1
01AE 93800086 STS send,R24
(0075) for(i=1;i<amount-1;i++)send[i]=*ptr++;//把发送的数据方到发信箱
01B0 E041 LDI R20,1
01B1 C00B RJMP 0x01BD
01B2 E886 LDI R24,0x86
01B3 E090 LDI R25,0
01B4 2FE4 MOV R30,R20
01B5 27FF CLR R31
01B6 0FE8 ADD R30,R24
01B7 1FF9 ADC R31,R25
01B8 01DB MOVW R26,R22
01B9 902D LD R2,X+
01BA 01BD MOVW R22,R26
01BB 8220 STD Z+0,R2
01BC 9543 INC R20
01BD 3049 CPI R20,0x9
01BE F398 BCS 0x01B2
(0076) send[amount-1]=crc8(send,amount-1); //计算发件箱的crc8校验码
01BF E029 LDI R18,0x9
01C0 E806 LDI R16,0x86
01C1 E010 LDI R17,0
01C2 DF72 RCALL _crc8
01C3 9300008F STS 0x8F,R16
(0077) usart_out(send,amount); //将发件箱的数据send[]发送出去
01C5 E02A LDI R18,0xA
01C6 E806 LDI R16,0x86
01C7 E010 LDI R17,0
01C8 DF50 RCALL _usart_out
01C9 940E020C CALL pop_gset2
01CB 9508 RET
_main:
01CC 9722 SBIW R28,2
(0078)
(0079) }
(0080)
(0081) //------------------------主函数---------------------------------
(0082) void main(void)
(0083) {
(0084) usart_init();
01CD DF3E RCALL _usart_init
(0085) SEI();
01CE 9478 BSET 7
(0086) LCD_init();
01CF DEB3 RCALL _LCD_init
(0087) LCD_write_string(0,0,"out:");
01D0 E787 LDI R24,0x77
01D1 E090 LDI R25,0
01D2 8399 STD Y+1,R25
01D3 8388 STD Y+0,R24
01D4 2722 CLR R18
01D5 2700 CLR R16
01D6 DF13 RCALL _LCD_write_string
(0088) LCD_write_string(0,1,"int:");
01D7 E782 LDI R24,0x72
01D8 E090 LDI R25,0
01D9 8399 STD Y+1,R25
01DA 8388 STD Y+0,R24
01DB E021 LDI R18,1
01DC 2700 CLR R16
01DD DF0C RCALL _LCD_write_string
01DE C02A RJMP 0x0209
(0089) while (1)
(0090) {
(0091) while(flag_me)
(0092) { LCD_write_string(4,1,inbox);
01DF E78C LDI R24,0x7C
01E0 E090 LDI R25,0
01E1 8399 STD Y+1,R25
01E2 8388 STD Y+0,R24
01E3 E021 LDI R18,1
01E4 E004 LDI R16,4
01E5 DF04 RCALL _LCD_write_string
(0093) n=0; //中断次数清0
01E6 2422 CLR R2
01E7 92200060 STS n,R2
(0094) inbox[0]=0; //收件箱地址清0
01E9 9220007C STS inbox,R2
(0095) flag_me=0;
01EB 92200061 STS flag_me,R2
(0096) out_485("3,ok!!!!");
01ED E609 LDI R16,0x69
01EE E010 LDI R17,0
01EF DFBA RCALL _out_485
(0097) LCD_write_string(4,0,send);
01F0 E886 LDI R24,0x86
01F1 E090 LDI R25,0
01F2 8399 STD Y+1,R25
01F3 8388 STD Y+0,R24
01F4 2722 CLR R18
01F5 E004 LDI R16,4
01F6 DEF3 RCALL _LCD_write_string
(0098) LCD_write_string(13,0," ");
01F7 E683 LDI R24,0x63
01F8 E090 LDI R25,0
01F9 8399 STD Y+1,R25
01FA 8388 STD Y+0,R24
01FB 2722 CLR R18
01FC E00D LDI R16,0xD
01FD DEEC RCALL _LCD_write_string
(0099) LCD_write_string(13,1," ");
01FE E683 LDI R24,0x63
01FF E090 LDI R25,0
0200 8399 STD Y+1,R25
0201 8388 STD Y+0,R24
0202 E021 LDI R18,1
0203 E00D LDI R16,0xD
0204 DEE5 RCALL _LCD_write_string
0205 90200061 LDS R2,flag_me
0207 2022 TST R2
0208 F6B1 BNE 0x01DF
0209 CFFB RJMP 0x0205
(0100)
(0101)
(0102) }
(0103) };
FILE: <library>
020A 9622 ADIW R28,2
020B 9508 RET
pop_gset2:
020C E0E2 LDI R30,2
020D 940C021E JMP pop
pop_gset3:
020F E0E4 LDI R30,4
0210 940C021E JMP pop
push_gset5:
0212 92FA ST R15,-Y
0213 92EA ST R14,-Y
push_gset4:
0214 92DA ST R13,-Y
0215 92CA ST R12,-Y
push_gset3:
0216 92BA ST R11,-Y
0217 92AA ST R10,-Y
push_gset2:
0218 937A ST R23,-Y
0219 936A ST R22,-Y
push_gset1:
021A 935A ST R21,-Y
021B 934A ST R20,-Y
021C 9508 RET
pop_gset1:
021D E0E1 LDI R30,1
pop:
021E 9149 LD R20,Y+
021F 9159 LD R21,Y+
0220 FDE0 SBRC R30,0
0221 9508 RET
0222 9169 LD R22,Y+
0223 9179 LD R23,Y+
0224 FDE1 SBRC R30,1
0225 9508 RET
0226 90A9 LD R10,Y+
0227 90B9 LD R11,Y+
0228 FDE2 SBRC R30,2
0229 9508 RET
022A 90C9 LD R12,Y+
022B 90D9 LD R13,Y+
022C FDE3 SBRC R30,3
022D 9508 RET
022E 90E9 LD R14,Y+
022F 90F9 LD R15,Y+
0230 9508 RET
push_lset:
0231 93FA ST R31,-Y
0232 93EA ST R30,-Y
0233 93BA ST R27,-Y
0234 93AA ST R26,-Y
0235 939A ST R25,-Y
0236 938A ST R24,-Y
0237 933A ST R19,-Y
0238 932A ST R18,-Y
0239 931A ST R17,-Y
023A 930A ST R16,-Y
023B 929A ST R9,-Y
023C 928A ST R8,-Y
023D 927A ST R7,-Y
023E 926A ST R6,-Y
023F 925A ST R5,-Y
0240 924A ST R4,-Y
0241 923A ST R3,-Y
0242 922A ST R2,-Y
0243 921A ST R1,-Y
0244 920A ST R0,-Y
0245 B60F IN R0,0x3F
0246 920A ST R0,-Y
0247 9508 RET
pop_lset:
0248 9009 LD R0,Y+
0249 BE0F OUT 0x3F,R0
024A 9009 LD R0,Y+
024B 9019 LD R1,Y+
024C 9029 LD R2,Y+
024D 9039 LD R3,Y+
024E 9049 LD R4,Y+
024F 9059 LD R5,Y+
0250 9069 LD R6,Y+
0251 9079 LD R7,Y+
0252 9089 LD R8,Y+
0253 9099 LD R9,Y+
0254 9109 LD R16,Y+
0255 9119 LD R17,Y+
0256 9129 LD R18,Y+
0257 9139 LD R19,Y+
0258 9189 LD R24,Y+
0259 9199 LD R25,Y+
025A 91A9 LD R26,Y+
025B 91B9 LD R27,Y+
025C 91E9 LD R30,Y+
025D 91F9 LD R31,Y+
025E 9508 RET
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -