野火Stm32f407ZGT6+Cubemax+LWIP+Freertos
前言
工作一年了,每天都忙忙碌碌,但是却总感觉没学到什么,正好被一个老乡写的博客启发,认真思考后决定要养成记录、总结和反思的习惯。
最近正好接手了stm32的项目,便从这个开始吧!项目主要使用stm32做网关,3399做主控制器,我也是第一次做stm32的开发,边学边做了。
使用Cubemax配置LWIP系统和Freertos系统
-
硬件资料
开发板:Stm32f407ZGT6
以太网:LAN8720A;
STM32CubeMX 5.3.0;
keil5;
接口:cmsis_v1;
原理:lan8720正常工作,C11电压1.2v。PHY地址设置:MAC层通过SMI总线对PHY进行读写操作,LAN8720通过设置RXER/PHYAD0引脚来设置PHY地址,芯片内部自带下拉电阻,当硬复位结束后,LAN8720会读取该引脚电平,作为器件的SMI地址;若该引脚接下拉电阻时(浮空也可,因为内部自带下拉电阻),SMI地址为0;若该引脚接上拉电阻,SMI地址为1;这里采用的是引脚浮空,即设置LAN8720地址为0,后面配置地址会用得到。
这里借鉴:https://blog.csdn.net/u014428915/article/details/125321137
-
时钟配置
使用野火例程代码配置
-
ETH配置
Mode选择RMII。
上面提高第10脚悬空时地址为0,配置PHY地址为0。
我这里选择Rx模式是中断模式。
PHY选择userPHY,index设置31,其他使用默认参数。
-
Freertos配置
Freertos选择CMSIS_V1,我添加了5个任务,其他使用默认参数
-
LWIP配置
我这里使用的是静态IP,如果想使用动态IP,可以学习下我上面参考的链接里的分享。
-
测试用例
注意:生成的代码LWIP初始化函数自动在任务里,可能会出现ping不通的情况,最好把初始化函数放在main函数里。
我编写的测试用例是使用LWIP的socket,stm32做TCP的服务端。
代码如下:
void Switchtask(void const * argument)
{
/* USER CODE BEGIN Switchtask */
/* Infinite loop */
struct sockaddr_in server_addr_key;
struct sockaddr_in connect_addr_key;
int socket_key;
int socket_connect_key;
socklen_t addr_len;
int err;
int recv_key = 0;
int send_key = 0;
unsigned char data_buffer_key[40];
socket_key = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(socket_key == -1)
{
closesocket(socket_key);
return;
}
memset(&server_addr_key, 0, sizeof(server_addr_key));
server_addr_key.sin_family = AF_INET;
server_addr_key.sin_addr.s_addr =inet_addr("192.168.5.100");
server_addr_key.sin_port = htons(9891);
addr_len = sizeof(struct sockaddr_in);
err = bind(socket_key, (struct sockaddr *)&server_addr_key, sizeof(server_addr_key));
if(err < 0)
{
closesocket(socket_key);
return;
}
err = listen(socket_key, 1);
if(err < 0)
{
closesocket(socket_key);
return;
}
while(1)
{
socket_connect_key = lwip_accept(socket_key, (struct sockaddr *)&connect_addr_key, &addr_len);
if(socket_connect_key >= 0)
{
send(socket_connect_key, "connect success!\n\r", 20, 0);
break;
}
else
{
vTaskDelay(10);
}
}
for(;;)
{
vTaskDelay(50);
recv_key = (int)lwip_recv(socket_connect_key, (void *)data_buffer_key, 40, 0);
if (recv_key > 0)
{
send_key = send(socket_connect_key, data_buffer_key, strlen((char*)data_buffer_key), 0);
if(send_key < 0) {
while(1)
{
closesocket(socket_connect_key);
socket_connect_key = lwip_accept(socket_key, (struct sockaddr *)&connect_addr_key, &addr_len);
if(socket_connect_key >= 0)
{
send(socket_connect_key, "connect success!\n\r", 20, 0);
break;
}
else
{
vTaskDelay(50);
}
}
}
}
}
/* USER CODE END Switchtask */
}
最后测试结果: