LED板子 RJ45网口通讯

学长板子改keil5几个注意事项:

①晶振修改为25M
STM32外部晶振8M更改为25M:
https://blog.csdn.net/a185531353/article/details/78512550?locationNum=1&fps=1

②usart.h中仅保留printf的功能。(不定义该功能而引用printf会导致卡死)
③去除delay.c中的delay相关函数,改成自己的delay函数。(会导致卡死)可再研究下25M的配置。对于跑马灯程序,其定时是准的。。
④定时器配置具体数值还需要再考虑

网口:

正点原子

学长板

修改了学长的reset管脚

学长的板子没有焊接晶振,是用PA8定时器1的 MCO1通道给输出25MHZ(是否为25M需要测试)
https://blog.csdn.net/weixi87/article/details/8309217
74LVC1G17GW:逻辑缓冲器施密特触发器,作用应该是整形
实验55网络通讯实验
http://openedv.com/forum.php?mod=viewthread&tid=43537&highlight=%CD%F8%C2%E7%CD%A8%D0%C5%CA%B5%D1%E9
修改晶振,delay,usart后,运行程序卡死:
My_RTC_Init(); //RTC初始化 会导致程序卡死,已注释




在LAN8720.c中加入MCO1初始化后,橙色灯亮起,程序不再卡死。

void MCO1(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_ClockSecuritySystemCmd(ENABLE);

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
     
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_MCO);
         
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;  //UP
    GPIO_Init(GPIOA, &GPIO_InitStructure);
 
    //RCC_MCO1Config(RCC_MCO1Source_PLLCLK, RCC_MCO1Div_5); 
    RCC_MCO1Config(RCC_MCO1Source_HSE, RCC_MCO1Div_1);  //输出25M
}

各网卡、各交换机等网络设备都不一样,一般来讲:绿灯分为亮或不亮(代表网络速度,黄灯分为闪烁或不闪烁(代表是否有数据收发)
绿灯:长亮 代表100M; 不亮 代表10M
黄灯:长亮 代表无数据收发; 闪烁 代表有数据收发
也有些千兆网卡的灯以颜色区分,不亮代表10M / 绿色代表100M / 黄色代表1000M
现在10M的网络基本看不到了,如果一个灯长亮,基本可以说明100M网络或更高,而另一个灯时而闪烁,那代表有数据收发,具体要看你的网络设备了。
甚至有些低等网卡如TP-Link,只有一个灯,亮代表连通,闪烁代表数据收发

https://blog.csdn.net/a827415225/article/details/51945222

正点原子的例程没有用到外部SRAM,因此可以不必修改malloc.c中的函数。实际调用中注意别用SRAMEX即可。

时钟系统:https://www.cnblogs.com/strongerHuang/p/5609969.html

DHCP先设置为0关闭

这样看来硬件电路应该是有错的。这里我猜测由于LED2原理图是下拉,模式编程OUT模式。 然后程序上输入25MHz时钟,被等效成25MHz晶振,然后内部倍频,正好能正常工作。。
把PLL_N改为300,MCO1改为PLL时钟3分频(输出50MHZ),程序死在



说明lwip_comm_init()一直不等于0

用举涛学长的程序调通:

举涛学长的程序当我从电脑发送到板子时,单片机会停止发送。原子程序无此bug
LED板子做TCP-SERVER
电脑做TCP-CLIENT
程序修改如下:


改成串口1

我的计算机网络配置:


PING指令:


电脑上网络调试助手:



串口助手:


原本的例程程序是在轮询的时候单片机才能发数据,测试收发频率,电脑发的周期在200ms会出错,250ms可以,电脑收信息周期要在500ms,400ms则会丢信息。但是我需要在收到数据时立刻返回数据,因此需要自定义一个主动发送的函数。
原本轮询发送函数在err_t tcp_server_poll(void *arg, struct tcp_pcb *tpcb)中进行,但是这个函数的输入参数是两个复杂的结构体,不知道怎么给,参考了原子论坛的相关说明,定义了两个全局变量,并在tcp_server_accept中赋值,从而实现立即发送数据。盖完之后,在5ms时收发都OK(注意是收发均可)。

struct tcp_server_struct *es_ex;    //用于立即发送数据,在tcp_server_accept中赋值
struct tcp_pcb *newpcb_ex;          //用于立即发送数据,在tcp_server_accept中赋值

//lwIP tcp_accept()的回调函数
err_t tcp_server_accept(void *arg,struct tcp_pcb *newpcb,err_t err)
{
    err_t ret_err;
    struct tcp_server_struct *es; 
    LWIP_UNUSED_ARG(arg);
    LWIP_UNUSED_ARG(err);
    tcp_setprio(newpcb,TCP_PRIO_MIN);//设置新创建的pcb优先级
    es=(struct tcp_server_struct*)mem_malloc(sizeof(struct tcp_server_struct)); //分配内存
    if(es!=NULL) //内存分配成功
    {
        es->state=ES_TCPSERVER_ACCEPTED;    //接收连接
        es->pcb=newpcb;
        es->p=NULL;
        
        tcp_arg(newpcb,es);
        tcp_recv(newpcb,tcp_server_recv);   //初始化tcp_recv()的回调函数
        tcp_err(newpcb,tcp_server_error);   //初始化tcp_err()回调函数
        tcp_poll(newpcb,tcp_server_poll,1); //初始化tcp_poll回调函数
        tcp_sent(newpcb,tcp_server_sent);   //初始化发送回调函数
          
        tcp_server_flag|=1<<5;              //标记有客户端连上了
        lwipdev.remoteip[0]=newpcb->remote_ip.addr&0xff;        //IADDR4
        lwipdev.remoteip[1]=(newpcb->remote_ip.addr>>8)&0xff;   //IADDR3
        lwipdev.remoteip[2]=(newpcb->remote_ip.addr>>16)&0xff;  //IADDR2
        lwipdev.remoteip[3]=(newpcb->remote_ip.addr>>24)&0xff;  //IADDR1 
        ret_err=ERR_OK;
    }else ret_err=ERR_MEM;
  //主要是在这里赋值    
    es_ex = es;
    newpcb_ex = newpcb;
    
    return ret_err;
}

//自己参照tcp_server_poll写的发送数据函数,用于立即发数据,而不必等到轮询
void mytcp_server_senddata(char *sendbuf)
{
    tcp_server_sendbuf = sendbuf;
    es_ex->p=pbuf_alloc(PBUF_TRANSPORT,strlen((char*)tcp_server_sendbuf),PBUF_POOL);//申请内存
    pbuf_take(es_ex->p,(char*)tcp_server_sendbuf,strlen((char*)tcp_server_sendbuf));
    tcp_server_senddata(newpcb_ex,es_ex);       //轮询的时候发送要发送的数据 
    tcp_server_flag&=~(1<<7);           //清除数据发送标志位
    tcp_server_sendbuf = NULL;          //发送区清空
    if(es_ex->p!=NULL)pbuf_free(es_ex->p);  //释放内存  
}

调用举例:

mytcp_server_senddata("data saved\r\n");
mytcp_server_senddata("hhhh hhhhh\r\n");

你可能感兴趣的:(LED板子 RJ45网口通讯)