📄 main.s
字号:
;
; Bit_Field_Clear(0x1c,0x08);//将EIR.TXIF位清零
ldi R18,8
ldi R16,28
xcall _Bit_Field_Clear
.dbline 96
; //Bit_Field_Set(0x1b,0x88);//将EIE.TXIE位和EIE.INTIE位置1允许在发送完成后产生中断。
; Bit_Field_Set(0x1f,0x08);//将ECON1.TXRTS 位置1开始发送
ldi R18,8
ldi R16,31
xcall _Bit_Field_Set
.dbline -2
.dbline 97
; }
L18:
adiw R28,3
xcall pop_gset1
.dbline 0 ; func end
ret
.dbsym r i 20 c
.dbend
.dbfunc e ARP_request_or_answer _ARP_request_or_answer fc
; ARPflag -> R16
.even
_ARP_request_or_answer::
.dbline -1
.dbline 100
; //########从当前接收到的数据包中判断是不是本地ARP请求帧,是则返回1,否返回0#########//
; uchar ARP_request_or_answer(void)
; {uchar ARPflag=0;//
.dbline 100
clr R16
.dbline 101
; if(Rec_packet[12]==0x08 && Rec_packet[13]==0x06)//如果符合则表示当前数据包是ARP帧
lds R24,_Rec_packet+12
cpi R24,8
brne L40
lds R24,_Rec_packet+13
cpi R24,6
brne L40
.dbline 102
; if(Rec_packet[20]==0x00 && Rec_packet[21]==0x01)//如果符合则表示当前数据包是ARP请求帧
lds R2,_Rec_packet+20
tst R2
brne L44
lds R24,_Rec_packet+21
cpi R24,1
brne L44
.dbline 103
; if(Rec_packet[38]==IpHead[12] && Rec_packet[39]==IpHead[13] && Rec_packet[40]==IpHead[14]&& Rec_packet[41]==IpHead[15])ARPflag=0x01;
lds R2,_IpHead+12
lds R3,_Rec_packet+38
cp R3,R2
brne L48
lds R2,_IpHead+13
lds R3,_Rec_packet+39
cp R3,R2
brne L48
lds R2,_IpHead+14
lds R3,_Rec_packet+40
cp R3,R2
brne L48
lds R2,_IpHead+15
lds R3,_Rec_packet+41
cp R3,R2
brne L48
.dbline 103
ldi R16,1
xjmp L49
L48:
.dbline 105
; //请求方希望获得MAC地址的IP地址是不是和本地IP地址一致,如果一致,则说明是要本地回答
; else ARPflag=0x00;
clr R16
L49:
L44:
L40:
.dbline 106
; return ARPflag;
.dbline -2
L39:
.dbline 0 ; func end
ret
.dbsym r ARPflag 16 c
.dbend
.dbfunc e Transmit_ARP_Packets _Transmit_ARP_Packets fV
; i -> R20
.even
_Transmit_ARP_Packets::
xcall push_gset1
.dbline -1
.dbline 110
; }
; //##########################发送ARP数据包##########################//
; void Transmit_ARP_Packets(void)
; {uchar i=0;
.dbline 110
clr R20
.dbline 111
; enc28j60SetBank(0x00);//通过ECON1先选中当前控制寄存器组是Bank0
clr R16
xcall _enc28j60SetBank
.dbline 112
; Write_Control_Register(0x02,0x00);//EWRPTL
clr R18
ldi R16,2
xcall _Write_Control_Register
.dbline 113
; Write_Control_Register(0x03,0x00);//EWRPTH
clr R18
ldi R16,3
xcall _Write_Control_Register
.dbline 114
; Write_Control_Register(0x04,0x00);//ETXSTL
clr R18
ldi R16,4
xcall _Write_Control_Register
.dbline 115
; Write_Control_Register(0x05,0x00);//ETXSTH
clr R18
ldi R16,5
xcall _Write_Control_Register
.dbline 116
; Bit_Field_Set(0x1e,0x80);//ECON2寄存器中的AUTOINC位置1,
ldi R18,128
ldi R16,30
xcall _Bit_Field_Set
.dbline 117
; Set_CS(0);//使能SPI器件
clr R16
xcall _Set_CS
.dbline 118
; Write_Buffer_Memory_date(0x7A);//送命令,28J60中写缓冲存储器操作前3位为011后5位为常量11010
ldi R16,122
xcall _Write_Buffer_Memory_date
.dbline 119
; Write_Buffer_Memory_date(0x0e);//28J60要求在待发送的数据包前添加一个包控制字节
ldi R16,14
xcall _Write_Buffer_Memory_date
.dbline 121
ldi R20,6
xjmp L62
L59:
.dbline 121
ldi R24,<_Rec_packet
ldi R25,>_Rec_packet
mov R30,R20
clr R31
add R30,R24
adc R31,R25
ldd R16,z+0
xcall _Write_Buffer_Memory_date
L60:
.dbline 121
inc R20
L62:
.dbline 121
;
; for(i=6;i<12;i++)Write_Buffer_Memory_date(Rec_packet[i]);//目标MAC地址6字节
cpi R20,12
brlo L59
.dbline 122
ldi R20,6
xjmp L66
L63:
.dbline 122
ldi R24,<_MACHead
ldi R25,>_MACHead
mov R30,R20
clr R31
add R30,R24
adc R31,R25
ldd R16,z+0
xcall _Write_Buffer_Memory_date
L64:
.dbline 122
inc R20
L66:
.dbline 122
; for(i=6;i<12;i++)Write_Buffer_Memory_date(MACHead[i]); //源MAC地址6字节
cpi R20,12
brlo L63
.dbline 123
ldi R20,12
xjmp L70
L67:
.dbline 123
ldi R24,<_Rec_packet
ldi R25,>_Rec_packet
mov R30,R20
clr R31
add R30,R24
adc R31,R25
ldd R16,z+0
xcall _Write_Buffer_Memory_date
L68:
.dbline 123
inc R20
L70:
.dbline 123
; for(i=12;i<20;i++)Write_Buffer_Memory_date(Rec_packet[i]);//0x08,0x06,0x00,0x01,0x08,0x00,0x06,0x04
cpi R20,20
brlo L67
.dbline 124
; Write_Buffer_Memory_date(0x00);
clr R16
xcall _Write_Buffer_Memory_date
.dbline 125
; Write_Buffer_Memory_date(0x02);//0x0002表示是应答帧
ldi R16,2
xcall _Write_Buffer_Memory_date
.dbline 126
ldi R20,6
xjmp L74
L71:
.dbline 126
ldi R24,<_MACHead
ldi R25,>_MACHead
mov R30,R20
clr R31
add R30,R24
adc R31,R25
ldd R16,z+0
xcall _Write_Buffer_Memory_date
L72:
.dbline 126
inc R20
L74:
.dbline 126
; for(i=6;i<12;i++)Write_Buffer_Memory_date(MACHead[i]); //源MAC地址6字节
cpi R20,12
brlo L71
.dbline 127
ldi R20,38
xjmp L78
L75:
.dbline 127
ldi R24,<_Rec_packet
ldi R25,>_Rec_packet
mov R30,R20
clr R31
add R30,R24
adc R31,R25
ldd R16,z+0
xcall _Write_Buffer_Memory_date
L76:
.dbline 127
inc R20
L78:
.dbline 127
; for(i=38;i<42;i++)Write_Buffer_Memory_date(Rec_packet[i]);//源IP地址
cpi R20,42
brlo L75
.dbline 128
ldi R20,22
xjmp L82
L79:
.dbline 128
ldi R24,<_Rec_packet
ldi R25,>_Rec_packet
mov R30,R20
clr R31
add R30,R24
adc R31,R25
ldd R16,z+0
xcall _Write_Buffer_Memory_date
L80:
.dbline 128
inc R20
L82:
.dbline 128
; for(i=22;i<32;i++)Write_Buffer_Memory_date(Rec_packet[i]);//目标MAC地址6字节,目标IP地址
cpi R20,32
brlo L79
.dbline 129
; Set_CS(1);//写缓冲寄存器结束
ldi R16,1
xcall _Set_CS
.dbline 130
; Write_Control_Register(0x06,42);//ETXNDL,6+6+2+20+8
ldi R18,42
ldi R16,6
xcall _Write_Control_Register
.dbline 131
; Write_Control_Register(0x07,0x00);//ETXNDH,即从0x0000开始写入数据
clr R18
ldi R16,7
xcall _Write_Control_Register
.dbline 133
;
; Bit_Field_Clear(0x1c,0x08);//将EIR.TXIF位清零
ldi R18,8
ldi R16,28
xcall _Bit_Field_Clear
.dbline 134
; Bit_Field_Set(0x1f,0x08);//将ECON1.TXRTS 位置1开始发送
ldi R18,8
ldi R16,31
xcall _Bit_Field_Set
.dbline -2
.dbline 135
; }
L58:
xcall pop_gset1
.dbline 0 ; func end
ret
.dbsym r i 20 c
.dbend
.dbfunc e Receive_Packets _Receive_Packets fV
; Receive_Byte_Number -> R20,R21
; i -> R22
.even
_Receive_Packets::
xcall push_gset2
.dbline -1
.dbline 138
; //##########################接收数据包处理##########################//
; void Receive_Packets(void)//
; {uchar i=0;
.dbline 138
clr R22
.dbline 139
; uint Receive_Byte_Number=0;
clr R20
clr R21
.dbline 140
; enc28j60SetBank(0x00);//通过ECON1先选中当前控制寄存器组是Bank0
clr R16
xcall _enc28j60SetBank
.dbline 141
; Receive_Status[0]=Read_Buffer_Memory();//存放下一个数据包的起始位置低8位
xcall _Read_Buffer_Memory
sts _Receive_Status,R16
.dbline 142
; Receive_Status[1]=Read_Buffer_Memory();//存放下一个数据包的起始位置高8位
xcall _Read_Buffer_Memory
sts _Receive_Status+1,R16
.dbline 143
; Receive_Status[2]=Read_Buffer_Memory();//存放当前接收到的数据包的字节数低8位
xcall _Read_Buffer_Memory
sts _Receive_Status+2,R16
.dbline 144
; Receive_Status[3]=Read_Buffer_Memory();//存放当前接收到的数据包的字节数高8位
xcall _Read_Buffer_Memory
sts _Receive_Status+3,R16
.dbline 145
; Receive_Status[4]=Read_Buffer_Memory();//其它,参看数据手册
xcall _Read_Buffer_Memory
sts _Receive_Status+4,R16
.dbline 146
; Receive_Status[5]=Read_Buffer_Memory();//其它,参看数据手册
xcall _Read_Buffer_Memory
sts _Receive_Status+5,R16
.dbline 148
;
; Receive_Byte_Number +=Receive_Status[3];
lds R2,_Receive_Status+3
clr R3
add R20,R2
adc R21,R3
.dbline 149
; Receive_Byte_Number =Receive_Byte_Number<<8;
mov R21,R20
clr R20
.dbline 150
; Receive_Byte_Number +=Receive_Status[2];
lds R2,_Receive_Status+2
clr R3
add R20,R2
adc R21,R3
.dbline 152
xjmp L94
L91:
.dbline 152
xcall _Read_Buffer_Memory
ldi R24,<_Rec_packet
ldi R25,>_Rec_packet
mov R30,R22
clr R31
add R30,R24
adc R31,R25
std z+0,R16
L92:
.dbline 152
inc R22
L94:
.dbline 152
; //得到接收到的数据包长度包括目标地址,源地址,类型/长度,数据,填充,CRC字段
; for(i=0;i<Receive_Byte_Number;i++)Rec_packet[i]=Read_Buffer_Memory();//将接收到的当前数据包存放在Rec_packet[255]中等待处理
mov R2,R22
clr R3
cp R2,R20
cpc R3,R21
brlo L91
.dbline 153
; i=ARP_request_or_answer();
xcall _ARP_request_or_answer
mov R22,R16
.dbline 154
; if(i==0x01)Transmit_ARP_Packets();//如果是本地ARP请求帧,则响应请求,发送ARP应答帧
cpi R16,1
brne L95
.dbline 154
xcall _Transmit_ARP_Packets
L95:
.dbline 156
;
; putchar(0x4C);
ldi R16,76
xcall _putchar
.dbline 157
; putchar(0x48);
ldi R16,72
xcall _putchar
.dbline 158
; putchar(0x46);//发送"LHF"通知上位机,紧接着要发送刚接收到的数据帧给上位机
ldi R16,70
xcall _putchar
.dbline 159
clr R22
xjmp L100
L97:
.dbline 159
ldi R24,<_Rec_packet
ldi R25,>_Rec_packet
mov R30,R22
clr R31
add R30,R24
adc R31,R25
ldd R16,z+0
xcall _putchar
L98:
.dbline 159
inc R22
L100:
.dbline 159
; for(i=0;i<Receive_Byte_Number;i++)putchar(Rec_packet[i]);
mov R2,R22
clr R3
cp R2,R20
cpc R3,R21
brlo L97
.dbline 162
; //将接收到的数据发送到上位机软件,包括目标地址,源地址,类型/长度,数据,填充,CRC字段。
;
; Bit_Field_Set(0x1e,0x40);//数据处理完后,然后清零待处理中断标志位PKTIF
ldi R18,64
ldi R16,30
xcall _Bit_Field_Set
.dbline 164
; //只能通过将ECON2中的PKTDEC置1时才能清PKTIF
; Write_Control_Register(0x00,Receive_Status[0]);//ERDPTL
lds R18,_Receive_Status
clr R16
xcall _Write_Control_Register
.dbline 165
; Write_Control_Register(0x01,Receive_Status[1]);//ERDPTH,读数据包指针起始位置,准备处理下一数据帧
lds R18,_Receive_Status+1
ldi R16,1
xcall _Write_Control_Register
.dbline 167
;
; enc28j60SetBank(0x01);//因为EPKTCNT寄存器在Bank1.
ldi R16,1
xcall _enc28j60SetBank
.dbline 168
; EPKTCNT=Read_Control_Register(ETH,0x19);//读取EPKTCNT值
ldi R18,25
clr R16
xcall _Read_Control_Register
sts _EPKTCNT,R16
.dbline -2
.dbline 169
; }
L83:
xcall pop_gset2
.dbline 0 ; func end
ret
.dbsym r Receive_Byte_Number 20 i
.dbsym r i 22 c
.dbend
.dbfunc e ENC28J60_Initialize _ENC28J60_Initialize fV
; state -> R20
.even
_ENC28J60_Initialize::
xcall push_gset1
sbiw R28,1
.dbline -1
.dbline 174
;
;
; //##############################28J60初始化程序###########################//
; void ENC28J60_Initialize(void)
; {uchar state=0;
.dbline 174
clr R20
.dbline 175
; Reset_28J60();//软复位
xcall _Reset_28J60
.dbline 176
; delay(2);//28J60复位要一定的时间
ldi R16,2
xcall _delay
xjmp L104
L103:
.dbline 177
ldi R18,29
clr R16
xcall _Read_Control_Register
mov R20,R16
L104:
.dbline 177
; while((state&0x01)==0)state=Read_Control_Register(ETH,0x1D);
sbrs R20,0
rjmp L103
.dbline 180
; //读状态寄存器ESTAT,确认CLKRDY时钟就绪位置1,确保已稳定,才能进行对MAC和PHY修改
;
; Write_Control_Register(0x08,0x00);//ERXSTL
clr R18
ldi R16,8
xcall _Write_Control_Register
.dbline 181
; Write_Control_Register(0x09,0x08);//ERXSTH,ERXST指针指定接收数据包放在RAM中的开始位置
ldi R18,8
ldi R16,9
xcall _Write_Control_Register
.dbline 182
; Write_Control_Register(0x0C,0x00);//ERXRDPTL
clr R18
ldi R16,12
xcall _Write_Control_Register
.dbline 183
; Write_Control_Register(0x0D,0x08);//ERXRDPTH,与ERXST值要保持相同
ldi R18,8
ldi R16,13
xcall _Write_Control_Register
.dbline 184
; Write_Control_Register(0x00,0x00);//ERDPTL
clr R18
clr R16
xcall _Write_Control_Register
.dbline 185
; Write_Control_Register(0x01,0x08);//ERDPTH,读数据包指针起始位置
ldi R18,8
ldi R16,1
xcall _Write_Control_Register
.dbline 187
;
; Write_Control_Register(0x0A,0xff);//ERXNDL
ldi R18,255
ldi R16,10
xcall _Write_Control_Register
.dbline 188
; Write_Control_Register(0x0B,0x1f);//ERXNDH,ERXND指针指定接收数据包放在RAM中的结束位置
ldi R18,31
ldi R16,11
xcall _Write_Control_Register
.dbline 191
; //指定接收缓冲区,起始处接收缓冲区要预留至少7个字节,将接收到的数据包放入0x0800-0x1fff
;
; Write_Control_Register(0x04,0x00);//ETXSTL
clr R18
ldi R16,4
xcall _Write_Control_Register
.dbline 192
; Write_Control_Register(0x05,0x00);//ETXSTH
clr R18
ldi R16,5
xcall _Write_Control_Register
.dbline 194
;
; enc28j60SetBank(0x01);//通过ECON1先选中当前控制寄存器组是Bank1,因为ERXFCON寄存器在Bank1。
ldi R16,1
xcall _enc28j60SetBank
.dbline 195
; Write_Control_Register(0x18,0x83);//将ERXFCON设定接收单播,广播的帧,丢掉CRC无效的数据包
ldi R18,131
ldi R16,24
xcall _Write_Control_Register
.dbline 197
;
; enc28j60SetBank(0x02);//通过ECON1先选中当前控制寄存器组是Bank2,因为MAC相关寄存器在Bank2。
ldi R16,2
xcall _enc28j60SetBank
.dbline 198
; Bit_Field_Clear(0x01,0x80);//将MACON2中的MARST位清零,使MAC退出复位状态。
ldi R18,128
ldi R16,1
xcall _Bit_Field_Clear
.dbline 199
; Write_Control_Register(0x00,0x0d);
ldi R18,13
clr R16
xcall _Write_Control_Register
.dbline 201
; //对MACON1进行配置,使能接收数据帧,如果是双工模式的话还要将TXPAUS和RXPAUS置1
; Write_Control_Register(0x02,0x33);//对MACON3进行配置,配置MACON3中的PADCFG、TXCRCEN、FRMLNEN.
ldi R18,51
ldi R16,2
xcall _Write_Control_Register
.dbline 204
; //大多数应用应使能自动填充(达到至少60字节),并始终追加一个有效的CRC.为了方便起见,许多应用可能还希望将FRMLNEN位置1
; //使能帧长度状态报告.如果应用连接到全双工远程节点,则应将FULDPX置1,否则应保持该位清零。
; Write_Control_Register(0x06,0x12);//配置非背对背包间间隔寄存器的低字节MAIPGL.大多数应用使用12h编程该寄存器。
ldi R18,18
ldi R16,6
xcall _Write_Control_Register
.dbline 207
; //Write_Control_Register(0x07,0x0c);//如果使用半双工模式,应编程非背对背包间间隔寄存器的高字节MAIPGH.
; //大多数应用使用0Ch编程该寄存器.
; Write_Control_Register(0x04,0x15);//配置背对背包间间隔寄存器MABBIPG.
ldi R18,21
ldi R16,4
xcall _Write_Control_Register
.dbline 209
; //当使用全双工模式时,大多数应用使用15h编程该寄存器,而使用半双工模式时则使用12h进行编程.
; Write_Control_Register(0x0a,0xf0);//MAMXFLL
ldi R18,240
ldi R16,10
xcall _Write_Control_Register
.dbline 210
; Write_Control_Register(0x0b,0x00);//MAMXFLH
clr R18
ldi R16,11
xcall _Write_Control_Register
.dbline 216
; //用允许接收或发送的最大帧长度编程MAMXFL寄存器.网络节点一般被设计为处理不大于1518字节的数据包.这里最大240
;
; //如果使用半双工模式,还需编程重发和冲突窗口寄存器MACLCON1 和MACLCON2。
; //大多数应用不需要更改默认的复位值。在网络线缆特别长的情况下,需要增加MACLCON2的默认值
;
; enc28j60SetBank(0x03);//通过ECON1先选中当前控制寄存器组是Bank3,因为MAADR相关寄存器在Bank3.
ldi R16,3
xcall _enc28j60SetBank
.dbline 218
;
; Write_Control_Register(0x01,MACHead[6]);//MAADR0,将本地MAC地址写入MAADR0:MAADR5寄存器.
lds R18,_MACHead+6
ldi R16,1
xcall _Write_Control_Register
.dbline 219
; Write_Control_Register(0x00,MACHead[7]);//MAADR1
lds R18,_MACHead+7
clr R16
xcall _Write_Control_Register
.dbline 220
; Write_Control_Register(0x03,MACHead[8]);//MAADR2
lds R18,_MACHead+8
ldi R16,3
xcall _Write_Control_Register
.dbline 221
; Write_Control_Register(0x02,MACHead[9]);//MAADR3
lds R18,_MACHead+9
ldi R16,2
xcall _Write_Control_Register
.dbline 222
; Write_Control_Register(0x05,MACHead[10]);//MAADR4
lds R18,_MACHead+10
ldi R16,5
xcall _Write_Control_Register
.dbline 223
; Write_Control_Register(0x04,MACHead[11]);//MAADR5
lds R18,_MACHead+11
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -