DM9051 SPI 接口以太网模块 + Nuvoton NuTinyM051 + uIP 实现 web server

jf7686 2016-01-23 05:18:42

最近在某個论坛裡,看到这篇STM32F103+DM9051_UIP_SPI to 以太网,透过該版主拿到了DM9051NP 以太网卡,刚好手上有Nuvoton NuTiny M051 和 M451,就先用M051拿来做一个简单的web server,透过web serve' 来控制开发板上的LED灯亮灭。

1. DM9051NP硬体相关描述
DM9051NP SPI接口以太网模块是聯傑國際(DAVICOM)为了方便嵌入式ARM、MCU单片机系统进行以太网通信而开发出的解决方案。DM9051NP晶片是带有行业标准串列外设介面(Serial Peripheral Interface,SPI)的独立以太网控制器。DM9051NP符合IEEE 802.3 规范,它还支援以DMA 模式來传输,以实现资料传送快速。DM9051NP通过1个中断引脚和SPI介面來进行与主控制器MCU单片机的通信,资料传输规格为10/100 M。相關介紹可以參考STM32F103+DM9051_UIP_SPI to 以太网。以下是DM9051NP 以太網卡特點:
• Package:32支接脚封装,QFN.
• IEEE 802.3az Energy Efficient Ethernet (EEE)
• Built-in integrated 3.3V to 1.8V regulator
• 远端唤醒 (WOL)
• 平行线/交叉线自动切换 HP Auto-MDIX
• Support 光口介面
• 具有16KB SRAM静态随机存取记忆
• EMI (Class B) and HBM ESD Rating 8KV
• 工业温度规范: –40度 to +85度
• 功率:(100/10 M) => 429/561 mW
• 连续工作温度<60度


上图是聯傑國際(DAVICOM) DM9051NP 以太网路卡SPI Pin的排列。

NuTinyM051使用的是SPI1与DM9051NP SPI脚位的硬体连接如下:
M0516 DM9051
P0.7(Pin32) CLK (Pin07)
P0.6(Pin33) MISO (Pin05)
P0.5(Pin34) MOSI (Pin03)
P0.4(Pin35) CSS (Pin01)


上图为M051 + DM9051硬体连接示意图。

2.DM9051网卡驱动
SPI 设定和 R/W data 参考M0516 Library SPI_Loopback sample code 可到nuvoton 官网下载M0516 Library, 再参考STM32F103+DM9051_UIP_SPI to 以太网附件中的驱动,将DM9051_Configuration() SPI设定改为M0516 SPI1 Pin Group 设定和修改DM9051_Read_Reg(), DM9051_Write_Reg(), DM9051_Read_Mem(), DM9051_Writer_Mem() , 修改如下:

(1) 首先配置M0516 SPI1 相关设定
void DM9051_Configuration(void)
{
/* Enable SPI1 peripheral clock */
CLK_EnableModuleClock(SPI1_MODULE);
/* Select HCLK as the clock source of SPI1 */
CLK_SetModuleClock(SPI1_MODULE, CLK_CLKSEL1_SPI1_S_HCLK, MODULE_NoMsk);

/* Reset IP */
SYS_ResetModule(SPI1_RST);

/* Setup SPI1 multi-function pins */
SYS->P0_MFP = SYS_MFP_P04_SPISS1 | SYS_MFP_P05_MOSI_1 | SYS_MFP_P06_MISO_1 | SYS_MFP_P07_SPICLK1;

/*---------------------------------------------------------------------------------------------------------*/
/* Init SPI */
/*---------------------------------------------------------------------------------------------------------*/
/* Configure SPI1 as a master, SPI clock rate 25MHz,
clock idle low, 32-bit transaction, drive output on falling clock edge and latch input on rising edge. */
SPI_Open(SPI1, SPI_MASTER, SPI_MODE_0, 8, 25000000);

/* Disable the automatic hardware slave selection function. Select the SPI1_SS pin and configure as low-active. */
SPI_DisableAutoSS(SPI1);

SPI_EnableFIFO(SPI1, 3, 3);
}


(2) 透过read cmd 读出register
/*------------------------------------------------------*/
/* DM9051_Read_Reg() */
/* SPI read command: bit7 = 0, */
/* bit[6:0] = Reg. offset addr */
/* Disable auto SPI slave chip select. */
/*------------------------------------------------------*/
uint8_t DM9051_Read_Reg(uint8_t Reg_Off)
{
SPI_SET_SS_LOW(SPI1);

/* SPI transfer DM9051 Read-Command and Reg. offset. */
//SPI_WRITE_TX0(SPI1, (uint32_t)Reg_Off); //Read command + Register offset address
while(SPI_GET_TX_FIFO_FULL_FLAG(SPI1));
SPI_WRITE_TX0(SPI1, Reg_Off); //Read command + Register offset address
while(SPI_IS_BUSY(SPI1));

SPI_WRITE_TX0(SPI1, 0x0); //Dummy for read register value.
while(SPI_IS_BUSY(SPI1));

SPI_READ_RX0(SPI1); // dummy read, jump 1st byte.

SPI_SET_SS_HIGH(SPI1);

return (SPI_READ_RX0(SPI1) & 0xFF);
}


(3)透过write cmd 写入register
/*------------------------------------------------------*/
/* DM9051_Write_Reg() */
/* SPI write command: bit7 = 1, */
/* bit[6:0] = Reg. offset addr */
/* Disable auto SPI slave chip select. */
/*------------------------------------------------------*/
void DM9051_Write_Reg(uint8_t Reg_Off, uint8_t spi_data)
{
uint32_t cmdaddr;

cmdaddr = (Reg_Off | 0x80);

SPI_SET_SS_LOW(SPI1);

/* SPI transfer DM9051 Read-Command and Reg. offset. */
SPI_WRITE_TX0(SPI1, cmdaddr); //Read command + Register offset address
while(SPI_IS_BUSY(SPI1));

SPI_WRITE_TX0(SPI1, (uint32_t)spi_data);
while(SPI_IS_BUSY(SPI1));

/*Clear SPI TX FIFO*/
SPI_ClearRxFIFO(SPI1);

SPI_SET_SS_HIGH(SPI1);

return;
}


(4) 连续读出 data 从spi array
/*------------------------------------------------------*/
/* DM9051_Read_Mem() */
/* */
/* DM9051 burst read command: SPI_RD_BURST = 0x72 */
/* Disable auto SPI slave chip select. */
/*------------------------------------------------------*/
void DM9051_Read_Mem(uint8_t* pu8data, uint32_t datalen)
{
uint32_t i;

// Read SPI_Data_Array back from the slave
uint8_t burstcmd = SPI_RD_BURST;

SPI_SET_SS_LOW(SPI1);

SPI_WRITE_TX0(SPI1, (uint32_t)burstcmd);
while(SPI_IS_BUSY(SPI1));
SPI_READ_RX0(SPI1);

for(i = 0 ; i < datalen; i++){
pu8data[i] = SPI_WRITE_TX0(SPI1, (uint32_t )0x0);
while(SPI_GET_RX_FIFO_EMPTY_FLAG(SPI1));
pu8data[i] = (uint8_t)SPI_READ_RX0(SPI1);
}

while(SPI_IS_BUSY(SPI1));
/*Clear SPI TX FIFO*/
SPI_ClearTxFIFO(SPI1);

SPI_SET_SS_HIGH(SPI1);
}


(5) 连续写入data到spi array
/*------------------------------------------------------*/
/* DM9051_Write_Mem() */
/* */
/* DM9051 burst write command: SPI_WR_BURST = 0xF8 */
/* Disable auto SPI slave chip select. */
/*------------------------------------------------------*/
void DM9051_Write_Mem(uint8_t* pu8data, uint32_t datalen)
{
uint32_t i;
uint8_t burstcmd = SPI_WR_BURST; /* Send the array to the slave*/

SPI_SET_SS_LOW(SPI1);

SPI_WRITE_TX0(SPI1, (uint32_t)burstcmd);
while(SPI_IS_BUSY(SPI1));
SPI_READ_RX0(SPI1);

for(i = 0; i < datalen; i++){
while(SPI_GET_TX_FIFO_FULL_FLAG(SPI1));
SPI_WRITE_TX0(SPI1, (uint32_t)pu8data[i]);
}

while(SPI_IS_BUSY(SPI1));
/*Clear SPI RX FIFO*/
SPI_ClearRxFIFO(SPI1);

SPI_SET_SS_HIGH(SPI1);
}


3. 简单的web server 控制 LED
uIP就不多介绍了,网路上有许多相关资料可以参考,在上一部份将驱动设置好后,將tapdev_init()、tapdev_read()、tapdev_send()對應到DM9051_init()、DM9051_rx()、DM9051_tx() function即可附件可參考,在main()中加入在 http_init(); 然后在http.c 在handle_input中天加 控制 LED function,新增web_led.c 和web_led.h 如下:

(1)首先先在 http.c handle_input()新增判斷:
static PT_THREAD(handle_input(struct httpd_state *s))
{
PSOCK_BEGIN(&s->sin);

PSOCK_READTO(&s->sin, ISO_space);

if(strncmp(s->inputbuf, http_get, 4) != 0) {
PSOCK_CLOSE_EXIT(&s->sin);
}

PSOCK_READTO(&s->sin, ISO_space);

if(s->inputbuf[0] != ISO_slash) {
PSOCK_CLOSE_EXIT(&s->sin);
}

if(s->inputbuf[1] == ISO_space) {
//strncpy(s->filename, http_index_html, sizeof(s->filename));
strncpy(s->filename, http_webMain_html, sizeof(s->filename));
}
#if 1 //web control led
/* Control led, 0 = OFF, 1 = ON, 2 = Flash */
else if (s->inputbuf[3] == 'L','E','D' && ((s->inputbuf[4] == '0') ||
(s->inputbuf[4] == '1') || (s->inputbuf[4] == '2'))){
Set_LED_mode(s->inputbuf[4]);
s->inputbuf[4]= 0;
//strncpy(s->filename, "/home.html", 10);
strncpy(s->filename, http_webMain_html, sizeof(s->filename));
}
#endif
else {
s->inputbuf[PSOCK_DATALEN(&s->sin) - 1] = 0;
strncpy(s->filename, &s->inputbuf[0], sizeof(s->filename));
}
/* httpd_log_file(uip_conn->ripaddr, s->filename);*/
s->state = STATE_OUTPUT;

while(1) {
PSOCK_READTO(&s->sin, ISO_nl);
if(strncmp(s->inputbuf, http_referer, 8) == 0) {
s->inputbuf[PSOCK_DATALEN(&s->sin) - 2] = 0;
/* httpd_log(&s->inputbuf[9]);*/
}
}
PSOCK_END(&s->sin);
}


(2)LED 设定和控制判断代码如下:
void Set_LED_mode(char lkkcode)
{
//int i;

GPIO_SetMode(P3, BIT6, GPIO_PMD_OUTPUT);

if(lkkcode == ('0')) // LED off
{
P36 = 1;
}else if (lkkcode == '1'){ // LED on
P36 = 0;
}else if(lkkcode == '2') // LED Flash
{
//for(i = 0 ; i< 30 ; ++i)
{
P36 = 0;
Delay(25);
P36 = 1;
Delay(25);
}
}
}


最后在网址列输入IP 192.168.XXX.XXX进入 uip web server控制LED,因为uip 有开DHCP 也可设定为固定IP ,看使用者设定输入正确的IP位址

就可以透过web 控制LED,如下可以看到MCU + DM9051相关讯息,最下面可以看到控制LED 选单,
按下on 、off 、Flash后网址后面会分别显示XXX.XXX.XXX.XXX / LED0、1、2让使用者可以知道目前设定

以上完成后就是一个简单webserver 控制LED应用了,最後附上程序:

DM9051 DataSheet

DM9051 SPI 接口以太网模块 + NuTinyM051 + uIP实现web server

希望版上各位大大能够提供一些想法或建议,多多学习,谢谢。
...全文
799 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
ic12580 2017-03-07
  • 打赏
  • 举报
回复
好东西,不知道,能否超越W5200
jf7686 2016-01-24
  • 打赏
  • 举报
回复
引用 1 楼 guyuguang8628391 的回复:
好,正是我需要的。
大大应用上有建议或想法可以提供一下,谢谢
图灵转世 2016-01-24
  • 打赏
  • 举报
回复
好,正是我需要的。
该智能家居解决方案基于新唐M0516+DM9051--SPI+以太网+web完成。 主要硬件: Nuvoton M051 ARM Cortex-M0, 50MHz. DAVICOM DM9051 SPI 介面网络芯片,10/100 Mbps MDI/MDIX 交叉直连自适应。 普通5V 制 220V继电器。 本DEMO实现的是透过以太网web实现一些智能家居小功能,实物截图: M051+DM9051 串口服务器/透传模块概述: M051+DM9051 串口服务器/透传模块专为串口终端设备连线上网络设计的模块。串口终端设备,不必增加任何硬体器件,只要几行设定指令或不修改软件,即可变成网络服务端或客户端的角色,动态接上网际网络。省去复杂 TCP/IP 程序和测试,快速将串口产品转化成网络产品,迅速进入物联网市场。 透过串口指令设定,全可储存于模块中,成为模块上电时的预设工作模式。所以透过一般电脑经由串口设定,即可应用于各种工作模式和环境。 特点: 内部集成 TCP,UDP,ARP,HTTP,ICMP 等协议,支持静态 IP 和动态 IP( DHCP),支持网关和代理服务器,可以通过互联网传输数据。 串口指令设定,可由外部或由串口设备下命令设定。支持虚拟串口程序虚拟串口与原有系统进行对接,原有系统只需改动串口设置之外不需任何改动。 两种工作方式灵活配置: 客户端工作方式,适用于串口设备主动连接主控设备的情况。 服务器端工作方式,适用于串口设备由其他设备完全控制,被动接收/发送数据的情况。 模拟家电控制风扇: 附件内容截图:

27,375

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧