本帖最后由 jf7686 于 2016-10-7 10:14 编辑
在前几个礼拜发了一篇 DM9051 SPI 接口以太网模块 + NuTinyM051 + uIP实现web server后,原本想在发一篇 DM9051 SPI 接口以太网模块 + NuTinyM451 + uIP,但 Nu_Micro大大已经先PO了 M451+DM9051(SPI接口网络芯片)的uIP demo code移植,所以我直接参考,再移植过程中发现DM9051的驱动与我之前的M0516 + DM9051写法有些不太一样,两者差异在M0516 SPI有4 level FIFO, M451 SPI支援8 level FIFO,所以直接参考修改,所以修改了部份的驅動且加上FreeRTOS OS,一样实现web server。
1.硬件描述
(1) 首先DM9051NP SPI接口以太网模块:
相关描述就不多说了,可以参考DM9051 SPI 接口以太网模块 + NuTinyM051 + uIP实现web server,或 STM32F103+DM9051_UIP_SPI to 以太网。
(2) NuTinyM451使用的是SPI0与DM9051NP SPI脚位硬体连接:
| NuTinyM451 | DM9051NP | CSS | PB.4 (Pin 95) | (Pin 01) | MOSI | PB.5 (Pin 04) | (Pin 03) | MISO | PB.3 (Pin 94) | (Pin 05) | CLK | PB.2 (Pin 93) | (Pin 07) |
下图是NuTinyM451 + DM9051NP 接线示意图:
2.驱动说明
在移植过程中发现,M451+DM9051(SPI接口网络芯片)的uIP demo code移植中的驱动写得有些复杂,所以我参考M051的驱动修改,修改完后正常动作且SPI Frequence 最高能设到24 Mhz。
(1). 首先配置M451 SPI0 相关设定- void DM9051_Configuration(void)
- {
- /* Enable SPI0 Module clock */
- CLK_EnableModuleClock(SPI0_MODULE);
- /* SPI0 module clock from EXT */
- CLK_SetModuleClock(SPI0_MODULE, CLK_CLKSEL2_SPI0SEL_PCLK0, MODULE_NoMsk);
- /* Reset IP */
- SYS_ResetModule(SPI0_RST);
- SYS->GPB_MFPL &= ~(SYS_GPB_MFPL_PB2MFP_Msk | SYS_GPB_MFPL_PB3MFP_Msk | SYS_GPB_MFPL_PB4MFP_Msk | SYS_GPB_MFPL_PB5MFP_Msk);
- SYS->GPB_MFPL |= (SYS_GPB_MFPL_PB2MFP_SPI0_CLK | SYS_GPB_MFPL_PB3MFP_SPI0_MISO0 | SYS_GPB_MFPL_PB4MFP_SPI0_SS | SYS_GPB_MFPL_PB5MFP_SPI0_MOSI0);
- /*---------------------------------------------------------------------------------------------------------*/
- /* Init SPI */
- /*---------------------------------------------------------------------------------------------------------*/
- /* Configure SPI0 as a master, SPI clock rate 24 MHz,
- clock idle low, 32-bit transaction, drive output on falling clock edge and latch input on rising edge. */
- SPI_Open(SPI0, SPI_MASTER, SPI_MODE_0, 8, 24000000);
-
- /* Enable the automatic hardware slave selection function. Select the SPI0_SS pin and configure as low-active. */
- //SPI_EnableAutoSS(SPI0, SPI_SS, SPI_SS_ACTIVE_LOW);
- SPI_DisableAutoSS(SPI0);
- SPI_ENABLE(SPI0);
-
- SPI_SetFIFO(SPI0, 7, 7);
- }
与Nu_Micro的M451+DM9051(SPI接口网络芯片)的uIP demo code移植的DM9051驱动改较多的部份是,SPI R/W spi array data, 修改如下:
(2). 连续读出 data 从spi array
- 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(SPI0);
- SPI_WRITE_TX(SPI0, (uint32_t)burstcmd);
- while(SPI_IS_BUSY(SPI0));
- SPI_READ_RX(SPI0); //Skip SPI RX FIFO
- for(i = 0 ; i < datalen; i++)
- {
- pu8data[i] = SPI_WRITE_TX(SPI0, (uint32_t )0x0);
- while(SPI_GET_RX_FIFO_EMPTY_FLAG(SPI0));
- pu8data[i] = (uint8_t)SPI_READ_RX(SPI0);
- }
- SPI_SET_SS_HIGH(SPI0);
- }
(3). 连续写入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(SPI0);
-
- SPI_WRITE_TX(SPI0, (uint32_t)burstcmd);
- while(SPI_IS_BUSY(SPI0));
- SPI_READ_RX(SPI0); //Skip SPI RX FIFO
-
- for(i = 0; i < datalen; i++)
- {
- while(SPI_GET_TX_FIFO_FULL_FLAG(SPI0));
- SPI_WRITE_TX(SPI0, (uint32_t)pu8data[i]);
- }
- while(SPI_IS_BUSY(SPI0));
- SPI_ClearRxFIFO(SPI0);
-
- SPI_SET_SS_HIGH(SPI0);
- }
3.FreeRTOS说明
FreeRTOS的部分可参考M451SeriesBSP_CMSIS Library 里的Sample做相关移植或网上找有满多相关说明,我直接拿Library 的sample把里面一些原本的Task拿掉只留下uIP 跟 LED 控制的 Task:
(1). Create Task
- int main( void )
- {
- /* Init System */
- prvSetupHardware();
- /* create task */
- xTaskCreate( vuIP_Task, ( signed portCHAR * ) "uIP", configMINIMAL_STACK_SIZE * 3, NULL, tskIDLE_PRIORITY + 4, NULL );
- xTaskCreate( vLEDTask, ( signed portCHAR * ) "LED", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL );
-
- printf("FreeRTOS is starting ...\n");
- /* start OS */
- vTaskStartScheduler();
-
- for(;;);
- }
(2). LED Task
- void vLEDTask( void *pvParameters )
- {
- /* Set LED */
- GPIO_EnableInt(PC, 9, GPIO_INT_FALLING);
- GPIO_SetMode(PC, BIT9, GPIO_MODE_OUTPUT);
-
- for( ;; )
- {
- if(Web_LED_FLASH == 1){
- PC9 = 1;
- vTaskDelay( 500 / portTICK_RATE_MS );
- PC9 = 0;
- vTaskDelay( 500 / portTICK_RATE_MS );
- }
- }
- }
(3). uIP Task
uIP Task 里面的写法与设定只是将原本的uIP的main()改成void vuIP_Task( void *pvParameters )在这就不多做介绍,在设定FreeRTOS Task Delay Timer 在while(1) 加上
- #ifdef __DHCPC_H__
- else if (timer_expired(&dhcp_timer)) {
- // for now turn off the led when we start the dhcp process
- //led_low();
- dhcpc_renew();
- timer_reset(&dhcp_timer);
- }
- #endif // __DHCPC_H__
- else{
- /* task delay */
- vTaskDelayUntil( &xLastWakeTime, xFrequency );
- //vTaskDelay( 100 / portTICK_RATE_MS );
- }
- }
- // return 0;
- }
4.简单的web server 控制 LED
Web Server与 DM9051 SPI 接口以太网模块 + NuTinyM051 + uIP实现web server 的设定大致相同一样能看到MCU 与 IP 相关讯息和控制LED,只是新增了一个选项Task_CON, 原本的设定FreeRTOS Task就是跑uIP 和LED闪烁,但进入网页后为了能使网页控制LED 设定的一个Web_LED_FLASH Flag 来判断目前LED状态,网页后按下ON、OFF、FLASH会暂停FreeRTOS 的LED Task , 在user 不想用网页控制时,在按下Task_Con就能切换为FreeRTOS控制。
一样输入IP地址 192.168.XXX.XXX进入 uip web server控制LED,因为uip 有开DHCP 也可设定为固定IP ,看使用者设定输入正确的IP地址
进入网页后就能控制LED,如下可以看到MCU + DM9051相关讯息,最下面可以看到控制LED 选单,按下on 、off 、Flash、Task_CON后网址后面会分别显示XXX.XXX.XXX.XXX / LED0、1、2、3让使用者可以知道目前设定
以上完成后就是一个简单webserver 控制LED应用了,最后一樣附上程序:
RAM 大约使用了 12264 ( 11.98kB)
ROM 大约使用了 43860 ( 42.83kB),因为有OS的关係,版上各位在应用上有想法或是问题都可以提出一起讨论,谢谢。
NUC-M451_FreeRTOS_uIP_DM9051_WebServer.rar
(895.01 KB, 下载次数: 112)
|
打赏榜单
21ic小喇叭 打赏了 10.00 元 2016-02-16 理由:原创分享~~
|