c - STM32F3如何使用MODBUS TCP?

标签 c stm32 ethernet modbus

作为大量研究的结果,我找到了这个 STM32f1 的源代码 this l ink我为 STM32f3 更改了它。然后构建并安装到我的 STM32。我的以太网电缆连接我的电脑和 enc28j60 模块。如果我调试这段代码,我的代码堆栈在 main.c 和 while 循环中:

  while (1)
    {


        eMBPoll();
        led_poll();

        /* 从网络设备读取一个IP包,返回数据长度 */
        uip_len = tapdev_read();
        /* 收到数据 */
        **if (uip_len > 0)**
        {
            /* 处理IP数据包 */
            if (BUF->type == htons(UIP_ETHTYPE_IP))
            {
                uip_arp_ipin();
                uip_input();

                if (uip_len > 0)
                {
                    uip_arp_out();
                    tapdev_send();
                }
            }
            /* 处理ARP报文 */
            else if (BUF->type == htons(UIP_ETHTYPE_ARP))
            {
                uip_arp_arpin();
                if (uip_len > 0)
                {
                    tapdev_send();
                }
            }
        }

我卡住了 if (uip_len > 0) 行,因为 uip_len 为这一行返回 0:

(我的代码与下面的 github 链接相同,所以我不共享所有代码)

enc28j_60.c 中的 unsigned int enc28j60_packet_receive(unsigned char *packet, unsigned int maxlen) 函数:

unsigned int enc28j60_packet_receive(unsigned char *packet, unsigned int maxlen)
{

    unsigned int rxstat;
    unsigned int len;

    if (enc28_read(EPKTCNT) == 0)
    {
        return (0);
    }

    enc28_write(ERDPTL, (next_pack_ptr));
    enc28_write(ERDPTH, (next_pack_ptr) >> 8);

    next_pack_ptr = enc28_readOp(ENC28J60_READ_BUF_MEM, 0);
    next_pack_ptr |= enc28_readOp(ENC28J60_READ_BUF_MEM, 0) << 8;

    len = enc28_readOp(ENC28J60_READ_BUF_MEM, 0);
    len |= enc28_readOp(ENC28J60_READ_BUF_MEM, 0) << 8;

    len -= 4;

    rxstat = enc28_readOp(ENC28J60_READ_BUF_MEM, 0);
    rxstat |= enc28_readOp(ENC28J60_READ_BUF_MEM, 0) << 8;

    if (len > maxlen - 1)
    {
        len = maxlen - 1;
    }

    **if ((rxstat & 0x80) == 0)
    {
        GPIO_SetBits(GPIOE, GPIO_Pin_9);

        len = 0;
    }**
    else
    {

        des_enc28_readBuffer(packet, len);
    }

    enc28_write(ERXRDPTL, (next_pack_ptr));
    enc28_write(ERXRDPTH, (next_pack_ptr) >> 8);

    enc28_writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);

    return (len);
}

为什么 rxstat & 0x80) == 0?我不明白。

最佳答案

根据ENC28J60 datasheet ,似乎 RXSTAT 标志应该在第 12 位:

ENC28J60 Phy Registers

我不确定 des_enc28_readOp(ENC28J60_READ_BUF_MEM, 0) 是否在读取正确的内容,但我相信您应该有类似的内容:

unsigned PHSTAT2 = des_enc28_readOp(ENC28J60_READ_BUF_MEM, 0);
PHSTAT2 |= des_enc28_readOp(ENC28J60_READ_BUF_MEM, 0) << 8;

unsigned RXSTAT = (PHSTAT2 & 0x1000) != 0;
if (RXSTAT)
{
    // RXSTAT flag is set
    des_enc28_readBuffer(packet, len);
}
else
{
    ...
}

我还会将该寄存器的值转储到日志或串行端口,以确保您了解其实际内容:

// I noticed serialprint in your other question, so I am presuming this is your log func
serialprint("PHSTAT2 = 0x%04x\n", PHSTAT2);

关于c - STM32F3如何使用MODBUS TCP?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53646174/

相关文章:

c - return语句是否被认为是C中的表达式语句?

c - 使用 STM32F0 ADC 单独读取不同的输入

arm - 在 Master (SPI) 中设置 nss_soft

qt - 通过 Wifi 的简单 TCP 通信太慢(秒延迟)?

c - 列出以太网 USB 适配器接口(interface)

c - OpenACC:如何从指向主机上相应数组的指针选择设备上的数组

c - 通过串行端口按位获取输入

STM32 和 SD 卡(FATFS 和 SPI)

python - 在 Windows 中使用 python 获取 ipconfig 结果

c++ - 嵌入式 Python 2.7.2 从用户定义的目录导入模块