STM32F103固件库在建立tcp客户端,在数据接收回调函数将数据一个一个写入环形缓冲区,并通过串口发送出去,代码
时间: 2024-03-10 07:48:35 浏览: 135
STM32 移植FreeModbus 详细过程.zip
可以参考以下代码实现:
```
#include "stm32f10x.h"
#include "stm32f10x_eth.h"
#include "stm32f10x_dma.h"
#include "lwip/tcp.h"
#define ETH_DMA_BUF_SIZE 1536
#define ETH_RX_BUF_SIZE ETH_DMA_BUF_SIZE
#define ETH_TX_BUF_SIZE ETH_DMA_BUF_SIZE
#define RX_RING_BUF_SIZE 2048
static uint8_t eth_rx_buf[ETH_RX_BUF_SIZE];
static uint8_t eth_tx_buf[ETH_TX_BUF_SIZE];
static uint8_t rx_ring_buf[RX_RING_BUF_SIZE];
static struct tcp_pcb *tcp_client_pcb = NULL;
static struct pbuf *tx_pbuf = NULL;
static void tcp_client_recv_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{
uint16_t i;
uint16_t len;
uint16_t ring_buf_free_size;
uint16_t pbuf_read_len;
uint8_t *pbuf_data_ptr;
if ((p == NULL) || (err != ERR_OK))
{
return;
}
pbuf_data_ptr = (uint8_t *)p->payload;
pbuf_read_len = p->len;
ring_buf_free_size = RX_RING_BUF_SIZE - ring_buf_tail;
if (pbuf_read_len > ring_buf_free_size)
{
pbuf_read_len = ring_buf_free_size;
}
for (i = 0; i < pbuf_read_len; i++)
{
rx_ring_buf[ring_buf_tail] = pbuf_data_ptr[i];
ring_buf_tail = (ring_buf_tail + 1) % RX_RING_BUF_SIZE;
}
tcp_recved(tpcb, p->tot_len);
pbuf_free(p);
}
static void tcp_client_sent_callback(void *arg, struct tcp_pcb *tpcb, uint16_t len)
{
pbuf_free(tx_pbuf);
tx_pbuf = NULL;
}
static err_t tcp_client_connect_callback(void *arg, struct tcp_pcb *tpcb, err_t err)
{
tcp_client_pcb = tpcb;
tcp_sent(tpcb, tcp_client_sent_callback);
return ERR_OK;
}
static void tcp_client_error_callback(void *arg, err_t err)
{
tcp_client_pcb = NULL;
}
void tcp_client_send_data(uint8_t *data, uint16_t len)
{
if (tcp_client_pcb == NULL)
{
return;
}
tx_pbuf = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
memcpy(tx_pbuf->payload, data, len);
tcp_write(tcp_client_pcb, tx_pbuf->payload, tx_pbuf->len, TCP_WRITE_FLAG_COPY);
}
void tcp_client_init(void)
{
struct ip_addr server_ip;
err_t err;
IP4_ADDR(&server_ip, 192, 168, 1, 100);
tcp_client_pcb = tcp_new();
tcp_arg(tcp_client_pcb, NULL);
tcp_recv(tcp_client_pcb, tcp_client_recv_callback);
tcp_err(tcp_client_pcb, tcp_client_error_callback);
err = tcp_connect(tcp_client_pcb, &server_ip, 5000, tcp_client_connect_callback);
if (err != ERR_OK)
{
tcp_client_pcb = NULL;
}
}
void eth_init(void)
{
ETH_InitTypeDef ETH_InitStructure;
ETH_DMAInitTypeDef ETH_DMA_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ETH_MAC | RCC_AHBPeriph_ETH_MAC_Tx | RCC_AHBPeriph_ETH_MAC_Rx, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_RMII);
ETH_DeInit();
ETH_InitStructure.ETH_AutoNegotiation = ETH_AutoNegotiation_Enable;
ETH_InitStructure.ETH_Speed = ETH_Speed_100M;
ETH_InitStructure.ETH_Mode = ETH_Mode_FullDuplex;
ETH_InitStructure.ETH_LoopbackMode = ETH_LoopbackMode_Disable;
ETH_InitStructure.ETH_RxMode = ETH_RxMode_Interrupt;
ETH_InitStructure.ETH_ChecksumOffload = ETH_ChecksumOffload_Enable;
ETH_InitStructure.ETH_PhyInterface = ETH_PhyInterface_RMII;
ETH_Init(Ð_InitStructure);
ETH_DMA_InitStructure.ETH_DMA_TxDescrBuf = (ETH_DMADescTypeDef*)eth_tx_buf;
ETH_DMA_InitStructure.ETH_DMA_RxDescrBuf = (ETH_DMADescTypeDef*)eth_rx_buf;
ETH_DMA_InitStructure.ETH_DMA_TxBufferSize = ETH_TX_BUF_SIZE;
ETH_DMA_InitStructure.ETH_DMA_RxBufferSize = ETH_RX_BUF_SIZE;
ETH_DMA_InitStructure.ETH_DMA_TxNumDescriptors = 3;
ETH_DMA_InitStructure.ETH_DMA_RxNumDescriptors = 3;
ETH_DMA_InitStructure.ETH_DMA_TxDescrSecondAddress = NULL;
ETH_DMA_InitStructure.ETH_DMA_RxDescrSecondAddress = NULL;
ETH_DMA_InitStructure.ETH_DMA_TxDescrThirdAddress = NULL;
ETH_DMA_InitStructure.ETH_DMA_RxDescrThirdAddress = NULL;
ETH_DMA_InitStructure.ETH_DMA_TxDescrRingLength = 3;
ETH_DMA_InitStructure.ETH_DMA_RxDescrRingLength = 3;
ETH_DMA_InitStructure.ETH_DMA_DefaultTxFlushTimeOut = 0x0000;
ETH_DMA_InitStructure.ETH_DMA_DefaultRxFlushTimeOut = 0x0000;
ETH_DMA_InitStructure.ETH_DMA_TxArbitration = ETH_DMA_TxArbitration_RoundRobin_RxBeforeTx;
ETH_DMA_InitStructure.ETH_DMA_RxArbitration = ETH_DMA_RxArbitration_RoundRobin;
ETH_DMA_InitStructure.ETH_DMA_TxDescrWb = ETH_DMA_TxDescrWb_Enable;
ETH_DMA_InitStructure.ETH_DMA_RxDescrWb = ETH_DMA_RxDescrWb_Enable;
ETH_DMA_InitStructure.ETH_DMA_DropTCPIPChecksumErrorFrame = ENABLE;
ETH_DMA_InitStructure.ETH_DMA_ReceiveStoreForward = ETH_DMA_ReceiveStoreForward_Enable;
ETH_DMA_Init(Ð_DMA_InitStructure);
ETH_DMARxDescChainInit((ETH_DMADescTypeDef*)eth_rx_buf, 3);
ETH_DMATxDescChainInit((ETH_DMADescTypeDef*)eth_tx_buf, 3);
ETH_Start();
}
int main(void)
{
eth_init();
tcp_client_init();
while (1)
{
// ...
}
}
```
在数据接收回调函数 `tcp_client_recv_callback` 中,将收到的数据一个一个写入环形缓冲区 `rx_ring_buf` 中,并通过串口发送出去。
在发送数据时,使用 `tcp_write` 函数将数据写入 tcp 发送缓冲区,当数据发送成功后,会回调 `tcp_client_sent_callback` 函数,在该函数中释放发送缓冲区的内存。
阅读全文