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

📄 main.s

📁 网卡控制器ENC28J60的AVR单片机ATmega16程序源代码(c),实现232toUDP功能,有非常详细的注释.
💻 S
📖 第 1 页 / 共 3 页
字号:
;  
;  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 + -