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

📄 485.lst

📁 485多机通讯
💻 LST
📖 第 1 页 / 共 3 页
字号:
    0228 939A      ST	R25,-Y
    0229 93EA      ST	R30,-Y
    022A 93FA      ST	R31,-Y
    022B B62F      IN	R2,0x3F
    022C 922A      ST	R2,-Y
FILE: D:\avr\+++精华+++\485\485_master\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 "delay.h" 
(0019) #include "1602.h" 
(0020) #include "usart.h" 
(0021) #include "crc8.h" //CRC校验函数就在这个文件里面 
(0022) #include "key.h" 
(0023) #define amount 10 //设定通讯数据量(包括1个地址帧,n个数据帧,1个校验帧) 
(0024) 
(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) 
(0034) //-------------------主机接收子程序-------------------------------- 
(0035) #pragma interrupt_handler RXC_Int: 12
(0036) void RXC_Int(void) //接收中断 
(0037) { 
(0038)  unsigned char ERROR=0; 
    022D 2700      CLR	R16
(0039)  if(UCSRA&0x08||UCSRA&0x10 )ERROR=1; //奇偶效验错误(avr自动完成)或者帧错误就记录下来
    022E 995B      SBIC	0x0B,3
    022F C002      RJMP	0x0232
    0230 9B5C      SBIS	0x0B,4
    0231 C001      RJMP	0x0233
    0232 E001      LDI	R16,1
(0040)  inbox[n]=UDR;
    0233 E886      LDI	R24,0x86
    0234 E090      LDI	R25,0
    0235 91E00060  LDS	R30,n
    0237 27FF      CLR	R31
    0238 0FE8      ADD	R30,R24
    0239 1FF9      ADC	R31,R25
    023A B02C      IN	R2,0x0C
    023B 8220      STD	Z+0,R2
(0041)  n++; //记忆中断次数 
    023C 91800060  LDS	R24,n
    023E 5F8F      SUBI	R24,0xFF
    023F 93800060  STS	n,R24
(0042)  if(ERROR) inbox[0]=0; //如果通讯有错,收件箱的地址帧就标记成无效地址0 
    0241 2300      TST	R16
    0242 F019      BEQ	0x0246
    0243 2422      CLR	R2
    0244 92200086  STS	inbox,R2
    0246 9029      LD	R2,Y+
    0247 BE2F      OUT	0x3F,R2
    0248 91F9      LD	R31,Y+
    0249 91E9      LD	R30,Y+
    024A 9199      LD	R25,Y+
    024B 9189      LD	R24,Y+
    024C 9109      LD	R16,Y+
    024D 9029      LD	R2,Y+
    024E 9518      RETI
(0043) } 
(0044) 
(0045) void int_485(void)//接收程序,在中断中调用或者扫描调用
(0046) {
(0047)  //if(n<3) 如果接收到的数据还不到3个,那么就是通讯线路故障 
(0048) 
(0049)    //如果收件箱已经收到amount个数据,并且crc8校验成功就... 
(0050)    if(n==amount && inbox[amount-1]==crc8(inbox,amount-1)) 
_int_485:
    024F 91800060  LDS	R24,n
    0251 308A      CPI	R24,0xA
    0252 F4B1      BNE	0x0269
    0253 E029      LDI	R18,0x9
    0254 E806      LDI	R16,0x86
    0255 E010      LDI	R17,0
    0256 DEE8      RCALL	_crc8
    0257 9020008F  LDS	R2,0x8F
    0259 1620      CP	R2,R16
    025A F471      BNE	0x0269
(0051)     { 
(0052)      if(inbox[0]==1)flag_me=1; 
    025B 91800086  LDS	R24,inbox
    025D 3081      CPI	R24,1
    025E F419      BNE	0x0262
    025F E081      LDI	R24,1
    0260 93800061  STS	flag_me,R24
(0053) 	 //接收完数据后会置标志位	 
(0054) 	 if(inbox[0]==255) flag_me=1; //请在这里添加收到广播数据的处理程序 
    0262 91800086  LDS	R24,inbox
    0264 3F8F      CPI	R24,0xFF
    0265 F419      BNE	0x0269
    0266 E081      LDI	R24,1
    0267 93800061  STS	flag_me,R24
(0055) 	  
(0056)     } 
    0269 9508      RET
_out_485:
  i                    --> R20
  ptr                  --> R22
  address              --> R20
    026A 940E0329  CALL	push_gset2
    026C 01B9      MOVW	R22,R18
    026D 2F40      MOV	R20,R16
(0057)   
(0058) }
(0059) 
(0060) 
(0061) 
(0062) void out_485(unsigned char address,unsigned char *ptr)
(0063) {unsigned char i;
(0064)    n=0; //中断次数清0 
    026E 2422      CLR	R2
    026F 92200060  STS	n,R2
(0065)    inbox[0]=0; //收件箱地址清0 
    0271 92200086  STS	inbox,R2
(0066)    //请更新准备发送的数据 
(0067)    //send[1]=? 
(0068)    //...... 
(0069)    //send[n]=? 
(0070)    send[0]=address; //改变这个地址就可以实现与某个从机对话 
    0273 93400090  STS	send,R20
(0071)    for(i=1;i<amount-1;i++)send[i]=*ptr++;//把发送的数据方到发信箱 
    0275 E041      LDI	R20,1
    0276 C00B      RJMP	0x0282
    0277 E980      LDI	R24,0x90
    0278 E090      LDI	R25,0
    0279 2FE4      MOV	R30,R20
    027A 27FF      CLR	R31
    027B 0FE8      ADD	R30,R24
    027C 1FF9      ADC	R31,R25
    027D 01DB      MOVW	R26,R22
    027E 902D      LD	R2,X+
    027F 01BD      MOVW	R22,R26
    0280 8220      STD	Z+0,R2
    0281 9543      INC	R20
    0282 3049      CPI	R20,0x9
    0283 F398      BCS	0x0277
(0072)    	 
(0073)    send[amount-1]=crc8(send,amount-1); //计算发件箱的crc8校验码 
    0284 E029      LDI	R18,0x9
    0285 E900      LDI	R16,0x90
    0286 E010      LDI	R17,0
    0287 DEB7      RCALL	_crc8
    0288 93000099  STS	0x99,R16
(0074)     
(0075)    usart_out(send,amount); //将发件箱的数据send[]发送出去; 
    028A E02A      LDI	R18,0xA
    028B E900      LDI	R16,0x90
    028C E010      LDI	R17,0
    028D DE90      RCALL	_usart_out
(0076)   
(0077)    //等待,从机接收到数据后会回复数据的,如果是10个字节数据量,不能少于13ms!!! 
(0078)    //这个时间由人工计算,要考虑从机由于各种中断延长回复时间的可能 
(0079) 
(0080)    delay_nms(15); 
    028E E00F      LDI	R16,0xF
    028F E010      LDI	R17,0
    0290 DDE8      RCALL	_delay_nms
    0291 940E031D  CALL	pop_gset2
    0293 9508      RET
_main:
  key                  --> Y+2
  j                    --> R22
  address              --> R10
  i                    --> R12
    0294 972A      SBIW	R28,0xA
(0081) }
(0082) 
(0083) 
(0084) 
(0085) void main(void) 
(0086) { unsigned char key[8],i,address,j;
(0087)  usart_init(); //串口初始化 
    0295 DE7B      RCALL	_usart_init
(0088)  UCSRA=0x00; //主机关闭地址筛选功能(多机通讯功能)
    0296 2422      CLR	R2
    0297 B82B      OUT	0x0B,R2
(0089)  LCD_init();//液晶初始化
    0298 DDEF      RCALL	_LCD_init
(0090)  SEI(); //打开全局中断,需要macros.h支持
    0299 9478      BSET	7
(0091)  LCD_write_string(0,0,"out:");
    029A E880      LDI	R24,0x80
    029B E090      LDI	R25,0
    029C 8399      STD	Y+1,R25
    029D 8388      STD	Y+0,R24
    029E 2722      CLR	R18
    029F 2700      CLR	R16
    02A0 DE4E      RCALL	_LCD_write_string
(0092)  LCD_write_string(0,1,"int:");
    02A1 E78B      LDI	R24,0x7B
    02A2 E090      LDI	R25,0
    02A3 8399      STD	Y+1,R25
    02A4 8388      STD	Y+0,R24
    02A5 E021      LDI	R18,1
    02A6 2700      CLR	R16
    02A7 DE47      RCALL	_LCD_write_string
    02A8 C071      RJMP	0x031A
(0093)     
(0094) 
(0095)  while(1) 
(0096)   {
(0097)   //-------------以下为测试语句------------------------------------
(0098)    
(0099)   if(flag_me)
    02A9 90200061  LDS	R2,flag_me
    02AB 2022      TST	R2
    02AC F051      BEQ	0x02B7
(0100)    {
(0101)     LCD_write_string(7,1,inbox);
    02AD E886      LDI	R24,0x86
    02AE E090      LDI	R25,0
    02AF 8399      STD	Y+1,R25
    02B0 8388      STD	Y+0,R24
    02B1 E021      LDI	R18,1
    02B2 E007      LDI	R16,7
    02B3 DE3B      RCALL	_LCD_write_string
(0102)     flag_me=0;
    02B4 2422      CLR	R2
    02B5 92200061  STS	flag_me,R2
(0103)    }
(0104)   i=get_key();
    02B7 DF4E      RCALL	_get_key
    02B8 2EC0      MOV	R12,R16
(0105)   switch (i)
    02B9 2D4C      MOV	R20,R12
    02BA 2755      CLR	R21
    02BB 334D      CPI	R20,0x3D
    02BC E0E0      LDI	R30,0
    02BD 075E      CPC	R21,R30
    02BE F139      BEQ	0x02E6
    02BF E38D      LDI	R24,0x3D
    02C0 E090      LDI	R25,0
    02C1 1784      CP	R24,R20
    02C2 0795      CPC	R25,R21
    02C3 F04C      BLT	0x02CD
    02C4 324B      CPI	R20,0x2B
    02C5 E0E0      LDI	R30,0
    02C6 075E      CPC	R21,R30
    02C7 F051      BEQ	0x02D2
    02C8 324D      CPI	R20,0x2D
    02C9 E0E0      LDI	R30,0
    02CA 075E      CPC	R21,R30
    02CB F081      BEQ	0x02DC
    02CC C028      RJMP	0x02F5
    02CD 3443      CPI	R20,0x43
    02CE E0E0      LDI	R30,0
    02CF 075E      CPC	R21,R30
    02D0 F0D9      BEQ	0x02EC
    02D1 C023      RJMP	0x02F5
(0106)   	{
(0107)   case '+':{address=2;LCD_write_string(4,0,"2>>");}
    02D2 E082      LDI	R24,2
    02D3 2EA8      MOV	R10,R24
    02D4 E787      LDI	R24,0x77
    02D5 E090      LDI	R25,0
    02D6 8399      STD	Y+1,R25
    02D7 8388      STD	Y+0,R24
    02D8 2722      CLR	R18
    02D9 E004      LDI	R16,4
    02DA DE14      RCALL	_LCD_write_string
(0108)   	break;
    02DB C030      RJMP	0x030C
(0109)   case '-':{address=3;LCD_write_string(4,0,"3>>");}
    02DC E083      LDI	R24,3
    02DD 2EA8      MOV	R10,R24
    02DE E783      LDI	R24,0x73
    02DF E090      LDI	R25,0
    02E0 8399      STD	Y+1,R25
    02E1 8388      STD	Y+0,R24
    02E2 2722      CLR	R18
    02E3 E004      LDI	R16,4
    02E4 DE0A      RCALL	_LCD_write_string
(0110)   	break;
    02E5 C026      RJMP	0x030C
(0111)   case '=':out_485(address,key);
    02E6 019E      MOVW	R18,R28
    02E7 5F2E      SUBI	R18,0xFE
    02E8 4F3F      SBCI	R19,0xFF
    02E9 2D0A      MOV	R16,R10
    02EA DF7F      RCALL	_out_485
(0112)   	break;
    02EB C020      RJMP	0x030C
(0113)   case 'C':{j=0;LCD_write_string(7,0,"         ");}
    02EC 2766      CLR	R22
    02ED E689      LDI	R24,0x69
    02EE E090      LDI	R25,0
    02EF 8399      STD	Y+1,R25
    02F0 8388      STD	Y+0,R24
    02F1 2722      CLR	R18
    02F2 E007      LDI	R16,7
    02F3 DDFB      RCALL	_LCD_write_string
(0114)   	break;
    02F4 C017      RJMP	0x030C
(0115) 	default: 
(0116) 	if(j<8&&i<='9'&&i>='0'){key[j++]=i;LCD_write_char(j+6,0,i);}
    02F5 3068      CPI	R22,0x8
    02F6 F4A8      BCC	0x030C
    02F7 E389      LDI	R24,0x39
    02F8 158C      CP	R24,R12
    02F9 F090      BCS	0x030C
    02FA 2D8C      MOV	R24,R12
    02FB 3380      CPI	R24,0x30
    02FC F078      BCS	0x030C
    02FD 2E26      MOV	R2,R22
    02FE 2433      CLR	R3
    02FF 5F6F      SUBI	R22,0xFF
    0300 01CE      MOVW	R24,R28
    0301 9602      ADIW	R24,2
    0302 2DE2      MOV	R30,R2
    0303 27FF      CLR	R31
    0304 0FE8      ADD	R30,R24
    0305 1FF9      ADC	R31,R25
    0306 82C0      STD	Z+0,R12
    0307 82C8      STD	Y+0,R12
    0308 2722      CLR	R18
    0309 2F06      MOV	R16,R22
    030A 5F0A      SUBI	R16,0xFA
    030B DDF9      RCALL	_LCD_write_char
(0117) 	
(0118)   	}
(0119)   
(0120)      LCD_write_string(4,1,inbox);
    030C E886      LDI	R24,0x86
    030D E090      LDI	R25,0
    030E 8399      STD	Y+1,R25
    030F 8388      STD	Y+0,R24
    0310 E021      LDI	R18,1
    0311 E004      LDI	R16,4
    0312 DDDC      RCALL	_LCD_write_string
(0121) 	 LCD_write_string(12,1,"     ");//数组没有结束符,所以要修正液晶后面多余的乱码
FILE: <library>
    0313 E683      LDI	R24,0x63
    0314 E090      LDI	R25,0
    0315 8399      STD	Y+1,R25
    0316 8388      STD	Y+0,R24
    0317 E021      LDI	R18,1
    0318 E00C      LDI	R16,0xC
    0319 DDD5      RCALL	_LCD_write_string
    031A CF8E      RJMP	0x02A9
    031B 962A      ADIW	R28,0xA
    031C 9508      RET
pop_gset2:
    031D E0E2      LDI	R30,2
    031E 940C032F  JMP	pop
pop_gset3:
    0320 E0E4      LDI	R30,4
    0321 940C032F  JMP	pop
push_gset5:
    0323 92FA      ST	R15,-Y
    0324 92EA      ST	R14,-Y
push_gset4:
    0325 92DA      ST	R13,-Y
    0326 92CA      ST	R12,-Y
push_gset3:
    0327 92BA      ST	R11,-Y
    0328 92AA      ST	R10,-Y
push_gset2:
    0329 937A      ST	R23,-Y
    032A 936A      ST	R22,-Y
push_gset1:
    032B 935A      ST	R21,-Y
    032C 934A      ST	R20,-Y
    032D 9508      RET
pop_gset1:
    032E E0E1      LDI	R30,1
pop:
    032F 9149      LD	R20,Y+
    0330 9159      LD	R21,Y+
    0331 FDE0      SBRC	R30,0
    0332 9508      RET
    0333 9169      LD	R22,Y+
    0334 9179      LD	R23,Y+
    0335 FDE1      SBRC	R30,1
    0336 9508      RET
    0337 90A9      LD	R10,Y+
    0338 90B9      LD	R11,Y+
    0339 FDE2      SBRC	R30,2
    033A 9508      RET
    033B 90C9      LD	R12,Y+
    033C 90D9      LD	R13,Y+
    033D FDE3      SBRC	R30,3
    033E 9508      RET
    033F 90E9      LD	R14,Y+
    0340 90F9      LD	R15,Y+
    0341 9508      RET

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -