📄 rs485.lst
字号:
00C8 708F ANDI R24,0xF
00C9 708F ANDI R24,0xF
00CA B225 IN R2,0x15
00CB 2A28 OR R2,R24
00CC BA25 OUT 0x15,R2
(0113) LCD_en_write();
00CD DFCA RCALL _LCD_en_write
(0114)
(0115) LCD_DATA_PORT&=0Xf0; //清高四位
00CE B385 IN R24,0x15
00CF 7F80 ANDI R24,0xF0
00D0 BB85 OUT 0x15,R24
(0116) LCD_DATA_PORT|=data&0x0f; //写低四位
00D1 2F84 MOV R24,R20
00D2 708F ANDI R24,0xF
00D3 B225 IN R2,0x15
00D4 2A28 OR R2,R24
00D5 BA25 OUT 0x15,R2
(0117) LCD_en_write();
00D6 DFC1 RCALL _LCD_en_write
00D7 940E0222 CALL pop_gset1
00D9 9508 RET
_LCD_set_xy:
address --> R20
y --> R20
x --> R22
00DA 940E021D CALL push_gset2
00DC 2F42 MOV R20,R18
00DD 2F60 MOV R22,R16
(0118)
(0119)
(0120) }
(0121)
(0122)
(0123) void LCD_set_xy( unsigned char x, unsigned char y ) //写地址函数
(0124) {
(0125) unsigned char address;
(0126) if (y == 0) address = 0x80 + x;
00DE 2344 TST R20
00DF F419 BNE 0x00E3
00E0 2F46 MOV R20,R22
00E1 5840 SUBI R20,0x80
00E2 C002 RJMP 0x00E5
(0127) else address = 0xc0 + x;
00E3 2F46 MOV R20,R22
00E4 5440 SUBI R20,0x40
(0128) LCD_write_command( address);
00E5 2F04 MOV R16,R20
00E6 DFB7 RCALL _LCD_write_command
00E7 940E0211 CALL pop_gset2
00E9 9508 RET
_LCD_write_string:
s --> R20
Y --> R10
X --> R22
00EA 940E021B CALL push_gset3
00EC 2EA2 MOV R10,R18
00ED 2F60 MOV R22,R16
00EE 814E LDD R20,Y+6
00EF 815F LDD R21,Y+7
(0129) }
(0130)
(0131) void LCD_write_string(unsigned char X,unsigned char Y,unsigned char *s) //列x=0~15,行y=0,1
(0132) {
(0133) LCD_set_xy( X, Y ); //写地址
00F0 2D2A MOV R18,R10
00F1 2F06 MOV R16,R22
00F2 DFE7 RCALL _LCD_set_xy
00F3 C005 RJMP 0x00F9
(0134) while (*s) // 写显示字符
(0135) {
(0136) LCD_write_data( *s );
00F4 01FA MOVW R30,R20
00F5 8100 LDD R16,Z+0
00F6 DFC5 RCALL _LCD_write_data
(0137) s ++;
00F7 5F4F SUBI R20,0xFF
00F8 4F5F SBCI R21,0xFF
00F9 01FA MOVW R30,R20
00FA 8020 LDD R2,Z+0
00FB 2022 TST R2
00FC F7B9 BNE 0x00F4
00FD 940E0214 CALL pop_gset3
00FF 9508 RET
_LCD_write_char:
data --> Y+4
Y --> R22
X --> R20
0100 940E021D CALL push_gset2
0102 2F62 MOV R22,R18
0103 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 ); //写地址
0104 2F26 MOV R18,R22
0105 2F04 MOV R16,R20
0106 DFD3 RCALL _LCD_set_xy
(0145) LCD_write_data( data);
0107 810C LDD R16,Y+4
0108 DFB3 RCALL _LCD_write_data
0109 940E0211 CALL pop_gset2
010B 9508 RET
FILE: F:\ChengXuCunFang\ChengXU\AVR单片机程序存放\max485多机通讯1\新建文件夹\485_slave3\usart.h
(0001) #define BAUDRATE 9600 //波特率
(0002) #define F_CPU 7327800
(0003)
(0004)
(0005) //波特率9600/9个数据位/1个停止位/奇校验/收发开启/接收中断
(0006) void usart_init(void)
(0007) {
(0008) UCSRA=0x01;//多机通讯模式(MPCM=1)
_usart_init:
010C E081 LDI R24,1
010D B98B OUT 0x0B,R24
(0009) UCSRB=0x9C;
010E E98C LDI R24,0x9C
010F B98A OUT 0x0A,R24
(0010) UCSRC=0xB6;
0110 EB86 LDI R24,0xB6
0111 BD80 OUT 0x20,R24
(0011) UBRRL= (F_CPU/BAUDRATE/16-1)%256;
0112 E28E LDI R24,0x2E
0113 B989 OUT 0x09,R24
(0012) UBRRH= (F_CPU/BAUDRATE/16-1)/256;
0114 2422 CLR R2
0115 BC20 OUT 0x20,R2
(0013) PORTD &=~(1<<PD4);
0116 9894 CBI 0x12,4
(0014) DDRD|=(1<<PD4);
0117 9A8C SBI 0x11,4
0118 9508 RET
_usart_out:
i --> R20
n --> R22
datas --> R10
0119 940E021B CALL push_gset3
011B 2F62 MOV R22,R18
011C 0158 MOVW R10,R16
(0015) }
(0016)
(0017) //-----------------------------------------------------------
(0018) //从数组datas[]的首地址开始发送amount个数据,其中第0个数据是地址帧,其他是数据帧
(0019) void usart_out(unsigned char *datas,unsigned char n)
(0020) {
(0021) unsigned char i=0;
011D 2744 CLR R20
(0022) //PORTD|=0x08; //使MAX485处于发送状态
(0023) PORTD |=(1<<PD4);
011E 9A94 SBI 0x12,4
011F C014 RJMP 0x0134
(0024) while(i<n )//一共发送amount个数据
(0025) {
(0026) if(i==0) UCSRB|=0x01;
0120 2344 TST R20
0121 F411 BNE 0x0124
0122 9A50 SBI 0x0A,0
0123 C003 RJMP 0x0127
(0027) else UCSRB&=0xfe;
0124 B18A IN R24,0x0A
0125 7F8E ANDI R24,0xFE
0126 B98A OUT 0x0A,R24
(0028) UDR=*(datas+i); //装载数据开始发送
0127 2FE4 MOV R30,R20
0128 27FF CLR R31
0129 0DEA ADD R30,R10
012A 1DFB ADC R31,R11
012B 8020 LDD R2,Z+0
012C B82C OUT 0x0C,R2
(0029) while((UCSRA&0x40)==0); //等待发送结束
012D 9B5E SBIS 0x0B,6
012E CFFE RJMP 0x012D
(0030) UCSRA|=0x40; //清除发送结束标志
012F 9A5E SBI 0x0B,6
(0031) i++; //发送次数统计
0130 9543 INC R20
(0032) delay_nus(100);//每次发送必须有间隔,这个是最小值,实际情况可能还要加大
0131 E604 LDI R16,0x64
0132 E010 LDI R17,0
0133 DF27 RCALL _delay_nus
0134 1746 CP R20,R22
0135 F350 BCS 0x0120
(0033) }
(0034) PORTD &=~(1<<PD4);
0136 9894 CBI 0x12,4
0137 940E0214 CALL pop_gset3
0139 9508 RET
_crc8:
crc --> R20
i --> R22
len --> R18
ptr --> R16
013A 940E021D CALL push_gset2
FILE: F:\ChengXuCunFang\ChengXU\AVR单片机程序存放\max485多机通讯1\新建文件夹\485_slave3\crc.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;
013C 2744 CLR R20
013D C020 RJMP 0x015E
(0008) while(len--!=0)
(0009) {
(0010) for(i=1; i!=0; i*=2)
013E E061 LDI R22,1
013F C01A RJMP 0x015A
(0011) {
(0012) if((crc&1)!=0) {crc/=2; crc^=0x8C;}
0140 FF40 SBRS R20,0
0141 C009 RJMP 0x014B
0142 9546 LSR R20
0143 E88C LDI R24,0x8C
0144 E090 LDI R25,0
0145 2E24 MOV R2,R20
0146 2433 CLR R3
0147 2628 EOR R2,R24
0148 2639 EOR R3,R25
0149 2D42 MOV R20,R2
014A C001 RJMP 0x014C
(0013) else crc/=2;
014B 9546 LSR R20
(0014) if((*ptr&i)!=0) crc^=0x8C;
014C 01F8 MOVW R30,R16
014D 8020 LDD R2,Z+0
014E 2226 AND R2,R22
014F F039 BEQ 0x0157
0150 E88C LDI R24,0x8C
0151 E090 LDI R25,0
0152 2E24 MOV R2,R20
0153 2433 CLR R3
0154 2628 EOR R2,R24
0155 2639 EOR R3,R25
0156 2D42 MOV R20,R2
0157 E082 LDI R24,2
0158 9F86 MUL R24,R22
0159 2D60 MOV R22,R0
015A 2366 TST R22
015B F721 BNE 0x0140
(0015) }
(0016) ptr++;
015C 5F0F SUBI R16,0xFF
015D 4F1F SBCI R17,0xFF
015E 2E22 MOV R2,R18
015F 2433 CLR R3
0160 5021 SUBI R18,1
0161 2022 TST R2
0162 F6D9 BNE 0x013E
(0017) }
(0018) return(crc);
0163 2F04 MOV R16,R20
0164 940E0211 CALL pop_gset2
0166 9508 RET
_RXC_Int:
ERROR --> R20
0167 940E0236 CALL push_lset
0169 940E021F CALL push_gset1
FILE: F:\ChengXuCunFang\ChengXU\AVR单片机程序存放\max485多机通讯1\新建文件夹\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 "crc.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;
016B 2744 CLR R20
(0037)
(0038) if( UCSRA&0x04 || UCSRA&0x10 ) ERROR=1; //记录奇偶效验错误或者帧错误
016C 995A SBIC 0x0B,2
016D C002 RJMP 0x0170
016E 9B5C SBIS 0x0B,4
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -