本例主要使用W7500P以太网模块实现串口udp透传。W7500P开发板来自某宝,可自行搜索。
官网链接:w7500p
开发软件:keil5,官网下载外设demo和以太网有关demo。
调试方式:使用j-link进行调试swd模式。
isp烧录:使用串口2进行烧录,烧录前将boot拉高,按一下reset。进入boot成功后,会提示打开串口成功。
功能:
1. 串口透传
2. 串口和socket配置本地IP地址和远程地址
3. 将ip参数等存储在flash中
主函数中,循环调用:
SystemInit();
delay_init();
UART_Configuration();
S_UART_Init(115200);
phy_init();
read_w7500_ip(); //从flash中读取本地和远程参数
set_w7500_ip((__network_info_common*)(&g_network_info_common)); //设置本地ip参数等
while(1)
{
udps(0,test_buf,g_network_info_common.local_port); //客户端0接收平台的数据,透传至串口0
udps(1,test_buf_485,g_network_info_common.local_port+1); //客户端1接收平台的数据,透传至串口1
uart_rcv_parse(); //串口0的数据通过本地端口0上传至远程平台,串口1的数据通过本地端口1上传至远程平台
}
模块重要的本地ip参数主要有:同一个工作现场,模块需要配置不同的mac地址
uint8_t mac[6] = {0x74, 0xe6, 0xe2, 0x2b, 0xb1, 0xb2}; //mac地址
uint8_t lip[4] = {192, 168,0,114}; //本地ip
uint8_t gw[4] = {192, 168,0,1}; //网关
uint8_t sub[4] = {255, 255, 255, 0}; //子网掩码
uint8_t dns_server[4] = {114,114,114,114}; //dns
uint16_t fac_local_port = 5000;
串口和flash部分,和其他的mcu差不多,此处不再赘述。
UDP部分:
int32_t udps(uint8_t sn, uint8_t* buf, uint16_t port)
{
int32_t ret;
uint16_t size, sentsize;
uint8_t destip[4];
uint16_t destport;
switch(getSn_SR(sn)) //获取socket的状态
{
case SOCK_UDP :
if((size = getSn_RX_RSR(sn)) > 0)
{
if(size > DATA_BUF_SIZE) size = DATA_BUF_SIZE;
ret = recvfrom(sn, buf, size, resip, (uint16_t*)&resport);/*W7500P接收数据,可能来自服务端,或者本地的pc客户端*/
if(ret <= 0)
{
printf("%d: recvfrom error. %ld\r\n",sn,ret);
}
size = (uint16_t) ret;
sentsize = 0;
while(sentsize != size)
{
u8 source_port = 0;
if(sn == 0)//根据sn号码,区分服务端发送的数据是下发给哪个客户端的,一个sn号对应一个本地端口
{
source_port = SOURCE_PORT_SCK;
}
else if(sn == 1)
{
source_port = SOURCE_PORT_SCK1;
}
sck_rcv_parse(sn,source_port,buf,size); //协议处理后透传至串口
sentsize += ret;
}
}
break;
case SOCK_CLOSED: //socket处于关闭状态,首次上电时调用,创建socket
if((ret = socket(sn, Sn_MR_UDP, port, 0x00)) != sn) //此处上电后首次将sn号码和本地端口绑定
return ret;
#ifdef _LOOPBACK_DEBUG_
printf("%d:Opened, UDP loopback, port [%d]\r\n", sn, port);
#endif
break;
default :
break;
}
return 1;
}
上述部分为socket接收到的数据处理过程,发送如下:
u8 ret = sendto(sn, buffer, buffer_size, remoteip, remoteport);/*sn为唯一识别号,发送数据至服务端*/
if(ret < 0)
{
#ifdef _LOOPBACK_DEBUG_
printf("%d: sendto error. %ld\r\n",sn,ret);
#endif
return ret;
}
此处,本地端口号和sn号很重要!!
测试时,可将远程端口绑定至字节电脑,用工具建立一个udp服务端。用串口0发送数据时,发现服务端收数据时的端口号为5000,串口2的为5001.
同时,可在本地电脑创建udp客户端,端口设置为5000/5001(需与程序中的本地端口一致),测试以太网模块是否正常运行。
嵌入式开发,初次接触硬件以太网,学到很多,加油。