320volt / Electronics Projects/

PIC16C74 Embedded 10BaseT Ethernet CS8900

Electronics Projects, PIC16C74 Embedded 10BaseT Ethernet CS8900 article "microchip projects, microcontroller projects, " tagged with

Advertisement

Embedded ethernet enables microcontroller based projects to send and receive packets over the network. The board shown on the left is actual size and incorporates all the circuitry needed to enable 10BaseT communications. The board is designed to minimize the pin count needed to interface with microcontrollers. An 8 bit data bus, 4 bit address bus, and three control signals (15 signals) with an optional interrupt signal are all that is needed to control the board. This is made possible by using the Crystal CS8900 ethernet transceiver running in 8-bit mode. All the information, schematics, and source code needed to perform TCP/IP communication over ethernet is detailed on this page. I’m using a Microchip PIC16C74 controller in this project however, any controller with enouph port capacity will also work. This would include the popular Motarola 68HC11.

The project described here is in two parts. The actual embedded ethernet board and the test circuit utilizing the PIC16C74. The code running on the PIC incorporates the necessary drivers for the board along with the TCP/IP layers needed to communicate on the network.

Overview of the Crystal CS8900

The Crystal CS8900 is a single chip solution capable of interfacing directly to the analog side of 10BaseT ethernet using only an isolation transformer and some passive components. The CS8900 has 4K of integrated memory allowing it to receive and send packets asynchronous to the microcontroller. This eliminates any timing issues that would normally be present and allows even the slowest microcontroller to talk on the ethernet. The CS8900 itself, is running at 20Mhz and requires an external crystal. Most ethernet transceivers operate directly on the ISA bus and use DMA to access external RAM for incoming and outgoing packets and control information. The Crystal part also operates in this mode but also has an 8 bit mode. Using this mode is similar to controlling ports in the PC architecture. For a write operation, the address is placed on the address bus, say 0x300, the data is placed on the data bus and then and then the /IOW signal is toggled. Address decode logic on one of the boards “sees” that it’s there port address (0x300) and then grabs the data from the data bus. For a read operation, the address, 0x300, is placed on the address bus and the /IOR signal is toggled, the card with this address places the data on the bus for the “in” instruction to read. This is how the CS8900 works in 8 bit mode and the default starting address for port access is 0x300 and continues to 0x30F. Notice that only 4 bits are really needed on the address bus to address all the register locations.

Other address bus pins are tied either high or low. By manipulating these 16 register locations, you can control the entire 4K of internal memory known as PacketPage memory. Essentially, the CS8900 incorporates and indirect set of registers for controlling a much larger 4K area of internal memory on the part. For example, the documentation states that the length of the frame received is at location 0x0402 and 0x0403 (The CS8900 always uses 16 bit values) so you place the value 0x0402 into the PacketPage pointer location (0xa and 0xb) and read the data from the PacketPage data location (0xc and 0xd). The actual data you’re reading is coming from the 0x0402 and 0x0403 locations within PacketPage memory. This technique is more completely described in the Crystal application note AN112.

Schematic of the embedded ethernet card shown above
This board was designed using ExpressPCB. The software for board layout design can be downloaded for free from their website and the ordering of boards is automated though the software package.

It should be mentioned that you will need to use a professionaly designed board for this project since the CS8900 is only available in a 100 pin QFP surface mount package. Don’t panic! I didn’t know anything about surface mount technology until I started this project, either. Here’s the technique I use to solder the chip to the board:

• Use a 3x/4x magnifying lamp.
• Get a soldering iron that has adjustable temperature settings, use 450-500 degrees farenheit.
• Since the CS8900 uses .020 inch spaced leads, use a tip that has a diameter less than this, I use a .015 inch tip.
• Get some flux at Radio Shack and place a very small amount on the surface mount pads.
• Get some silicon-based adhesive from Radio Shack and place a small amount on the belly of the CS8900. This will allow you to place the part and center it over the pads. Take your time and go slow.

• When the silicon hardens, heat up the iron and on the outer-edge pins, place your iron on the pad and allow a small amount of solder to flow. What we’re trying to do here is anchor the part on the four sides. Repeat for each side.

• From this point on, don’t use ANY SOLDER. The board as manufactured by ExpressPCB has been tin-lead plated and the pads already contain all the solder necessary to form a good inter-metalic bond. Merely touch the iron to each pin and allow the solder to reflow. This goes very fast and you can solder all the remaining 96 pins in under 5 minutes.

Overview of the test circuit A Microchip PIC16C74 is used to drive the CS8900 and to implement some basic TCP/IP functionallity. The test circuit, once connected to the ethernet backbone, can be pinged from another node. Also, a Windows Sockets program is included that connects to the test circuit who is listening on UDP port 7 (echo). The echo service sends back any data that it receives.

The programs are all setup to use IP address 192.168.1.2 and Ethernet address (also called an OUI- Organizationally Unique Identifier) of 00:00:00:12:34:56. Since these are ficticious numbers, you may need to change them. Two places that need modification, the program running on the PIC has equates for these values and the IP address is hard coded in the testudp.c program. If you don’t change them, and are testing under NT (recommended) you may need to add a static route using the command route add 192.168.1.2 your.ip.gateway.address. This will cause all traffic to the board to go through the default gateway of you’re local machine.

Schematic of the test circuit

PIC16C74 Embedded 10BaseT Ethernet CS8900 test 10baset schematic 150x150 PIC16C74 Embedded 10BaseT Ethernet CS8900 cs8900 pic16c74 10baset schematic 150x150

In conclusion: I originally worked on this project in anticipation of selling the technology but circumstances changed and I hope that the embedded community will benifit from this work. Embedded ethernet is not without it’s problems. For example. I was planning on using an EEPROM as the storage for packet data but quickly realized that the write/erase times would not be sufficient. Typical write times are 5ms which brought the ping time for a 500 byte packet to 1.5 seconds. I believe now that the key to using this technology is to write specifically to the problem domain.

By Gary T. Desrosiers
Copyright © Gary T. Desrosiers, 1998

Embedded 10BaseT Ethernet PCB files (express pcb) pic16c74-embedded-10baset-ethernet-cs8900.rar

Embedded 10BaseT Ethernet Assembly code

        list    p=pic16c74
        __config h'3ffa'        ;HS crystal, 20Mhz
        include 

;
; *Change these* : Configuration equates. 
;
IP1     equ     d'192'                  ;first octet of IP address
IP2     equ     d'168'                  ;second octet of IP address
IP3     equ     d'1'                    ;third octet of IP address
IP4     equ     d'2'                    ;fourth octet of IP address
;
MAC1    equ     0x00                    ;\
MAC2    equ     0x00                    ;  \
MAC3    equ     0x00                    ;    \
MAC4    equ     0x12                    ;    48 bit IEEE OUI (Organizationally Unique Identifier)
MAC5    equ     0x34                    ;  /
MAC6    equ     0x56                    ;/
;
; Some useful macros
;
ppRD    macro   addr            ;Read PacketPage port
        movlw   addr&0xff
        movwf   offsetL
        movlw   addr>>8
        movwf   offsetH
        call    ReadPP
        endm
;
ppWR    macro   addr,val        ;Write PacketPage port
        movlw   addr&0xff
        movwf   offsetL
        movlw   addr>>8
        movwf   offsetH
        movlw   val&0xff
        movwf   valueL
        movlw   val>>8
        movwf   valueH
        call    WritePP
        endm

;
Dinput  macro                   ;Change the data bus to input
        bsf     STATUS,RP0
        movlw   0xff          
        movwf   TRISB         
        bcf     STATUS,RP0
        endm
;
Doutput macro                   ;Change the data bus to output
        bsf     STATUS,RP0
        clrf    TRISB         
        bcf     STATUS,RP0
        endm
;
ior     macro   port            ;I/O port read 
        movlw   port
        call    ioRead
        endm
;
iow     macro   port            ;I/O port write
        movwf   PORTB
        movlw   port
        movwf   PORTA          
        call    ioWrite
        endm

;
; Crystal CS8900 PacketPage equates
;
portRxTxData  equ 0x00   ;Receive/Transmit data (port 0)
portRxTxData1 equ 0x02   ;Receive/Transmit data (port 0)
portTxCmd     equ 0x04   ;Transmit Commnad
portTxLength  equ 0x06   ;Transmit Length
portISQ       equ 0x08   ;Interrupt status queue
portPtr       equ 0x0a   ;PacketPage pointer
portData      equ 0x0c   ;PacketPage data (port 0)
portData1     equ 0x0e   ;PacketPage data (port 1)
;
; CS8900 PacketPage Offsets 
;
ppEISA       equ 0x0000  ;EISA Registration number of CS8900
ppProdID     equ 0x0002  ;Product ID Number
ppIOBase     equ 0x0020  ;I/O Base Address
ppIntNum     equ 0x0022  ;Interrupt number (0,1,2, or 3)
ppMemBase    equ 0x002C  ;Memory Base address register (20 bit)
ppRxCfg      equ 0x0102  ;Receiver Configuration
ppRxCtl      equ 0x0104  ;Receiver Control
ppTxCfg      equ 0x0106  ;Transmit Configuration
ppBufCfg     equ 0x010A  ;Buffer Configuration
ppLineCtl    equ 0x0112  ;Line Control
ppSelfCtl    equ 0x0114  ;Self Control
ppBusCtl     equ 0x0116  ;Bus Control
ppTestCtl    equ 0x0118  ;Test Control
ppISQ        equ 0x0120  ;Interrupt status queue
ppRxEvt      equ 0x0124  ;Receiver Event
ppTxEvt      equ 0x0128  ;Transmitter Event
ppBufEvt     equ 0x012C  ;Buffer Event
ppRxMiss     equ 0x0130  ;Receiver Miss Counter
ppTxCol      equ 0x0132  ;Transmit Collision Counter
ppLineSt     equ 0x0134  ;Line Status
ppSelfSt     equ 0x0136  ;Self Status
ppBusSt      equ 0x0138  ;Bus Status
ppTxCmd      equ 0x0144  ;Transmit Command Request
ppTxLength   equ 0x0146  ;Transmit Length
ppIndAddr    equ 0x0158  ;Individual Address (IA)
ppRxStat     equ 0x0400  ;Receive Status
ppRxLength   equ 0x0402  ;Receive Length
ppRxFrame    equ 0x0404  ;Receive Frame Location
ppTxFrame    equ 0x0A00  ;Transmit Frame Location
;
; Register Numbers 
;
REG_NUM_MASK        equ     0x003F
REG_NUM_RX_EVENT    equ     0x0004
REG_NUM_TX_EVENT    equ     0x0008
REG_NUM_BUF_EVENT   equ     0x000C
REG_NUM_RX_MISS     equ     0x0010
REG_NUM_TX_COL      equ     0x0012
;
; Self Control Register
;
SELF_CTL_RESET      equ     0x0040
SELF_CTL_HC1E       equ     0x2000
SELF_CTL_HCB1       equ     0x8000
;
; Self Status Register 
;
SELF_ST_INIT_DONE   equ     0x0080
SELF_ST_SI_BUSY     equ     0x0100
SELF_ST_EEP_PRES    equ     0x0200
SELF_ST_EEP_OK      equ     0x0400
SELF_ST_EL_PRES     equ     0x0800
;
; Bus Control Register 
;
BUS_CTL_USE_SA      equ     0x0200
BUS_CTL_MEM_MODE    equ     0x0400
BUS_CTL_IOCHRDY     equ     0x1000
BUS_CTL_INT_ENBL    equ     0x8000
;
; Bus Status Register 
;
BUS_ST_TX_BID_ERR   equ     0x0080
BUS_ST_RDY4TXNOW    equ     0x0100
;
; Line Control Register 
;
LINE_CTL_RX_ON      equ     0x0040
LINE_CTL_TX_ON      equ     0x0080
LINE_CTL_AUI_ONLY   equ     0x0100
LINE_CTL_10BASET    equ     0x0000
;
; Test Control Register 
;
TEST_CTL_DIS_LT     equ     0x0080
TEST_CTL_ENDEC_LP   equ     0x0200
TEST_CTL_AUI_LOOP   equ     0x0400
TEST_CTL_DIS_BKOFF  equ     0x0800
TEST_CTL_FDX        equ     0x4000
;
; Receiver Configuration Register 
;
RX_CFG_SKIP         equ     0x0040
RX_CFG_RX_OK_IE     equ     0x0100
RX_CFG_CRC_ERR_IE   equ     0x1000
RX_CFG_RUNT_IE      equ     0x2000
RX_CFG_X_DATA_IE    equ     0x4000
;
; Receiver Event Register 
;
RX_EVENT_RX_OK      equ     0x0100
RX_EVENT_IND_ADDR   equ     0x0400
RX_EVENT_BCAST      equ     0x0800
RX_EVENT_CRC_ERR    equ     0x1000
RX_EVENT_RUNT       equ     0x2000
RX_EVENT_X_DATA     equ     0x4000
;
;Receiver Control Register 
;
RX_CTL_RX_OK_A      equ     0x0100
RX_CTL_MCAST_A      equ     0x0200
RX_CTL_IND_A        equ     0x0400
RX_CTL_BCAST_A      equ     0x0800
RX_CTL_CRC_ERR_A    equ     0x1000
RX_CTL_RUNT_A       equ     0x2000
RX_CTL_X_DATA_A     equ     0x4000
;
;Transmit Configuration Register 
;
TX_CFG_LOSS_CRS_IE  equ     0x0040
TX_CFG_SQE_ERR_IE   equ     0x0080
TX_CFG_TX_OK_IE     equ     0x0100
TX_CFG_OUT_WIN_IE   equ     0x0200
TX_CFG_JABBER_IE    equ     0x0400
TX_CFG_16_COLL_IE   equ     0x8000
TX_CFG_ALL_IE       equ     0x8FC0
;
;Transmit Event Register 
;
TX_EVENT_TX_OK      equ     0x0100
TX_EVENT_OUT_WIN    equ     0x0200
TX_EVENT_JABBER     equ     0x0400
TX_EVENT_16_COLL    equ     0x1000
;
; Transmit Command Register
;
TX_CMD_START_5      equ     0x0000
TX_CMD_START_381    equ     0x0080
TX_CMD_START_1021   equ     0x0040
TX_CMD_START_ALL    equ     0x00C0
TX_CMD_FORCE        equ     0x0100
TX_CMD_ONE_COLL     equ     0x0200
TX_CMD_NO_CRC       equ     0x1000
TX_CMD_NO_PAD       equ     0x2000
;
;Buffer Configuration Register 
;
BUF_CFG_SW_INT      equ     0x0040
BUF_CFG_RDY4TX_IE   equ     0x0100
BUF_CFG_TX_UNDR_IE  equ     0x0200
;
; PORTA pin assignments (Crystal address bus)
;
SA0     equ     0
SA1     equ     1
SA2     equ     2
SA3     equ     3
;RA4    equ     4 ;not used (ST)
;RA5    equ     5 ;not used (TTL)
;
; PORTB pin assignments (Crystal data bus)
;
SD0     equ     0
SD1     equ     1
SD2     equ     2
SD3     equ     3
SD4     equ     4
SD5     equ     5
SD6     equ     6
SD7     equ     7
;
; PORTC pin assignments (Crystal signals CHIPSEL/IOW/IOR)
;
IOR     equ     0       ;active low signal to initiate I/O read operation
IOW     equ     1       ;active low signal to initiate I/O write operation
CHIPSEL equ     2       ;active low signal to select the CS8900 chip
INTR    equ     3       ;active HIGH interrupt pending signal. Auto cleared after read of ISQ
;RC4    equ     4       ;not used (ST)
;RC5    equ     5       ;not used (ST)
;RC6    equ     6       ;not used (ST)
;RC7    equ     7       ;not used (ST)
;
; PORTD pin assignments
;
;RD0    equ     0       ;not used
;RD1    equ     1       ;not used
;RD2    equ     2       ;not used
;RD3    equ     3       ;not used
;RD4    equ     4       ;not used
;RD5    equ     5       ;not used
;RD6    equ     6       ;not used
;RD7    equ     7       ;not used
;
; PORTE pin assignments (LCD control)
;
;RE0     equ     0       ;not used
;RE1     equ     1       ;not used
;RE2     equ     2       ;not used
;
; Register file assignments
;
tempH     equ   0x20
tempL     equ   0x21
loops     equ   0x22
loops2    equ   0x23
loops3    equ   0x24
char      equ   0x25
cnt_low   equ   0x26
cnt_mid   equ   0x27
cnt_hi    equ   0x28
bcd1      equ   0x29
bcd2      equ   0x2a
bcd3      equ   0x2b
valueH    equ   0x2c
valueL    equ   0x2d
offsetH   equ   0x2e
offsetL   equ   0x2f
flags     equ   0x30
hextemp   equ   0x31
lengthH   equ   0x32
lengthL   equ   0x33
packet    equ   0x34 ;the highest register file location is 3F because we need 64 bytes after this.
;
; Packet offset equates
;
;
; Packet header
;
pktLenH   equ   0x00
pktLenL   equ   0x01
pktDest0H equ   0x02
pktDest0L equ   0x03
pktDest1H equ   0x04
pktDest1L equ   0x05
pktDest2H equ   0x06
pktDest2L equ   0x07
pktSrc0H  equ   0x08
pktSrc0L  equ   0x09
pktSrc1H  equ   0x0a
pktSrc1L  equ   0x0b
pktSrc2H  equ   0x0c
pktSrc2L  equ   0x0d
pktTypeH  equ   0x0e
pktTypeL  equ   0x0f
;
; ARP
;
ar_hwtype equ   0x10            ;hardware type
ar_prtype equ   0x12            ;protocol type
ar_hwlen  equ   0x14            ;hardware address length
ar_prlen  equ   0x15            ;protocol address length
ar_op     equ   0x16            ;ARP operation (1=request, 2=reply)
ar_sha    equ   0x18            ;senders hardware address
ar_spa    equ   0x1e            ;senders IP address
ar_tha    equ   0x22            ;target hardware address
ar_tpa    equ   0x28            ;target IP address
;
; IP header
;
ip_verlen equ   0x10            ;IP version and header length(in longs)
ip_tos    equ   0x11            ;IP type of service
ip_len    equ   0x12            ;packet length (length-header_length)
ip_id     equ   0x14            ;datagram id
ip_fragoff equ  0x16            ;fragment offset
ip_ttl    equ   0x18            ;time to live (in gateway hops)
ip_proto  equ   0x19            ;protocol (ICMP=1, TCP=6, EGP=8, UDP=17)
ip_cksum  equ   0x1a            ;header checksum
ip_src    equ   0x1c            ;IP address of source
ip_dst    equ   0x20            ;IP addess of destination
ip_data   equ   0x24
;
; IP value equates
;
IPT_ICMP  equ   1               ;protocol type for ICMP packets
IPT_TCP   equ   6               ;protocol type for TCP packets
IPT_EGP   equ   8               ;protocol type for EGP packets
IPT_UDP   equ   0x11            ;protocol type for UDP packets
;
; ICMP header
;
ic_type   equ   ip_data         ;0=reply, 8=request, others=who-cares
ic_code   equ   ic_type+1       ;code
ic_cksum  equ   ic_code+1       ;checksum of header+data
ic_id     equ   ic_cksum+2      ;message id
ic_seq    equ   ic_id+2         ;sequence number
;
; UDP Header
;
u_src     equ   ip_data         ;source udp port number
u_dst     equ   u_src+2         ;destination UDP port number
u_len     equ   u_dst+2         ;length of UDP header+data
u_cksum   equ   u_len+2         ;checksum  (see note)
u_data    equ   u_cksum+2       ;start of data
;
; Note: checksum is calculated by taking the 16 bit sums of the ip_src, ip_dst,
; ip_proto, u_len, and the sum starting at u_src for a length of u_len
; yes, this means that u_len is taken twice! u_cksum is zero during the calc.
; The sum is then one's complemented. This is the checksum
;
        org     0
        goto    start
;
        org     4
        retfie
;
start   bsf     STATUS,RP0
        movlw   0xff                    ;make all RA/RE
        movwf   ADCON1                  ;pins digital I/O
        clrf    TRISA                   ;crystal address bus output
        clrf    TRISB                   ;crystal data bus output
        clrf    TRISC                   ;crystal control signals output
        bcf     STATUS,RP0
        bsf     PORTC,IOR               ;no read on crystal
        bsf     PORTC,IOW               ;no write on crystal
        bsf     PORTC,CHIPSEL           ;address enable
        clrf    PORTA                   ;clear address bus
        call    VerChip
        call    ResetChip
        call    InitChip

        clrf    flags

loop    btfss   PORTC,INTR      ;wait for interrupt
        goto    loop
        call    ProcessISQ
        btfss   flags,0                 ;received frame flag
        goto    loop
        bcf     flags,0                 ;clear the receive flag
        btfss   flags,1                 ;bit set when valid arp
        goto    loop
        bcf     flags,1                 ;clear the valid arp request flag
        call    SendARP
        goto    loop
;
; wait for W milliseconds
;
wait    movwf   loops
wait0   movlw   5
        movwf   loops2
wait1   movlw   .110
        movwf   loops3
wait2   nop
        nop
        nop
        nop
        nop
        nop
        decfsz  loops3,1
        goto    wait2
        decfsz  loops2,1
        goto    wait1
        decfsz  loops,1
        goto    wait0
        return

;
; Compare two 16 bit numbers and return the result in STATUS,C
; If C=0,  valueH/valueL is less than tempH/tempL
; if C=1, then valueH/valueL is greater than or equal to tempH/tempL
; valueH/valueH are destroyed in the process.
cmp16   movf    tempL,0                 ;get low 
        subwf   valueL,1
        btfsc   STATUS,C                ;C=0 means its neg
        goto    cmpH                    ;C=1, valueL is >= 0x7f
        movlw   1
        subwf   valueH,1                ;decrement high
        btfss   STATUS,C                ;if it goes neg, then
        goto    cmpIsLess               ; value is less than 0x7f
cmpH    movf    tempH,0                 ;0x00 part of 0x007f
        subwf   valueH,1                ;subtract
        btfss   STATUS,C
        goto    cmpIsLess
        bsf     STATUS,C                ; valueH/valueL is greater or equal  to tempH/tempL
        return
cmpIsLess
        bcf     STATUS,C                ;valueH/valueL is less than 0x007F
        return


;************************************************************************
;*         C S 8 9 0 0   D r i v e r   F u n c t i o n s                *
;************************************************************************
;
; SendARP - Send a response ARP to the requestor 
;
SendARP
        Doutput
        movlw   TX_CMD_START_ALL
        iow     portTxCmd
        movlw   0
        iow     portTxCmd+1
        movlw   d'42'					;length of ARP response frame
        iow     portTxLength
        movlw   0
        iow     portTxLength+1
RTGetStat
        ppRD    ppBusSt					;get BusStatus
        btfss   valueH,0				;is BUS_ST_RDY4TXNOW (ready for transmit)
        goto    RTGetStat				;no, wait for it

        Doutput
; Send dest   (6)
        movf    packet+pktSrc0H,0
        iow     portRxTxData
        movf    packet+pktSrc0L,0
        iow     portRxTxData+1
        movf    packet+pktSrc1H,0
        iow     portRxTxData
        movf    packet+pktSrc1L,0
        iow     portRxTxData+1
        movf    packet+pktSrc2H,0
        iow     portRxTxData
        movf    packet+pktSrc2L,0
        iow     portRxTxData+1
; Send src     (6)
        movlw   MAC1
        iow     portRxTxData
        movlw   MAC2
        iow     portRxTxData+1
        movlw   MAC3    
        iow     portRxTxData
        movlw   MAC4
        iow     portRxTxData+1
        movlw   MAC5
        iow     portRxTxData
        movlw   MAC6
        iow     portRxTxData+1
; Send type    (2)
        movlw   0x08
        iow     portRxTxData
        movlw   0x06
        iow     portRxTxData+1
; Send hwtype    (2)
        movlw   0x00
        iow     portRxTxData
        movlw   0x01   
        iow     portRxTxData+1
; Send prtype (protocol type) (2)
        movlw   0x08
        iow     portRxTxData
        movlw   0x00
        iow     portRxTxData+1
; Send hardware and protocol address lengths (2)
        movlw   0x06
        iow     portRxTxData
        movlw   0x04
        iow     portRxTxData+1
; Send operation (response) (2)
        movlw   0x00
        iow     portRxTxData
        movlw   0x02
        iow     portRxTxData+1
; Send Senders HW address      (6)
        movlw   MAC1
        iow     portRxTxData
        movlw   MAC2
        iow     portRxTxData+1
        movlw   MAC3
        iow     portRxTxData
        movlw   MAC4
        iow     portRxTxData+1
        movlw   MAC5
        iow     portRxTxData
        movlw   MAC6
        iow     portRxTxData+1
; Send Senders IP    (4)
        movlw   IP1
        iow     portRxTxData
        movlw   IP2
        iow     portRxTxData+1
        movlw   IP3
        iow     portRxTxData
        movlw   IP4
        iow     portRxTxData+1
; Send Target HW address (6)
        movf    packet+pktSrc0H,0
        iow     portRxTxData
        movf    packet+pktSrc0L,0
        iow     portRxTxData+1
        movf    packet+pktSrc1H,0
        iow     portRxTxData
        movf    packet+pktSrc1L,0
        iow     portRxTxData+1
        movf    packet+pktSrc2H,0
        iow     portRxTxData
        movf    packet+pktSrc2L,0
        iow     portRxTxData+1
; Send Target IP    (4)
        movf    packet+ar_spa,0
        iow     portRxTxData
        movf    packet+ar_spa+1,0
        iow     portRxTxData+1
        movf    packet+ar_spa+2,0
        iow     portRxTxData
        movf    packet+ar_spa+3,0
        iow     portRxTxData+1
        return
;
;
;
; Receive Event
; Input with RxEvent in valueH
;
ReceiveEvent
        Dinput                          ;make data bus input
;
; It's important to read the status and length high-order
; byte first. 
;

        ior     portRxTxData+1          ;read and discard status
        ior     portRxTxData            ;read and discard status

        movlw   packet+2                ;set indirect
        movwf   FSR                     ; address

        ior     portRxTxData+1          ;get length high
        movwf   packet+pktLenH          ;save in header area
        movwf   lengthH                 ; and in lengthH
        movwf   valueH                  ;save for compare
        ior     portRxTxData            ;get length low
        movwf   packet+pktLenL          ;save in header area
        movwf   lengthL                 ; and in lengthL
        movwf   valueL                  ;save for compare


ReadFrame
        movlw   0x7f-packet             ;this is the max packet length
        addlw   packet
        subwf   FSR,0
        btfsc   STATUS,C
        goto    RFCont                   ;done
; if C=0 (FSR-packet+64 is neg) then we have not received max bytes yet so write to register file
        ior     portRxTxData             ;read from CS8900
        movwf   INDF                     ;write it to file register
        incf    FSR,1                    ;increment file location
        ior     portRxTxData+1           ;read from CS8900
        movwf   INDF                     ;write it to file register
        incf    FSR,1                    ;increment file location
        goto    RFCont                   ;continue

RFCont  movlw	2
        subwf   lengthL,1
        btfsc   STATUS,C                 ;see if negative (C=0)
        goto    RF1                      ;C set so result is zero or better
        movlw   1
        subwf   lengthH,1                ;decrement high
        btfss   STATUS,C
        goto    ReadDone                 ;high went neg, we're done
RF1     movf    lengthL,0                ;get low
        btfss   STATUS,Z
        goto    ReadFrame                ;not zero, continue
        movf    lengthH,0
        btfss   STATUS,Z
        goto    ReadFrame                ;not zero, continue
ReadDone
        movlw   1
        iorwf   flags,1                  ;flag frame read

        movlw   0x08                    ;check if
        subwf   packet+pktTypeH,0       ; packet type
        btfss   STATUS,Z                ; is 0x0806 (ARP)
        goto    ChkIP                   ;no, check IP
        movlw   0x06
        subwf   packet+pktTypeL,0
        btfsc   STATUS,Z
        goto    DoArp

ChkIP   movlw   0x08                    ;check if
        subwf   packet+pktTypeH,0       ; packet type
        btfss   STATUS,Z                ; is 0x0800 (IP)
        return                          ;no, just return
        movf    packet+pktTypeL,0
        btfsc   STATUS,Z
        goto    DoIP                    ;process IP packet
        return

discard ppRD    ppRxCfg
        movlw   RX_CFG_SKIP
        iorwf   valueL,1
        call    WritePP					;discard frame
        return
;
; It's an arp request, Could be a request or a response.
; ARP packets are small so the whole thing is always in
; the register file.
;
DoArp   movlw   0x01                    ;make sure it's 1
        subwf   packet+ar_hwtype+1,0    ;compare to low
        btfss   STATUS,Z
        return                          ;exit, bad request

        movlw   0x08                    ;make sure it's 0x0800
        subwf   packet+ar_prtype,0      ;compare to high
        btfss   STATUS,Z
        return                          ;exit, bad request
        movlw   0                       ;make sure it's 0x0800
        subwf   packet+ar_prtype+1,0    ;compare to low
        btfss   STATUS,Z
        return                          ;exit, bad request

        movlw   0x06                    ;make sure it's 6 for hwlen
        subwf   packet+ar_hwlen,0       ;compare to high
        btfss   STATUS,Z
        return                          ;exit, bad request
        movlw   0x04                    ;make sure it's 4 for protocol length
        subwf   packet+ar_prlen,0       ;compare to low
        btfss   STATUS,Z
        return                          ;exit, bad request

        movlw   0x01                    ;make sure it's 0x0001 for arp request
        subwf   packet+ar_op+1,0        ;compare to low
        btfss   STATUS,Z
        return                          ;exit, bad request

        movlw   IP1                     ;First IP octet
        subwf   packet+ar_tpa,0
        btfss   STATUS,Z
        return                          ;exit, bad request
        movlw   IP2                     ;second IP octet
        subwf   packet+ar_tpa+1,0
        btfss   STATUS,Z
        return                          ;exit, bad request
        movlw   IP3                     ;Third IP octet
        subwf   packet+ar_tpa+2,0
        btfss   STATUS,Z
        return                          ;exit, bad request
        movlw   IP4                     ;fourth IP octet
        subwf   packet+ar_tpa+3,0
        btfss   STATUS,Z
        return                          ;exit, bad request

; If we got to here, then we have a valid ARP request for our IP address
        movlw   2
        iorwf   flags,1
        return

;
; Process IP packet for ICMP or UDP requests
;
DoIP    movlw   IPT_ICMP                ;get protocol number for ICMP
        subwf   packet+ip_proto,0       ;compare to this packet's proto
        btfsc   STATUS,Z                ;if zero, then it's ICMP
        goto    DoICMP                  ;go process ICMP packet
        movlw   IPT_UDP                 ;get protocol number for UDP
        subwf   packet+ip_proto,0       ;compare to this packet's proto
        btfss   STATUS,Z                ;if zero, then it's ICMP
        return                          ;just return, we dont process this type

DoUDP   movlw   7                       ;port we're listing for requests on
        subwf   packet+u_dst+1,0        ;compare to UDP packet
        btfss   STATUS,Z                ;if zero, then it's echo port
        return                          ;otherwise, just return
        clrf    packet+ip_cksum         ;clear
        clrf    packet+ip_cksum+1       ; checksum
        movf    packet+ip_src,0         ;move
        movwf   packet+ip_dst           ; ip
        movf    packet+ip_src+1,0       ;  of 
        movwf   packet+ip_dst+1         ;   source
        movf    packet+ip_src+2,0       ;    to
        movwf   packet+ip_dst+2         ;     dest
        movf    packet+ip_src+3,0 
        movwf   packet+ip_dst+3   
        movlw   IP1                     ;move
        movwf   packet+ip_src           ; our
        movlw   IP2                     ;  ip
        movwf   packet+ip_src+1         ;   address
        movlw   IP3                     ;    to
        movwf   packet+ip_src+2         ;     source
        movlw   IP4   
        movwf   packet+ip_src+3

        movf    packet+pktSrc0H,0       ;move
        movwf   packet+pktDest0H        ; mac src to dest
        movf    packet+pktSrc0L,0      
        movwf   packet+pktDest0L       
        movf    packet+pktSrc1H,0       ;move
        movwf   packet+pktDest1H        ; mac src to dest
        movf    packet+pktSrc1L,0      
        movwf   packet+pktDest1L       
        movf    packet+pktSrc2H,0       ;move
        movwf   packet+pktDest2H        ; mac src to dest
        movf    packet+pktSrc2L,0      
        movwf   packet+pktDest2L

        movlw   MAC1                    ;move
        movwf   packet+pktSrc0H         ; our
        movlw   MAC2                    ;  MAC
        movwf   packet+pktSrc0L         ;   address
        movlw   MAC3                    ;    to 
        movwf   packet+pktSrc1H         ;     source
        movlw   MAC4
        movwf   packet+pktSrc1L
        movlw   MAC5
        movwf   packet+pktSrc2H
        movlw   MAC6
        movwf   packet+pktSrc2L

        movlw   d'20'
        movwf   lengthL
        clrf    lengthH
        movlw   packet+ip_verlen
        call    cksum
        movf    valueH,0
        movwf   packet+ip_cksum         ;save new checksum
        movf    valueL,0
        movwf   packet+ip_cksum+1

        movf    packet+u_src,0          ;get src port
        movwf   tempL            
        movf    packet+u_dst,0          ;put dest port 
        movwf   packet+u_src            ;in source
        movf    tempL,0
        movwf   packet+u_dst            ;put source port in dest

        movf    packet+u_src+1,0        ;get src port
        movwf   tempL            
        movf    packet+u_dst+1,0        ;put dest port 
        movwf   packet+u_src+1          ;in source
        movf    tempL,0
        movwf   packet+u_dst+1          ;put source port in dest


        clrf    packet+u_cksum  ;clear UDP checksum for new calc
        clrf    packet+u_cksum+1  ;clear byte two

        clrf    cnt_low
        clrf    cnt_mid          ;clear checksum accum
        clrf    cnt_hi
        movlw   packet+ip_src
        movwf   FSR
        movlw   d'8'            ;IP_ALEN*2
        call    UDPCkSum

        movf    packet+ip_proto,0 ;get protocol (1 byte)
        addwf   cnt_low,1         ;add to accum
        btfss   STATUS,C
        goto    ProtoDone
        movlw   1
        addwf   cnt_mid,1
        btfsc   STATUS,C
        incf    cnt_hi,1
ProtoDone

        movlw   packet+u_len    ;add in UDP len
        movwf   FSR
        movlw   d'2'       
        call    UDPCkSum
        movlw   packet+u_src
        movwf   FSR
        movf    packet+u_len+1,0
        call    UDPCkSum

        movf    cnt_hi,0
        addwf   cnt_low,1
        btfsc   STATUS,C
        incf    cnt_mid,1
        comf    cnt_mid,0
        movwf   packet+u_cksum
        comf    cnt_low,0
        movwf   packet+u_cksum+1

        Doutput
        movlw   TX_CMD_START_ALL
        iow     portTxCmd
        movlw   0
        iow     portTxCmd+1

        movf    packet+pktLenL,0        ;length of ARP response frame
        iow     portTxLength
        movf    packet+pktLenH,0
        iow     portTxLength+1
UDPGetStat
        ppRD    ppBusSt         ;get BusStatus
        btfss   valueH,0        ;is BUS_ST_RDY4TXNOW (ready for transmit)
        goto    UDPGetStat      ;no, wait for it

        Doutput
        btfss   packet+pktLenL,0
        goto    WriteEven        ;even # of bytes
        movf    packet+pktLenL,0 ;get length
        addlw   packet
        movwf   FSR
        clrf    INDF            ;clear byte

WriteEven
        movlw   packet+2
        movwf   FSR
        movf    packet+pktLenL,0
        movwf   tempL            ;save length of send in temp

WriteUDP
        movf    INDF,0
        iow     portRxTxData
        incf    FSR,1
        movf    INDF,0
        iow     portRxTxData+1
        incf    FSR,1
        movlw   2
        subwf   tempL,1
        btfsc   STATUS,Z
        goto    UDPDone
        btfsc   STATUS,C
        goto    WriteUDP
UDPDone
        return

;
; Calc (cumulative) checksum of UDP header/data
;
UDPCkSum
        movwf   tempL           ;save length of buffer
        bcf     STATUS,C        ;clear carry
        rrf     tempL,1         ;/2 cuz we process 2 bytes at a time
UDPCklp movf    INDF,0          ;get next byte high
        movwf   valueH          ;save it
        incf    FSR,1           ;increment to low byte
        movf    INDF,0          ;get low
        incf    FSR,1           ;increment
        addwf   cnt_low,1       ;add to accum
        btfss   STATUS,C
        goto    UDPLcarry
        movlw   1
        addwf   cnt_mid,1
        btfsc   STATUS,C
        incf    cnt_hi,1
UDPLcarry
        movf    valueH,0        ;get the high again
        addwf   cnt_mid,1
        btfsc   STATUS,C
        incf    cnt_hi,1
        decfsz  tempL,1
        goto    UDPCklp
        return



;
; Process ICMP (ping) requests
;
DoICMP  ;we might want to check in the future for IA or broadcast requests
        clrf    packet+ip_cksum
        clrf    packet+ip_cksum+1       ;clear checksum

        movf    packet+ip_src,0         ;move
        movwf   packet+ip_dst           ; ip
        movf    packet+ip_src+1,0       ;  of 
        movwf   packet+ip_dst+1         ;   source
        movf    packet+ip_src+2,0       ;    to
        movwf   packet+ip_dst+2         ;     dest
        movf    packet+ip_src+3,0 
        movwf   packet+ip_dst+3   
        movlw   IP1                     ;move
        movwf   packet+ip_src           ; our
        movlw   IP2                     ;  ip
        movwf   packet+ip_src+1         ;   address
        movlw   IP3                     ;    to
        movwf   packet+ip_src+2         ;     source
        movlw   IP4   
        movwf   packet+ip_src+3

        clrf    packet+ic_cksum         ;clear ICMP
        clrf    packet+ic_cksum+1       ; checksum

        clrf    packet+ic_type          ;make type a reply
        clrf    packet+ic_code          ;clear code

        movf    packet+pktSrc0H,0       ;move
        movwf   packet+pktDest0H        ; mac src to dest
        movf    packet+pktSrc0L,0      
        movwf   packet+pktDest0L       
        movf    packet+pktSrc1H,0       ;move
        movwf   packet+pktDest1H        ; mac src to dest
        movf    packet+pktSrc1L,0      
        movwf   packet+pktDest1L       
        movf    packet+pktSrc2H,0       ;move
        movwf   packet+pktDest2H        ; mac src to dest
        movf    packet+pktSrc2L,0      
        movwf   packet+pktDest2L

        movlw   MAC1                    ;move
        movwf   packet+pktSrc0H         ; our
        movlw   MAC2                    ;  MAC
        movwf   packet+pktSrc0L         ;   address
        movlw   MAC3                    ;    to 
        movwf   packet+pktSrc1H         ;     source
        movlw   MAC4
        movwf   packet+pktSrc1L
        movlw   MAC5
        movwf   packet+pktSrc2H
        movlw   MAC6
        movwf   packet+pktSrc2L


        movlw   d'20'                   ;length of IP header
        movwf   lengthL                 ;set length of
        clrf    lengthH                 ; checksum calculation
        movlw   packet+ip_verlen        ;displacement to start of IP header
        call    cksum                   ;calculate the checksum

        movf    valueH,0
        movwf   packet+ip_cksum         ;set new checksum
        movf    valueL,0
        movwf   packet+ip_cksum+1

        movf    packet+ip_len,0         ;get length high
        movwf   lengthH
        movlw   d'20'                   ;ip header length
        subwf   packet+ip_len+1,0       ;calc length of ICMP header+data
        movwf   lengthL
        btfss   STATUS,C
        decf    lengthH,1               ;if prev sub went neg then dec high
        movlw   packet+ic_type          ;start of ICMP header
        call    cksum

        movf    valueH,0                ;set new checksum
        movwf   packet+ic_cksum
        movf    valueL,0
        movwf   packet+ic_cksum+1

        Doutput
        movlw   TX_CMD_START_ALL
        iow     portTxCmd
        movlw   0
        iow     portTxCmd+1

        movf    packet+pktLenL,0        ;length of ICMP response frame
        iow     portTxLength            ; is the same as
        movf    packet+pktLenH,0        ;  the request.
        iow     portTxLength+1
ICMPGetStat
        ppRD    ppBusSt         ;get BusStatus
        btfss   valueH,0        ;is BUS_ST_RDY4TXNOW (ready for transmit)
        goto    ICMPGetStat     ;no, wait for it

        Doutput
        movlw   packet+pktDest0H
        movwf   FSR

        movf    packet+pktLenL,0        ;length
        movwf   lengthL                 ; to
        movf    packet+pktLenH,0        ;  send
        movwf   lengthH

WritePing
        movf    INDF,0                  ;get next byte
        incf    FSR,1
        iow     portRxTxData
        movf    INDF,0                  ;get next byte
        incf    FSR,1
        iow     portRxTxData+1

        movlw   2                       ;subtract
        subwf   lengthL,1               ; two byte from length
        btfsc   STATUS,C                ;see if negative (C=0)
        goto    WP1                     ;C set so result is zero or better
        movlw   1
        subwf   lengthH,1               ;decrement high
        btfss   STATUS,C                ;c=0 means negative
        goto    ICMPDone                ;high went neg, we're done
WP1     movf    lengthL,0               ;get low
        btfss   STATUS,Z
        goto    WritePing               ;not zero, continue
        movf    lengthH,0
        btfss   STATUS,Z
        goto    WritePing               ;not zero, continue
ICMPDone
        return


;
; Calc checksum. Reads packet at offset W for
; LengthH/LengthL bytes and calculates the checksum
; in valueH/valueL.
;
cksum   movwf   FSR
        clrf    cnt_low                 ;we do the arithmetic
        clrf    cnt_mid                 ; using a 24
        clrf    cnt_hi                  ;  bit area
cksuml  movf    INDF,0                  ;get high byte of 16-bit word
        movwf   valueH                  ;save it
        incf    FSR,1
        movf    INDF,0
        incf    FSR,1
        addwf   cnt_low,1               ;add to accum
        btfss   STATUS,C
        goto    noLcarry
        movlw   1
        addwf   cnt_mid,1
        btfsc   STATUS,C
        incf    cnt_hi,1
noLcarry
        movf    valueH,0                ;get the high again
        addwf   cnt_mid,1
        btfsc   STATUS,C
        incf    cnt_hi,1
;
        movlw   2                       ;subtract
        subwf   lengthL,1               ; two byte from length
        btfsc   STATUS,C                ;see if negative (C=0)
        goto    CK1                     ;C set so result is zero or better
        movlw   1
        subwf   lengthH,1               ;decrement high
        btfss   STATUS,C                ;c=0 means negative
        goto    CkDone                  ;high went neg, we're done
CK1     movf    lengthL,0               ;get low
        btfss   STATUS,Z
        goto    cksuml                  ;not zero, continue
        movf    lengthH,0
        btfss   STATUS,Z
        goto    cksuml                  ;not zero, continue
;
CkDone  movf    cnt_hi,0                ;get the third byte of 24 bit area
        addwf   cnt_low,1               ;any carries into this are added in
        btfsc   STATUS,C                ;if that caused a carry, then
        incf    cnt_mid,1               ; increment the middle byte
        comf    cnt_low,0               ;get and ones complement
        movwf   valueL                  ;save it to low
        comf    cnt_mid,0               ;get and ones complement
        movwf   valueH                  ;save as high
        return


;
; Transmit Event
;
TransmitEvent
        return
;
; Processes the pending interrupt requests from the Interrupt Status Queue
;
ProcessISQ
        ; Read the ISQ
NextEvt Dinput
        ior     portISQ         ;read interrupt status queue
        movwf   valueL          ;save value low
        ior     portISQ+1       ;read interrupt status queue high
        movwf   valueH          ;save value high
        movf    valueL,0        ;get val
        btfsc   STATUS,Z
        return                  ;if zero, then done 
        movlw   REG_NUM_RX_EVENT 
        subwf   valueL,0        ;RxEvent?
        btfsc   STATUS,Z
        goto    evtRecv
        movlw   REG_NUM_TX_EVENT 
        subwf   valueL,0        ;TxEvent?
        btfsc   STATUS,Z        ;Ingore BufEvent, RxMiss, and TxCol
        call    TransmitEvent
        goto    NextEvt
evtRecv call    ReceiveEvent
        goto    NextEvt


;
; Initializes the chip 
;
InitChip
         ppWR   ppLineCtl,LINE_CTL_10BASET  ;set to 10BaseT
         ppWR   ppTestCtl,TEST_CTL_FDX      ;set to full duplex
         ppWR   ppRxCfg,RX_CFG_RX_OK_IE     ;enable RxOK interrupt
         ppWR   ppRxCtl,(RX_CTL_RX_OK_A|RX_CTL_IND_A|RX_CTL_BCAST_A)
         ppWR   ppTxCfg,TX_CFG_ALL_IE
;
; Important: The IA needs to be byte revered IA=aa:bb:cc:dd:ee:ff
;
         ppWR   ppIndAddr,(MAC2<<8|MAC1)        ;0xbbaa Write
         ppWR   ppIndAddr+2,(MAC4<<8|MAC3)      ;0xddcc  out
         ppWR   ppIndAddr+4,(MAC6<<8|MAC5)  ;0xffee   48 bit IA
         ppWR   ppIntNum,0x00               ;INT is on INTRQ0

         ppRD   ppBusCtl                    ;get Bus Control
         bsf    valueH,7                    ;enable irq
         call   WritePP                     ;write it back

         ppRD   ppLineCtl                   ;get Line Control
         bsf    valueL,6                    ;set SerRxOn
         bsf    valueL,7                    ;set SerTxOn
         call   WritePP                     ;write it back
         return

;
; Resets the CS8900
;
ResetChip 
        ppWR    ppSelfCtl,SELF_CTL_RESET ;issue a reset to the chip
ResetWait
        movlw   d'1'            ;wait for
        call    wait            ;a millisecond
        ppRD    ppSelfCtl       ;get the Self Control status
        btfsc   valueL,6        ;see it bit 6 (RESET) was cleared
        goto    ResetWait       ;no, then still in reset, wait some more
        ppRD    ppSelfSt        ;get self status
        btfss   valueL,7        ;bit 7 is INITD     
        goto    ResetWait       ; when set, initialization of the CS8900 is done
        return
    
;
; Verifies that the CS8900 is attached and sets the STATUS,Z flag to
; indicate success or not set if failure.
;
VerChip
        Dinput                  ;make the data bus input
        ; first, get the signature at portPtr which should be 0x3000
        ior     portPtr         ;read PacketPage Ptr
        movwf   valueL          ;save value low
        ior     portPtr+1       ;read PacketPage Ptr for high order byte
        movwf   PORTA           ;set the address bus
        movwf   valueH          ;save high low
        movf    valueL,0        ;get low value
        btfss   STATUS,Z        ;should be 0 (i.e. 0x3000 low is 0x00)
        goto    VerBad
        movlw   0x30            ;high part of 0x3000
        subwf   valueH,0        ;subtract from value obtained
        btfss   STATUS,Z        ;see if compared okay
        goto    VerBad
        ppRD    ppEISA          ;get the EISA number whoch should be 0x630E
        movlw   0x63
        subwf   valueH,0        ;compare to 0x63
        btfss   STATUS,Z
        goto    VerBad
        movlw   0x0e            ;compare to 0x0e
        subwf   valueL,0        
        btfss   STATUS,Z
        goto    VerBad
        ppRD    ppProdID        ;get the Product ID which should be 000x xxxx 0000 0000
                                ;where x xxxx = 0 0011 for rev E and 0 0101 for rev F
        movf    valueL,0        ;set return status
VerBad  return                  ;return with status,z indicating success (Z) or not set for failure


;
; Writes the value at valueH/valueL to the PagePacket register who's
; address is in offsetH/offsetL
;
WritePP
        Doutput                 ;make the data bus output
        movf    offsetL,0       ;get the low order byte
        iow     portPtr         ;write to PacketPage Ptr
        movf    offsetH,0       ;get the high order byte
        iow     portPtr+1       ;write to PacketPage ptr
        movf    valueL,0        ;get low order value to write
        iow     portData        ;write to PacketPage data
        movf    valueH,0        ;get high order data
        iow     portData+1      ;write to PacketPage data
        return
;
; Reads the PagePacket at offsetH/offsetL and returns the result in
; valueH/valueL.
;
ReadPP  Doutput                 ;make the data bus output
        movf    offsetL,0       ;get the offset to read
        iow     portPtr         ;write to PacketPage Ptr
        movf    offsetH,0       ;get the high order offset
        iow     portPtr+1       ;PagePacket Pointer Register high byte
        Dinput                  ;make the data bus input
        ior     portData        ;read the PacketPage data
        movwf   valueL          ;save value low
        ior     portData+1      ;read the high order byte
        movwf   valueH          ;save the high order byte value
        return

ioRead  movwf   PORTA
        bcf     PORTC,CHIPSEL
        bcf     PORTC,IOR    
        nop
        movf    PORTB,0      
        bsf     PORTC,IOR    
        bsf     PORTC,CHIPSEL
        return
;
ioWrite bcf     PORTC,CHIPSEL
        bcf     PORTC,IOW      
        nop
        bsf     PORTC,IOW       
        bsf     PORTC,CHIPSEL  
        return



        end




Embedded 10BaseT Ethernet C code

#include <winsock.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
 

int main(int argc, char **argv) { 
char szBuf[256];
struct sockaddr_in sin; 
WSADATA wsaData; 
SOCKET  s; 
int rc,i;
 
 	if (WSAStartup(0x101,&wsaData) == SOCKET_ERROR) 
	{ 
		printf("WSAStartup() failed, rc=%d\n",WSAGetLastError()); 
		WSACleanup(); 
		return -1; 
	} 
	sin.sin_addr.S_un.S_addr = inet_addr("192.168.1.2"); 
	sin.sin_family = AF_INET; 
	sin.sin_port = htons(7); 
 	s = socket(AF_INET,SOCK_DGRAM,0); 
	if(s<0)
	{ 
		printf("Couldn't get a socket, rc=%d\n",WSAGetLastError()); 
		WSACleanup(); 
		return -1; 
	} 
 
	if(connect(s,(struct sockaddr*)&sin,sizeof(sin)) == SOCKET_ERROR) 
	{ 
		printf("connect() failed, rc=%d\n",WSAGetLastError()); 
		WSACleanup(); 
		return -1; 
	} 
 
	for(i=0;i<5;i++)
	{
		wsprintf(szBuf,"Test %d",i+1); 
		rc = send(s,szBuf,strlen(szBuf),0); 
		if (rc == SOCKET_ERROR) { 
			printf("send() failed,rc=%d\n",WSAGetLastError()); 
			WSACleanup(); 
			return -1; 
		} 
		printf("Sent Data [%s]\n",szBuf); 
		rc = recv(s,szBuf,sizeof(szBuf),0 ); 
		if (rc == SOCKET_ERROR) { 
			printf("recv() failed, rc=%d\n",WSAGetLastError()); 
			closesocket(s); 
			WSACleanup(); 
			return -1; 
		} 
		if (rc == 0) { 
			printf("Server closed connection\n"); 
			closesocket(s); 
			WSACleanup(); 
			return -1; 
		} 
		printf("Received %d bytes, data [%s] from the board\n",rc,szBuf); 
	} 
	closesocket(s); 
	WSACleanup(); 
} 

  1. Electronics Circuits