通过CUBEMX配置,驱动LAN8720A芯片实现和电脑通过TCP通讯。
配置ETH
首先通过CUBEMX配置ETH的引脚,选择模式为RMII
根据原理图上的引脚进行对应的配置,还有一个是LAN8720A的复位引脚,我所使用的是PJ12
根据自己硬件连接去进行配置相应的引脚。
配置LWIP
关闭DHCP 根据自己电脑的ip地址和网关 进行手动配置静态ip,
这里PHY芯片选择LAN8742
这里选择freertosCMSIS_V1
然后生成代码
在lwip.c文件里在这里添加复位代码
在任务中初始化LWIP
然后编译烧录 此时应该是可以ping通状态
单片机作为服务器和客户端
新建一个.C文件 加入工程中,将以下代码复制进去
通过修改宏定义 TCP_MODE来切换服务器和客户端模式 TCP_MODE =2时为服务器模式 为3是客户端模式 自行修改相应的ip和端口号 去进行TCP连接。
#include "tcpecho.h"
#include "lwip/opt.h"
#include "lwip/sys.h"
#include "lwip/api.h"
#include <lwip/sockets.h>
#define TCP_MODE 2
#if TCP_MODE ==2
/* socket_tcp_server.c */
#define SERVER_PORT 3333 // 端口号
#define BUFF_SIZE 1024
#define SERVER_IP "192.168.1.10"
static char ReadBuff[BUFF_SIZE];
uint8_t send_buf[]= "This is a TCP Client test...\n";
/* TCP服务器端(server)任务 */
void vTCPServer_Task(void *thread_param)
{
int sfd, cfd;
int read_len; // 读的数据长度
struct sockaddr_in server_addr, client_addr; // 服务器和客户端的结构体
socklen_t client_addr_len;
// 创建socket
sfd = socket(AF_INET, SOCK_STREAM, 0); // IPV4 socker连接 默认协议
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT);
server_addr.sin_addr.s_addr = inet_addr(SERVER_IP); // 从本机获取
// 绑定socket
bind(sfd, (struct sockaddr *)&server_addr, sizeof(server_addr)); // 文件描述符 IP地址加端口号 addr长度 返回值
// 监听socket
listen(sfd, 5); // 文件描述符 握手队列总和
// 等待客户端连接
client_addr_len = sizeof(client_addr);
cfd = accept(sfd, (struct sockaddr *)&client_addr, &client_addr_len); // 文件描述符 IP地址加端口号 返回值
// printf("client is connect cfd = %d\r\n", cfd);
while (1) // 等待客户端发送数据,然后进行大小写转换,再写回客户端
{
read_len = lwip_read(cfd, ReadBuff, BUFF_SIZE);
for (int i = 0; i < read_len; i++)
{
ReadBuff[i] = toupper(ReadBuff[i]); // 小写转换为大写
}
lwip_write(cfd, ReadBuff, read_len);
}
}
void
client_init(void)
{
sys_thread_new("server", vTCPServer_Task, NULL, 512, 4);
}
#endif
#if TCP_MODE ==3
/* socket_tcp_client.c */
#define CLIENT_PORT 3333 // 端口号
#define BUFF_SIZE 1024
#define CLIENT_IP "192.168.1.108"
static char ReadBuff[BUFF_SIZE];
/* TCP客户端端(client)任务 */
void vTCPClient_Task(void *thread_param)
{
int cfd;
int read_len; // 读的数据长度
struct sockaddr_in client_addr; // 服务器结构体
// 创建socket
cfd = socket(AF_INET, SOCK_STREAM, 0); // IPV4 socker连接 默认协议
client_addr.sin_family = AF_INET;
client_addr.sin_port = htons(CLIENT_PORT);
client_addr.sin_addr.s_addr = inet_addr(CLIENT_IP); // 本机IPV4
// 连接到服务器
connect(cfd, (struct sockaddr *)&client_addr, sizeof(client_addr)); // 文件描述符 ip地址和端口号 大小
while (1)
{
read_len = read(cfd, ReadBuff, BUFF_SIZE); // 等待服务器发送数据
for (int i = 0; i < read_len; i++)
{
ReadBuff[i] = toupper(ReadBuff[i]); // 小写转换为大写
}
write(cfd, ReadBuff, read_len); // 再写回服务器
}
}
void
client_init(void)
{
sys_thread_new("client", vTCPClient_Task, NULL, 512, 4);
}
#endif
同时在.H文件里外部声明函数 在主任务里运行函数即可
通过TCP与电脑连接上之后 发送小写字母回回复大写字母。
此时即完成了TCP通讯。
参考文档
bhttps://blog.csdn.net/qq_36347513/article/details/125931365