上图是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;
-
- /* 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);
-
- /* Enable the automatic hardware slave selection function. Select the SPI1_SS pin and configure as low-active. */
- //SPI_EnableAutoSS(SPI1, SPI_SS, SPI_SS_ACTIVE_LOW);
- SPI_DisableAutoSS(SPI1);
- //SPI_ENABLE(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.
- SPI_WRITE_TX0(SPI1, (uint32_t)Reg_Off); //Read command + Register offset address
- //SPI_TRIGGER(SPI1);
- while(SPI_IS_BUSY(SPI1));
- SPI_WRITE_TX0(SPI1, (uint32_t)0x0); //Dummy for read register value.
- //SPI_TRIGGER(SPI1);
- 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.
- //while(SPI_GET_TX_FIFO_FULL_FLAG(SPI1) == 0);
- SPI_WRITE_TX0(SPI1, cmdaddr); //Read command + Register offset address
- //SPI_TRIGGER(SPI1);
- while(SPI_IS_BUSY(SPI1));
-
- SPI_WRITE_TX0(SPI1, (uint32_t)spi_data);
- //SPI_TRIGGER(SPI1);
- while(SPI_IS_BUSY(SPI1));
-
- /*Clear SPI RX FIFO*/
- SPI_ClearRxFIFO(SPI1);
-
- SPI_SET_SS_HIGH(SPI1);
-
- return;
- }
复制代码
(4) 连续读出 data 从spi array
- void DM9051_Read_Mem(uint8_t* pu8data, uint32_t datalen)
- {
- uint32_t i;
- //uint32_t mdata;
-
- // Read SPI_Data_Array back from the slave
- uint8_t burstcmd = SPI_RD_BURST;
-
- SPI_SET_SS_LOW(SPI1);
-
- //SPI_ClearTxFIFO(SPI1);
- SPI_WRITE_TX0(SPI1, (uint32_t)burstcmd);
- while(SPI_IS_BUSY(SPI1));
- SPI_READ_RX0(SPI1); //Skip SPI RX FIFO
- /* 1 level FIFO */
- for(i = 0 ; i < datalen; i++)
- {
- pu8data[i] = SPI_WRITE_TX0(SPI1, (uint32_t )0x0);
- //SPI_TRIGGER(SPI1);
- while(SPI_IS_BUSY(SPI1));
- pu8data[i] = (uint8_t)SPI_READ_RX0(SPI1);
- }
- //Clear SPI RX FIFO
- //SPI_ClearRxFIFO(SPI1);
-
- SPI_SET_SS_HIGH(SPI1);
- }
复制代码
(5) 连续写入data到spi array
- void DM9051_Write_Mem(uint8_t* pu8data, uint32_t datalen)
- {
- uint32_t i;
-
- // Send the array to the slave
- uint8_t burstcmd = SPI_WR_BURST;
-
- SPI_SET_SS_LOW(SPI1);
- //SPI_ClearTxFIFO(SPI1);
- SPI_WRITE_TX0(SPI1, (uint32_t)burstcmd);
- //SPI_TRIGGER(SPI1);
- while(SPI_IS_BUSY(SPI1));
- SPI_READ_RX0(SPI1); //Skip SPI RX FIFO
- for(i=0; i
- while(SPI_GET_TX_FIFO_FULL_FLAG(SPI1));
- SPI_WRITE_TX0(SPI1, (uint32_t)pu8data[i]);
- }
- while(SPI_IS_BUSY(SPI1));
- SPI_ClearRxFIFO(SPI1); //Clear SPI RX FIFO
-
- 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 Command
- /* 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应用了,最後附上程序和DM9051NP datasheet:
0