中国(深圳)国际机器视觉展览会暨机器视觉技术及工业应用研讨会→ 立即报名 ←
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » DM9051 SPI 接口以太网模块 + NuTinyM051 + uIP实现w

共1条 1/1 1 跳转至

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

菜鸟
2016-01-20 16:42:57    评分

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

1. DM9051NP硬体相关描述

DM9051NP SPI介面网卡芯片是聯傑國際(DAVICOM)为了方便MCU单片机系统进行乙太网通信而开发出的解决方案。DM9051NP晶片是带有行业标准串列外设介面(Serial Peripheral Interface,SPI)的独立乙太网控制器。DM9051NP符合IEEE 802.3 规范,它还支援以DMA 模式來传输,以实现资料传送快速。DM9051NP通过1个中断引脚和SPI介面來进行与主控制器/MCU单片机的通信,资料传输规格为10/100 M。相關介紹可以參考STM32F103+DM9051_UIP_SPI to 以太网

• 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)


上图为M0516 + DM9051硬体连接示意图


2.网卡驱动:

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 200 KHz,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
uint8_t DM9051_Read_Reg(uint8_t Reg_Off)
{ 
	SPI_SET_SS_LOW(SPI1);

	/* SPI transfer DM9051 Read-Command and Reg. offset. */
	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
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); // Set CSS High
	return;
}

(4) 连续读出 data 从spi array

void DM9051_Read_Mem(uint8_t* pu8data, uint32_t datalen)
{
	uint32_t i;
	uint8_t burstcmd = SPI_RD_BURST; /* Read SPI_Data_Array back from 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++) { 
		pu8data = SPI_WRITE_TX0(SPI1, (uint32_t )0x0); 
		while(SPI_GET_RX_FIFO_EMPTY_FLAG(SPI1)); 
		pu8data = (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

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); 
	} 
	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_webMain_html, sizeof(s->filename));
	} 
#if 1 //web 控制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, 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); // Set LED, GPIO Group 3 bit 6

	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应用了,最後附上程序和DM9051NP datasheet:


DM9051(I)-12-MCO-DS-P01_03302015.pdf


NUC_M051_uIP_SPI1_DM9051_webserver.rar






关键词: DM9051     SPI     uIP     WebServer    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]