【1】去lwip的官方网站下载最新的lwip-2.0.2.zip
【2】新建空白STM32工程,建工程时一定要在Manage Run-Time Environment对话框里勾选启动文件
【3】新建一个main.c文件,文件内容如下:
#include <stdio.h>
#include <stm32f10x.h>
#include "lwip/etharp.h" // etharp_tmr函数所在的头文件
#include "lwip/init.h" // lwip_init函数所在的头文件
#include "lwip/priv/tcp_priv.h" // tcp_tmr函数所在的头文件
#include "netif/ethernet.h" // ethernet_input函数所在头文件
#include "ENC28J60.h"
// 这两个函数位于ethernetif.c中, 但没有头文件声明
err_t ethernetif_init(struct netif *netif);
void ethernetif_input(struct netif *netif);
// 声明httptest.c中的函数
void init_http(void);
// printf串口输出
// 必须要在项目属性里勾选Use MicroLIB后才能使用
int fputc(int ch, FILE *fp)
{
if (fp == &__stdout)
{
USART1->DR = ch;
while ((USART1->SR & USART_SR_TXE) == 0);
}
return ch;
}
int main(void)
{
struct ip4_addr ipaddr, netmask, gw;
struct netif enc28j60;
uint8_t cnt = 0;
// 配置PA口
RCC->APB2ENR = RCC_APB2ENR_IOPAEN;
GPIOA->CRH = 0x000004b3; // PA8为开发板上的一个LED灯
GPIOA->CRL = 0xb4bb0080;
GPIOA->BSRR = GPIO_BSRR_BS1; // PA1为网卡中断输出
// 配置SPI
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
SPI1->CR1 = SPI_CR1_MSTR | SPI_CR1_BR_1; // 主机模式, 时钟至少需要8分频(BR=010), 也就是72MHz/8=9MHz
SPI1->CR2 = SPI_CR2_SSOE; // 开CS片选输出
// 配置串口
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
USART1->BRR = 0x271; // 波特率: 115200
USART1->CR1 = USART_CR1_UE | USART_CR1_TE;
printf("Hello World!\r\n");
// 配置定时器
RCC->APB1ENR = RCC_APB1ENR_TIM6EN;
TIM6->ARR = 2499; // 共2500个数, 2500*0.1ms=250ms
TIM6->PSC = 7199; // 72MHz/7200=10kHz -> 0.1ms
TIM6->CR1 = TIM_CR1_URS; // 防止UG=1时UIF置位
TIM6->EGR = TIM_EGR_UG; // 应用上述设置
TIM6->CR1 |= TIM_CR1_CEN; // 开定时器
lwip_init();
IP4_ADDR(&ipaddr, 192, 168, 0, 2); // IP地址
IP4_ADDR(&netmask, 255, 255, 255, 0); // 子网掩码
IP4_ADDR(&gw, 192, 168, 0, 1); // 网关
netif_add(&enc28j60, &ipaddr, &netmask, &gw, NULL, ethernetif_init, ethernet_input);
netif_set_default(&enc28j60); // 设为默认网卡
netif_set_up(&enc28j60);
printf("进入主循环...\r\n");
init_http(); // 初始化HTTP服务
while (1)
{
if (ENC28J60_GetPacketNum() != 0)
{
GPIOA->ODR ^= GPIO_ODR_ODR8; // PA8上的LED灯闪烁表明系统正常工作
ethernetif_input(&enc28j60);
}
// 若定时器溢出
if (TIM6->SR & TIM_SR_UIF)
{
// 250ms
TIM6->SR &= ~TIM_SR_UIF; // 清除溢出标志
cnt++;
if (cnt >= 20)
{
// 250ms * 20 = 5s
GPIOA->ODR ^= GPIO_ODR_ODR8; // LED灯每5秒钟改变一次状态
cnt = 0;
etharp_tmr(); // ARP定时处理
}
tcp_tmr(); // TCP定时处理
}
}
}