📄 485.lst
字号:
(0114)
(0115) LCD_DATA_PORT&=0Xf0; //清高四位
00EA B385 IN R24,0x15
00EB 7F80 ANDI R24,0xF0
00EC BB85 OUT 0x15,R24
(0116) LCD_DATA_PORT|=data&0x0f; //写低四位
00ED 2F84 MOV R24,R20
00EE 708F ANDI R24,0xF
00EF B225 IN R2,0x15
00F0 2A28 OR R2,R24
00F1 BA25 OUT 0x15,R2
(0117) LCD_en_write();
00F2 DFC1 RCALL _LCD_en_write
00F3 940E026C CALL pop_gset1
00F5 9508 RET
_LCD_set_xy:
address --> R20
y --> R20
x --> R22
00F6 940E0267 CALL push_gset2
00F8 2F42 MOV R20,R18
00F9 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;
00FA 2344 TST R20
00FB F419 BNE 0x00FF
00FC 2F46 MOV R20,R22
00FD 5840 SUBI R20,0x80
00FE C002 RJMP 0x0101
(0127) else address = 0xc0 + x;
00FF 2F46 MOV R20,R22
0100 5440 SUBI R20,0x40
(0128) LCD_write_command( address);
0101 2F04 MOV R16,R20
0102 DFB7 RCALL _LCD_write_command
0103 940E025B CALL pop_gset2
0105 9508 RET
_LCD_write_string:
s --> R20
Y --> R10
X --> R22
0106 940E0265 CALL push_gset3
0108 2EA2 MOV R10,R18
0109 2F60 MOV R22,R16
010A 814E LDD R20,Y+6
010B 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 ); //写地址
010C 2D2A MOV R18,R10
010D 2F06 MOV R16,R22
010E DFE7 RCALL _LCD_set_xy
010F C005 RJMP 0x0115
(0134) while (*s) // 写显示字符
(0135) {
(0136) LCD_write_data( *s );
0110 01FA MOVW R30,R20
0111 8100 LDD R16,Z+0
0112 DFC5 RCALL _LCD_write_data
(0137) s ++;
0113 5F4F SUBI R20,0xFF
0114 4F5F SBCI R21,0xFF
0115 01FA MOVW R30,R20
0116 8020 LDD R2,Z+0
0117 2022 TST R2
0118 F7B9 BNE 0x0110
0119 940E025E CALL pop_gset3
011B 9508 RET
_LCD_write_char:
data --> Y+4
Y --> R22
X --> R20
011C 940E0267 CALL push_gset2
011E 2F62 MOV R22,R18
011F 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 ); //写地址
0120 2F26 MOV R18,R22
0121 2F04 MOV R16,R20
0122 DFD3 RCALL _LCD_set_xy
(0145) LCD_write_data( data);
0123 810C LDD R16,Y+4
0124 DFB3 RCALL _LCD_write_data
0125 940E025B CALL pop_gset2
0127 9508 RET
FILE: D:\mojinpan\485\485_slave2\usart.h
(0001) #define BAUDRATE 9600 //波特率
(0002) #define F_CPU 8000000
(0003)
(0004)
(0005) //波特率9600/9个数据位/1个停止位/奇校验/收发开启/接收中断
(0006) void usart_init(void)
(0007) {
(0008) UCSR1A=0x01;
_usart_init:
0128 E081 LDI R24,1
0129 9380009B STS 0x9B,R24
(0009) UCSR1B=0x9C;
012B E98C LDI R24,0x9C
012C 9380009A STS 0x9A,R24
(0010) UCSR1C=0x36;
012E E386 LDI R24,0x36
012F 9380009D STS 0x9D,R24
(0011) UBRR1L= (F_CPU/BAUDRATE/16-1)%256;
0131 E383 LDI R24,0x33
0132 93800099 STS 0x99,R24
(0012) UBRR1H= (F_CPU/BAUDRATE/16-1)/256;
0134 2422 CLR R2
0135 92200098 STS 0x98,R2
(0013)
(0014) PORTE&=~0x80; //MAX485平时工作在接收状态
0137 981F CBI 0x03,7
(0015) DDRE|=0x80;
0138 9A17 SBI 0x02,7
0139 9508 RET
_usart_out:
i --> R20
n --> R22
datas --> R10
013A 940E0265 CALL push_gset3
013C 2F62 MOV R22,R18
013D 0158 MOVW R10,R16
(0016) }
(0017)
(0018) //-----------------------------------------------------------
(0019) //从数组datas[]的首地址开始发送amount个数据,其中第0个数据是地址帧,其他是数据帧
(0020) void usart_out(unsigned char *datas,unsigned char n)
(0021) {
(0022) unsigned char i=0;
013E 2744 CLR R20
(0023) PORTE|=0x80; //使MAX485处于发送状态
013F 9A1F SBI 0x03,7
0140 C021 RJMP 0x0162
(0024) while(i<n) //一共发送amount个数据
(0025) {
(0026) if(i==0) UCSR1B|=0x01;
0141 2344 TST R20
0142 F431 BNE 0x0149
0143 9180009A LDS R24,0x9A
0145 6081 ORI R24,1
0146 9380009A STS 0x9A,R24
0148 C005 RJMP 0x014E
(0027) else UCSR1B&=0xfe;
0149 9180009A LDS R24,0x9A
014B 7F8E ANDI R24,0xFE
014C 9380009A STS 0x9A,R24
(0028) UDR1=*(datas+i); //装载数据开始发送
014E 2FE4 MOV R30,R20
014F 27FF CLR R31
0150 0DEA ADD R30,R10
0151 1DFB ADC R31,R11
0152 8020 LDD R2,Z+0
0153 9220009C STS 0x9C,R2
(0029) while((UCSR1A&0x40)==0); //等待发送结束
0155 9020009B LDS R2,0x9B
0157 FE26 SBRS R2,6
0158 CFFC RJMP 0x0155
(0030) UCSR1A|=0x40; //清除发送结束标志
0159 9180009B LDS R24,0x9B
015B 6480 ORI R24,0x40
015C 9380009B STS 0x9B,R24
(0031) i++; //发送次数统计
015E 9543 INC R20
(0032) delay_nus(100);//每次发送必须有间隔,这个是最小值,实际情况可能还要加大
015F E604 LDI R16,0x64
0160 E010 LDI R17,0
0161 DF15 RCALL _delay_nus
0162 1746 CP R20,R22
0163 F2E8 BCS 0x0141
(0033) }
(0034) PORTE&=~0x80; //使MAX485处于接收状态
0164 981F CBI 0x03,7
0165 940E025E CALL pop_gset3
0167 9508 RET
_crc8:
crc --> R20
i --> R22
len --> R18
ptr --> R16
0168 940E0267 CALL push_gset2
FILE: D:\mojinpan\485\485_slave2\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;
016A 2744 CLR R20
016B C020 RJMP 0x018C
(0008) while(len--!=0)
(0009) {
(0010) for(i=1; i!=0; i*=2)
016C E061 LDI R22,1
016D C01A RJMP 0x0188
(0011) {
(0012) if((crc&1)!=0) {crc/=2; crc^=0x8C;}
016E FF40 SBRS R20,0
016F C009 RJMP 0x0179
0170 9546 LSR R20
0171 E88C LDI R24,0x8C
0172 E090 LDI R25,0
0173 2E24 MOV R2,R20
0174 2433 CLR R3
0175 2628 EOR R2,R24
0176 2639 EOR R3,R25
0177 2D42 MOV R20,R2
0178 C001 RJMP 0x017A
(0013) else crc/=2;
0179 9546 LSR R20
(0014) if((*ptr&i)!=0) crc^=0x8C;
017A 01F8 MOVW R30,R16
017B 8020 LDD R2,Z+0
017C 2226 AND R2,R22
017D F039 BEQ 0x0185
017E E88C LDI R24,0x8C
017F E090 LDI R25,0
0180 2E24 MOV R2,R20
0181 2433 CLR R3
0182 2628 EOR R2,R24
0183 2639 EOR R3,R25
0184 2D42 MOV R20,R2
0185 E082 LDI R24,2
0186 9F86 MUL R24,R22
0187 2D60 MOV R22,R0
0188 2366 TST R22
0189 F721 BNE 0x016E
(0015) }
(0016) ptr++;
018A 5F0F SUBI R16,0xFF
018B 4F1F SBCI R17,0xFF
018C 2E22 MOV R2,R18
018D 2433 CLR R3
018E 5021 SUBI R18,1
018F 2022 TST R2
0190 F6D9 BNE 0x016C
(0017) }
(0018) return(crc);
0191 2F04 MOV R16,R20
0192 940E025B CALL pop_gset2
0194 9508 RET
_RXC_Int:
ERROR --> R20
0195 940E0280 CALL push_lset
0197 940E0269 CALL push_gset1
0199 9722 SBIW R28,2
FILE: D:\mojinpan\485\485_slave2\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 <iom64v.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 2 //请在这里设定本机地址
(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: 31
(0034) void RXC_Int(void) //接收中断
(0035) {
(0036) unsigned char ERROR=0;
019A 2744 CLR R20
(0037)
(0038) if( UCSR1A&0x04 || UCSR1A&0x10 ) ERROR=1; //记录奇偶效验错误或者帧错误
019B 9020009B LDS R2,0x9B
019D FC22 SBRC R2,2
019E C004 RJMP 0x01A3
019F 9020009B LDS R2,0x9B
01A1 FE24 SBRS R2,4
01A2 C001 RJMP 0x01A4
01A3 E041 LDI R20,1
(0039) inbox[n]=UDR1; //把接收到的数据保存到收件箱
01A4 E18C LDI R24,0x1C
01A5 E091 LDI R25,1
01A6 91E00100 LDS R30,n
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -