零死角玩转stm32-高级篇之以太网(ENC28J60)

作者:
上传时间为: 2013-09-09 10:21 PM
2013-09-09
阅读:

    7、以太网(ENC28J60)

   7.1 实验描述及工程文件清单

实验描述:

在浏览器上创建一个web服务器,通过web里面的命令来

控制开发板上的LED的亮灭。

应用->

1:在PC机的DOS界面输入: ping 192.168.1.15 ,看能否ping通。

2:在IE浏览器中输入:http://192.168.1.15/123456 则会出

现一个网页,通过网页中的命令可以控制开发板中的LED的

亮灭。

硬件连接:

PE4 :ENC28J60-INT

PA6-SPI1-MISO :ENC28J60-SO

PA7-SPI1-MOSI :ENC28J60-SI

PA5-SPI1-SCK :ENC28J60-SCK

PA4-SPI1-NSS :ENC28J60-CS

PE1 :ENC28J60-RST

用到的库文件:

startup/start_stm32f10x_hd.c

CMSIS/core_cm3.c

CMSIS/system_stm32f10x.c

FWlib/stm32f10x_gpio.c

FWlib/stm32f10x_rcc.c

FWlib/stm32f10x_usart.c

FWlib/stm32f10x_spi.c

用户编写的文件:

USER/main.c

USER/stm32f10x_it.c

USER/led.c

USER/usart.c

USER/spi_enc28j60.c

USER/enc28j60.c

USER/ip_arp_udp_tcp.c

USER/web_server.c

野火STM32开发板中10M以太网ENC28J60的硬件原理图

   7.2 ENC28J60简介

ENC28J60 是带有行业标准串行外设接口 (SerialPeripheral Interface,SPI)的独立以太网控制器。 它可作为任何配备有 SPI 的控制器的以太网接口。ENC28J60 符合 IEEE 802.3 的全部规范,采用了一系列包过滤机制以对传入数据包进行限制。 它还提供了一个内部 DMA 模块,以实现快速数据吞吐和硬件支持的IP校验和计算。 与主控制器的通信通过两个中断引脚和SPI 实现,数据传输速率高达 10 Mb/s。两个专用的引脚用于连接 LED,进行网络活动状态指示。

下图所示为ENC28J60的简化框图。 图 1-2所示为使用该器件的典型应用电路。 要将单片机连接到速率为10 Mbps 的以太网,只需 ENC28J60、两个脉冲变压器和一些无源元件即可。本开发板中用的网络变压器的型号为911105A。

ENC28J60 由七个主要功能模块组成:

1. SPI 接口——充当主控制器和ENC28J60 之间通信通道。

2. 控制寄存器——用于控制和监视 ENC28J60。

3. 双端口RAM缓冲器——用于接收和发送数据包。

4. 判优器——当DMA、发送和接收模块发出请求时对 RAM 缓冲器的访问进

行控制。

5. 总线接口——对通过SPI 接收的数据和命令进行解析。

6. MAC (Medium Access Control)模块——实现符合 IEEE 802.3 标准的

MAC 逻辑。

7. PHY(物理层)模块——对双绞线上的模拟数据进行编码和译码。

该器件还包括其他支持模块,诸如振荡器、片内稳压器、电平变换器(提供可

以接受 5V 电压的 I/O 引脚)和系统控制逻辑。

  7.3 实验讲解

建议阅读程序的顺序为:spi_enc28j60.c -> enc28j60.c -> ip_arp_udp_tcp.c ->web_server.c 。

spi_enc28j60.c :ENC28J60(以太网芯片) SPI接口应用函数库。

enc28j60.c : Microchip ENC28J60 Ethernet Interface Driver。

ip_arp_udp_tcp.c :IP, Arp, UDP and TCP functions(这部分野火仍在学习)。

web_server.c :web服务程序应用函数库。

其中enc28j60.c 、ip_arp_udp_tcp.c web_server.c是从 国外的一个开源项目里面移植过来的,源文件基本上没有做修改。spi_enc28j60.c是由我们用户实现的底层函数接口,还有我们修改了web_server.c这个文件中网页命令控制部分的服务程序。

在配置好需要用的库文件之后,下面我们从main函数开始讲解,有关库函数是如何添加的情参考前面的教程,这里不再赘述。

/*

* 函数名:main

* 描述  :主函数

* 输入  :无

* 输出  :无

*/

int main (void)

{

/* 配置系统时钟为72M */

SystemInit();

/* 配置 LED */

LED_GPIO_Config();

/* ENC28J60 SPI 接口初始化 */

SPI_Enc28j60_Init();

/* ENC28J60 WEB 服务程序 */

Web_Server();

//return 0;

}

在进入main函数代码段后,我们首先调用系统库函数 SystemInit();将我们的系统时钟配置为72MHZ,如果用的是3.5.0版本的库则不需要,因为已在启动文件里面调用了。

 LED_GPIO_Config();用于初始化LED,因为我们我们在我们的web服务器中要控制的就是LED,所以在这里要先把LED配置好,好让它接下来能工作。

SPI_Enc28j60_Init();用于配置以太网芯片ENC28J60所用到的数据通信口SPI2和其他控制I/O。这是我们用户在spi_enc28j60.c中实现的底层程序。

/*

* 函数名:SPI1_Init

* 描述  :ENC28J60 SPI 接口初始化

* 输入  :无

* 输出  :无

* 返回  :无

*/

void SPI_Enc28j60_Init(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

SPI_InitTypeDef  SPI_InitStructure;

/* 使能 SPI1 时钟 */

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1, ENABLE);

/*

* PA5-SPI1-SCK :ENC28J60_SCK

* PA6-SPI1-MISO:ENC28J60_SO

* PA7-SPI1-MOSI:ENC28J60_SI

*/

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;      // 复用输出

GPIO_Init(GPIOA, &GPIO_InitStructure);

/* PA4-SPI1-NSS:ENC28J60_CS */ // 片选

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;       // 推免输出

GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_SetBits(GPIOA, GPIO_Pin_4);

/* PB13:ENC28J60_INT */ // 中断引脚没用到

/* PE1:ENC28J60_RST*/   // 复位似乎不用也可以

/* SPI1 配置 */

SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;

SPI_InitStructure.SPI_Mode = SPI_Mode_Master;

SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;

SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;

SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;

SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;

SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;

SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;

SPI_InitStructure.SPI_CRCPolynomial = 7;

SPI_Init(SPI1, &SPI_InitStructure);

/* 使能 SPI1  */

SPI_Cmd(SPI1, ENABLE);

}

在这个函数中不知大家有没注意到没有这两条注释:

/* PB13:ENC28J60_INT */ // 中断引脚没用到

/* PE1:ENC28J60_RST*/   // 复位似乎不用也可以

enc28j60的中断引脚没用到很正常,但是复位引脚也没用到,这我就很纳闷了。我想原因可能是enc28j60有个上电自动复位的功能,这里它的复位引脚只能暂时没有用到而已,也或许是我们的开发板中引脚PE1(接enc28j60的复位脚)收到什么信号的干扰,产生了类似复位的信号。这里我们先把这问题搁一边先,毕竟程序还是工作了。至于具体的原因我以后有时间再深究下。

 Web_Server();函数实现的功能是创建一个网页服务器,在这个网页服务器上我可以点击我们设定好的命令按钮来控制我们开发板上LED的亮灭。其实,从这里面我们就可以看到有点智能家居的味道了,所谓智能家居就是通过网络来控制我们家电的状态,如开和断。举个例子:我们可以在遥远的地方可以通过网络来控制家里的电视、电冰箱等,是不是很神奇哩?只要你学会了这个实验,再经过自己的再深入学习,这些都是小菜一碟。^_^,本实验旨在引导大家入门。

 Web_Server();在web_server.c中实现。在web_server.c的开头包含了头文件:

#include "enc28j60.h"

#include "ip_arp_udp_tcp.h"

#include "net.h"

enc28j60.h : Microchip ENC28J60 Ethernet Interface Driver Header file

ip_arp_udp_tcp.h : IP, Arp, UDP and TCP functions Header file . For more Infermation Please See http://www.gnu.org/licenses/gpl.html

net.h : Based on the net.h file from the AVRlib library by Pascal Stang.

For AVRlib See http://www.procyonengineering.com/

Used with explicit permission of Pascal Stang.

有关这三个头文件对应的C文件的功能,请大家阅读源码。

接下来我们具体看看Web_Server();这个函数具体做了什么,由于这个函数的源码较多,在这里我就不贴出来了。

 enc28j60Init(mymac); 这个函数用来初始化 enc28j60 的MAC地址(物理地址),这个函数必须要调用一次。mymacweb_server.c的开头定义:

static unsigned char mymac[6] = {0x54,0x55,0x58,0x10,0x00,0x24}; 这里要注意的是:mac地址在局域网内必须唯一,否则将与其他主机冲突,导致连接不成功。mymac数组里面的数值可随便初始化,但万万不可与局域网内的mac地址冲突,否则当另外一部主机在上网时,你是上不了网的。

 enc28j60PhyWrite(PHLCON,0x476);这个函数用于设定网络变压器中LED的颜色,不同的颜色指示不同的状态。网络变压器在没有工作的情况下,这两个LED是不会被点亮的,当网络变压器工作正常时,绿色LED表示link状态,黄色LED表示通信状态。本实验中,我们的程序工作正常时,绿色LED常亮,黄色LED是一闪一闪的。

 init_ip_arp_udp_tcp(mymac,myip,mywwwport); 这个函数用于初始化以太网的IP层。这里面涉及到三个参数:mymac、myip、mywwwport。其中mymac在前面已经讲解过。ip 指的是我们开发板的ip地址,要想通过网页来访问我们的服务器(即开发板),则必须要有ipip 地址跟mac 地址一样,在局域网能要保持唯一,不能够与其他主机的ip地址产生冲突。还要注意的一点就是:开发板的ip 与我们电脑的ip必须保持在同一个网段,即ip地址的前三段要保持一致,后面一段不同。在本地链接中可查看到我们电脑的ip地址。我的电脑的ip地址是:192.168.1.106,如下截图所示:

所以,在此设置我们开发板的ipstatic unsigned char myip[4] = {192,168,1,15}; ip的最后一段的值 15 可改为其他值,但要注意不要产生冲突。

接下来的是一个无限循环while ( 1 ),在这里面我们创建了一个网页,在网页中注入了我们自己的信息,并随时监控我们命令状态的改变,好实时地控制我们的LED,有关这些功能的实现请大家自行阅读源码,这里不再详述。我们仅来看看LED控制的部分:

if (cmd==1)     // 用户程序

{

LED1(ON);

i=1;        // 命令 = 1

}

if (cmd==0)     // 用户程序

{

LED1(OFF);

i=0;          // 命令 = 0

}

当我们在网页上点击 点亮LED这个按钮时,网页发送命令1给开发板,这是开发板中的LED被点亮,反之,LED则被关闭。

这里我们仅提供简单的web服务程序,如果要实现更加复杂的功能,仍需大家的努力。当然,野火也会跟大家一起奋斗,开发出更多的应用程序跟大家分享。

这里面的操作涉及到很多enc28j60的知识,特别是寄存器的操作,具体的请大家参考enc28j60的datasheet,大家一定要看看,而且是要认认真真、仔仔细细地看,直到弄懂为止。

   7.4实验现象

将野火STM32开发板供电(DC5V),插上JLINK,插上网口线,网口线一端连接路由器,一端连开发板。注意:电脑跟开发板的网线连接的路由器要同在一个局域网中。将编译好的程序下载到开发板。

1:打开电脑的DOS界面,输入: ping 192.168.1.15 ,看看能否ping 通。打印出如下信息则表示ping通,其中192.168.1.15是我们开发板的ip。

2:打开IE浏览器,在地址栏输入:http://192.168.1.15/123456 ,其中123456是我们自己设置的密码。然后按 Enter 键进入,如果成功则会出现一个如下网页,通过网页中的命令按钮 点亮LED /关闭LED 就可以控制我们 开发板中LED的亮灭,这里控制的是开发板中的LED1。

LED1 灭

LED1 亮

全部评论 ()
条评论
写评论

创建讨论帖子

登录 后参与评论
系统提示