Files
STM32F4-Base/Drivers/BSP/CH395F/ch395f.c
2026-07-19 15:27:49 +08:00

1253 lines
35 KiB
C
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* 模å<C2A1>—å<E28094><C3A5>称:CH395F SPI Ethernet Protocol Stack Driver
* 模å<C2A1>—功能:CH395F 以太ç½å<E28098><C3A5>议栈芯片 SPI 驱动实现,æ<C592><C3A6>ä¾èŠ¯ç‰‡æ£€æµã€<C3A3>åˆ<C3A5>å§åŒï¿? * ç½ç»œå<C593>æ•°é…<C3A9>ç½®ã€<C3A3>PHY 管ç<C2A1>†ã€<C3A3>DHCPã€<C3A3>Socket 管ç<C2A1>†å<E280A0>Šæ•°æ<C2B0>®æ”¶å<C2B6>功ï¿? * é€ç”¨å¹³å<C2B3>°ï¼šSTM32F4 系列(SPI2 接å<C2A5>£ï¿? * 作者:王建ï¿? * 创建日期ï¿?026-03-14
* 修改记录ï¿? * 2026-03-14 王建ï¿? åˆå»ºåˆ<C3A5>å§ç‰ˆæœ¬ï¼ŒæŒ‰ä»£ç <C3A7>规范é‡<C3A9>æž„
* 2026-07-18 王建ï¿? 改�?write_send_buf / read_recv_buf 使用 SPI2 DMA 批é‡<C3A9>传输
*/
/* 头æ‡ä»¶åŒ…å<E280A6>«åŒº - 先包å<E280A6>«ç³»ç»Ÿå¤´æ‡ä»¶ï¼Œå†<C3A5>包å<E280A6>«æœ¬æ¨¡å<C2A1>—头æ‡ä»¶ */
#include <string.h>
#include <stdio.h>
#include "ch395f.h"
#include "spi.h"
#include "usart.h"
/*
* 调试输出é…<C3A9>ç½®
*/
#define DBG_TAG "[CH395]"
#include "dbg_log.h"
/*
* ç§<C3A7>有å®<C3A5>定义区
*/
#define CH395F_CHECK_EXIST_TEST_DATA 0x57U /* 芯片检测测试字�*/
#define CH395F_RESET_DELAY_MS 20U /* å¤<C3A5>ä½<C3A4>å<EFBFBD>Žç­‰å¾…延时(msï¿?*/
#define CH395F_INIT_TIMEOUT_MS 500U /* åˆ<C3A5>å§åŒè¶…时时间(msï¿?*/
#define CH395F_SPI_BEGIN_DELAY_MS 1U /* SPI äºåС开å§å»¶æ—¶ï¼ˆmsï¿?*/
#define CH395F_DMA_BUF_SIZE 1500U /* DMA 缓冲区最大字节数 */
/*
* ç§<C3A7>有å<E280B0>˜é‡<C3A9>ï¿?- DMA 传输相关
*/
static volatile uint8_t s_spi2_dma_done = 0U; /* DMA 传输完æˆ<C3A6>标志 */
__attribute__((aligned(4)))
static uint8_t s_spi2_dma_tx_buf[CH395F_DMA_BUF_SIZE]; /* DMA å<>é€<C3A9>缓冲区 */
__attribute__((aligned(4)))
static uint8_t s_spi2_dma_rx_buf[CH395F_DMA_BUF_SIZE]; /* DMA 接收缓冲�*/
/*
* ç§<C3A7>有函数声明ï¿? */
static void ch395f_spi_begin(void);
static void ch395f_spi_end(void);
static void ch395f_spi_dma_transfer(uint16_t len);
/*
* ç§<C3A7>有函数实现ï¿? */
/*
* 函数功能:开ï¿?SPI äºåŠ¡ï¼ˆCS 拉高 -> 拉低ï¿? * 函数说明:æ‰å†Œè¦<C3A8>ï¿?SPI 模å¼<C3A5>ä¸å­—èŠé—´æ— éœ€é—´éš”ï¿? * CS æ‰é«˜å†<C3A5>æ‰ä½Žæ»¡è¶³æœ€å°<C3A5>片选间隔è¦<C3A8>ï¿? */
static void ch395f_spi_begin(void) {
/* CS å…ˆæ‰é«˜ï¼Œç¡®ä¿<C3A4>空闲状�?*/
HAL_GPIO_WritePin(CH395_SCS_GPIO_Port, CH395_SCS_Pin, GPIO_PIN_SET);
/* CS æ‰ä½Žï¼Œå<C592>¯åЍäºåŠ¡ï¼ˆæ— éœ€é¢<C3A9>å¤å»¶æ—¶ï¼ŒSPI æ—¶åº<C3A5>ï¿?SCK 频率决定ï¿?*/
HAL_GPIO_WritePin(CH395_SCS_GPIO_Port, CH395_SCS_Pin, GPIO_PIN_RESET);
}
/*
* 函数功能:结ï¿?SPI äºåŠ¡ï¼ˆCS 拉高ï¿? */
static void ch395f_spi_end(void) {
/* CS æ‰é«˜ï¼Œç»“æ<E2809C>Ÿäºï¿?*/
HAL_GPIO_WritePin(CH395_SCS_GPIO_Port, CH395_SCS_Pin, GPIO_PIN_SET);
}
/*
* 函数功能:DMA å…¨å<C2A8>Œå·¥ä¼ è¾“并等待完æˆ<C3A6>
* å…¥å<C2A5>£å<C2A3>数:len - 传输字节ï¿? uint16_t
* 函数说明:å<C5A1>ï¿?s_spi2_dma_tx_buf,接收到 s_spi2_dma_rx_bufï¿? * 阻塞等待 DMA 完æˆ<C3A6>åžè°ƒç½®ä½<C3A4>标志
*/
static void ch395f_spi_dma_transfer(uint16_t len) {
HAL_StatusTypeDef status;
uint32_t tickstart;
volatile uint32_t loop_cnt = 0U;
s_spi2_dma_done = 0U;
status = HAL_SPI_TransmitReceive_DMA(&hspi2, s_spi2_dma_tx_buf, s_spi2_dma_rx_buf, len);
if (status != HAL_OK) {
DBG_ERROR("HAL_SPI_TransmitReceive_DMA FAIL: %d, SPI_State=%d, SPI_Error=0x%lX, DMA_State=%d",
(int)status,
(int)hspi2.State,
hspi2.ErrorCode,
(int)hspi2.hdmarx->State);
return;
}
tickstart = HAL_GetTick();
while (s_spi2_dma_done == 0U) {
loop_cnt++;
if ((HAL_GetTick() - tickstart) > 1000U) {
DBG_ERROR("TIMEOUT after 1s, len=%d, loop=%lu, SPI_State=%d, SPI_Error=0x%lX",
(int)len, loop_cnt,
(int)hspi2.State,
hspi2.ErrorCode);
DBG_ERROR(" DMA_RX: State=%d, Dir=%lu, CNT=%lu",
(int)hspi2.hdmarx->State,
hspi2.hdmarx->Init.Direction,
__HAL_DMA_GET_COUNTER(hspi2.hdmarx));
DBG_ERROR(" DMA_TX: State=%d, Dir=%lu, CNT=%lu",
(int)hspi2.hdmatx->State,
hspi2.hdmatx->Init.Direction,
__HAL_DMA_GET_COUNTER(hspi2.hdmatx));
DBG_ERROR(" SPI2_CR1=0x%lX, CR2=0x%lX, SR=0x%lX",
SPI2->CR1, SPI2->CR2, SPI2->SR);
/* 强制å¤<C3A5>ä½<C3A4> SPI2 DMA 状æ€<C3A6>,é<C592>¿å…<C3A5>æ­»é”<C3A9> */
HAL_SPI_Abort(&hspi2);
return;
}
}
/* 检查传输是å<C2AF>¦æˆ<C3A6>功:SPI 错误ç <C3A7>必须为 0 */
if (hspi2.ErrorCode != 0U) {
DBG_INFO("SPI DMA done with errors: ErrorCode=0x%lX, SPI_State=%d",
hspi2.ErrorCode, (int)hspi2.State);
__HAL_SPI_CLEAR_OVRFLAG(&hspi2);
}
}
/*
* 函数功能:SPI æ”¶å<C2B6>完æˆ<C3A6>åžè°ƒ
* 函数说明:由 HAL SPI 驱动ï¿?DMA TX+RX 完æˆ<C3A6>å<EFBFBD>Žè°ƒç”¨ï¼ˆHAL_SPI_TransmitReceive_DMA 触å<C2A6>æ­¤åžè°ƒï¼‰
*/
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) {
if (hspi->Instance == SPI2) {
s_spi2_dma_done = 1U;
}
}
/*
* 函数功能:SPI 错误回调
* 函数说明:由 HAL SPI 驱动�DMA 传输出错时调用,释放等待
*/
void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi) {
if (hspi->Instance == SPI2) {
s_spi2_dma_done = 1U;
}
}
/*
* 公共函数实现� */
/*
* 函数功能:å<C5A1> CH395 写入命令字节
* å…¥å<C2A5>£å<C2A3>数:cmd - 命令ï¿? uint8_t 0x00 - 0xFF
* è¿”åžå€¼ï¼šå½ä»¤ç <C3A7>åžæ˜¾ï¿½? uint8_t
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šéœ€ï¿?ch395f_spi_begin() ï¿?ch395f_spi_end() 之间调用
* 函数说明:SPI 模å¼<C3A5>ä¸å½ä»¤ä¸Žæ•°æ<C2B0>®ä¹é—´æ— éœ€é—´éš”
*/
uint8_t ch395f_write_cmd(uint8_t cmd) {
uint8_t rx_data;
/* 通过 SPI å<>é€<C3A9>å½ä»¤å¹¶æŽ¥æ”¶åžæ˜¾ */
HAL_SPI_TransmitReceive(&hspi2, &cmd, &rx_data, 1, HAL_MAX_DELAY);
return rx_data;
}
/*
* 函数功能:å<C5A1> CH395 写入数æ<C2B0>®å­—èŠ
* å…¥å<C2A5>£å<C2A3>数:data - æ•°æ<C2B0>®å­—èŠ uint8_t 0x00 - 0xFF
* è¿”åžå€¼ï¼šæ•°æ<C2B0>®åžæ˜¾ï¿? uint8_t
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šéœ€ï¿?ch395f_spi_begin() ï¿?ch395f_spi_end() 之间调用
*/
uint8_t ch395f_write_data(uint8_t data) {
uint8_t rx_data;
/* 通过 SPI å<>é€<C3A9>æ•°æ<C2B0>®å¹¶æŽ¥æ”¶åžæ˜¾ */
HAL_SPI_TransmitReceive(&hspi2, &data, &rx_data, 1, HAL_MAX_DELAY);
return rx_data;
}
/*
* 函数功能:从 CH395 读å<C2BB>æ•°æ<C2B0>®å­—èŠ
* è¿”åžå€¼ï¼šæŽ¥æ”¶åˆ°çš„æ•°æ<C2B0>®å­—èŠ uint8_t
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šéœ€ï¿?ch395f_spi_begin() ï¿?ch395f_spi_end() 之间调用
*/
uint8_t ch395f_read_data(void) {
uint8_t tx_dummy = 0xFFU;
uint8_t rx_data;
/* å<>�?0xFF ä½œä¸ºæ—¶éŸæº<C3A6>,读å<C2BB>芯片返åžçš„æ•°ï¿?*/
HAL_SPI_TransmitReceive(&hspi2, &tx_dummy, &rx_data, 1, HAL_MAX_DELAY);
return rx_data;
}
/*
* 函数功能:检ï¿?CH395 芯片是å<C2AF>¦å­˜åœ¨ä¸”通信正常
* è¿”åžå€¼ï¼šCH395F_STATUS_OK - 检æµåˆ°èŠ¯ç‰‡ï¼ŒCH395F_STATUS_NOT_DETECTED - 未检测到
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šSPI2 已正确åˆ<C3A5>å§åŒ
* 函数说明:å<C5A1>ï¿?CMD_CHECK_EXIST (0x06) å<>Šæµè¯•å­—ï¿?0x57ï¿? * èŠ¯ç‰‡åº”è¿”åžæŒ‰ä½<C3A4>å<EFBFBD>å<E28093><C3A5>�?0xA8
*/
ch395f_status_t ch395f_check_exist(void) {
uint8_t test_data = CH395F_CHECK_EXIST_TEST_DATA;
uint8_t reply_data;
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>é€<C3A9>检æµå½ï¿?*/
ch395f_write_cmd(CH395F_CMD_CHECK_EXIST);
/* å<>é€<C3A9>æµè¯•æ•°ï¿?*/
ch395f_write_data(test_data);
/* 读å<C2BB>芯片åžå¤<C3A5> */
reply_data = ch395f_read_data();
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
/* 验è¯<C3A8>åžå¤<C3A5>是å<C2AF>¦ä¸ºæµè¯•æ•°æ<C2B0>®çš„æŒ‰ä½<C3A4>å<EFBFBD>å<E28093><C3A5> */
if (reply_data == (uint8_t)(~test_data)) {
return CH395F_STATUS_OK;
}
return CH395F_STATUS_NOT_DETECTED;
}
/*
* 函数功能:读ï¿?CH395 芯片版本ï¿? * è¿”åžå€¼ï¼šç‰ˆæœ¬å­—èŠï¼ˆbit5:0 为版本å<C2AC>·ï¼‰uint8_t
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šèŠ¯ç‰‡å·²é€šè¿‡ ch395f_check_exist() 检ï¿? */
uint8_t ch395f_get_version(void) {
uint8_t version;
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>é€<C3A9>版本读å<C2BB>å½ï¿?*/
ch395f_write_cmd(CH395F_CMD_GET_IC_VER);
/* 读å<C2BB>版本ï¿?*/
version = ch395f_read_data();
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
return version;
}
/*
* 函数功能:获å<C2B7>远ï¿?IP 和端ï¿? * å…¥å<C2A5>£å<C2A3>数:sock - Socket 索引 uint8_t 0 - 7
* p_buf - 6 å­—èŠè¾“出缓冲区(­—èŠIP + 2å­—èŠç«¯å<C2AF>£ï¿? * é™<C3A9>定æ<C5A1>¡ä»¶ï¼šTCP Server 模å¼<C3A5>ä¸è¿žæŽ¥å»ºç«å<E280B9>Žè°ƒç”¨
* 函数说明:IP 低字èŠåœ¨å‰<C3A5>,端å<C2AF>£ä½Žå­—èŠåœ¨ï¿? */
void ch395f_get_remot_ipp(uint8_t sock, uint8_t *p_buf) {
uint8_t i;
/* 检查输入å<C2A5>æ•°å<C2B0>ˆæ³•�?*/
if (p_buf == NULL) {
return;
}
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>é€<C3A9>获å<C2B7>远ï¿?IP åŒç«¯å<C2AF>£å½ï¿?*/
ch395f_write_cmd(CH395F_CMD_GET_REMOT_IPP_SN);
/* å<>�?Socket 索引 */
ch395f_write_data(sock);
/* 读å<C2BB> 4 字节 IP 地å<C2B0>€ */
for (i = 0; i < 4; i++) {
p_buf[i] = ch395f_read_data();
}
/* 读å<C2BB> 2 å­—èŠç«¯å<C2AF>£ï¿?*/
for (i = 4; i < 6; i++) {
p_buf[i] = ch395f_read_data();
}
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:设ï¿?CH395 功能å<C2BD>æ•°
* å…¥å<C2A5>£å<C2A3>数:para - 4 å­—èŠåŠŸèƒ½å<C2BD>æ•° uint32_t
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šå¿…须在 ch395f_init() ä¹å‰<C3A5>调用
*/
void ch395f_set_fun_para(uint32_t para) {
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>é€<C3A9>设置功能å<C2BD>æ•°å½ï¿?*/
ch395f_write_cmd(CH395F_CMD_SET_FUN_PARA);
/* å<>�?4 å­—èŠå<E2809A>数(低字èŠåœ¨å‰<C3A5>ï¿?*/
ch395f_write_data((uint8_t)(para));
ch395f_write_data((uint8_t)(para >> 8));
ch395f_write_data((uint8_t)(para >> 16));
ch395f_write_data((uint8_t)(para >> 24));
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:设�TCP MSS
* å…¥å<C2A5>£å<C2A3>数:mss - MSS ï¿? uint16_t 60~1460
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šå¿…须在 ch395f_init() ä¹å‰<C3A5>调用
*/
void ch395f_set_tcp_mss(uint16_t mss) {
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>é€<C3A9>设ï¿?TCP MSS 命令 */
ch395f_write_cmd(CH395F_CMD_SET_TCP_MSS);
/* å<>�?2 字节 MSS 值(低字èŠåœ¨å‰<C3A5>) */
ch395f_write_data(mss & 0xFFU);
ch395f_write_data((mss >> 8) & 0xFFU);
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:设ï¿?Socket 接收缓冲ï¿? * å…¥å<C2A5>£å<C2A3>数:sock - Socket 索引 uint8_t 0 - 7
* start_block - èµ·å§å<E280B9>—地å<C2B0>€ uint8_t
* block_count - å<>—个ï¿? uint8_t
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šå¿…须在 OPEN_SOCKET_SN ä¹å‰<C3A5>调用
*/
void ch395f_set_recv_buf(uint8_t sock, uint8_t start_block, uint8_t block_count) {
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>é€<C3A9>设置接收缓冲区å½ä»¤ */
ch395f_write_cmd(CH395F_CMD_SET_RECV_BUF);
/* å<>�?Socket 索引 */
ch395f_write_data(sock);
/* å<>é€<C3A9>èµ·å§å<E280B9>—地å<C2B0>€ */
ch395f_write_data(start_block);
/* å<>é€<C3A9>å<EFBFBD>—个数 */
ch395f_write_data(block_count);
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:设ï¿?Socket å<>é€<C3A9>缓冲区
* å…¥å<C2A5>£å<C2A3>数:sock - Socket 索引 uint8_t 0 - 7
* start_block - èµ·å§å<E280B9>—地å<C2B0>€ uint8_t
* block_count - å<>—个ï¿? uint8_t
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šå¿…须在 OPEN_SOCKET_SN ä¹å‰<C3A5>调用
*/
void ch395f_set_send_buf(uint8_t sock, uint8_t start_block, uint8_t block_count) {
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>é€<C3A9>设置å<C2AE>é€<C3A9>缓冲区å½ä»¤ */
ch395f_write_cmd(CH395F_CMD_SET_SEND_BUF);
/* å<>�?Socket 索引 */
ch395f_write_data(sock);
/* å<>é€<C3A9>èµ·å§å<E280B9>—地å<C2B0>€ */
ch395f_write_data(start_block);
/* å<>é€<C3A9>å<EFBFBD>—个数 */
ch395f_write_data(block_count);
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:清ï¿?Socket 接收缓冲ï¿? * å…¥å<C2A5>£å<C2A3>数:sock - Socket 索引 uint8_t 0 - 7
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šSocket 已打开
*/
void ch395f_clear_recv_buf(uint8_t sock) {
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>é€<C3A9>清空接收缓冲区å½ä»¤ */
ch395f_write_cmd(CH395F_CMD_CLEAR_RECV_BUF_SN);
/* å<>�?Socket 索引 */
ch395f_write_data(sock);
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:设�TCP KeepAlive 空闲时间
* å…¥å<C2A5>£å<C2A3>数:time - 空闲时间(秒ï¿? uint32_t
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šå¿…须在 ch395f_init() ä¹å‰<C3A5>调用
*/
void ch395f_set_keepalive_idle(uint32_t time) {
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>é€<C3A9>设ï¿?KeepAlive 空闲时间命令 */
ch395f_write_cmd(CH395F_CMD_SET_KEEPALIVE_IDLE);
/* å<>�?4 å­—èŠæ—¶é—´å€¼ï¼ˆä½Žå­—èŠåœ¨å‰<C3A5>) */
ch395f_write_data((uint8_t)(time));
ch395f_write_data((uint8_t)(time >> 8));
ch395f_write_data((uint8_t)(time >> 16));
ch395f_write_data((uint8_t)(time >> 24));
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:设�TCP KeepAlive 探测间隔
* å…¥å<C2A5>£å<C2A3>数:time - 间隔时间(秒ï¿? uint32_t
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šå¿…须在 ch395f_init() ä¹å‰<C3A5>调用
*/
void ch395f_set_keepalive_intvl(uint32_t time) {
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>é€<C3A9>设ï¿?KeepAlive 探测间隔命令 */
ch395f_write_cmd(CH395F_CMD_SET_KEEPALIVE_INTVL);
/* å<>�?4 å­—èŠæ—¶é—´å€¼ï¼ˆä½Žå­—èŠåœ¨å‰<C3A5>) */
ch395f_write_data((uint8_t)(time));
ch395f_write_data((uint8_t)(time >> 8));
ch395f_write_data((uint8_t)(time >> 16));
ch395f_write_data((uint8_t)(time >> 24));
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:设�TCP KeepAlive 探测次数
* å…¥å<C2A5>£å<C2A3>数:cnt - 探测次数 uint8_t
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šå¿…须在 ch395f_init() ä¹å‰<C3A5>调用
*/
void ch395f_set_keepalive_cnt(uint8_t cnt) {
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>é€<C3A9>设ï¿?KeepAlive 探测次数命令 */
ch395f_write_cmd(CH395F_CMD_SET_KEEPALIVE_CNT);
/* å<>é€<C3A9>æŽ¢æµæ¬¡ï¿?*/
ch395f_write_data(cnt);
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:å<C5A1>¯ï¿?ç¦<C3A7>用指定 Socket ï¿?KeepAlive
* å…¥å<C2A5>£å<C2A3>数:sock - Socket 索引 uint8_t 0 - 7
* enable - 1 å<>¯ç”¨ï¿? ç¦<C3A7>用 uint8_t
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šSocket 已打开
*/
void ch395f_set_keepalive_enable(uint8_t sock, uint8_t enable) {
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>é€<C3A9>设ï¿?KeepAlive 使能命令 */
ch395f_write_cmd(CH395F_CMD_SET_KEEPALIVE_SN);
/* å<>�?Socket 索引 */
ch395f_write_data(sock);
/* å<>é€<C3A9>使能标ï¿?*/
ch395f_write_data(enable);
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:设ï¿?TCP é‡<C3A9>传次数
* å…¥å<C2A5>£å<C2A3>数:cnt - é‡<C3A9>传次数 uint8_tï¿?=使用默认ï¿?ï¿? * é™<C3A9>定æ<C5A1>¡ä»¶ï¼šå¿…须在 ch395f_init() ä¹å‰<C3A5>调用
*/
void ch395f_set_retrans_count(uint8_t cnt) {
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>é€<C3A9>设置é‡<C3A9>传次数å½ï¿?*/
ch395f_write_cmd(CH395F_CMD_SET_RETRAN_COUNT);
/* å<>é€<C3A9>é‡<C3A9>传次ï¿?*/
ch395f_write_data(cnt);
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:设ï¿?TCP é‡<C3A9>传卿œŸ
* å…¥å<C2A5>£å<C2A3>数:period - é‡<C3A9>传卿œŸï¼ˆæ¯«ç§ï¼‰ uint16_t
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šå¿…须在 ch395f_init() ä¹å‰<C3A5>调用
*/
void ch395f_set_retrans_period(uint16_t period) {
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>é€<C3A9>设置é‡<C3A9>传卿œŸå½ï¿?*/
ch395f_write_cmd(CH395F_CMD_SET_RETRAN_PERIOD);
/* å<>�?2 å­—èŠå¨æœŸå€¼ï¼ˆä½Žå­—èŠåœ¨å‰<C3A5>) */
ch395f_write_data(period & 0xFFU);
ch395f_write_data((period >> 8) & 0xFFU);
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:软件å¤<C3A5>ï¿?CH395
* è¿”åžå€¼ï¼šCH395F_STATUS_OK
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šSPI2 已正确åˆ<C3A5>å§åŒ
* 函数说明:å¤<C3A5>ä½<C3A4>耗时ï¿?15ms(TE0),函数内部已包å<E280A6>«å»¶ï¿? */
ch395f_status_t ch395f_reset(void) {
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>é€<C3A9>å¤<C3A5>ä½<C3A4>å½ï¿?*/
ch395f_write_cmd(CH395F_CMD_RESET_ALL);
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
/* 等待å¤<C3A5>ä½<C3A4>完æˆ<C3A6>(TE0 = 15ms 典型值,等待 20msï¿?*/
HAL_Delay(CH395F_RESET_DELAY_MS);
return CH395F_STATUS_OK;
}
/*
* 函数功能:查询命令执行状ï¿? * è¿”åžå€¼ï¼šçжæ€<C3A6>å­—èŠï¼ˆCH395F_ERR_SUCCESS / CH395F_ERR_BUSY / ...)uint8_t
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šä»…在长执行å½ä»¤ï¼ˆå¦åˆ<C3A5>å§åŒï¼‰å<E280B0>Žè°ƒï¿? */
uint8_t ch395f_get_cmd_status(void) {
uint8_t status;
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>é€<C3A9>状æ€<C3A6>查询å½ï¿?*/
ch395f_write_cmd(CH395F_CMD_GET_CMD_STATUS);
/* 读å<C2BB>状æ€<C3A6>å­—ï¿?*/
status = ch395f_read_data();
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
return status;
}
/*
* 函数功能:轮询等待命令执行完ï¿? * å…¥å<C2A5>£å<C2A3>数:timeout_ms - 超时时间(毫秒) uint32_t
* è¿”åžå€¼ï¼šå½ä»¤æ‰§è¡Œçжæ€<C3A6>ç <C3A7>(CH395F_ERR_SUCCESS ï¿?CH395F_CMD_RET_ABORTï¿? * é™<C3A9>定æ<C5A1>¡ä»¶ï¼šåœ¨å<C2A8>é€<C3A9>长执行å½ä»¤å<C2A4>Žè°ƒï¿? * 函数说明:æ¯<C3A6> 20ms 查询一次,ç´åˆ°å½ä»¤å®Œæˆ<C3A6>æˆè¶…ï¿? */
uint8_t ch395f_poll_cmd_status(uint32_t timeout_ms) {
uint8_t status;
uint32_t retry_count = 0U;
uint32_t max_retries = (timeout_ms + 20U - 1U) / 20U;
while (1) {
HAL_Delay(20U);
status = ch395f_get_cmd_status();
if (status != CH395F_ERR_BUSY) {
return status;
}
if (++retry_count >= max_retries) {
return CH395F_ERR_BUSY; /* è¶…æ—¶ */
}
}
}
/*
* 函数功能:åˆ<C3A5>å§åŒ CH395(包ï¿?MACã€<C3A3>PHYã€<C3A3>TCP/IP å<><C3A5>议栈)
* è¿”åžå€¼ï¼šCH395F_STATUS_OK - æˆ<C3A6>功,CH395F_STATUS_TIMEOUT - 超时失败
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šèŠ¯ç‰‡å·²é€šè¿‡ ch395f_reset() å¤<C3A5>ä½<C3A4>
* 函数说明:阻塞等待åˆ<C3A5>å§åŒå®Œæˆ<C3A6>æˆè¶…时(芯片需è¦<C3A8>约 200ms,这里等最ï¿?4sï¿? */
ch395f_status_t ch395f_init(void) {
uint8_t status;
ch395f_spi_begin();
ch395f_write_cmd(CH395F_CMD_INIT_CH395);
ch395f_spi_end();
status = ch395f_poll_cmd_status(4000U);
if (status == CH395F_ERR_SUCCESS) {
return CH395F_STATUS_OK;
}
return (status == CH395F_ERR_BUSY) ? CH395F_STATUS_TIMEOUT : CH395F_STATUS_ERROR;
}
/*
* 函数功能:设ï¿?CH395 IP 地å<C2B0>€ï¼ˆä½Žå­—èŠåœ¨å‰<C3A5>ï¿? * å…¥å<C2A5>£å<C2A3>数:p_ip - 4 字节 IP 地å<C2B0>€æŒ‡éˆ uint8_t*
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šæŒ‡éˆé<CB86>žç©ºï¼ŒèŠ¯ç‰‡å·²åˆ<C3A5>å§åŒ
*/
void ch395f_set_ip_addr(uint8_t *p_ip) {
uint8_t i;
/* 检查输入å<C2A5>æ•°å<C2B0>ˆæ³•�?*/
if (p_ip == NULL) {
return;
}
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>é€<C3A9>设ï¿?IP 命令 */
ch395f_write_cmd(CH395F_CMD_SET_IP_ADDR);
/* é€<C3A9>å­—èŠå<E2809A>ï¿?IP 地å<C2B0>€ */
for (i = 0; i < 4; i++) {
ch395f_write_data(p_ip[i]);
}
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:设置网ï¿?IP 地å<C2B0>€ï¼ˆä½Žå­—èŠåœ¨å‰<C3A5>ï¿? * å…¥å<C2A5>£å<C2A3>数:p_gwip - 4 字节网关 IP 指针 uint8_t*
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šæŒ‡éˆé<CB86>žç©ºï¼ŒèŠ¯ç‰‡å·²åˆ<C3A5>å§åŒ
*/
void ch395f_set_gwip_addr(uint8_t *p_gwip) {
uint8_t i;
/* 检查输入å<C2A5>æ•°å<C2B0>ˆæ³•�?*/
if (p_gwip == NULL) {
return;
}
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>é€<C3A9>设置ç½å…³å½ï¿?*/
ch395f_write_cmd(CH395F_CMD_SET_GWIP_ADDR);
/* é€<C3A9>å­—èŠå<E2809A>é€<C3A9>ç½ï¿?IP */
for (i = 0; i < 4; i++) {
ch395f_write_data(p_gwip[i]);
}
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:设置å­<C3A5>ç½æŽ©ç <C3A7>(低字èŠåœ¨å‰<C3A5>)
* å…¥å<C2A5>£å<C2A3>数:p_mask - 4 å­—èŠå­<C3A5>ç½æŽ©ç <C3A7>æŒ‡éˆ uint8_t*
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šæŒ‡éˆé<CB86>žç©ºï¼ŒèŠ¯ç‰‡å·²åˆ<C3A5>å§åŒ
*/
void ch395f_set_mask_addr(uint8_t *p_mask) {
uint8_t i;
/* 检查输入å<C2A5>æ•°å<C2B0>ˆæ³•�?*/
if (p_mask == NULL) {
return;
}
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>é€<C3A9>设置掩ç <C3A7>å½ï¿?*/
ch395f_write_cmd(CH395F_CMD_SET_MASK_ADDR);
/* é€<C3A9>å­—èŠå<E2809A>é€<C3A9>å­<C3A5>ç½æŽ©ï¿?*/
for (i = 0; i < 4; i++) {
ch395f_write_data(p_mask[i]);
}
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:设ï¿?MAC 地å<C2B0>€ï¼ˆä½Žå­—èŠåœ¨å‰<C3A5>,存å¨äºŽ EEPROMï¿? * å…¥å<C2A5>£å<C2A3>数:p_mac - 6 字节 MAC 地å<C2B0>€æŒ‡éˆ uint8_t*
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šæŒ‡éˆé<CB86>žç©ºï¼ŒèŠ¯ç‰‡å·²åˆ<C3A5>å§åŒ
* 函数说明:执行耗时�30us(TE5� */
void ch395f_set_mac_addr(uint8_t *p_mac) {
uint8_t i;
/* 检查输入å<C2A5>æ•°å<C2B0>ˆæ³•�?*/
if (p_mac == NULL) {
return;
}
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>é€<C3A9>设ï¿?MAC 命令 */
ch395f_write_cmd(CH395F_CMD_SET_MAC_ADDR);
/* é€<C3A9>å­—èŠå<E2809A>ï¿?MAC 地å<C2B0>€ */
for (i = 0; i < 6; i++) {
ch395f_write_data(p_mac[i]);
}
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:从 CH395 读å<C2BB> MAC 地å<C2B0>
* 出å<C2BA>£å<C2A3>数:p_mac - 6 字节 MAC 地å<C2B0>€ç¼“冲区指ï¿? uint8_t*
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šæŒ‡éˆé<CB86>žï¿? */
void ch395f_get_mac_addr(uint8_t *p_mac) {
uint8_t i;
/* 检查输入å<C2A5>æ•°å<C2B0>ˆæ³•�?*/
if (p_mac == NULL) {
return;
}
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>é€<C3A9>读ï¿?MAC 命令 */
ch395f_write_cmd(CH395F_CMD_GET_MAC_ADDR);
/* é€<C3A9>å­—èŠè¯»ï¿?MAC 地å<C2B0>€ */
for (i = 0; i < 6; i++) {
p_mac[i] = ch395f_read_data();
}
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:读ï¿?IP ä¿¡æ<C2A1>¯ï¼ˆIP + 掩ç <C3A7> + DNS,共 20 字节ï¿? * 出å<C2BA>£å<C2A3>数:p_buf - 20 字节缓冲区指ï¿? uint8_t*
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šæŒ‡éˆé<CB86>žï¿? */
void ch395f_get_ip_inf(uint8_t *p_buf) {
uint8_t i;
/* 检查输入å<C2A5>æ•°å<C2B0>ˆæ³•�?*/
if (p_buf == NULL) {
return;
}
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>é€<C3A9>读ï¿?IP ä¿¡æ<C2A1>¯å½ä»¤ */
ch395f_write_cmd(CH395F_CMD_GET_IP_INF);
/* é€<C3A9>å­—èŠè¯»ï¿?IP ä¿¡æ<C2A1>¯ï¼ˆå…± 20 字节ï¿?*/
for (i = 0; i < 20; i++) {
p_buf[i] = ch395f_read_data();
}
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:获ï¿?PHY 连接状�? * è¿”åžå€¼ï¼šPHY 状æ€<C3A6>ç <C3A7>(CH395F_PHY_DISCONNã€<C3A3>CH395F_PHY_10M_FULL 等)uint8_t
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šèŠ¯ç‰‡å·²åˆ<C3A5>å§ï¿? */
uint8_t ch395f_get_phy_status(void) {
uint8_t status;
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>é€<C3A9>读ï¿?PHY 状æ€<C3A6>å½ï¿?*/
ch395f_write_cmd(CH395F_CMD_GET_PHY_STATUS);
/* 读å<C2BB> PHY 状�?*/
status = ch395f_read_data();
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
return status;
}
/*
* 函数功能:设ï¿?PHY 连接模å¼<C3A5>
* å…¥å<C2A5>£å<C2A3>数:phystat - 连接模å¼<C3A5>ï¿? uint8_t 0x20 = 自动å<C2A8><C3A5>商
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šèŠ¯ç‰‡å·²åˆ<C3A5>å§ï¿? */
void ch395f_set_phy(uint8_t phystat) {
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>é€<C3A9>设ï¿?PHY 命令 */
ch395f_write_cmd(CH395F_CMD_SET_PHY);
/* å<>é€<C3A9>连接模å¼<C3A5>å<EFBFBD>ï¿?*/
ch395f_write_data(phystat);
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:使ï¿?关闭 CH395 å“<C3A5>应 PING
* å…¥å<C2A5>£å<C2A3>数:enable - 1 使能 PING å“<C3A5>应ï¿? 关闭
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šèŠ¯ç‰‡å·²åˆ<C3A5>å§ï¿? * 函数说明:手ï¿?5.37 CMD_PING_ENABLE,默认关ï¿? */
void ch395f_ping_enable(uint8_t enable) {
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>�?PING 使能命令 */
ch395f_write_cmd(CH395F_CMD_PING_ENABLE);
/* å<>é€<C3A9>使能标ï¿?*/
ch395f_write_data(enable);
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:å<C5A1>¯ï¿?ç¦<C3A7>用 DHCP
* å…¥å<C2A5>£å<C2A3>数:enable - 1 å<>¯ç”¨ï¿? ç¦<C3A7>用 uint8_t
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šèŠ¯ç‰‡å·²åˆ<C3A5>å§ï¿? */
void ch395f_set_dhcp(uint8_t enable) {
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>�?DHCP 使能命令 */
ch395f_write_cmd(CH395F_CMD_DHCP_ENABLE);
/* å<>é€<C3A9>å<EFBFBD>¯ï¿?ç¦<C3A7>用å<C2A8>æ•° */
ch395f_write_data(enable);
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:获ï¿?DHCP 状�? * è¿”åžå€¼ï¼š0 = æˆ<C3A6>功,é<C592>žï¿?= 错误/è¶…æ—¶ uint8_t
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šèŠ¯ç‰‡å·²åˆ<C3A5>å§åŒä¸” DHCP å·²å<C2B2>¯ï¿? */
uint8_t ch395f_get_dhcp_status(void) {
uint8_t status;
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>é€<C3A9>读ï¿?DHCP 状æ€<C3A6>å½ï¿?*/
ch395f_write_cmd(CH395F_CMD_GET_DHCP_STATUS);
/* 读å<C2BB> DHCP 状�?*/
status = ch395f_read_data();
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
return status;
}
/*
* 函数功能:设ï¿?Socket å<><C3A5>议类åž
* å…¥å<C2A5>£å<C2A3>数:sock - Socket 索引 uint8_t 0 - 3
* proto - å<><C3A5>è®®ç±»åž uint8_t CH395F_PROTO_TYPE_xxx
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šSocket 未打开
*/
void ch395f_set_proto_type(uint8_t sock, uint8_t proto) {
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>é€<C3A9>设置å<C2AE><C3A5>议类åžå½ï¿?*/
ch395f_write_cmd(CH395F_CMD_SET_PROTO_TYPE_SN);
/* å<>�?Socket 索引 */
ch395f_write_data(sock);
/* å<>é€<C3A9>å<EFBFBD><C3A5>议类ï¿?*/
ch395f_write_data(proto);
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:设ï¿?Socket 目标 IP 地å<C2B0>
* å…¥å<C2A5>£å<C2A3>数:sock - Socket 索引 uint8_t 0 - 3
* p_ip - 4 字节目标 IP 指针 uint8_t*
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šæŒ‡éˆé<CB86>žï¿? */
void ch395f_set_des_ip(uint8_t sock, uint8_t *p_ip) {
uint8_t i;
/* 检查输入å<C2A5>æ•°å<C2B0>ˆæ³•�?*/
if (p_ip == NULL) {
return;
}
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>é€<C3A9>设置ç®ï¿?IP 命令 */
ch395f_write_cmd(CH395F_CMD_SET_IP_ADDR_SN);
/* å<>�?Socket 索引 */
ch395f_write_data(sock);
/* é€<C3A9>å­—èŠå<E2809A>é€<C3A9>ç®ï¿?IP */
for (i = 0; i < 4; i++) {
ch395f_write_data(p_ip[i]);
}
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:设ï¿?Socket ç®æ ‡ç«¯å<C2AF>£ï¼ˆå°<C3A5>端åº<C3A5>ï¿? * å…¥å<C2A5>£å<C2A3>数:sock - Socket 索引 uint8_t 0 - 3
* port - ç®æ ‡ç«¯å<C2AF>£ uint16_t
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šæ— 
*/
void ch395f_set_des_port(uint8_t sock, uint16_t port) {
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>é€<C3A9>è®¾ç½®ç®æ ‡ç«¯å<C2AF>£å½ï¿?*/
ch395f_write_cmd(CH395F_CMD_SET_DES_PORT_SN);
/* å<>�?Socket 索引 */
ch395f_write_data(sock);
/* å<>é€<C3A9>端å<C2AF>£ä½Žå­—èŠ */
ch395f_write_data(port & 0xFFU);
/* å<>é€<C3A9>端å<C2AF>£é«˜å­—èŠ */
ch395f_write_data((port >> 8) & 0xFFU);
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:设ï¿?Socket æº<C3A6>端å<C2AF>£ï¼ˆå°<C3A5>端åº<C3A5>)
* å…¥å<C2A5>£å<C2A3>数:sock - Socket 索引 uint8_t 0 - 3
* port - æº<C3A6>端ï¿? uint16_t
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šæ— 
*/
void ch395f_set_sour_port(uint8_t sock, uint16_t port) {
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>é€<C3A9>设置æº<C3A6>端å<C2AF>£å½ä»¤ */
ch395f_write_cmd(CH395F_CMD_SET_SOUR_PORT_SN);
/* å<>�?Socket 索引 */
ch395f_write_data(sock);
/* å<>é€<C3A9>端å<C2AF>£ä½Žå­—èŠ */
ch395f_write_data(port & 0xFFU);
/* å<>é€<C3A9>端å<C2AF>£é«˜å­—èŠ */
ch395f_write_data((port >> 8) & 0xFFU);
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
}
/*
* 函数功能:打开 Socket
* å…¥å<C2A5>£å<C2A3>数:sock - Socket 索引 uint8_t 0 - 7
* è¿”åžå€¼ï¼šå½ä»¤æ‰§è¡Œçжæ€<C3A6>ç <C3A7>(CH395F_ERR_SUCCESS 表示æˆ<C3A6>功ï¿? uint8_t
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šå<C5A1><C3A5>议类åžã€<C3A3>ç®ï¿?IPã€<C3A3>端å<C2AF>£å·²è®¾ç½®
*/
uint8_t ch395f_open_socket(uint8_t sock) {
ch395f_spi_begin();
ch395f_write_cmd(CH395F_CMD_OPEN_SOCKET_SN);
ch395f_write_data(sock);
ch395f_spi_end();
return ch395f_poll_cmd_status(4000U);
}
/*
* 函数功能:关�Socket
* å…¥å<C2A5>£å<C2A3>数:sock - Socket 索引 uint8_t 0 - 7
* è¿”åžå€¼ï¼šå½ä»¤æ‰§è¡Œçжæ€<C3A6>ç <C3A7>(CH395F_ERR_SUCCESS 表示æˆ<C3A6>功ï¿? uint8_t
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šSocket 已打开
*/
uint8_t ch395f_close_socket(uint8_t sock) {
ch395f_spi_begin();
ch395f_write_cmd(CH395F_CMD_CLOSE_SOCKET_SN);
ch395f_write_data(sock);
ch395f_spi_end();
return ch395f_poll_cmd_status(4000U);
}
/*
* 函数功能:å<C5A1>¯ï¿?TCP çå<E28098>¬æ¨¡å¼<C3A5>
* å…¥å<C2A5>£å<C2A3>数:sock - Socket 索引 uint8_t 0 - 7
* è¿”åžå€¼ï¼šå½ä»¤æ‰§è¡Œçжæ€<C3A6>ç <C3A7>(CH395F_ERR_SUCCESS 表示æˆ<C3A6>功ï¿? uint8_t
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šSocket 已打开且å<E2809D><C3A5>议类åžä¸º TCP
*/
uint8_t ch395f_tcp_listen(uint8_t sock) {
ch395f_spi_begin();
ch395f_write_cmd(CH395F_CMD_TCP_LISTEN_SN);
ch395f_write_data(sock);
ch395f_spi_end();
return ch395f_poll_cmd_status(4000U);
}
/*
* 函数功能:å<C5A1>¯ï¿?TCP 连接
* å…¥å<C2A5>£å<C2A3>数:sock - Socket 索引 uint8_t 0 - 7
* è¿”åžå€¼ï¼šå½ä»¤æ‰§è¡Œçжæ€<C3A6>ç <C3A7>(CH395F_ERR_SUCCESS 表示æˆ<C3A6>功ï¿? uint8_t
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šSocket 已打开且å<E2809D><C3A5>议类åžä¸º TCP
*/
uint8_t ch395f_tcp_connect(uint8_t sock) {
ch395f_spi_begin();
ch395f_write_cmd(CH395F_CMD_TCP_CONNECT_SN);
ch395f_write_data(sock);
ch395f_spi_end();
return ch395f_poll_cmd_status(4000U);
}
/*
* 函数功能:断开 TCP 连接
* å…¥å<C2A5>£å<C2A3>数:sock - Socket 索引 uint8_t 0 - 7
* è¿”åžå€¼ï¼šå½ä»¤æ‰§è¡Œçжæ€<C3A6>ç <C3A7>(CH395F_ERR_SUCCESS 表示æˆ<C3A6>功ï¿? uint8_t
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šTCP 已建立连ï¿? */
uint8_t ch395f_tcp_disconnect(uint8_t sock) {
ch395f_spi_begin();
ch395f_write_cmd(CH395F_CMD_TCP_DISCONNECT_SN);
ch395f_write_data(sock);
ch395f_spi_end();
return ch395f_poll_cmd_status(4000U);
}
/*
* 函数功能:å<C5A1> Socket å<>é€<C3A9>缓冲区写入数æ<C2B0>®ï¼ˆDMA 批é‡<C3A9>传输ï¿? * å…¥å<C2A5>£å<C2A3>数:sock - Socket 索引 uint8_t 0 - 3
* p_data - æ•°æ<C2B0>®æŒ‡éˆ uint8_t*
* len - æ•°æ<C2B0>®é•¿åº¦ uint16_t
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šæŒ‡éˆé<CB86>žç©ºï¼Œé•¿åº¦å¤§äºŽ 0,TCP 已连接或 UDP 已打开
* 函数说明:将å½ä»¤å¤´åŒæ•°æ<C2B0>®æ‰“包ï¿?DMA 缓冲区,一ï¿?SPI DMA 传输完æˆ<C3A6>
*/
void ch395f_write_send_buf(uint8_t sock, uint8_t *p_data, uint16_t len) {
uint16_t total;
/* 检查输入å<C2A5>æ•°å<C2B0>ˆæ³•�?*/
if (p_data == NULL) {
return;
}
/* 计算总长度:1(cmd) + 1(sock) + 2(len) + data */
total = 4U + len;
if (total > CH395F_DMA_BUF_SIZE) {
return;
}
/* 打包命令头到 DMA å<>é€<C3A9>缓冲区 */
s_spi2_dma_tx_buf[0] = CH395F_CMD_WRITE_SEND_BUF_SN;
s_spi2_dma_tx_buf[1] = sock;
s_spi2_dma_tx_buf[2] = len & 0xFFU;
s_spi2_dma_tx_buf[3] = (len >> 8) & 0xFFU;
/* æ·è´<C3A8>用户数æ<C2B0>®ï¿?DMA å<>é€<C3A9>缓冲区 */
memcpy(&s_spi2_dma_tx_buf[4], p_data, len);
/* æ•°æ<C2B0>®å<C2AE>Œæ­¥å±<C3A5>障:确ï¿?memcpy 写入ï¿?DMA 读å<C2BB>å‰<C3A5>对总线å<C2BF>¯è§<C3A8> */
__DSB();
/* CS 拉低 -> DMA 批é‡<C3A9>传输 -> CS 拉高 */
ch395f_spi_begin();
ch395f_spi_dma_transfer(total);
ch395f_spi_end();
}
/*
* 函数功能:从 Socket 接收缓冲区读å<C2BB>æ•°æ<C2B0>®ï¼ˆDMA 批é‡<C3A9>传输ï¿? * å…¥å<C2A5>£å<C2A3>数:sock - Socket 索引 uint8_t 0 - 3
* p_data - 输出缓冲区指� uint8_t*
* len - 待读å<C2BB>æ•°æ<C2B0>®é•¿ï¿? uint16_t
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šæŒ‡éˆé<CB86>žç©ºï¼Œé•¿åº¦å¤§äºŽ 0,接收缓冲区有数ï¿? * 函数说明:å½ä»¤å¤´æ‰“包到å<C2B0>é€<C3A9>缓冲区(数æ<C2B0>®éƒ¨åˆ†å¡« 0xFF 作时钟)ï¿? * 一ï¿?SPI DMA å…¨å<C2A8>Œå·¥ä¼ è¾“,有效数æ<C2B0>®ä»ŽæŽ¥æ”¶ç¼“冲区å<C2BA><C3A5>ç§» 4 字节处拷ï¿? */
void ch395f_read_recv_buf(uint8_t sock, uint8_t *p_data, uint16_t len) {
uint16_t total;
/* 检查输入å<C2A5>æ•°å<C2B0>ˆæ³•�?*/
if (p_data == NULL) {
return;
}
/* 计算总长度:1(cmd) + 1(sock) + 2(len) + data */
total = 4U + len;
if (total > CH395F_DMA_BUF_SIZE) {
return;
}
/* 命令头打包到 DMA å<>é€<C3A9>缓冲区 */
s_spi2_dma_tx_buf[0] = CH395F_CMD_READ_RECV_BUF_SN;
s_spi2_dma_tx_buf[1] = sock;
s_spi2_dma_tx_buf[2] = len & 0xFFU;
s_spi2_dma_tx_buf[3] = (len >> 8) & 0xFFU;
/* æ•°æ<C2B0>®éƒ¨åˆ†å¡«å…… 0xFF(SPI 时钟驱动用) */
memset(&s_spi2_dma_tx_buf[4], 0xFFU, len);
/* CS 拉低 -> DMA å…¨å<C2A8>Œå·¥ä¼ è¾“(å<CB86>å½ä»¤å¤´ + æ”¶æ•°æ<C2B0>®ï¼‰ -> CS 拉高 */
ch395f_spi_begin();
ch395f_spi_dma_transfer(total);
ch395f_spi_end();
/* ï¿?DMA 接收缓冲区å<C2BA><C3A5>ï¿?4 å­—èŠå¤„æ·è´<C3A8>有效数æ<C2B0>®åˆ°ç”¨æˆ·ç¼“冲ï¿?*/
memcpy(p_data, &s_spi2_dma_rx_buf[4], len);
}
/*
* 函数功能:获ï¿?Socket 接收缓冲区数æ<C2B0>®é•¿ï¿? * å…¥å<C2A5>£å<C2A3>数:sock - Socket 索引 uint8_t 0 - 3
* è¿”åžå€¼ï¼šæŽ¥æ”¶æ•°æ<C2B0>®é•¿åº¦ uint16_t
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šSocket 已打开
*/
uint16_t ch395f_get_recv_len(uint8_t sock) {
uint16_t recv_len;
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>é€<C3A9>获å<C2B7>接收长度å½ï¿?*/
ch395f_write_cmd(CH395F_CMD_GET_RECV_LEN_SN);
/* å<>�?Socket 索引 */
ch395f_write_data(sock);
/* 读å<C2BB>长度低字ï¿?*/
recv_len = ch395f_read_data();
/* 读å<C2BB>长度高字èŠå¹¶ç»„å<E2809E>ˆ */
recv_len |= (uint16_t)ch395f_read_data() << 8;
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
return recv_len;
}
/*
* 函数功能:获å<C2B7>全局中æ­çŠ¶ï¿½? * è¿”åžå€¼ï¼šä¸­æ­çжæ€<C3A6>å­—ï¿? uint8_t
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šèŠ¯ç‰‡å·²åˆ<C3A5>å§ï¿? */
uint8_t ch395f_get_glob_int_status(void) {
uint8_t status;
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>é€<C3A9>读å<C2BB>全局中æ­çжæ€<C3A6>å½ï¿?*/
ch395f_write_cmd(CH395F_CMD_GET_GLOB_INT_STATUS);
/* 读å<C2BB>中æ­çŠ¶ï¿½?*/
status = ch395f_read_data();
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
return status;
}
/*
* 函数功能:获å<C2B7>全局中æ­çжæ€<C3A6>(2 å­—èŠç‰ˆï¼Œæ”¯æŒ<C3A6> Socket 0~7ï¿? * 返回值:中断状�?uint16_t(低字èŠ=Socket 0~3 + PHY/DHCP,高字èŠ=Socket 4~7 + DHCPv6ï¿? * é™<C3A9>定æ<C5A1>¡ä»¶ï¼šèŠ¯ç‰‡å·²åˆ<C3A5>å§ï¿? */
uint16_t ch395f_get_glob_int_status_all(void) {
uint16_t status;
ch395f_spi_begin();
ch395f_write_cmd(CH395F_CMD_GET_GLOB_INT_STATUS_ALL);
status = (uint16_t)ch395f_read_data();
status |= ((uint16_t)ch395f_read_data() << 8U);
ch395f_spi_end();
return status;
}
/*
* 函数功能:获ï¿?Socket 中断状�? * å…¥å<C2A5>£å<C2A3>数:sock - Socket 索引 uint8_t 0 - 7
* è¿”åžå€¼ï¼šSocket 中æ­çжæ€<C3A6>å­—ï¿? uint8_t
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šèŠ¯ç‰‡å·²åˆ<C3A5>å§ï¿? */
uint8_t ch395f_get_sock_int_status(uint8_t sock) {
uint8_t status;
/* 开�SPI 事务 */
ch395f_spi_begin();
/* å<>é€<C3A9>读ï¿?Socket 中æ­çжæ€<C3A6>å½ï¿?*/
ch395f_write_cmd(CH395F_CMD_GET_INT_STATUS_SN);
/* å<>�?Socket 索引 */
ch395f_write_data(sock);
/* 读å<C2BB>中æ­çŠ¶ï¿½?*/
status = ch395f_read_data();
/* 结æ<E2809C>Ÿ SPI 事务 */
ch395f_spi_end();
return status;
}
/*
* 函数功能:获ï¿?Socket 状æ€<C3A6>(2 字节输出ï¿? * å…¥å<C2A5>£å<C2A3>数:sock - Socket 索引 uint8_t 0 - 7
* status - 2 字节输出缓冲ï¿?[0]=Socket状�? [1]=TCP状�? * é™<C3A9>定æ<C5A1>¡ä»¶ï¼šèŠ¯ç‰‡å·²åˆ<C3A5>å§ï¿? */
void ch395f_get_socket_status(uint8_t sock, uint8_t *p_status) {
ch395f_spi_begin();
ch395f_write_cmd(CH395F_CMD_GET_SOCKET_STATUS_SN);
ch395f_write_data(sock);
p_status[0] = ch395f_read_data();
p_status[1] = ch395f_read_data();
ch395f_spi_end();
}
/*
* 函数功能:设ï¿?ARP é‡<C3A9>ä¼ å<C2A0>æ•°
* å…¥å<C2A5>£å<C2A3>数:period_100ms - ARP é‡<C3A9>传卿œŸï¼ˆå<CB86>•ï¿?100msï¿?=默认ï¿?10ï¿?秒) uint8_t
* cnt - ARP é‡<C3A9>传次数ï¿?=默认ï¿?3ï¿? uint8_t
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šåº”ï¿?ch395f_init() ä¹å<E280B9>Žè°ƒç”¨
* 函数说明:周期最大值约 25.5 ç§ï¼Œ255 表示无é™<C3A9>é‡<C3A9>ä¼ 
*/
void ch395f_set_arp(uint8_t period_100ms, uint8_t cnt) {
ch395f_spi_begin();
ch395f_write_cmd(CH395F_CMD_SET_ARP);
ch395f_write_data(period_100ms);
ch395f_write_data(cnt);
ch395f_spi_end();
}
/*
* 函数功能:设�Socket TTL
* å…¥å<C2A5>£å<C2A3>数:sock - Socket 索引 uint8_t 0 - 7
* ttl - TTL � uint8_t 最�128
* é™<C3A9>定æ<C5A1>¡ä»¶ï¼šSocket 已打开,TCP Server 模å¼<C3A5>ä¸ä¸<C3A4>生效
*/
void ch395f_set_ttl(uint8_t sock, uint8_t ttl) {
ch395f_spi_begin();
ch395f_write_cmd(CH395F_CMD_SET_TTL);
ch395f_write_data(sock);
ch395f_write_data(ttl);
ch395f_spi_end();
}
/*
* 函数功能:获å<C2B7>ä¸<C3A4>å<EFBFBD>¯è¾¾ä¿¡æ<C2A1>¯ï¼ˆç”¨äºŽè°ƒè¯•连接失败原å ï¼‰
* 出å<C2BA>£å<C2A3>数:p_buf - 8 字节输出缓冲区(类型+å<><C3A5>è®®ï¿?端å<C2AF>£+IPï¿? * é™<C3A9>定æ<C5A1>¡ä»¶ï¼šæ”¶ï¿?GINT_STAT_UNREACH 中æ­å<C2AD>Žè°ƒï¿? */
void ch395f_get_unreach_info(uint8_t *p_buf) {
uint8_t i = 0;
ch395f_spi_begin();
ch395f_write_cmd(CH395F_CMD_GET_UNREACH_IPPT);
for (i = 0; i < 8; i++) {
p_buf[i] = ch395f_read_data();
}
ch395f_spi_end();
}