嵌入式以太网第三部分——以太网协议实现
目錄:
1:概述
2:MAC地址設置
3:以太網協議
4:PING指令測試
1、概述
1.1:以太網是實現LAN的一種技術,它允許嵌入式系統連接到一個LAN中,并可通過使用網關經Internet連接到外部世界,以太網的主要目的是向LAN發送和從LAN接收以太網幀,在TCP/IP協議族中,不包括以太網協議,可以理解它為TCP/IP中的網絡接口層(物理層和數據鏈路層),為TCP/IP中的上層協議(比如:IP協議和ARP協議)提供服務;
1.2:ENC28J60是帶SPI接口的以太網控制器,支持IEEE802.3協議,當然,也兼容Ethernet第二版的協議,此協議幀結構簡單,被大量使用;
1.3:以太網幀結構:目的mac地址+源mac地址+協議類型+數據;
1.4:本篇編寫ENC28J60驅動,實現以太網控制,將我們的嵌入式設備連接到LAN中,并使用ping命令進行測試;
1.7:開發板:STM32F103ZERT 奮斗開發板V5 軟件環境:KEIL MDK5
2、MAC地址設置
2.1:MAC地址是在以太網mac層定義的,也就是物理地址,每一種LAN技術的網絡都有其唯一對應的MAC地址,常用的格式為48位;
2.2:mac地址的47位是單一地址或者組地址位,該位為0,表示一個單一的站地址;該位為1,表示一個組地址(多播地址),所有位都為1,表示廣播地址;
2.3:mac地址的46位是全球管理或者本地管理位,該位為0,mac地址遵循全球地址管理格式,接下來的22位是生產商標識符,最后剩下的24位是由相關機構分配的唯一地址,我們的電腦都遵循這種方式的編址方式;該位為1,剩下的64位構成本地管理地址,由人為規定;
2.4:enc28j60模塊不提供mac地址,需要用戶自己定義mac地址,如果是用于私有網路,任意定義即可,如果需要訪問外網,就必須由用戶定義一個全球唯一的mac地址,如果需要,可以利用某些廠家的芯片上的mac地址來定義,比如:美國微芯的24AA02E48串行eeprom芯片中的mac地址;一般將定義的mac地址存放在flash或者eeprom中,如果使用24AA02E48芯片,即可省去這一步;
2.5:本例程中,為了方便,任意定義了mac地址;
3、以太網協議
3.1:建立keil工程,如下圖,APP目錄中的app.c文件中實現main函數;TCP/IP STACK協議棧目錄中ethernet.c文件中實現以太網協議調用的函數,都是包裹函數,包裹enc28j60驅動中的函數;DRIVEER中實現定時器、串口(用于控制臺)、spi、enc28j60驅動;
3.2:以太網部分的實現,主要完成ethernet.h、ethernet.c和app.c三個文件;
ethernet.h文件:定義以太網頭部結構體,RX_FRAME、TX_FRAME宏定義,所有以太網數據幀的讀寫都是通過這兩個宏來實現;
#ifndef ETHERNET #define ETHERNET#include "stack.h" #include "enc28j60.h"/*地址定義*/ #define MAC_ADDRESS {0x00,0x14,0x0B,0x3F,0x04,0xB1} #define IP_ADDRESS {192,168,1,25} #define GATEWAY_ADDRESS {192,168,1,1} #define SUBNETMASK {255,255,255,0}/*協議類型定義*/ #define ARP_PROTOCOL 0x0806 #define IP_PROTOCOL 0x0800 #define ICMP_PROTOCOL 1 #define UDP_PROTOCOL 17 #define TCP_PROTOCOL 6#define RX_FRAME ((struct eth_header *)&rx_buff[0]) #define TX_FRAME ((struct eth_header *)&tx_buff[0])/*以太網頭部定義*/ #pragma pack(1) struct eth_header {unsigned char destination[6];unsigned char source[6];unsigned short protocol; }; #pragma pack()extern char rx_buff[PACKAGE_BUFF_SIZE]; extern char tx_buff[PACKAGE_BUFF_SIZE];void ethernet_init(void); unsigned int ethernet_read(void); void ethernet_send(void);#endif
3.3:實現main函數,完成所需模塊的初始化,然后阻塞等待以太網接口接受到數據幀,如果收到數據幀,打印收到的以太網數據幀,包括目的mac地址、源mac地址、協議類型; app.c #include "stm32f10x.h" #include "usart_init.h" #include "time3_init.h" #include "ethernet.h" #include "spi_init.h" #include "enc28j60.h" #include "ethernet.h"u32 baud_menu[] = {1200,2400,3840,4800,5760,9600,19200,115200}; u16 ARR = 0;int main() {unsigned int len = 0;ARR = T_35_Set(baud_menu[7]); //根據3.5T時間,計算定時器3重載寄存器的值NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //設置NVIC中斷分組2:2位搶占優先級,2位響應優先級 Usart_Init(baud_menu[7]); //串口初始化TIM3_Int_Init(ARR,71); //定時器初始化,3.5T時間中斷 spi_init(); //spi初始化ethernet_init(); //以太網芯片初始化while(1){len = ethernet_read();if(len > 0){printf("*****************Ethernet Frame*******************\r\n");printf("\r\n");printf("Destination Address: %02x-%02x-%02x-%02x-%02x-%02x\r\n",RX_FRAME->destination[0],RX_FRAME->destination[1],RX_FRAME->destination[2],RX_FRAME->destination[3],RX_FRAME->destination[4],RX_FRAME->destination[5]);printf("\r\n");printf("Source Address: %02x-%02x-%02x-%02x-%02x-%02x\r\n",RX_FRAME->source[0],RX_FRAME->source[1],RX_FRAME->source[2],RX_FRAME->source[3],RX_FRAME->source[4],RX_FRAME->source[5]);printf("\r\n");printf("Protocol Type:%04x\r\n",HTONS(RX_FRAME->protocol));printf("\r\n");printf("*****************Ethernet Frame*******************\r\n\r\n");}/*接收串口數據成功,處理接受到的數據*/if(Usart_Receive_Ok == 1){Usart_Receive_Ok = 0;Usart_Handle_func(); //處理接收到的數據}} }
4、PING指令測試
4.1:將開發板通過網線連接至路由器,此時,電腦和開發板在同一個局域網,然后在電腦上使用ping指令,確保ping指令的ip地址沒有被占用且ip地址和路由器地址在同一個網段,如ping 192.168.1.16; 4.2:ping指令是基于ICMP協議的程序,當ping一個IP時,如果此ip地址沒有在ARP條目中,ping程序會發送一個廣播的以太網幀至局域網來跟新arp條目; 4.3:當使用ping指令連接一個未連接過的ip時,本例程會受到一個以太網廣播幀,并將其打印出來,包括全為1的目的mac地址+源mac地址(電腦mac地址+0806(協議類型)),如下圖:
總結
以上是生活随笔為你收集整理的嵌入式以太网第三部分——以太网协议实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring Boot自定义starte
- 下一篇: android .9图片的使用