 |
STM32F103C8的Flash容量是64KB,RAM容量為20KB。這樣小的晶片上也能運行lwip協議棧! 移植前的源程序是運行在STM32F103RC晶片上的: https://zh.arslanbar.net/post.php?t=24571 程序修改步驟: 【1】由於STM32F103C8沒有定時器6,只有TIM1~TIM4四個定時器,因此打開main.c文件,把文件中所有的TIM6都替換為TIM4。 【2】打開lwipopts.h文件,把MEM_SIZE的值修改為512,減小內存開銷。 【3】簡化HTTP協議的響應過程。打開httptest.c,修改http_recv函數的實現: err_t http_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { const char *str = "HTTP/1.1 200 OK\r\nContent-Length: 19\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: text/html\r\n\r\n<b>Hello World!</b>"; if (p != NULL) { tcp_write(tpcb, str, strlen(str), 0); pbuf_free(p); } return ERR_OK; } 【4】在項目屬性的Device選項卡里選擇STM32F103C8晶片,點擊OK保存設置後,可以發現啟動文件已變成startup_stm32f10x_md.s: 
|
 |
另外,由於本人的開發板上接的LED燈是在PC13口上,因此在源程序中添加: // 配置PC口 RCC->APB2ENR = RCC_APB2ENR_IOPCEN; GPIOC->CRH = 0x00300000; // PC13為開發板上的一個LED燈 並且,把LED燈狀態翻轉語句改為: GPIOC->ODR ^= GPIO_ODR_ODR13; (原來的語句是GPIOA->ODR ^= GPIO_ODR_ODR8;,全部替換成上面的語句)
|
 |
【程序編譯結果】 *** Using Compiler 'V5.06 update 1 (build 61)', folder: 'C:\Keil_v5\ARM\ARMCC\Bin' Build target 'Target 1' compiling main.c... linking... Program Size: Code=40136 RO-data=980 RW-data=156 ZI-data=19732 FromELF: creating hex file... ".\Objects\lwip_test2.axf" - 0 Error(s), 0 Warning(s). Build Time Elapsed: 00:00:01
|
 |
佔用的Flash大小=Code+RO+RW=40136+980+156=41272(容量:65536) 佔用的RAM大小=RW+ZI=156+19732=19888(容量:20480)
|
 |
由於程序過大,Keil本身已經無法完成程序的下載。所以改用J-Link官方的SEGGER J-Flash V6.10n軟件下載。下載前首先要生成hex文件,在Keil中的項目屬性里的Output選項卡中勾選Create HEX File,生成的hex文件位於Objects文件夾中。 
|
 |
【程序運行時串口輸出的內容】 
|
 |
能夠ping通,並且開發板上的LED燈正常閃爍: 
|
 |
網頁也能正常打開: 
|
 |
對於簡化前的http_recv函數: err_t error[4]; error[0] = tcp_write(tpcb, STR_AND_SIZE("HTTP/1.1 200 OK\r\nContent-Length: "), TCP_WRITE_FLAG_MORE); error[1] = tcp_write(tpcb, STR_AND_SIZE(len), TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE); error[2] = tcp_write(tpcb, STR_AND_SIZE("\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: text/html\r\n\r\n"), TCP_WRITE_FLAG_MORE); error[3] = tcp_write(tpcb, STR_AND_SIZE(str), TCP_WRITE_FLAG_COPY); // 發送HTML內容 printf("tpcb->snd_buf=%d, err0=%d, err1=%d, err2=%d, err3=%d\n", tpcb->snd_buf, error[0], error[1], error[2], error[3]); 在STM32F103C8單片機上執行,輸出如下: tpcb->snd_buf=2802, err0=0, err1=-1, err2=0, err3=-1 因此第二個和第四個tcp_write執行出現了錯誤,返回值為-1,也就是ERR_MEM,這是內存不足的錯誤。
|
 |
10樓
巨大八爪鱼
2017-3-20 10:11
解決辦法很簡單,把第二步要發送的len字符串和第四步的str字符串改成全局變量,然後去掉TCP_WRITE_FLAG_COPY屬性就行了: char len[10]; // 存放HTML內容的長度 char str[200]; // 存放HTML內容
err_t http_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { char name[100]; char *pstr; uint8_t i = 0; err_t error[4]; if (p != NULL) { // 提取頁面名稱 pstr = (char *)p->payload; while (*pstr++ != ' '); while (*pstr != ' ') name[i++] = *pstr++; name[i] = '\0'; // 不要忘了結束name字符串 tcp_recved(tpcb, p->tot_len); // 生成HTML內容 sprintf(str, "<meta charset=\"gb2312\"><title>獲取網頁名稱</title><div style=\"font-family:Arial\"><b>請求的網頁文件名稱是: </b>%s</div>", name); sprintf(len, "%d", strlen(str)); // HTML內容的長度 error[0] = tcp_write(tpcb, STR_AND_SIZE("HTTP/1.1 200 OK\r\nContent-Length: "), TCP_WRITE_FLAG_MORE); error[1] = tcp_write(tpcb, STR_AND_SIZE(len), TCP_WRITE_FLAG_MORE); error[2] = tcp_write(tpcb, STR_AND_SIZE("\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: text/html\r\n\r\n"), TCP_WRITE_FLAG_MORE); error[3] = tcp_write(tpcb, STR_AND_SIZE(str), 0); // 發送HTML內容 printf("tpcb->snd_buf=%d, err0=%d, err1=%d, err2=%d, err3=%d\n", tpcb->snd_buf, error[0], error[1], error[2], error[3]); pbuf_free(p); } return ERR_OK; }
|