arduino enc28j600 怎样设为半双工

& 相关文章 &
stm32f4驱动enc28j60(吐槽篇)
鼓捣enc28j60这个模块过程还是比较曲折的! 买这个模块的时候,卖家只附送了51的驱动工程。或者说,就51的工程能用! 在51上,一编译一下载就搞定了! ========================吐槽下============================== 在F4这个平台上呢!因为enc28j60.c这个文件的问题,导致我创建了20多份不同的工程来测试!比较坑爹! 刚开始的时候,想移植51的这个文件,发现改动量太大了,改了一下,测试不成功就放弃之! 再拿野火stm32f103
ENC28J60学习笔记——第4部分
enc28j60SetBank(ECON1);
/* 使能中断 全局中断 接收中断 接收错误中断 */
enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE|EIE_RXERIE);
/* 接收使能位 */
enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
} 7 总结 ENC28J60的驱动编写算是比较复杂
ENC28J60学习笔记——第2部分
/* 禁止ENC28J60 */
ENC28J60_CSH();
} 3.3 读写PHY寄存器 PHY寄存器和被ENC28J60控制的LED指示灯有关,控制该寄存器可以控制LED驱动方式和发生相应事件时LED显示方式。一般情况下,一个LED指示灯用于指示网络状态(常亮可理解为网络接通),另一个LED指示灯显示接收活动,有数据输入时产生一个点亮脉冲。PHY是比较特殊的寄存器,先要想一个控制寄存器写入PHY寄存器的地址,再向两个控制寄存器依次写入PHY寄存器的具体数据的高8位和低8位
Manual 标题: STM32F4DISCOVERY STM32F4 high-performance discovery board 文档说明:STM32F4-DISCOVERY开发板资源介绍与使用说明 链接: 链接地址
索引:UM1467 User Manual 标题:Getting started with software and firmware environments for the STM32F4DISCOVERY Kit 文档说明:文档第一句话就很好地说明了一切
ENC28J60学习笔记——第1部分
的一个开源项目。把最原始的代码拿来细细品味,以太网协议就不那么神秘了。在这里说一下ENC28J60的使用,熟悉了ENC28J60的驱动可以分几步走。第一步,通过ENC28J60移植uIP或者lwIP协议栈,实现TCP或是UDP通信,第二,顺着AVRNET项目走,实现一个简单的web服务器,运行静态或者动态网页。嵌入式以太网和计算机以太网开发不同,对于TCP通信而言没有socket套接字,对于网页编程而言也没有IIS或PHP,所示实现起来会相对麻烦,但是也非常有乐趣。 1.2 资料准备 嵌入式
自动检测,既可直接驱动LED,又可灌电流驱动。复位时ENC28J60检测LED的连接,并按照PHLCON寄存器的默认设置驱动。本设计LEDB采用拉电流的方式点亮LED。复位时该位清零且PHY默认在半双工模式下工作。 3 系统软件设计 3.1 SPI接口 ENC28J60与微控制器MCU的连接通过SPI接口实现,支持10 Mb/s。但ENC28J60只支持SPI模式00,即CPOL=0和CPHA=0。另外,在空闲状态时SPI端口要求SCK为低电平,且不支持时钟极性选择。以下为SPI接口初始化的源代码
的项目,并立即动手干。然后就是坚持,坚持…………再坚持。
3、开发板网卡(我用的是enc28j60)的mac地址怎么设置?
我设置的是:ee:dd:cc:bb:aa:00,有些规则(比如最低4位要为0),但新手暂且不用管,具体再查找,论坛有详细说明。
4、开发板网卡(我用的是enc28j60)与谁通信?网卡ip怎么设置?
我做测试时,enc28j60 与 “VMware的虚拟网卡:VMware Network Adapter VMnet8”通信。 开发板网卡ip要与
状态信息标志位 char name[2]; //
网络接口使用的设备驱动类型的种类 u8_ //
用来标示使用同种驱动类型的不同网络接口 };
next 字段是指向下一个 netif 结构的指针。我们的一个产品可能会有多个网卡芯片, LWIP 会把所有网卡芯片的结构体链成一个链表进行管理,有一个 netif_list 的全局变量指向该链 表的头部。next 字段就是用于链表用。 ip_addr、netmask、gw 三个字段用于发送和处理数据包用,分别表示 IP 地址、子网掩
代码量:UIP1.0代码(100K左右),个人完成单片机的定时器和SPI驱动,以太网卡驱动。uip1.0协议属移植。在实际完成中大量参考了老外的Avrnet开源项目(自己网络知识真的很有限,恶补了好长时间,囧)。 协议移植周期:30天 硬件开发周期:无,淘宝购买的现成模块 简介:在工业以太网卡ENC28J60和单片机组成的系统上实现UIP1.0的代码。底层部分包含定时器,SPI及以太网的驱动,上层协议实现了IP,MAC,PING,以及简单的HTTP协议,HTTP实现的网页部分实现了交互功能控制
MCU51单片机uIP协议栈+ENC28J60网卡 移植、应用
ENC28J60驱动:... 7 7
uIP协议栈TCP应用demo:... 8 7.1
uIP代码结构:... 8 7.2
main.c代码说明:... 9 8
应用程序接口uip_appcall():... 10 8.1
uip_send使用举例:... 12 9
配置参数:... 12 9.1
用户设定:... 13 9.2
固定(仅供测试):... 14 10
= NETIF_FLAG_BROADCAST | \
NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
enc28j60_init(netif-&hwaddr); //与底层驱动硬件驱动程序密切相关的硬件初始化函数 }
至此,终于变量 enc28j60 被初始化好了,而且它描述的网卡芯片 enc28j60 也被初始化好了, 而且变量 enc28j60 也被链入链表 netif_list。
接着上上上上面的语句(8)调用
ENC28J60学习笔记——第3部分
0.相关资料
相关资料中包括其他精彩博文和代码仓库
【/article/p-705050.html】
【ENC28J60学习笔记——索引】 【/article/p-704986.html】【/article/p-704987.html】【/article/p-704989.html
:Microduino nRF 以太网:Microduino Ethernet(可选ENC28J60或W5500) 供电:Microduino DUO H2
节点: 核心:Microduino Core 2.4G:Microduino nRF 220V市电控制:Microduino 电器控制板 温度传感器:DS18B20(仅饮水机需要)
Microduino提供了两种以太网方案选择:Enc28J60以及Wiznet W5500,我对他们两都各自写了主机程序。 节点的程序都是一样的,分为饮水机和灯泡
的是ENC28J60的工作原理,这也是AVRNET项目的使用的以太网驱动芯片。AVRNET项目侧重于web方式实现设备控制和状态查询。为了实现web功能,需要学习HTML相关技术,例如表单,输入框,按钮和提交按钮等,必须理解GET方法和POST方法,必须理解HTTP请求和响应格式。当学习完那么多的基础知识之后,其实实现web控制也就是编写HTML文本,然后通过TCP发送HTML文本。 AVRNET项目 国内的许多淘宝店家甩卖的ENC28J60代码可能都出自该项目。硬件电路设计和软件部分设计都是很好
STM32F4 Discovery 使用MDK-ARM Debug Viewer调试没有打印信息的原因之一
硬件:STM32F4 Discovery开发板 软件:MDK-ARM 新建一个工程,根据上一篇设置printf打印调试信息 但是始终没有打印信息出现 各种对比发现设置都一样啊,文件也没找到哪里不同。 解决方法: 之前的demo例程里使用是好的,写一个LED闪烁的例子,Delay函数延迟闪烁LED,在好使的工程和新建的工程里,main函数的内容都写一样的。 然后下载运行,发现好使的工程运行时,LED闪烁频率很快,我自己新建的工程,则LED闪烁的较慢。 试了几个参数,发现当Delay的参数在好使
LwIP学习笔记——STM32 ENC28J60移植与入门
去年(2013年)的整理了LwIP相关代码,并在STM32上“裸奔”成功。一直没有时间深入整理,在这里借博文整理总结。LwIP的移植过程细节很多,博文也不可能一一详解个别部分只能点到为止。
【本文要点】
【1】不带操作系统的LwIP移植,LwIP版本为1.4.1。
【2】MCU为STM32F103VE,网卡为ENC28J60。
【3】移植过程重点描述ethernetif.c和LwIP宏配置等。
【4】一个简单的TCP echo例子
以太网方案的选择—ENC28J60与W5100
对于单片机的以太网接入方案~W5100和ENC28J60都是被常常使用到的芯片,这两种方案也可以说是硬件协议栈和软件协议栈的典型代表,两者都是经住了市场考验的~关于他们的使用和讨论也比较多,除了在传统单片机的以太网接入中被广泛使用,我们也能看到他们在开源硬件中发挥的重要作用~让我们看看部分论坛的讨论吧。 ———————- 来自“极客工坊”: http://www./forum.php?mod=viewthread&tid=2671 “ArduinoCN
arduino uno enc28j60 ping webserver webclient
: no-cache\r\n\r\n")));
// prepare the webpage by writing the data to the tcp send buffer
uint16_t print_webpage(uint8_t *buf)
plen=http200ok();
plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("&html&&head&&title&Arduino ENC28J60
前言 物联网的IPV6应用是一个趋势,contiki是集成了6lowpan的一个集成开发工具。uip是集成在内部的,支持IPV6以及IPV4,这里先通过IPV4与平台连接建立一个数据通道。后续会跟进IPV6以及6lowpan的应用。而且uip不需要OS支持,以事件驱动的方式编程,占用的RAM以及ROM都符合嵌入式的需求。 之前我们需要了解一些背景知识: 1,http的相关知识 2,yeelink http请求格式分析 (分析很透彻) 3,tcp/ip的连接 4,stm32平台+enc28j60
相关的帖子),我借博客再整理一下,随着时间的推移有些知识自己都会忘记,以前有“考试”可以给老师和家人一个交代,现在有博客算是给自己一个交代吧。 2.需要总结的内容 关于UIP/LWIP 【uIP学习笔记】 关于MODBUS/FreeMODBUS/MODBUS-TCP/NMODBUS 【MODBUS】 关于AVRNET 【ENC28J60驱动】 【ARP协议实现】 【/article/p-705028.html】 UDP协议实现 TCP协议实现
& 2012 - 2014 &
&All Rights Reserved. &
/*爱悠闲图+*/
var cpro_id = "u1888441";
/*爱悠闲底部960*75*/
var cpro_id = "u1888128";二次元同好交流新大陆
扫码下载App
汇聚2000万达人的兴趣社区下载即送20张免费照片冲印
扫码下载App
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
我在使用DM9000A往PC发送数据时,wireshark上会显示FCS,如下图,为何有时能显示FCS,有时不能?
&至于ENC28J60到底有没有发送FCS,目前想到了使用示波器捕获波形来验证,制作一根测试专用的网线,设置发送一个较短的帧,并且由于ENC28J60是10Mbps以太网,物理层编码方式较为简单,所以波形也不难分析,大概会占用半天时间。暂时不准备研究这个,后面有需求再搞。
&回到主题,ENC28J60驱动程序中关于CRC的部分是如何处理的:
所谓驱动,指官方提供的这4个文件:
ENC28J60在发送数据包时,ENC28J60 内的MAC 在发送时会自动生成前导符和帧起始定界符。 此外,MAC 可根据配置生成填充(如果需要)和CRC 字段。主控制器必须生成所有其他帧字段,并将它们写入缓冲存储器,以待发送。datasheet 7.1
&参照驱动程序中enc28j60PacketSend函数:
void enc28j60PacketSend(unsigned int len, unsigned char* packet)
// write per-packet control byte (0x00 means use macon3 settings)
enc28j60WriteOp(ENC28J60_WRITE_BUF_MEM, 0, 0x00);
对照datasheet 图7.1,此处写入0x00,最低位为0时,其它位无效,数据包发送的方式由MACON3中的值确定。
&MACON3的值在芯片初始化时决定,在enc28j60Init中:
enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN|MACON3_FULDPX);
对照enc28j60.h文件中宏定义,该语句实际上给MACON3寄存器赋值0x33,用二进制序列表示:
&MACON3寄存器的值如下:
//bit 7-5 PADCFG2:PACDFG0:自动填充和CRC 配置位
//111 = 用0 填充所有短帧至64 字节长,并追加一个有效的CRC
//110 = 不自动填充短帧
//101 = MAC 自动检测具有8100h 类型字段的VLAN 协议帧,并自动填充到64 字节长。如果不
//是VLAN 帧,则填充至60 字节长。填充后还要追加一个有效的CRC
//100 = 不自动填充短帧
//011 = 用0 填充所有短帧至64 字节长,并追加一个有效的CRC
//010 = 不自动填充短帧
//001 = 用0 填充所有短帧至60 字节长,并追加一个有效的CRC
//000 = 不自动填充短帧
//bit 4 TXCRCEN:发送CRC 使能位
// 1= 不管PADCFG如何,MAC都会在发送帧的末尾追加一个有效的CRC。 如果PADCFG规定要
//追加有效的CRC,则必须将TXCRCEN 置1。
// 0 = MAC不会追加CRC。 检查最后4 个字节,如果不是有效的CRC 则报告给发送状态向量。
//bit 0 FULDPX:MAC 全双工使能位
// 1= MAC工作在全双工模式下。 PHCON1.PDPXMD 位必须置1。
// 0 = MAC工作在半双工模式下。 PHCON1.PDPXMD 位必须清零。
&实际上跟CRC相关的为高4位,0011,表示用0 填充所有短帧至60 字节长,并追加一个有效的CRC。ENC28J60芯片发送数据时,与CRC相关的设置就在此处。
&从驱动程序上来看,芯片也应该发送了FCS。
阅读(336)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
在LOFTER的更多文章
loftPermalink:'',
id:'fks_',
blogTitle:'ENC28J60 CRC细节',
blogAbstract:'\n&记录一些以太网开发过程中的细节,供日后参考。\n设备使用ENC28J60芯片,关于芯片详细的配置(CRC部分),后文会加以描述;\nPC使用Atheros AR5007EG无线网卡(接收端的一些信息跟网卡特性是强相关的);\nPC使用win7 32位系统。\n\n&使用设备往PC发送小于最短帧长的数据。PC端使用wireshark捕获数据如下,没有FCS。\n\n\t帧长为60字节,加上缺失的4字节FCS,刚好为以太网最小帧长64字节。\n',
blogTag:'enc28j60,fcs,crc',
blogUrl:'blog/static/',
isPublished:1,
istop:false,
modifyTime:4,
publishTime:7,
permalink:'blog/static/',
commentCount:0,
mainCommentCount:0,
recommendCount:0,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:false,
hostIntro:'',
hmcon:'0',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}【连载】【ALIENTEK 战舰STM32开发板】STM32开发指南--第五十七章 ENC28J60网络实验 - STM32 - 意法半导体STM32/STM8技术社区
后使用快捷导航没有帐号?
查看: 2618|回复: 4
【连载】【ALIENTEK 战舰STM32开发板】STM32开发指南--第五十七章 ENC28J60网络实验
主题帖子积分
初级会员, 积分 59, 距离下一级还需 141 积分
初级会员, 积分 59, 距离下一级还需 141 积分
&a name=&_Toc&&57.1.1 ENC28J60简介
ENC28J60 是带有行业标准串行外设接口(Serial Peripheral Interface,SPI)的独立以太网控制器。它可作为任何配备有SPI 的控制器的以太网接口。ENC28J60 符合IEEE 802.3 的全部规范,采用了一系列包过滤机制以对传入数据包进行限制。 它还提供了一个内部DMA 模块,以实现快速数据吞吐和硬件支持的IP校验和计算。 与主控制器的通信通过两个中断引脚和
SPI 实现,数据传输速率高达10 Mb/s。两个专用的引脚用于连接LED,进行网络活动状态指示。
ENC28J60的主要特点如下:
l 兼容IEEE802.3协议的以太网控制器
l 集成MAC和10 BASE-T物理层
l 支持全双工和半双工模式
l 数据冲突时可编程自动重发
l SPI接口速度可达10Mbps
l 8K数据接收和发送双端口RAM
l 提供快速数据移动的内部DMA控制器
l 可配置的接收和发送缓冲区大小
l 两个可编程LED输出
l 带7个中断源的两个中断引脚
l TTL电平输入
l 提供多种封装:SOIC/SSOP/SPDIP/QFN等
ENC28J60的典型应用电路如图57.1.1.1所示:
http://www.stmcu.org/file:///C:/Documents%20and%20Settings/Administrator/桌面/论坛推广/第57章/新建%20Microsoft%20Word%20文档.files/image001.jpg
图57.1.1.1 ENC28J60典型应用电路
ENC28J60 由七个主要功能模块组成:
1) SPI 接口,充当主控制器和ENC28J60 之间通信通道。
2) 控制寄存器,用于控制和监视ENC28J60。
3) 双端口RAM缓冲器,用于接收和发送数据包。
4) 判优器,当DMA、发送和接收模块发出请求时对RAM 缓冲器的访问进行控制。
5) 总线接口,对通过SPI 接收的数据和命令进行解析。
6) MAC(Medium Access Control)模块,实现符合IEEE 802.3 标准的MAC 逻辑。
7) PHY(物理层)模块,对双绞线上的模拟数据进行编码和译码。
ENC28J60还包括其他支持模块,诸如振荡器、片内稳压器、电平变换器(提供可以接受5V 电压的I/O 引脚)和系统控制逻辑。
ENC28J60的功能框图如图57.1.1.2所示:
http://www.stmcu.org/file:///C:/Documents%20and%20Settings/Administrator/桌面/论坛推广/第57章/新建%20Microsoft%20Word%20文档.files/image002.jpg
图57.1.1.2 ENC28J60功能框图
ALIENTEK ENC28J60网络模块采用ENC28J60作为主芯片,单芯片即可实现以太网接入,利用该模块,基本上只要是个单片机,就可以实现以太网连接。ALIENTEK ENC28J60网络模块原理图如图57.1.1.3所示:
http://www.stmcu.org/file:///C:/Documents%20and%20Settings/Administrator/桌面/论坛推广/第57章/新建%20Microsoft%20Word%20文档.files/image003.jpg
图57.1.1.3 ALIENTEK ENC28J60网络模块原理图
ALIENTEK ENC28J60网络模块外观图如图57.1.1.4所示:
http://www.stmcu.org/file:///C:/Documents%20and%20Settings/Administrator/桌面/论坛推广/第57章/新建%20Microsoft%20Word%20文档.files/image004.png
图57.1.1.4 ALIENTEK ENC28J60网络模块外观图
该模块通过一个8个引脚的排针与外部电路连接,这8个引脚分别是:GND、RST、MISO、SCK、MOSI、INT、CS和V3.3。其中GND和V3.3用于给模块供电,MISO/MOSI/SCK用于SPI通信,CS是片选信号,INT为中断输出引脚,RST为模块复位信号。
uIP 由瑞典计算机科学学院(网络嵌入式系统小组)的Adam Dunkels 开发。其源代码由C 语言编写,并完全公开,uIP的最新版本是1.0 版本,本指南移植和使用的版本正是此版本。
uIP 协议栈去掉了完整的TCP/IP 中不常用的功能,简化了通讯流程,但保留了网络通信必须使用的协议,设计重点放在了IP/TCP/ICMP/UDP/ARP 这些网络层和传输层协议上,保证了其代码的通用性和结构的稳定性。
由于uIP 协议栈专门为嵌入式系统而设计,因此还具有如下优越功能:
1) 代码非常少,其协议栈代码不到6K,很方便阅读和移植。
2) 占用的内存数非常少,RAM 占用仅几百字节。
3) 其硬件处理层、协议栈层和应用层共用一个全局缓存区,不存在数据的拷贝,且发送和接收都是依靠这个缓存区,极大的节省空间和时间。
4) 支持多个主动连接和被动连接并发。
5) 其源代码中提供一套实例程序:web 服务器,web 客户端,电子邮件发送程序(SMTP 客户端),Telnet 服务器, DNS 主机名解析程序等。通用性强,移植起来基本不用修改就可以通过。
6) 对数据的处理采用轮循机制,不需要操作系统的支持。
由于uIP 对资源的需求少和移植容易,大部分的8 位微控制器都使用过uIP协议栈, 而且很多的著名的嵌入式产品和项目(如卫星,Cisco 路由器,无线传感器网络)中都在使用uIP 协议栈。
uIP相当于一个代码库,通过一系列的函数实现与底层硬件和高层应用程序的通讯,对于整个系统来说它内部的协议组是透明的,从而增加了协议的通用性。uIP协议栈与系统底层和高层应用之间的关系如图57.1.2.1所示:
http://www.stmcu.org/file:///C:/Documents%20and%20Settings/Administrator/桌面/论坛推广/第57章/新建%20Microsoft%20Word%20文档.files/image005.png
图57.1.2.1 uIP在系统中的位置
从上图可以看出,uIP协议栈主要提供2个函数供系统底层调用:uip_input和uip_periodic。另外和应用程序联系主要是通过UIP_APPCALL函数。
当网卡驱动收到一个输入包时,将放入全局缓冲区uip_buf 中,包的大小由全局变量uip_len 约束。同时将调用uip_input()函数,这个函数将会根据包首部的协议处理这个包和需要时调用应用程序。当uip_input()返回时,一个输出包同样放在全局缓冲区uip_buf 里,大小赋给uip_len。如果uip_len 是0,则说明没有包要发送。否则调用底层系统的发包函数将包发送到网络上。
uIP 周期计时是用于驱动所有的uIP 内部时钟事件。当周期计时激发,每一个TCP 连接都会调用uIP 函数uip_periodic()。类似于uip_input()函数。uip_periodic()函数返回时,输出的IP 包要放到uip_buf 中,供底层系统查询uip_len 的大小发送。
由于使用TCP/IP 的应用场景很多,因此应用程序作为单独的模块由用户实现。uIP 协议栈提供一系列接口函数供用户程序调用,其中大部分函数是作为C的宏命令实现的,主要是为了速度、代码大小、效率和堆栈的使用。用户需要将应用层入口程序作为接口提供给uIP 协议栈, 并将这个函数定义为宏UIP_APPCALL()。这样,uIP 在接受到底层传来的数据包后,在需要送到上层应用程序处理的地方,调用UIP_APPCALL( )。在不用修改协议栈的情况下可以适配不同的应用程序。
uIP协议栈提供了我们很多接口函数,这些函数在 uip.h 中定义,为了减少函数调用造成的额外支出,大部分接口函数以宏命令实现的,uIP提供的接口函数有:
1,初始化uIP协议栈:uip_init()
2.处理输入包:uip_input()
3.处理周期计时事件:uip_periodic()
4.开始监听端口:uip_listen()
5.连接到远程主机:uip_connect()
6.接收到连接请求:uip_connected()
7.主动关闭连接:uip_close()
8.连接被关闭:uip_closed()
9.发出去的数据被应答:uip_acked()
10.在当前连接发送数据:uip_send()
11.在当前连接上收到新的数据:uip_newdata()
12.告诉对方要停止连接:uip_stop()
13.连接被意外终止:uip_aborted()
接下来,我们看看uIP的移植过程。首先,uIP1.0的源码包里面有如下内容,如图57.1.2.2所示:
http://www.stmcu.org/file:///C:/Documents%20and%20Settings/Administrator/桌面/论坛推广/第57章/新建%20Microsoft%20Word%20文档.files/image006.jpg
图57.1.2.2 uIP 1.0源码包内容
其中apps文件夹里面是uip提供的各种参考代码,本章我们主要有用到里面的webserver部分。doc文件夹里面是一些uip的使用及说明文件,是学习uip的官方资料。lib文件夹里面是用于内存管理的一个代码,本章我们没有用到。uip里面就是uip 1.0的源码了,我们全盘照收。unix里面提供的是具体的应用实例,我们移植参考主要是依照这个里面的代码。
移植第一步:实现在unix/tapdev.c里面的三个函数。首先是tapdev_init函数,该函数用于初始化网卡(也就是我们的ENC28J60),通过这个函数实现网卡初始化。其次,是tapdev_read函数,该函数用于从网卡读取一包数据,将读到的数据存放在uip_buf里面,数据长度返回给uip_len。最后,是tapdev_send函数,该函数用于向网卡发送一包数据,将全局缓存区uip_buf里面的数据发送出去(长度为uip_len)。其实这三个函数就是实现最底层的网卡操作。
第二步,因为uIP协议栈需要使用时钟,为TCP和ARP的定时器服务,因此我们需要STM32提供一个定时器做时钟,提供10ms计时(假设clock-arch.h里面的CLOCK_CONF_SECOND为100),通过clock-arch.c里面的clock_time函数返回给uIP使用。
第三步,配置uip-conf.h里面的宏定义选项。主要用于设置TCP最大连接数、TCP监听端口数、CPU大小端模式等,这个大家根据自己需要配置即可。
通过以上3步的修改,我们基本上就完成了uIP的移植。在使用uIP的时候,一般通过如下顺序:
1)实现接口函数(回调函数)UIP_APPCALL。
该函数是我们使用uIP最关键的部分,它是uIP和应用程序的接口,我们必须根据自己的需要,在该函数做各种处理,而做这些处理的触发条件,就是前面提到的uIP提供的那些接口函数,如uip_newdata、uip_acked、uip_closed等等。另外,如果是UDP,那么还需要实现UIP_UDP_APPCALL回调函数。
2)调用tapdev_init函数,先初始化网卡。
此步先初始化网卡,配置MAC地址,为uIP和网络通信做好准备。
3)调用uip_init函数,初始化uIP协议栈。
此步主要用于uip自身的初始化,我们直接调用就是。
4)设置IP地址、网关以及掩码
这个和电脑上网差不多,只不过我们这里是通过uip_ipaddr、uip_sethostaddr、uip_setdraddr和uip_setnetmask等函数实现。
5)设置监听端口
uIP根据你设定的不同监听端口,实现不同的服务,比如我们实现Web Server就监听80端口(浏览器默认的端口是80端口),凡是发现80端口的数据,都通过Web Server的APPCALL函数处理。根据自己的需要设置不同的监听端口。不过uIP有本地端口(lport)和远程端口(rport)之分,如果是做服务端,我们通过监听本地端口(lport)实现;如果是做客户端,则需要去连接远程端口(rport)。
6)处理uIP事件
最后,uIP通过uip_polling函数轮询处理uIP事件。该函数必须插入到用户的主循环里面(也就是必须每隔一定时间调用一次)。
本节实验功能简介:开机检测ENC28J60,如果检测不成功,则提示报错。在成功检测到ENC28J60之后,初始化uIP,并设置IP地址(192.168.1.16)等,然后监听80端口和1200端口,并尝试连接远程1400端口,80端口用于实现WEB Server功能,1200端口用于实现TCP Server功能,连接1400端口实现TCP Client功能。此时,我们在电脑浏览器输入 ,就可以登录到一个界面,该界面可以控制开发板上两个LED灯的亮灭,还会显示开发板的当前时间以及开发板STM32芯片的温度(每10秒自动刷新一次)。另外,我们通过网络调试软件(做TCP Server时,设置IP地址为:192.168.1.103,端口为1400;做TCP Client时,设置IP地址为:192.168.1.16,端口为1200)同开发板连接,即可实现开发板与网络调试软件之间的数据互发。按KEY0,由开发板的TCP Server端发送数据到电脑的TCP Client端。按KEY2,则由开发板的TCP Client端发送数据到电脑的TCP Server端。LCD显示当前连接状态。
所要用到的硬件资源如下:
1) 指示灯DS0 、DS1
2) KEY0/KEY2两个按键
4) TFTLCD模块
5) ENC28J60网络模块
前面4部分都已经详细介绍过,本章,我们重点看看ALIENTEK ENC28J60网络模块同ALIENTEK 战舰STM32开发板的连接,前面我们介绍了ALIENTEK ENC28J60网络模块的接口,我们通过杜邦线(或排线)连接网络模块和开发板的P12端口,连接关系如表56.2.1所示:
http://www.stmcu.org/file:///C:/Documents%20and%20Settings/Administrator/桌面/论坛推广/第57章/新建%20Microsoft%20Word%20文档.files/image007.jpg
表56.2.1 ENC28J60网络模块同战舰STM32开发板连接关系表
上表可以看出,其实网络模块同战舰STM32开发板的线序是一一对应的,所以如果你有一个1*8的排线,就可以直接对插即可。这里需要注意,本来开发板的P12端口是用来连接SD卡,实现SPI读写SD卡的,如果要连接网络模块,我们需要把跳线帽连接到P10和P11,这样还是可以通过SDIO访问SD卡。
在开发板连接网络模块以后,我们还需要一根网线(自备),连接网络模块和路由器,这样我们才能实现和电脑的连接。
本章,我们在第二十八章实验 (实验23 )的基础上修改,在该工程源码下面加入uIP-1.0文件夹,存放uIP1.0源码,再新建uIP-APP文件夹,存放应用部分代码,因为uIP自己有一个timer.c和timer.h的文件,所以我们还需要修改HARDWARE里面的timer.c和timer.h为不同的名字,本章我们改为timerx.c和timerx.h,我们还需要实现ENC28J60的驱动代码,存放在HARDWARE文件夹下的ENC28J60文件夹里面。详细的步骤我们就不一一阐述了,全部改好之后,工程如图57.3.1所示:
http://www.stmcu.org/file:///C:/Documents%20and%20Settings/Administrator/桌面/论坛推广/第57章/新建%20Microsoft%20Word%20文档.files/image008.jpg
图57.3.1 移植完后,MDK工程图
图中uIP-1.0文件夹里面的代码全部是uIP提供的协议栈源码,而uIP-APP里面的代码则部分是我们自己实现的,部分是uIP提供的,其中:
clock-arch.c,属于uIP协议栈,uIP通过该代码里面的clock_time函数获取时钟节拍。
tapdev.c,同样是uIP提供,用来实现uIP与网卡的接口,该文件实现tapdev_init、tapdev_read和tapdev_send三个重要函数。
tcp_demo.c,完成UIP_APPCALL函数的实现,即tcp_demo_appcall函数。该函数根据端口的不同,分别调用不同的appcall函数,实现不同功能。同时该文件还实现了uip_log函数,用于打印日志。
tcp_client_demo.c,完成一个简单的TCP客户端应用,实现与电脑TCP服务端的数据收发。
tcp_server_demo.c,完成一个简单的TCP服务端应用,实现与电脑TCP客户端的数据收发。
httpd.c、httpd-cgi.c、httpd-fs.c和httpd-strings.h,属于uIP提供的WEB服务器参考代码,我们通过修改部分代码,实现一个简单的WEB服务器。
本章代码很多,我们仅挑一些重点和大家介绍。
首先是tapdev.c里面的三个函数,代码如下:
//MAC地址,必须唯一
//如果你有两个战舰开发板,想连入路由器,则需要修改MAC地址不一样!
const u8 mymac[6]={0x04,0x02,0x35,0x00,0x00,0x01};
//配置网卡硬件,并设置MAC地址
//返回值:0,正常;1,失败;
u8 tapdev_init(void)
u8 i,res=0;
res=ENC28J60_Init((u8*)mymac);
//初始化ENC28J60
//把IP地址和MAC地址写入缓存区
for (i = 0; i & 6; i++)uip_ethaddr.addr=mymac;
//指示灯状态:0x476 is PHLCON LEDA(绿)=links status, LEDB(红)=receive/transmit
//PHLCON:PHY 模块LED 控制寄存器
ENC28J60_PHY_Write(PHLCON,0x0476);
//读取一包数据
uint16_t tapdev_read(void)
ENC28J60_Packet_Receive(MAX_FRAMELEN,uip_buf);
//发送一包数据
void tapdev_send(void)
ENC28J60_Packet_Send(uip_len,uip_buf);
tapdev_init函数,该函数用于初始化网卡,即初始化我们的ENC28J60,初始化工作主要通过调用ENC28J60_Init函数实现,该函数在enc28j60.c里面实现,同时该函数还用于设置MAC地址,这里请确保MAC地址的唯一性。在初始化enc28j60以后,我们设置enc28j60的LED控制器工作方式,即完成对ENC28J60的全部初始化工作。该函数的返回值用于判断网卡初始化是否成功。
tapdev_read函数,该函数调用ENC28J60_Packet_Receive函数,实现从网卡(ENC28J60)读取一包数据,数据被存放在uip_buf里面,同时返回读到的包长度(包长度一般是存放在uip_len里面的)。
tapdev_send函数,该函数调用ENC28J60_Packet_Send函数,实现从网卡(ENC28J60)发送一包数据到网络,数据内容存放在uip_buf,数据长度为uip_len。
再来看看tcp_demo.c里面的tcp_demo_appcall函数,该函数代码如下:
//TCP应用接口函数(UIP_APPCALL)
//完成TCP服务(包括server和client)和HTTP服务
void tcp_demo_appcall(void)
switch(uip_conn-&lport)//本地监听端口80和1200
case HTONS(80):
httpd_appcall();
case HTONS(1200):
tcp_server_demo_appcall();
switch(uip_conn-&rport)
//远程连接1400端口
case HTONS(1400):
tcp_client_demo_appcall();
该函数即UIP_APPCALL函数,是uIP同应用程序的接口函数,该函数通过端口号选择不同的appcall函数,实现不同的服务。其中80端口用于实现WEB服务,通过调用httpd_appcall实现;1200端口用于实现TCP服务器,通过调用tcp_server_demo_appcall函数实现;1400是远程端口,用于实现TCP客户端,调用tcp_client_demo_appcall函数实现。
接着,我们来看看这3个appcall函数,首先是WEB服务器的appcall函数:httpd_appcall,该函数在httpd.c里面实现,源码如下:
//http服务(WEB)处理
void httpd_appcall(void)
struct httpd_state *s = (struct httpd_state *)&(uip_conn-&appstate);//读取连接状态
if(uip_closed() || uip_aborted() || uip_timedout())//异常处理(这里无任何处理)
else if(uip_connected())//连接成功
PSOCK_INIT(&s-&sin, s-&inputbuf, sizeof(s-&inputbuf) - 1);
PSOCK_INIT(&s-&sout, s-&inputbuf, sizeof(s-&inputbuf) - 1);
PT_INIT(&s-&outputpt);
s-&state = STATE_WAITING;
timer_set(&s-&timer, CLOCK_SECOND * 100);*/
s-&timer = 0;
handle_connection(s);//处理
}else if(s!=NULL)
if(uip_poll())
if(s-&timer &= 20)uip_abort();
else s-&timer = 0;
handle_connection(s);
}else uip_abort();//
该函数在连接建立的时候,通handle_connection函数处理http数据,handle_connection函数代码如下:
//分析http数据
static void handle_connection(struct httpd_state *s)
handle_input(s);
//处理http输入数据
if(s-&state==STATE_OUTPUT)handle_output(s);//输出状态,处理输出数据
该函数调用handle_input处理http输入数据,通过调用handle_output实现http网页输出。对我们来说最重要的是handle_input函数,handle_input函数代码如下:
extern unsigned char data_index_html[];//在httpd-fsdata.c里面定义,用于存放html网页源代码
extern void get_temperature(u8 *temp);
//在main函数实现,用于获取温度字符串
extern void get_time(u8 *time);
//在main函数实现,用于获取时间字符串
const u8 * LED0_ON_PIC_ADDR=&/upload//ad65ee9f478ca
beed5b5dbcc_971.gif&;
//LED0亮,图标地址
const u8 * LED1_ON_PIC_ADDR=&/upload//bab5bef0379dc
//LED1亮,图标地址
const u8 * LED_OFF_PIC_ADDR=&/upload//ccecf4ebeb84b
feb0cecc671_254.gif&;
//LED灭,图标地址
//处理HTTP输入数据
static PT_THREAD(handle_input(struct httpd_state *s))
u8 dbuf[17];
PSOCK_BEGIN(&s-&sin);
PSOCK_READTO(&s-&sin, ISO_space);
if(strncmp(s-&inputbuf, http_get, 4)!=0)PSOCK_CLOSE_EXIT(&s-&sin);
//比较客户端
//浏览器输入的指令是否是申请WEB指令 “GET ”
PSOCK_READTO(&s-&sin, ISO_space);
if(s-&inputbuf[0] != ISO_slash)PSOCK_CLOSE_EXIT(&s-&sin);
//判断第一个数据
//(去掉IP地址之后),是否是&/&
if(s-&inputbuf[1] == ISO_space||s-&inputbuf[1] == '?')
//第二个数据是空格/问号
if(s-&inputbuf[1]=='?'&&s-&inputbuf[6]==0x31)//LED1
LED0=!LED0;
strx=strstr((const char*)(data_index_html+13),&LED0状态&);
if(strx)//存在&LED0状态&这个字符串
strx=strstr((const char*)strx,&color:#&);//找到&color:#&字符串
if(LED0)//LED0灭
strncpy(strx+7,&5B5B5B&,6); //灰色
strncpy(strx+24,&灭&,2);
strx=strstr((const char*)strx,&http:&);//找到&http:&字符串
strncpy(strx,(const char*)LED_OFF_PIC_ADDR,strlen((const char*)
LED_OFF_PIC_ADDR));//LED0灭图片
strncpy(strx+7,&FF0000&,6);
strncpy(strx+24,&亮&,2);
strx=strstr((const char*)strx,&http:&);//找到&http:&字符串
strncpy(strx,(const char*)LED0_ON_PIC_ADDR,strlen((const char*)
LED0_ON_PIC_ADDR));//LED0亮图片
}else if(s-&inputbuf[1]=='?'&&s-&inputbuf[6]==0x32)//LED2
LED1=!LED1;
strx=strstr((const char*)(data_index_html+13),&LED1状态&);
if(strx)//存在&LED1状态&这个字符串
strx=strstr((const char*)strx,&color:#&);//找到&color:#&字符串
if(LED1)//LED1灭
strncpy(strx+7,&5B5B5B&,6); //灰色
strncpy(strx+24,&灭&,2);
strx=strstr((const char*)strx,&http:&);//找到&http:&字符串
strncpy(strx,(const char*)LED_OFF_PIC_ADDR,strlen((const char*)
LED_OFF_PIC_ADDR));//LED1灭图片
strncpy(strx+7,&00FF00&,6);
strncpy(strx+24,&亮&,2);
strx=strstr((const char*)strx,&http:&);//找到&http:&字符串
strncpy(strx,(const char*)LED1_ON_PIC_ADDR,strlen((const char*)
LED1_ON_PIC_ADDR));//LED1亮图片
strx=strstr((const char*)(data_index_html+13),&℃&);//找到&℃&字符
get_temperature(dbuf);
//得到温度
strncpy(strx-4,(const char*)dbuf,4);
//更新温度
strx=strstr((const char*)strx,&RTC时间:&);
//找到&RTC时间:&字符
get_time(dbuf);
//得到时间
strncpy(strx+33,(const char*)dbuf,16); //更新时间
strncpy(s-&filename, http_index_html, sizeof(s-&filename));
}else //如果不是' '/'?'
s-&inputbuf[PSOCK_DATALEN(&s-&sin)-1] = 0;
strncpy(s-&filename,&s-&inputbuf[0],sizeof(s-&filename));
s-&state = STATE_OUTPUT;
PSOCK_READTO(&s-&sin, ISO_nl);
if(strncmp(s-&inputbuf, http_referer, 8) == 0)
s-&inputbuf[PSOCK_DATALEN(&s-&sin) - 2] = 0;
PSOCK_END(&s-&sin);
这里,我们需要了解uIP是把网页数据(源文件)存放在data_index_html,通过将这里面的数据发送给电脑浏览器,浏览器就会显示出我们所设计的界面了。当用户在网页上面操作的时候,浏览器就会发送消息给WEB服务器,服务器根据收到的消息内容,判断用户所执行的操作,然后发送新的页面到浏览器,这样用户就可以看到操作结果了。本章,我们实现的WEB服界面如图57.3.2所示:
http://www.stmcu.org/file:///C:/Documents%20and%20Settings/Administrator/桌面/论坛推广/第57章/新建%20Microsoft%20Word%20文档.files/image009.png
图57.3.2 WEB服务器界面
图中两个按键分别控制DS0和DS1的亮灭,然后还显示了STM32芯片的温度和RTC时间等信息。
控制DS0,DS1亮灭我们是通过发送不同的页面请求来实现的,这里我们采用的是Get方法(科普找百度),将请求参数放到URL里面,然后WEB服务器根据URL的参数来相应内容,这样实际上STM32就是从URL获取控制参数,以控制DS0和DS1的亮灭。uIP在得到Get请求后判断URL内容,然后做出相应控制,最后修改data_index_html里面的部分内容(比如指示灯图标的变化,以及提示文字的变化等),再将data_index_html发送给浏览器,显示新的界面。
显示STM32温度和RTC时间是通过刷新实现的,uIP每次得到来自浏览器的请求就会更新data_index_html里面的温度和时间等信息,然后将data_index_html发送给浏览器,这样达到更新温度和时间的目的。但是这样我们需要手动刷新,比较笨,所以我们在网页源码里面加入了自动刷新的控制代码,每10秒钟刷新一次,这样就不需要手动刷新了。
handle_input函数实现了我们所说的这一切功能,另外请注意data_index_html是存放在httpd-fsdata.c(该文件通过include的方式包含进工程里面)里面的一个数组,并且由于该数组的内容需要不停的刷新,所以我们定义它为sram数据,data_index_html里面的数据,则是通过一个工具软件:amo的编程小工具集合V1.2.6.exe,将网页源码转换而来,该软件在光盘有提供,如果想自己做网页的朋友,可以通过该软件转换。
WEB服务器就为大家介绍这么多。
23:29 上传
点击文件名下载附件
1.32 MB, 下载次数: 27
23:30 上传
点击文件名下载附件
1.12 MB, 下载次数: 28
主题帖子积分
初级会员, 积分 59, 距离下一级还需 141 积分
初级会员, 积分 59, 距离下一级还需 141 积分
回复:【连载】【ALIENTEK 战舰STM32开发板】STM32开发指南--第五十七章 ENC28J60网络实验
接下来看看TCP服务器appcall函数:tcp_server_demo_appcall,该函数在tcp_server_demo.c里面实现,该函数代码如下:
u8 tcp_server_databuf[200];
//发送数据缓存
u8 tcp_server_
//服务端状态
//[7]:0,无连接;1,已经连接;
//[6]:0,无数据;1,收到客户端数据
//[5]:0,无数据;1,有数据需要发送
//这是一个TCP 服务器应用回调函数。
//该函数通过UIP_APPCALL(tcp_demo_appcall)调用,实现Web Server的功能.
//当uip事件发生时,UIP_APPCALL函数会被调用,根据所属端口(1200),确定是否执行该函数。
//例如 : 当一个TCP连接被创建时、有新的数据到达、数据已经被应答、数据需要重发等事件
void tcp_server_demo_appcall(void)
struct tcp_demo_appstate *s = (struct tcp_demo_appstate *)&uip_conn-&
if(uip_aborted())tcp_server_aborted();
//连接终止
if(uip_timedout())tcp_server_timedout();
//连接超时
if(uip_closed())tcp_server_closed();
//连接关闭
if(uip_connected())tcp_server_connected();
//连接成功
if(uip_acked())tcp_server_acked();
//发送的数据成功送达
//接收到一个新的TCP数据包
if (uip_newdata())//收到客户端发过来的数据
&span lang=&EN-US&&
if((tcp_server_sta&(1
主题帖子积分
初级会员, 积分 186, 距离下一级还需 14 积分
初级会员, 积分 186, 距离下一级还需 14 积分
RE:【连载】【ALIENTEK 战舰STM32开发板】STM32开发指南--第五十七章 ENC28J60网络实验
神舟的网络这个东西资料我看更实用
主题帖子积分
新手上路, 积分 12, 距离下一级还需 38 积分
新手上路, 积分 12, 距离下一级还需 38 积分
RE:【连载】【ALIENTEK 战舰STM32开发板】STM32开发指南--第五十七章 ENC28J60网络实验
看不到图片呀!顶顶顶顶
主题帖子积分
新手上路, 积分 38, 距离下一级还需 12 积分
新手上路, 积分 38, 距离下一级还需 12 积分
楼主做过RS232转以太网的吗 基于stm32 ENC28j60的
Tel: 3-8056
备案号: 苏ICP备号-2
Powered by

我要回帖

更多关于 enc28j60 w5500 的文章

 

随机推荐