📜 ⬆️ ⬇️

Web server in 5 minutes based on PIC and W5100

Everything you wanted to know about how to launch a simple web server on a W5100 chip in 5 minutes, but were too shy to ask.

image

The article will simply, in detail and clearly describe how to run, for example, a web server on a wonderful and inexpensive W5100 chip from Wiznet.
')
What is she wonderful?
Secondly - inexpensive.
And in the first place, she does all the work for you. You just have to lazily send-receive TEXT (more precisely, HTML) data.

Disclaimer1: An electronic engineer with ... ten years of experience article may seem superficial and simplified, since they are (possibly) in the subject. This article is designed for those who have some experience in electronics, or at least in the programming of microcontrollers, and simply, damn it, wants, finally (together), to run this ... (crossed out) (okay, let it be “great” ) W5100 chip.

Disclaimer 2: I did not set a goal for universal education, a full translation of the datasheet and the interpretation of all its points. My task is to clarify entangled moments and show how to use the W5100 chip and how to run an application on it (for example, a web server).

Based on my explanations and an example of an application, anyone who has experience in microcontrollers and at least the basic concepts in networks will be able to figure out the rest on their own.

Disclaimer 3: Please do not conduct this experiment at home. And it is desirable that there was a nearby adult.

SCOPE


The article does not intend to give comprehensive knowledge of the extensive network topic, there are manuals for this, but it will provide an opportunity to understand what, in principle, is happening and why, and what information to look for in-depth understanding of the subject.

However, the example presented at the end will allow you to figure out how to use the Internet (more precisely, Ethernet and TCP / IP) in your applications on microcontrollers, and, despite its simplicity, it can be fully applied in practice. You will be able to complicate it, because you will understand how to work with a client-server bundle, and finally, having something at hand working and now understanding the topic much better - it will be much easier for you to deepen your knowledge without falling asleep over a dozen pages with descriptions assignment of registers, principles of NAT configuration, or the correct indication of the fragment offset in packets.

("... fragments in the packages .." What was it like Woody Allen?)

From my own experience: usually, the person who writes the article is sabzhekt clear and understandable, so he writes briefly and “clearly”.
However, this is often not the case for the reader, who may not be in the subject line, and often has to guess what exactly the author had in mind, and should one understand a certain statement like this, or is it quite the opposite? Therefore, wherever possible, I will not begin to rassusoliv, and in those places where you need to chew to the utmost clarity and unambiguity of understanding - I will not save words.

At the same time, remember that no one is perfect (even me), so forgive me if someone left unsatisfied.

For those who read to the end, there is a bonus: at the end of the article, the WORKING code on a simple “C” with a bunch of comments will be given so that even a fifth-grader can understand what is happening in the program. The code is written for ordinary PICa (aren't everyone still around AVR-boxes and Arduin-boxes?).

Ingredients


If you do not yet have a particular desire to make a motherboard and solder a chip in the TQFP80 package to it, I recommend taking the usual Arduin's Ethernet Shield based on the W5100. You will also need a simple and inexpensive PIC, a layout for the PICa and some connecting wires, an Ethernet patch cord and, to taste, an RS232 serial cable, in case you suddenly wonder what is going on inside the server during operation (the lines for output associated information - to the terminal).

Lyrics (can be skipped)


Anyone who has some experience in development, this situation is familiar (or not? Or is it just me that loser?)

You take a certain chip on which you need to run the application. For simplicity, let us assume that you are also familiar with the topic / area in which this application will be used (for example, Ethernet, TCP / IP, HTTP, CGI etc).

First, you take a datasheet on a chip, in 100,500 pages,
do not skip lyrics

and read it carefully. Then you reread it a few more times and finally begin to understand how to work with this chip. Then you take errata and repeat the same iterations.

After reading these, you finally understand how the chip works, how to program it correctly (100,500 registers -1), but so far it is still not entirely clear how to RIGHT it should be launched. (For example, does the order refer to the registers, and if so, which order is correct, and if it doesn’t matter, does it really matter?).

Of course, a lot of useful information can be found on the internet and on the forums, but of all the examples found there, it is not quite clear which WORKS work, which work despite the abundance of terrifying mistakes (which you still do not suspect), and which “examples "- just a figment of the imagination of the author, who wrote, but did not check it, hoping that he would run it.

Ok, you went through all these stages, NOW everything is clear to you.

You correctly connect all the pins of the chip to what you should, correctly connect the chip to the processor, correctly set all the registers and what else it has inside, and lo and behold! - finally…
Yes, everything is in order - nothing worked.

This is the most nasty stage - when everything is done correctly and strictly according to the datasheet, but it still does not work. You have a long and dreary understanding of what the problem is, and finally find 1 ... 5 ... 17 bugs. Well, of course! This is what was said in datashit / errata. Well, now it is clear what exactly they had in mind (and what you yourself could guess).

Everything.
Application earned.
Now you are special on this chip.
Fanfare Award. Beer. Crowds of fans. Glory and the next didline.


This article is designed to help readers skip the tedious stages and go straight to the “everything worked” stage and then - in the text.

Lyrics - 2 (you can skip)


Many years ago (even a little more), back in pre-Windows98 times, my friend cooked that they were saying that these false users had divorced, the DOS commands don’t know, they think that if there is Windows 3.11, then go in config.sys not necessarily, but there too, they want a computer.
skip Lyrics 2?
I have always believed that someone likes to poke around inside, but someone just wants to use and not to bathe. And both species have the right to exist. (Guy Kawasaki: “... How can a microwave give an error message? A microwave should just warm up! No one should go through special microwave programming courses!”).

Today, complaints are often heard that, well, they say, these Arduins spoil the people and multiply ignoramuses - there is no need to unlearn years n and gain experience for another years n + 1 - everyone rushed to rivet their projects, not trying to get deep knowledge in programming and electronics.
Horror, horror.
So what?
I think that this is normal - a person with a creative streak and creative thought came up with an idea (or vice versa) and wants to realize it. Not having the deepest knowledge. And that's fine.

Also, at the dawn of the Internet, there was such a mod proudly pointing at the bottom of the page: “the site was created entirely manually in notepad.exe. No HTML editors! ”. Nothing like?

At the same time, for example, I did not start from C and not even from assembler - my first computer, built from scratch and completely empty, to fill in at least a bootloader for it, I programmed in binary code with 16 address bus switches and 8 data bus toggle switches.
For a long time in a dream, long rows of large red zeros and ones came to me, and when mother sent me to buy bread, my first thought was:
"To go for bread ... this is what CODE?"

And even I, a bugger with experience, support progress, increased opportunities for newcomers, and a variety of user types.

Client - Server. In outline


It probably makes sense to start from the end and move up.

You launch the browser program, enter the site name in it - and get the contents of the web page on the screen.
Of course, the browser does not get a beautiful page with pictures, but a bunch of text, HTML tags, links to pictures / videos, etc., puts it all together, and gives you a beautiful (sometimes) web page.

All this is transmitted between the server and the browser via HTTP, which also controls the establishment of the connection between them and their behavior.

Since we are dealing with a network / Internet, then in order to be transferred according to the rules adopted on the network / Internet, all this data (HTML, around which HTTP is wrapped) is wrapped in a new “layer” - TCP / IP.

TCP (Transmission Control Protocol) is used to ensure guaranteed connection and delivery of data packets. Web browsers (like email clients) use TCP.

Probably, I should mention that in addition to TCP, there is also User Datagram Protocol (UDP), which is not at all puzzled by such trifles as establishing a connection and guaranteed message delivery, and since it doesn’t waste time, it writes packets like a machine gun , but it can be used only if the connection (channel) is of high quality and reliable, or if there are no strict requirements for the loss (or, more precisely, NOT the loss) of packets (God, who counts them!).

In this article, UDP will not be considered, but the W5100 can also.

Since our web server will be connected to the computer via an Ethernet connection, it all turns into another layer - Ethernet frames.

In fact, as you know, we could transmit TCP / IP even over a normal RS-232 channel, without any Ethernet.

So, we have a nested doll: Ethernet frame, consisting of service bytes ("headers") and bytes with the actual data (Payload).

This data contains TCP / IP packets, which, in turn, also consist of header bytes and the actual data.

And these latest data, in turn, consist of HTTP-headers and have long been waiting and had a little cool HTML-formatted text and / or images.

We will omit the tale about Ethertet, TCP and IP, because the W5100 takes all these difficulties on us, removing the headache from us (this is its beauty!) (I mean the beauty of the W5100, not a headache).

But we’ll stop on HTTP a bit more, because we’ll have to pick it up from the W5100 and process it (when the web browser makes a request to our server) and vice versa - create it and give it to the W5100 when we (the server) answer the web the browser.

Fully disclose all the nuances of the HTTP protocol in this article is not possible (referring to HTTP / 1.1 RFC 2616 curious), here we will look at the most basic and what will help us to raise a simple (but quite usable) web server.

When we open a web site with a browser (for example: opticaldt.us is not an advertisement!), The browser sends a request to the web site server:

GET / HTTP/1.1
Host: opticaldt.us
Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8,ru;q=0.6


Pay attention to this line: GET ...

After “... /” and before “HTTP / 1.1” it is empty.
This means that, by default, the index.html file (or index.htm) is requested.
If there really is an index.html file in this subdirectory on the server, then the browser will open it successfully. If this file does not exist (or, in general, you made a request for the missing file with any name and extension), the server will respond to you with the “error 404” page (which also does not come from the air — giving it in response to an incorrect request is the server’s task. there is now directly you must create such a page).

As can be seen from the title, the client (browser) reports a lot of interesting and useful about itself.
Since our server will be quite simple, and we will not send anything so special to the client (for example, we will not pull out all intimate details from the header and wow the user with something like, “Hello, you came from such and such ip, then the address on the second floor, although the apartment is not yours at all, the provider’s bill will end in 3 days, don’t forget to replenish, it’s time to feed your cat Fedor, with such a resolution of the screen and WindowsXP it’s not good to visit our amazing site that looked much better would be if you were not Mozilla, a IE 11, oh yeah, you have a Ukrainian ip, that's why “healthy bulls”, although no, this is Evpatoria, therefore “hello again! Etc., etc.), we only the first line will be interested in the request from the browser - we will need it, as people say, “parse” to find out exactly which file the client (browser) wants to receive from our server.

In the simplest version, just to test that the server is working, you can generally send the same HTML page to any request (that is, a request from any file).
(Looking ahead, in our example, we will still give the “file” to index.html if they request it, and the page with an error, if they request something else).

So, we made the above request, by lucky coincidence on this site in this place there is an index.html file, and the server responds to the browser with a message consisting of the header and the actual contents of the index.html file:

HTTP/1.1 200 OK
Date: Sun, 13 Jul 2014 21:32:49 GMT
Server: Apache
Accept-Ranges: bytes
Vary: Accept-Encoding
Content-Length: 185
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html


 <html> <head> <meta http-equiv = "Content-Type" content = "text / html; charset = Windows-1251"> <title> W5100 WebServer </ title> </ head> <body> <center> Well, sho, <br> <b> hello World?! </ b> </ center> </ html>


In the first line (“... 200 OK ..”) the server reports that the request is correct (that is, there is such a file).
In the “Content-Length: 185” line, the server warns the client (that is, the browser) about the length of the transmitted file (more precisely, specifically and specifically about the length of the web page that comes immediately after the HTTP headers).

In order to ensure more or less correct work with the browser, we (the server) will have to give in response (in addition to the HTML file) at least three parameters in the HTTP header:

HTTP / 1.1 200 OK
Content-Type: text / html (if we send exactly this, and not, for example, a picture).
Content-Length: (calculate later)

In fact, modern browsers are very liberal, so you can discard the third header line. Moreover, in our example, after giving the “web page” to the client, we break the connection, so the client (browser) will guess that he has received everything.

But ... If your page is long, or, for example, you are going to send pictures, etc. - it is better to specify the length of the sent data block (Content-Length).

Just a little bit about TCP / IP


When I wrote above that the W5100 does all the work for us with Ethernet and TCP / IP, I just embellished the reality. Something (quite a bit) we still have to do ourselves. Namely: to manage the process of establishing a connection and its termination.

In short, the server and the client communicate by transferring IP packets to each other, which may contain “useful” data (for example, an HTML page), and may be purely official, without “useful” data.

Let's open the datasheet of the W5100 chip (yes, now it's time) and consider how the client (browser) and the W5100 communicate in server mode:

image

Initially, the W5100 in OPEN mode opens / creates a socket (network connection) and enters the listening mode (LISTEN), waiting for a request from a client (ie, a browser).

When a request from the client arrives, and a connection is established between the server and the client, the server (W5100) switches to ESTABLISHED mode and data is exchanged between the parties.

Note: according to the charter, the maximum size of data in the IP packet is 1500 bytes. If your data does not fit into one package (large size of HTML code, or you need to transfer a picture and so on), you will have to divide the data into portions less than 1500 bytes and transfer them one by one.

Further, when the parties expressed to each other everything that went up in their souls, one of them (as in life) was the first to “hang up” by sending a Disconnect Request.

Note: the disconnection does not always occur after the (full) data transfer. For example, you have a slow channel, or interference has gone, and the browser is tired of waiting for completion and has disconnected due to a timeout. Either something went wrong at the web server and he decided to terminate the connection in the most interesting place. Well, in general, anything in life happens.

After the connection between them is broken, the server goes into the mode of closing the connection (socket) - CLOSED (no, well, everything that was needed - it was said / sent, why still wait for that?).

Everything.

If you are a supporter of fleeting connections and / or once you have more than enough - you can stop there.
If you are an optimist in life (or just persistent) and believe that your server may well still be contacted, and more than once - you just need to go back to the “OPEN” step and then follow the picture. (Decent servers usually do this). Although ... maybe in the future there will be cheap plastic disposable server? Type used 1 time - and threw it away?

One could do without it (thanks to the W5100), but I’ll still mention. In real life, with each exchange of akket between the client and the server and with each change of the connection status, flags are set in the packets that are sent, indicating what is happening and how to live with it.

Take the most common IP stack:

Let no one be frightened by the beautiful word “stack”; sorcerers and magicians from IBM-360 and AS-400 specially invent intricate terms in order to suppress any desire of ordinary mortals to touch their Temple with unwashed hands. In fact, this is just a protocol, a data transfer format, in which how long and in which order the service fields and the actual data follow. (Zhvanetsky: "... and even the Bulgarians cannot understand our expression, that" despite the weather conditions "- it means just rain!")

image

We are interested in the three bits in the seventh byte: FLAGS.

The combinations of these three bits form the following flags: FIN, SYN, RST, PSH, ACK, URG.

FIN - indicates the end of the session;
SYN - connection initialization;
RST - interruption of the connection (usually in response to an error);
ACK - acknowledgment of receipt (packet);
PSH - simply - the requirement for the immediate expulsion of confirmation;
URG - an indication of the aristocracy of this package.

If you are curious (which is commendable and useful), how in reality is the exchange of packages and which flags are set and in which cases, and everything else - what are the other header fields for (good, good, “stack”) - you have to find it yourself. In this article, we will not consider this, since the W5100 takes all the care of the packages and flags, but we are dealing with an accomplished fact - the status of the connection at the moment (OPEN, LISTEN, ESTABLISHED, CLOSED).

As brief as possible, the description of the W5100


Well, further it is not possible to delay this moment, it is time to consider the W5100 from the hardware and software sides.

image

On the one hand, the W5100 is connected to the Ethernet connector (via a transformer and matching circuits), on the other hand, from a microcontroller.
It can be connected to the microcontroller (to taste and situation) either using address and data buses, or via the SPI interface.
How exactly to connect the chip - I will not begin to paint, there are many ready-made diagrams with a description on the Internet. Especially (well, I will reveal the secret) that in our example we will use a ready-made board with this chip.

The chip contains Ethernet PHY and MAC, implemented in hardware handlers for Ethernet frames and several IP group protocols, allows you to create up to 4 sockets (network connections) and contains RX and TX buffers with 8K bytes of memory each, which can be distributed between each socket fraternally or fairness (or equally), allocating 1,2,4 or 8 KB per socket (but not forgetting that the size of the entire buffer is 8KB for reception and 8KB for transmission).

Memory allocation:

image

As can be seen from the figure:

from the address 0x0000 to the address 0x002F are common to all registers,
from the address 0x0400 to the address 0x07FF - 4 identical groups of registers - one for each socket,
from the address 0x4000 to the address 0x5FFF - transfer buffer (8KB), which you can distribute between sockets at your discretion,
from address 0x6000 to 0x7FFF - receive buffer (8KB), which you can also distribute between sockets at your discretion.

All registers are 8 bit. Most can be both read and write.

We will not consider all registers, but only those that we need to create a web server, however, you can easily understand the general idea and further develop it for your specific tasks.

An important point: the W5100 uses the byte order, which is popularly called “big endian” or “network order”. The deep scientific meaning comes down to the fact that the high bit of the high byte goes first (transmitted) and the last low bit of the low byte, and, most importantly, the high bytes are located in the lower memory addresses. Ie, for example, to write 4 bytes of the IP address of your server (say 192.168.0.155) to the Source IP Address 0x000F ... 0x0012 (SIPR0 ... SIPR3) registers, you should write "192" to the SIPR0 register, "168" - in SIPR1, "0" - in SIPR2 and "155" - in SIPR3.

General registers


(General means they affect the operation of the whole chip and all sockets, that is, they do not refer to a specific socket).

0x0000 MR - Mode - everything is clear here - through them we set the mode of operation;
0x0001 ..0x0004 GAR0..3 - Gateway Address (ex. 192.168.0.254);
0x0005 ... 0x0008 SUBR0..3 - Subnet mask Address (ex. 255.255.255.0);
0x0009..0x000E SHAR0..5 - Source Hardware Address
(to put it simply - MAC address, for example, 0A 1B 2C 3D 4E 5F).
(if you are not going to flood the market with your servers, you can specify any MAS, the main thing is that there are no devices with the same MAC address in your network - we don’t need conflicts, right?)

0x000F ... 0x0012 SIPR0..3 - Source IP Address - the address of our web server, for example: 192.168.0.155;
0x001A - RMSR - RX Memory Size - here you specify how much memory the receive buffer will have on each socket;
0001 - MSR - X Memory Size - here you specify how much memory of the transmission buffer will be on each socket;

Socket registers


In our example, we will work with only one socket and only with its registers that are needed for a TCP / IP server, therefore, we consider only these registers:

00400 S0_MR - Socket0 Mode Register - set the mode of operation of this particular socket;
00401 S0_CR - Socket0 Command Register - here we will issue commands to control the state of the connection;
00403 S0_SR - Socket0 Status Register - from here we will read data about the current status of what is happening;
0x0404, 0x0405 S0_PORT0, S0_PORT1 - Socket0 Source Port - the port on which our server is available (if more correct - the port on which the socket opened by us is available).

To be honest, when accessing the service, we must fully indicate the protocol, server address of the service, and port number (as well as the file name and full path to it).

For example, if we need the index.html file located on the server with the address 192.168.0.155 with access to the socket through port 123, then in the browser URL line (that is, in the address line) we will need to write:

192.168.0.155 : 123 / index.html (wait until you press Enter).

But ... For connections of the "http: // ..." type (that is, for the HTTP protocol), it is customary to allocate port 80.
Therefore, if we assign port number 80 to Socket0 Source Port, we can omit it in the address bar of the browser, because if the port is not specified, the browser will by definition refer to this port, resulting in a URL of the form 192.168.0.155/index. html will work fine without errors. (Speaking more generally, this is true for all cases for which there are default ports
- if you do not specify them when accessing the service, the client goes to the default port: 80 for HTTP, 23 for Telnet, and so on).

Also, as we discussed earlier, if you do not specify the name of the requested file, it is customary for both parties to mean that we are talking about the index.html (or index.htm) file (or index.php). Therefore, specifying in the address bar of the browser: 192.168.0.155 , we will get the correct response from the server (that is, if the client does not ask us for a specific file name, then we understand that he is waiting for the index file) (remember that if for example, a client has requested a directory, the contents of which we are embarrassed to show to everyone and everyone (for example, pictures with cats, or scripts, etc.), it will be quite comical to give him a “404 error” page.

Well, in order to completely save time on entering the address - if you do not specify the type of protocol, the browser will automatically assume that this is HTTP (if, of course, the browser is not IE who loves it ... Ok, it doesn’t matter, forget it).

Thus, simply by writing in the address bar 192.168.0.155 - all parties will understand that we are talking about 192.168.0.155 : 80 / index.html

So it's decided, yes? Let's set the address of the socket port - 80 in our server.
At the same time, we don’t forget about “big endian”, therefore 80 (more precisely - 0080) will be written like this: S0_PORT0 = 00, S0_PORT1 = 80 (yes, and do not forget - these are decimal “80”, not hexa).

00420, 00421 S0_TX_FSR0, S0_TX_FSR1 - Socket0 TX Free Size - the size of the free space in the transfer buffer of Socket 0;
0x0422, 0x0423 S0_TX_RD0, S0_TX_RD1 - Socket0 TX Read Pointer (* read only) - indicates in the transmission buffer the beginning of the data block, which (data) we are going to send to the client.

There is a tricky trick (Wiznet decided to chew up kanfetku): if, for example, you read Socket0 TX Read Pointer, and he points, for example, to the address 0x4200, then ... correctly - this does not mean at all that you have to write your transmission data buffer starting from this place. Aha, aha ... ("if a woman behind the wheel shows a left turn - this does not mean that she is going to go straight!" (C)). We will talk more about this later.

00424, 00425 S0_TX_WR0, S0_TX_WR1 - Socket0 TX Write Pointer - indicates in the send buffer to the end of the data block, which (data) we are going to send to the client.

Here it is necessary (again) to make an important explanation.
The last two registers do not define the physical addresses at which we have to write a block of data for transmission in the buffer. We must calculate these addresses ourselves.

One more note: let's say you allocated 2K to the transfer buffer. You read Socket0 TX Read Pointer and it turned out that it points to the last 10 bytes of the buffer. In general, you intended to transfer (ie, write to the buffer) 1000 bytes. What to do?
It's simple: you write your data to transfer to these 10 bytes, then go to the very beginning of the buffer and continue to write the rest of the data further (ie, 1000 of your data, 10 bytes will be placed at the end of the buffer, and the rest 990 bytes - at the beginning buffers).
The W5100 knows about this disgrace (in fact, he nagged them) and therefore, having reached the end, he will jump to the beginning of the buffer and patiently read the remaining portion.

Well, now let's deal with this mutant - as from the pointers specified in the registers, calculate the physical addresses at which you should write the data to the transfer buffer.

, , , , , 3 , .

, - , , . ( , ; , , ).

, :

S0_TX_BASE — 0.

, 04000.
W5100 ? , , «» , ( ) 01984.
: 0 , 1 ( ) , .
, «-» TMSR ( ), , «» .

, , , , :
S0_TX_BASE = 0x4000.

S0_TX_MASK - mask, we will need further in the "calculations".

Similarly, the mask, in an amicable way, must be calculated for each socket on the basis of what is written (by the way, by you) in the register of memory allocation of the buffer between sockets (TMSR).

I do not calculate anything (I used to think that I was a bummer, but when I became a regular reader, Habra found out that everything is alright - I just have procrastination), I allocated 2KB for each socket (which, as you remember, are not equal to 2000 grams, but 2048 bytes), respectively, the mask is 2048 -1 = 2047 (0x07FF).

Total, in our example will be: S0_TX_MASK = 0x07FF.

Now we add confusion, and then unraveling it with honor:

, (read only) S0_TX_RD0, S0_TX_RD1– , .
– , , , (, , ).
, ( ) , ( ), S0_TX_WR0, S0_TX_WR1.

, , W5100 , S0_TX_RD0, S0_TX_RD1, , , , () , S0_TX_WR0, S0_TX_WR1, . (, , S0_TX_RD0, S0_TX_RD1 S0_TX_WR0, S0_TX_WR1).

, , , – ( ). , , coffee break .

, - .
5- , , , .

:

: S0_TX_OFFSET = make16 ( S0_TX_RD0, S0_TX_RD1 )

// 16- «» 8- -
// , «-», S0_TX_RD0,
// — S0_TX_RD1

, ( – ), , , , ( ).
():

S0_TX_OFFSET = ( S0_TX_OFFSET & S0_TX_MASK )

, , :

S0_TX_Start_Addr = S0_TX_OFFSET + S0_TX_BASE

, , , (0), () — , .

, ?
() – Socket0 TX Write Pointer.

Socket0 TX Read Pointer Socket0 TX Write Pointer .
(. ) , ( ), – .

, – .
Attention! — , , – .
:

Socket0 TX Write Pointer = Socket0 TX Write Pointer + __.

, , , «Socket0 TX Write Pointer» (16 ) 8- S0_TX_WR0 ( ) S0_TX_WR1 ( ).

( — , — – , ...)

! … , … . , , – – – , .
: ? , . - – . Deal?


Algorithm


If I had a hope to get an invite for an article, it melts with each new paragraph.

Yes - the readers probably think that they bought it so they bought it on "... server in 5 minutes"! Wait - you have not seen the code yet! No, that is, it is not short, of course, but a little on the contrary, but this is all because of the abundance of comments and inserts for debugging. If you need to remove extras so that only a useful code remains - it can be written on a napkin in general! And then, it is better to spend 10 minutes reading here than 2 days to read a datasheet of 100 pages. Well, again - “hard in training - 5 minutes in battle "- no one has canceled.


Yes, so, the algorithm.

I usually like to understand what is being done in the program, and I prefer to have a flock chart. In the same way, despite the overwhelming desire to immediately write code, I usually manage to pull myself up and start by drawing a flock to first debug the logic of working on it, and only then go to the code. So, let's see how our web server will work (see picture):

image

If the principle “it’s better to see 100 times - than once to hear” still works, then there’s probably no point in describing what is written in the picture?

Only two words:

Process control will occur through S0_CR (Socket0 Command Register) (00401).

Checking current states (connections and other) through S0_SR (Socket0 Status Register) (00403).

, ( ), , , – .

Ethernet Shield — PIC


image

— .

: 23 ( , ) — . , , .

– . , , , .

( – !)


(?), , - ( ) – , , .

CCS . ( – ) IDE.

PIC16F77 ( -). ( – ) PIC. , print ( ), .

, «» RS232 — , . – .

( ) HTTP , , . index.html « ». , – .

:

GET / HTTP / 1.1

Pay attention to the space after the first "/" and before "HTTP" - in this place could be your advertisement could be the name of the requested file.

Once there is empty (space) - it means that it is index.html that is requested. (Ok, the explanation is not entirely correct. Usually, when visiting the site, you simply specify the name of the site, without any slash and file name there. The guys on both sides paid to who you need , agreed that if the file name is not specified, then we will issue response index file).

For example, entering the address of the browser in the address:

192.168.0.155/kotiki.jpg

Send a request to the server that looks like this:

GET /kotiki.jpg HTTP / 1.1

— HTTP – «» index.html ( ). - — _404.

, , - HTML .

… ( ! ! ) , . : HTTP , « », :

HTTP/1.1 404 Page not found

( , HTTP/1.1 200 OK)

HTML , , . Internet Explorer. , , - Internet Explorer.

, , : HTTP « » « » — \r \n ( ASCII: 0D 0A ). , ( ) . , HTTP HTML of these combinations (that is, \ r \ n \ r \ n or 0D0A0D0A in ASCII codes) otherwise not only you yourself know what browser but others will not understand you either.

Oh, and more (still valuable experience and you should know about it). Another fly in the barrel of an overly scrupulous browser (well, you understand): I somehow made a mistake in the HTTP header, indicating the length of the subsequent HTML code (Content-Lenght: ...) literally indicated 1 character more than in fact (well, that is, there are symbols, say, 665, and I indicated that there would be 666).
So, all browsers swallowed the page with an eye without blinking, and IE honestly waited until it was blue until the 666th character arrived and until it came - refused to show the page at all.

-, - . , main(), – . , , ( ) main() , , .

, , ping ( ping ( 192.168.0.155) — .
ping — .
/, ( ), ping .
, ping IP , ICMP (Internet Control Message Protocol), , IP ( — RFC 792 ), , , ping- .
W5100 .

, : , , .

– , , , , .

, , .
— « 5 ».

-, !

( - - 6 )
 // =====  -   W5100  Wiznet ====== // *     Ethernet Shield //   W5100 //=========================================================== #include <16F77.H> #fuses HS //  ,  #use delay(clock=16M) ) //    16  //     –   #use rs232(baud=19200, xmit=PIN_A2, rcv=PIN_A3) //    RS232 // *  CCS   « printf» - , //       - // **   //   PICa    Ethernet Shield #define RESET pin_B2 // *active LOW #define MISO pin_B3 // input #define MOSI pin_B5 // output #define SS pin_B0 // output. SlaveSelect, Active LOW #define SCK pin_B1 // output. //**********   W5100 ********************* //************************************************************** #define MR 0x0000 // MODE register #define GAR0 0x0001 // GATEWAY Addr register0 (MSB) #define GAR1 0x0002 // GATEWAY Addr register1 #define GAR2 0x0003 // GATEWAY Addr register2 #define GAR3 0x0004 // GATEWAY Addr register3 (LSB) #define SUBR0 0x0005 // SUBNET MASK Addr register0 (MSB) #define SUBR1 0x0006 // SUBNET MASK Addr register1 #define SUBR2 0x0007 // SUBNET MASK Addr register2 #define SUBR3 0x0008 // SUBNET MASK Addr register3 (LSB) // MAC   #define SHAR0 0x0009 // SOURCE HARDWARE Addr register0 (MSB) #define SHAR1 0x000A // SOURCE HARDWARE Addr register1 #define SHAR2 0x000B // SOURCE HARDWARE Addr register2 #define SHAR3 0x000C // SOURCE HARDWARE Addr register3 #define SHAR4 0x000D // SOURCE HARDWARE Addr register4 #define SHAR5 0x000E // SOURCE HARDWARE Addr register5 (LSB) #define SIPR0 0x000F // Source IP Addr register0 (MSB) #define SIPR1 0x0010 // Source IP Addr register1 #define SIPR2 0x0011 // Source IP Addr register2 #define SIPR3 0x0012 // Source IP Addr register3 (LSB) #define RMSR 0x001A // RX memory size (1K,2K,4K or 8K per socket, from total 8K) #define TMSR 0x001B // TX memory size (1K,2K,4K or 8K per socket, from total 8K) //--  Socket0 (*       ) #define S0_MR 0x0400 // Socket0 MODE register #define S0_CR 0x0401 // Socket0 COMMAND register #define S0_SR 0x0403 // Socket0 STATUS register #define S0_PORT0 0x0404 // Socket0 SOURCE Port register0 (H byte) #define S0_PORT1 0x0405 // Socket0 SOURCE Port register1 (L byte) #define S0_TX_FSR0 0x0420 // Socket0 TX Free SIZE register0 #define S0_TX_FSR1 0x0421 // Socket0 TX Free SIZE register1 #define S0_TX_RD0 0x0422 // Socket0 TX Read POINTER register0 #define S0_TX_RD1 0x0423 // Socket0 TX Read POINTER register1 #define S0_TX_WR0 0x0424 // Socket0 TX Write POINTER register0 #define S0_TX_WR1 0x0425 // Socket0 TX Write POINTER register1 #define S0_RX_RSR0 0x0426 // Socket0 RX Received SIZE register0 (H byte) #define S0_RX_RSR1 0x0427 // Socket0 RX Received SIZE register1 ( L byte) #define S0_RX_RD0 0x0428 // Socket0 RX Read POINTER0 (H byte) #define S0_RX_RD1 0x0429 // Socket0 RX Read POINTER1 (L byte) // -----   (     0 ) ----- #define OPEN 0x01 #define LISTEN 0x02 #define CONNECT 0x04 #define DISCON 0x08 #define CLOSE 0x10 #define SEND 0x20 #define SEND_MAC 0x21 #define SEND_KEEP 0x02 #define RECV 0x40 // -----   (    STATUS 0 ) --- #define SOCK_CLOSED 0x00 #define SOCK_INIT 0x13 #define SOCK_LISTEN 0x14 #define SOCK_ESTABLISHED 0x17 #define SOCK_CLOSE_WAIT 0x1C // ----------  «»  ----------- #define SERVER_IP0 192 //    192.168.0.155 #define SERVER_IP1 168 #define SERVER_IP2 0 #define SERVER_IP3 155 #define SERVER_PORT0 0 //    :80 #define SERVER_PORT1 80 #define GATEWAY_IP0 192 //  .     -  #define GATEWAY_IP1 168 #define GATEWAY_IP2 0 #define GATEWAY_IP3 254 #define SUBNET_MASK0 255 //   ( ) #define SUBNET_MASK1 255 #define SUBNET_MASK2 255 #define SUBNET_MASK3 0 #define MAC0 0x00 //   , ,     #define MAC1 0x1A //        #define MAC2 0x2B #define MAC3 0x3C #define MAC4 0x4D #define MAC5 0x5E //-----------    --------------- void SSPI_write(int Data); //  1   W5100  SPI int SSPI_read ( void); //  1   W5100  SPI void SetW5100register (int16 regaddr, int data); // ()  W5100  SPI int GetW5100register (int16 regaddr); //     W5100  SPI void Init (void); //  W5100   int Open_Socket0(void); //      (/) int Listen_Socket0(void); //      (/) int Socket0_Connection_Established (void); //        (/) int Socket0_Received_Data_Size (void); //    ,    ( 0   ) void Socket0_Received_Data_Reading (void); //      //   -    int Socket0_FIN_Received(void); //       FIN   / void Socket0_Disconnect(void); //    W5100     int Socket0_Closed(void); //       / int Socket0_Connection_Timeout(void); //     -    / void Socket0_Closing(void); //   int Socket0_Received_Request_is_index_html(void); //          Index.html //   / void Socket0_Send_index_html (void); //   «» index.html void Socket0_Send_404_error (void); //   «» « 404» //------------   ----------------------------------- int16 S0_RX_BASE; //   ,   RX   0 int16 S0_RX_MASK; //  RX  0 int16 S0_RX_OFFSET; //        RX  int16 S0_RX_Start_Addr; //        RX  int16 S0_RX_RSR ; //       int16 S0_TX_BASE; //   ,   X   0 int16 S0_TX_MASK; //  X  0 int16 S0_TX_OFFSET ; //        ,     //     int16 S0_TX_Start_Addr; //       ,    //      int16 S0_TX_End_Addr; //        ,   W5100 //        // ---      HTTP   «-» // *   [222]      .       // ** CONST –       (   ) CONST char INDEX[222] = { "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Lenght: 43\r\n\r\n<HTML><CENTER>HELLO WORLD !</CENTER></HTML>"}; //     «index.html” CONST char ERROR404[222] = { "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Lenght: 39\r\n\r\n<HTML><CENTER>ERROR 404</CENTER></HTML>"}; //     « 404” //     , //       « 404»,     , ... //CONST char ERROR404[222] = { "HTTP/1.1 404 Page not found\r\nContent-Type: text/html\r\nContent-Lenght: 39\r\n\r\n<HTML><CENTER>ERROR 404</CENTER></HTML>"}; // ..  IExplorer   HTTP  "HTTP/1.1 404 Page not found" //    ,   ,     int try=0; // ,  .    –  //===================== MAIN ============================================ //======================================================================= void main() { Init(); //  W5100   ( ) OpenSocket0: //ooooooooooooooooooo   0 oooooooooooooooooooooooo if ( ! Open_Socket0() ) goto OpenSocket0; //      //ooooooooooooooooo   ooooooooooooooooooooooooo if ( Listen_Socket0() == FALSE ) goto OpenSocket0; //    «» -      //oooooooooooooo   ? oooooooooooooo CheckConnection: // if (Socket0_Connection_Established() == FALSE ) goto CheckConnection; //      (       ) printf("> Connection Established... \r\n"); //   (  )   //ooooooo(   )    - ? oooooo if ( Socket0_Received_Data_Size() == 0 ) { printf("\r\n> (Zero) Received Data size is: %Lu (bytes) \r\n", S0_RX_RSR); //   (  )   goto CheckFIN; //          //      FIN } //    ( =0)        else { printf("\r\n> (NonZero) Received Data size is: %Lu (bytes) \r\n", S0_RX_RSR); //   (  )   } // oooooooooo (    )  * ooooooooooooooo //         //       Socket0_Received_Data_Reading(); //   (  )   // oooooooooooooo    ooooooooooooooooooooooooooooooo //    HTTP   HTML  if ( Socket0_Received_Request_is_index_html() == TRUE) Socket0_Send_index_html (); //    "index.html"    index.html else Socket0_Send_404_error (); //        «» « 404» //ooooooooooo   FIN ? ooooooooooooooooooooooooooo //        CheckFIN: if ( Socket0_FIN_Received() == TRUE) goto CloseConnection; //  FIN  -    0 //ooooooooooo   ooooooooooooooooooooooo Socket0_Disconnect(); //   0 //ooooooooooo   ? ooooooooooooooooooooooooooooooo if (Socket0_Closed() == TRUE ) goto CloseConnection; //    –    //ooooooooooo    -   ? ooooooooooooooooooo if ( Socket0_Connection_Timeout() == TRUE) goto CloseConnection; //   ,   -, –    CloseConnection: //ooooooooooo   ooooooooooooooooooooooooooooooooooo Socket0_Closing(); //oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo goto OpenSocket0; //    ,  . //         (    «-» ) } //=================== END of MAIN =========================== //============================================================ //--------------------------------------------------------------- //--------------------------INIT ------------------------------- void Init (void) { output_low(RESET); //  «»   Ethernet  delay_ms(1); output_high(RESET); output_low(SCK); //   ()  SPI output_high(SS) ; //   W5100. SetW5100register(MR, 0x80); //   RST  W5100 Mode Register //------------   (W5100)   0 ------------- SetW5100register(RMSR, 0x55); //  RX :  2    S0_RX_BASE = 0x6000; //   RX   0 S0_RX_MASK = 0x07FF ; // (2048 -1 )= 0x07FF, RX  ( = _ – 1 ) SetW5100register(TMSR, 0x55); //  X :  2    S0_TX_BASE = 0x4000; //   TX   0 S0_TX_MASK = 0x07FF; // (2048 -1 )= 0x07FF,   ( = _ – 1 ) //------------     -------------- // ..      W5100 // –       SetW5100register(SHAR0, MAC0); SetW5100register(SHAR1, MAC1); SetW5100register(SHAR2, MAC2); SetW5100register(SHAR3, MAC3); SetW5100register(SHAR4, MAC4); SetW5100register(SHAR5, MAC5); //------------   IP -------------- //   -    W5100 –   SetW5100register(SIPR0, SERVER_IP0); SetW5100register(SIPR1, SERVER_IP1); SetW5100register(SIPR2, SERVER_IP2); SetW5100register(SIPR3, SERVER_IP3); //------------   PORT -------------- //   –   –   SetW5100register(S0_PORT0, SERVER_PORT0); SetW5100register(S0_PORT1, SERVER_PORT1); //------------  Gateway addr -------------- //   –   –   SetW5100register(GAR0, GATEWAY_IP0); SetW5100register(GAR1, GATEWAY_IP1); SetW5100register(GAR2, GATEWAY_IP2); SetW5100register(GAR3, GATEWAY_IP3); //------------ set Subnet Mask -------------- SetW5100register(SUBR0, SUBNET_MASK0); SetW5100register(SUBR1, SUBNET_MASK1); SetW5100register(SUBR2, SUBNET_MASK2); SetW5100register(SUBR3, SUBNET_MASK3); printf(" \r\n\r\n > =============== W5100 - ==========\r\n\r\n"); //   (  )   } //-------------------------------------------------------------- //-------------   0 ---------------------------- int Open_Socket0(void) { //   (  )   printf(" \r\n =========== TRY # %u ====================\r\n", try); if (try ==255) try =0; else try++; printf("\r\n> Start Open Socket... \r\n"); //   –   ,    SetW5100register(S0_MR, 0x01); //     –   ( ) SetW5100register(S0_CR, OPEN); //      // *    ,  «SOCK_INIT»      if (GetW5100register(S0_SR) != SOCK_INIT) //  STATUS  { SetW5100register(S0_CR, CLOSE); //      return FALSE ; //     0 } return TRUE; // .    1 } //-------------------------------------------------------------- //-------------  0    ------------ int Listen_Socket0 (void) { printf("> Sock opened. Go Listen... \r\n"); //   (  )   //           // * – ..  – ,      SetW5100register(S0_CR, LISTEN); if ( GetW5100register(S0_SR) != SOCK_LISTEN) //    { SetW5100register(S0_CR, CLOSE); //        return FALSE; //       0 } return TRUE; //    ,    1 } //-------------------------------------------------------------------------- //-------------      0 ? -------- // *     ( ) int Socket0_Connection_Established(void) { //  W5100      ,     //    ACK      SOCK_ESTABLISHED // («   ) //         , //    -    if ( GetW5100register(S0_SR) == SOCK_ESTABLISHED) return TRUE ; //   . //    () = «SOCK_ESTABLISHED»    1 else return FALSE; //   –    0 printf("> Connection Established... \r\n"); //   (  )   // *    ,    /  } //----      ------------- //----------------------------------------------------- // * «»        //          // (,  /  -) int Socket0_Received_Data_Size (void) //        =    { S0_RX_RSR = make16 (GetW5100register(S0_RX_RSR0), GetW5100register(S0_RX_RSR1) ); //   8-     // RSR0 –  , RSR1 –   //  «» 16-  -    printf("> Received Data size is: %Lu (bytes) \r\n", S0_RX_RSR); //   (  )   if (S0_RX_RSR == 0 ) return FALSE; //   ( .. =0 ) //    0 else return TRUE; //     ( ..  -) //    1 } //----------      --------------- //------------------------------------------------------------ // *     .    void Socket0_Received_Data_Reading (void) { int16 n; int RXbyte; S0_RX_OFFSET = make16 ( GetW5100register(S0_RX_RD0), GetW5100register(S0_RX_RD1) ); //   8-   16   - //       RX  0 printf("> S0_RX_RD (RX mem read pointer) = %LX \r\n", make16 ( GetW5100register(S0_RX_RD0), GetW5100register(S0_RX_RD1) ) ); S0_RX_OFFSET = (S0_RX_OFFSET & S0_RX_MASK ) ; //         0  printf("> S0_RX_Offset = S0_RX_RD & S0_RX_MASK = %LX \r\n\r\n",S0_RX_OFFSET ); S0_RX_Start_Addr = S0_RX_OFFSET + S0_RX_BASE ; //         printf("> S0_RX_Start_Addr = S0_RX_OFFSET + S0_RX_BASE = %LX (physical)\r\n\r\n", S0_RX_Start_Addr ); printf("> Going to print-out Received Data... \r\n\r\n"); printf("ooooooooooooooooooooooooooooooooooooooooooo\r\n"); for (n=0; n < S0_RX_RSR ; n++) { if ( S0_RX_Start_Addr > (S0_RX_BASE + S0_RX_MASK) ) S0_RX_Start_Addr = S0_RX_BASE; RXbyte = GetW5100register(S0_RX_Start_Addr); printf("%c", RXbyte); S0_RX_Start_Addr++; } printf("\r\noooooooooooooooo END of received data oooooooooooooo\r\n\r\n"); } // ---        INDEX.HTML  ------ //---------------------------------------------------------------------- int Socket0_Received_Request_is_index_html(void) { int RXbyte=0; S0_RX_OFFSET = make16 ( GetW5100register(S0_RX_RD0), GetW5100register(S0_RX_RD1) ); //   8-   16   - //       RX  0 S0_RX_OFFSET = (S0_RX_OFFSET & S0_RX_MASK ) ; //         0  S0_RX_Start_Addr = S0_RX_OFFSET + S0_RX_BASE ; //         printf("\r\n>----------- parsing HTTP header-------------\r\n"); //   (  )   while (RXbyte != 0x2F) //   "/"  HTTP  { if ( S0_RX_Start_Addr > (S0_RX_BASE + S0_RX_MASK) ) S0_RX_Start_Addr = S0_RX_BASE; //           // ,       //   –      –       RXbyte = GetW5100register(S0_RX_Start_Addr); //    RX ,     printf("%c", RXbyte); //   (  )   S0_RX_Start_Addr++; //   –       } //       («»)    HTTP   “/” //        "/" . //      - RXbyte = GetW5100register(S0_RX_Start_Addr); //   printf("\r\n> -------- END of parsing HTTP header -------\r\n"); //   (  )   if (RXbyte == 0x20) return TRUE; //   «» -      ,  index.html //     1 else return FALSE; //         ,    index.html //     - 0 } //------    « 404» ------------ //------------------------------------------------------------- //    0    HTTP   HTML  //  « 404»,   W5100    //     ,     void Socket0_Send_404_error (void) { int16 n; char TXbyte; int16 datalength; S0_TX_OFFSET = make16 ( GetW5100register(S0_TX_RD0), GetW5100register(S0_TX_RD1) ); //   8-   16   -  //  ,        X  0 S0_TX_OFFSET = (S0_TX_OFFSET & S0_TX_MASK ) ; //         0  S0_TX_Start_Addr = S0_TX_OFFSET + S0_TX_BASE ; //           //    HTTP   HTML  datalength=0; while ( ERROR404[datalength] !=0) datalength++; //   «datalength»      000   // (000 -   ) //  ,  W5100   ,    //    ,   ,    . //  , W5100       . //            W5100: //     -        //     2-  // *(           //       «»  ) S0_TX_End_Addr = make16 ( GetW5100register(S0_TX_WR0), GetW5100register(S0_TX_WR1) ); //    -       S0_TX_End_Addr += datalength ; // increment to fatalength //   (     )  «» //  2       SetW5100register(S0_TX_WR0, make8( S0_TX_End_Addr ,1) ); //   SetW5100register(S0_TX_WR1, make8( S0_TX_End_Addr,0) ); //   printf("\r\n>Data length is: %Lu \r\n", datalength); printf("\r\n>--- Filling TX buffer w data: -----------\r\n"); //   (  )   //        –   For (n=0; n < datalength; n++) //      { TXbyte = ERROR404[n]; //     ,      « » // ( HTTP   HTML ) //  «»   W5100        //      ,  ,   10  //   ,         // ,        if (S0_TX_Start_Addr > (S0_TX_BASE + S0_TX_MASK)) S0_TX_Start_Addr = S0_TX_BASE; // ..       –       // * W5100     (        ))  //   - ,  ,      //(  ,       ) –    //    //          //        –       SetW5100register( S0_TX_Start_Addr, TXbyte ) ; putc(TXbyte); //   (  )   S0_TX_Start_Addr++ ; //    (    ) } printf("\r\n>--- end of Filling -----------\r\n"); //   (  )   // ,        , // ,    ,      //      -  SEND SetW5100register(S0_CR, SEND); printf("> Data was sent \r\n\r\n"); //   (  )   } //----------------------------------------------------------- //--    «index.html» --------------- //------------------------------------------------------------------- void Socket0_Send_index_html (void) // send index.html "page" index.html { //    –         « 404» //  «»  HTTP   HTML  –  int16 n; char TXbyte; int16 datalength; printf("\r\n>...... going to send INDEX.HTML.....\r\n"); //   (  )   S0_TX_OFFSET = make16 ( GetW5100register(S0_TX_RD0), GetW5100register(S0_TX_RD1) ); //  2-         S0_TX_OFFSET = (S0_TX_OFFSET & S0_TX_MASK ) ; S0_TX_Start_Addr = S0_TX_OFFSET + S0_TX_BASE ; //         printf("\r\n INDEX[i], datalegth -------------\r\n"); //   (  )   //    datalength=0; while ( INDEX[datalength] !=0) datalength++; //    –      000 –    printf("%c %Lu ",INDEX[datalength], datalength ); //   (  )   //   W5100        S0_TX_End_Addr = make16 ( GetW5100register(S0_TX_WR0), GetW5100register(S0_TX_WR1) ); // «»  2    S0_TX_End_Addr += datalength ; // increment to fatalength //      //       1-  SetW5100register(S0_TX_WR0, make8( S0_TX_End_Addr ,1) ); //   SetW5100register(S0_TX_WR1, make8( S0_TX_End_Addr,0) ); //   printf("\r\n>Data length is: %Lu \r\n", datalength); printf("\r\n>--- Filling TX buffer w data: -----------\r\n"); //   (  )   //   –     For (n=0; n < datalength; n++) { TXbyte= INDEX[n]; //       « » index.html // (.. HTTP Header + HTML code) if (S0_TX_Start_Addr > (S0_TX_BASE + S0_TX_MASK)) S0_TX_Start_Addr = S0_TX_BASE; //       ,    –    SetW5100register( S0_TX_Start_Addr, TXbyte ) ; //      ( « ») –    putc(TXbyte); // printout to Terminal ( for testing purpose) //   (  )   S0_TX_Start_Addr++ ; //       } printf("\r\n>--- end of Filling -----------\r\n"); //   (  )   //     ,     //      -  SEND SetW5100register(S0_CR, SEND); printf("> Data was sent \r\n\r\n"); //   (  )   } //-------------------------------------------------------- //---   ,   ,   FIN ? ------ //----------------------------------------------------------------------------- int Socket0_FIN_Received(void) { //        ( ) //    FIN -     //         //    –     0 //   1  FIN    0  FIN   if ( GetW5100register(S0_SR) == SOCK_CLOSE_WAIT) return TRUE; else return FALSE; } //--------------------------------------------------------- // ------    Socket0 ----------------- //------------------------------------------------------------- void Socket0_Disconnect(void) { //       //       0 SetW5100register(S0_CR, DISCON); } // ------   0  -------------------- //-------------------------------------------------------- int Socket0_Closed(void) { //            //   (CLOSE),   -,     //   0   // *        , //    -    If ( GetW5100register(S0_SR) == SOCK_CLOSED) return TRUE; else return FALSE; //   1   (  0)  //   0        } // -----   -   0 ? ------------ //------------------------------------------------------------- int Socket0_Connection_Timeout(void) { //    ,     ,     //     –    - //   ,        // (   TCP  )   ,   //      // -        //     –     0 // :  ,     «SOCK_CLOSED» // -     -?? //            -, //   W5100  «SOCK_CLOSED»     - //      –   If ( GetW5100register(S0_SR) == SOCK_CLOSED) return TRUE; else return FALSE; //   1  - ,   0  -   } // ------------  0 ---------------------------- //---------------------------------------------------------------- void Socket0_Closing(void) { // should be performed in case that connection is closed after data exchange, // socket should be closed with Timeout occurrence, // or forcible disconnection is necessary due to abnormal operation etc. printf(">going to Close Socket0 ..... \r\n"); //   (  )   //     0     SetW5100register(S0_CR, CLOSE); printf("> ------ Socket CLOSED ----- \r\n\r\n"); //   (  )   } // ----  ()   SPI ------------- //-------------------------------------------------------- //*     «SSPI» ,      //   (SPI… )  .      //      ()   –     //   –     SPI //    «»  (    )  //   -      //*    -   W5100     0  1 void SSPI_write( int Data) { int i; int mask=0x80; //      (    ) //     SPI  W5100   //    -   ( MSB first) output_low(SCK); //       –  «»  for (i=0; i<8;i++) //    8  { output_low(MOSI); //   «»   -  0 if ( (mask & Data) != 0) output_high(MOSI); //  ( & ) =1     1 //   –       0,    output_high(SCK); //    (  0  1) -       //    SPI –   W5100 mask = mask>>1; ; //    1   // *       //        //     (  ) output_low(SCK); //  ,    «»  ( 0 ) } // «..    » () } //---------------------------------------------------------- //-----------     SPI ------------------ //----------------------------------------------------------- //*    «SSPI» ,      //   (SPI… )  .      //        –     //   –    //    «»  //     // *     W5100 -      1  0 //*           //           0  1 //         1,   //  «»     1  0 int SSPI_read ( void) { int Data=0; int i; int mask=0x80; //      (    ) //     SPI  W5100   //    -   ( MSB first) output_low(SCK); //       –  «»  for (i=0; i<8;i++) //    8  { output_high(SCK); //    (  0  1) if ( input(MISO)!= 0) Data = Data | mask ; //    1,     –    «»  mask = mask>>1; ; //    1   // *     //        //     (  ) output_low(SCK); //  ,    «»  ( 0 ) } return Data; } //--------------------------------------------------------------- //-------  ( )  W5100 ------------- //-------------------------------------------------------------- void SetW5100register (int16 regaddr, int8 data) // 2 : 16     8     { output_low(SS); //    (   0) SSPI_write (0xF0); //       //* make8 –  16  -  8  SSPI_write ( make8(regaddr,1) ); //      (MSB) //     SPI SSPI_write ( make8(regaddr,0) ); //      (LSB) //     SPI SSPI_write (data); //   SPI      output_high(SS); //   (   1) } //--------------------------------------------------------- //-----    W5100 ---------- //---------------------------------------------------- int GetW5100register (int16 regaddr) // – 2-   // : 1      { int RegData; output_low(SS); //    (   0) SSPI_write (0x0F); //     //* make8 –  16   8  SSPI_write ( make8(regaddr,1) ); //      (MSB) //     SPI SSPI_write ( make8(regaddr,0) ); //      (LSB) //     SPI RegData = SSPI_read (); //    W5100    (8 ) //       output_high(SS); //   (   1) return RegData; //     } //************* END of PROGRAM ************** 


Source: https://habr.com/ru/post/230661/


All Articles