CH395Q驱动代码---全

多的不说,直接上代码,干就完了!!!!

CH395Q.c

#include "ch395q.h"
#include "delay.h"
#include <string.h>
#include "usart.h" 

uint8_t tcp_connect = 0;
uint8_t status[2];
	
uint8_t  socket_buff[8][1024];                                           /* 数据缓冲区 */


/********************************** (C) COPYRIGHT  *******************************
* File Name          : CH395_interface_operation.c
* Author             : WCH
* Version            : V1.0.0
* Date               : 2020/10/12
* Description        : CH395各接口实现函数
*******************************************************************************/ 
uint8_t ITDATA[2];
/*******************************************************************************
* Function Name  : ch395_cmd_reset
* Description    : 软复位
* Input          : None
* Return         : None
*******************************************************************************/
void ch395_cmd_reset(void)
{
    ch395_write_cmd(CMD00_RESET_ALL);
    ch395_scs_hign;
}

/*******************************************************************************
* Function Name  : ch395_cmd_hard_reset
* Description    : 软复位
* Input          : None
* Return         : None
*******************************************************************************/
void ch395_cmd_hard_reset(void)
{
    GPIO_ResetBits(GPIOA,GPIO_Pin_1);
	delay_ms(100);
	GPIO_SetBits(GPIOA,GPIO_Pin_1);
}
/*******************************************************************************
* Function Name  : ch395_cmd_sleep
* Description    : 进入睡眠模式
* Input          : None
* Return         : None
*******************************************************************************/
void ch395_cmd_sleep(void)
{
    ch395_write_cmd(CMD00_ENTER_SLEEP);
    ch395_scs_hign;
}

uint8_t ch395_cmd_get_ver(void)
{
    uint8_t i;
	
    ch395_write_cmd(CMD01_GET_IC_VER);
    i = ch395_read_data();
    ch395_scs_hign;
    return i;
}

uint8_t ch395_cmd_check_exist(uint8_t testdata)
{
    uint8_t i;

    ch395_write_cmd(CMD11_CHECK_EXIST);
    ch395_write_data(testdata);
	
	delay_us(10);
    i = ch395_read_data();
//	printf("ch395_cmd_check_exist=%02x\r\n",i);
	delay_us(1);
    ch395_scs_hign;
    return i;
}


/*******************************************************************************
* Function Name  : ch395_cmd_set_phy
* Description    : 设置phy,主要设置CH395 phy为100/10m 或者全双工半双工,CH395默为自动协商。
* Input          : None
* Return         : None
*******************************************************************************/ 
void ch395_cmd_set_phy(uint8_t phystat)
{
    ch395_write_cmd(CMD10_SET_PHY);
    ch395_write_data(phystat);
    ch395_scs_hign;
}

/*******************************************************************************
* Function Name  : ch395_cmd_get_phy_status
* Description    : 获取phy的状态
* Input          : None
* Return         : 当前ch395phy状态,参考phy参数/状态定义
*******************************************************************************/ 
uint8_t ch395_cmd_get_phy_status(void)
{
    uint8_t i;

    ch395_write_cmd(CMD01_GET_PHY_STATUS);
    i = ch395_read_data();
    ch395_scs_hign;
//	printf("phy_status:%04x\n",i);
    return i;
}

/*******************************************************************************
* Function Name  : ch395_cmd_get_glob_int_status
* Description    : 获取全局中断状态,收到此命令CH395自动取消中断,0x43及以下版本使用
* Input          : None
* Return         : 返回当前的全局中断状态
*******************************************************************************/ 
uint8_t ch395_cmd_get_glob_int_status(void)
{
    uint8_t init_status;

    ch395_write_cmd(CMD01_GET_GLOB_INT_STATUS);
    init_status = ch395_read_data();
    ch395_scs_hign;
    return  init_status;
}


/*******************************************************************************
* Function Name  : ch395_cmd_init
* Description    : 初始化CH395芯片
* Input          : None
* Return         : 返回执行结果
*******************************************************************************/ 
uint8_t ch395_cmd_init(void)
{
    uint8_t i = 0;
    uint8_t s = 0;

    ch395_write_cmd(CMD0W_INIT_CH395);
    ch395_scs_hign;
	
    while (1)
    {
        delay_ms(10);                          /* 延时查询,建议2MS以上 */
        s = ch395_get_cmd_status();            /* 不能过于频繁查询 */

        if (s != CH395_ERR_BUSY)
        {
            break;         /* 如果CH395芯片返回忙状态 */
        }

        if (i++ > 200)
        {
            return CH395_ERR_UNKNOW; /* 超时退出,本函数需要500MS以上执行完毕 */
        }
    }

    return s;
}


/*******************************************************************************
* Function Name  : ch395_cmd_set_uart_baud_rate
* Description    : 设置CH395串口波特率,仅在串口模式下有效
* Input          : baudrate
* Return         : None
*******************************************************************************/ 
#ifdef USE_USART2_CTRL_CH395
void ch395_cmd_set_uart_baud_rate(uint32_t baudrate)
{
    ch395_write_cmd(CMD31_SET_BAUDRATE);
    ch395_write_data((uint8_t)baudrate);
    ch395_write_data((uint8_t)((uint16_t)baudrate >> 8));
    ch395_write_data((uint8_t)(baudrate >> 16));
	delay_ms(1);
	set_usart2_bandrate(UART_WORK_BAUDRATE);
	
    uint8_t i = ch395_read_data();
	printf("baudrate_i:%02x\n",i);
    ch395_scs_hign;
}
#endif

/*******************************************************************************
* Function Name  : ch395_get_cmd_status
* Description    : 获取命令执行状态,某些命令需要等待命令执行结果
* Input          : None
* Return         : 返回上一条命令执行状态
*******************************************************************************/ 
uint8_t ch395_get_cmd_status(void)
{
    uint8_t i;

    ch395_write_cmd(CMD01_GET_CMD_STATUS);
    i = ch395_read_data();
//	printf("ch395_get_cmd_status:%06x\n",i);
    ch395_scs_hign;
    return i;
}


/*******************************************************************************
* Function Name  : ch395_get_cmd_status
* Description    : 设置CH395的ip地址
* Input          : ipaddr:ip地址
* Return         : None
*******************************************************************************/
void ch395_cmd_set_ipaddr(uint8_t *ipaddr)
{
    uint8_t i;

    ch395_write_cmd(CMD40_SET_IP_ADDR);

    for (i = 0; i < 4; i++)
    {
        ch395_write_data(*ipaddr++);
    }

    ch395_scs_hign;
}


/*******************************************************************************
* Function Name  : ch395_cmd_set_gw_ipaddr
* Description    : 设置CH395的网关ip地址
* Input          : gwipaddr
* Return         : None
*******************************************************************************/
void ch395_cmd_set_gw_ipaddr(uint8_t *gwipaddr)
{
    uint8_t i;

    ch395_write_cmd(CMD40_SET_GWIP_ADDR);

    for (i = 0; i < 4; i++)
    {
        ch395_write_data(*gwipaddr++);
    }

    ch395_scs_hign;
}


/*******************************************************************************
* Function Name  : ch395_cmd_set_maskaddr
* Description    : 设置CH395的子网掩码,默认为255.255.255.0
* Input          : maskaddr 指子网掩码地址
* Return         : None
*******************************************************************************/
void ch395_cmd_set_maskaddr(uint8_t *maskaddr)
{
    uint8_t i;

    ch395_write_cmd(CMD40_SET_MASK_ADDR);

    for (i = 0; i < 4; i++)
    {
        ch395_write_data(*maskaddr++);
    }

    ch395_scs_hign;
}

/*******************************************************************************
* Function Name  : ch395_cmd_set_macaddr
* Description    : 设置CH395的mac地址。
* Input          : mcaddr mac地址指针
* Return         : None
*******************************************************************************/
void ch395_cmd_set_macaddr(uint8_t *amcaddr)
{
    uint8_t i;

    ch395_write_cmd(CMD60_SET_MAC_ADDR);

    for (i = 0; i < 6; i++)
    {
        ch395_write_data(*amcaddr++);
    }

    ch395_scs_hign;
    delay_ms(100);
}


/*******************************************************************************
* Function Name  : ch395_cmd_get_macaddr
* Description    : 获取CH395的mac地址。
* Input          : amcaddr mac地址指针
* Return         : None
*******************************************************************************/
void ch395_cmd_get_macaddr(uint8_t *amcaddr)
{
    uint8_t i;

    ch395_write_cmd(CMD06_GET_MAC_ADDR);

    for (i = 0; i < 6; i++)
    {
        *amcaddr++ = ch395_read_data();
    }

    ch395_scs_hign;
}



/*******************************************************************************
* Function Name  : ch395_cmd_set_macfilt
* Description    : 设置mac过滤。
* Input          : filtype
				   table0 hash0
				   table1 hash1
* Return         : None
*******************************************************************************/
void ch395_cmd_set_macfilt(uint8_t filtype, uint32_t table0, uint32_t table1)
{
    ch395_write_cmd(CMD90_SET_MAC_FILT);
    ch395_write_data(filtype);
    ch395_write_data((uint8_t)table0);
    ch395_write_data((uint8_t)((uint16_t)table0 >> 8));
    ch395_write_data((uint8_t)(table0 >> 16));
    ch395_write_data((uint8_t)(table0 >> 24));

    ch395_write_data((uint8_t)table1);
    ch395_write_data((uint8_t)((uint16_t)table1 >> 8));
    ch395_write_data((uint8_t)(table1 >> 16));
    ch395_write_data((uint8_t)(table1 >> 24));
    ch395_scs_hign;
}

/*******************************************************************************
* Function Name  : ch395_cmd_get_unreachippt
* Description    : 保存获取到的不可达
* Input          : list
*	arg          : 第1个字节为不可达代码,请参考 不可达代码(ch395inc.h)
				   第2个字节为ip包协议类型
			       第3-4字节为端口号
				   第4-8字节为ip地址
* Return         : None
*******************************************************************************/
void ch395_cmd_get_unreachippt(uint8_t *list)
{
    uint8_t i;

    ch395_write_cmd(CMD08_GET_UNREACH_IPPORT);

    for (i = 0; i < 8; i++)
    {
        *list++ = ch395_read_data();
    }

    ch395_scs_hign;
}

/**
 * @brief       获取远端的ip和端口地址,一般在tcp server模式下使用
 * @param       sockindex socket索引
 * @param       list 保存ip和端口
 * @retval      无
 */

/*******************************************************************************
* Function Name  : ch395_cmd_get_remoteipp
* Description    : 获取远端的ip和端口地址,一般在tcp server模式下使用
* Input          : sockindex socket索引
                   list 保存ip和端口
* Return         : None
*******************************************************************************/
void ch395_cmd_get_remoteipp(uint8_t sockindex, uint8_t *list)
{
    uint8_t i;

    ch395_write_cmd(CMD06_GET_REMOT_IPP_SN);
    ch395_write_data(sockindex);

    for (i = 0; i < 6; i++)
    {
        *list++ = ch395_read_data();
    }

    ch395_scs_hign;
}



/*******************************************************************************
* Function Name  : ch395_set_socket_desip
* Description    : 设置socket n的目的ip地址
* Input          : sockindex socket索引
                   ipaddr 指向ip地址
* Return         : None
*******************************************************************************/
void ch395_set_socket_desip(uint8_t sockindex, uint8_t *ipaddr)
{
    ch395_write_cmd(CMD50_SET_IP_ADDR_SN);
    ch395_write_data(sockindex);
    ch395_write_data(*ipaddr++);
    ch395_write_data(*ipaddr++);
    ch395_write_data(*ipaddr++);
    ch395_write_data(*ipaddr++);
    ch395_scs_hign;
}



/*******************************************************************************
* Function Name  : ch395_set_socket_prot_type
* Description    : 设置socket 的协议类型
* Input          : sockindex socket索引
                   prottype
				   请参考 socket协议类型定义(ch395inc.h)
* Return         : None
*******************************************************************************/
void ch395_set_socket_prot_type(uint8_t sockindex, uint8_t prottype)
{
    ch395_write_cmd(CMD20_SET_PROTO_TYPE_SN);
    ch395_write_data(sockindex);
    ch395_write_data(prottype);
    ch395_scs_hign;
}


/*******************************************************************************
* Function Name  : ch395_set_socket_desport
* Description    : 设置socket n的协议类型
* Input          : sockindex socket索引
                   desprot 2字节目的端口
* Return         : None
*******************************************************************************/
void ch395_set_socket_desport(uint8_t sockindex, uint16_t desprot)
{
    ch395_write_cmd(CMD30_SET_DES_PORT_SN);
    ch395_write_data(sockindex);
    ch395_write_data((uint8_t)desprot);
    ch395_write_data((uint8_t)(desprot >> 8));
    ch395_scs_hign;
}


/*******************************************************************************
* Function Name  : ch395_set_socket_sourport
* Description    : 设置socket n的协议类型
* Input          : sockindex socket索引
                   desprot 2字节源端口
* Return         : None
*******************************************************************************/
void ch395_set_socket_sourport(uint8_t sockindex, uint16_t surprot)
{
    ch395_write_cmd(CMD30_SET_SOUR_PORT_SN);
    ch395_write_data(sockindex);
    ch395_write_data((uint8_t)surprot);
    ch395_write_data((uint8_t)(surprot >> 8));
    ch395_scs_hign;
}


/*******************************************************************************
* Function Name  : ch395_set_socket_ipraw_proto
* Description    : ip模式下,socket ip包协议字段
* Input          : sockindex socket索引
                   prototype ipraw模式1字节协议字段
* Return         : None
*******************************************************************************/
void ch395_set_socket_ipraw_proto(uint8_t sockindex, uint8_t prototype)
{
    ch395_write_cmd(CMD20_SET_IPRAW_PRO_SN);
    ch395_write_data(sockindex);
    ch395_write_data(prototype);
    ch395_scs_hign;
}


/*******************************************************************************
* Function Name  : ch395_enable_ping
* Description    : 开启/关闭 ping
* Input          : senable :0 / 1
				   1:  开启ping
				   0:  关闭ping
* Return         : None
*******************************************************************************/
void ch395_enable_ping(uint8_t enable)
{
    ch395_write_cmd(CMD01_PING_ENABLE);
    ch395_write_data(enable);
    ch395_scs_hign;
}


/*******************************************************************************
* Function Name  : ch395_send_data
* Description    : 向发送缓冲区写数据
* Input          : sockindex socket索引
                   databuf  数据缓冲区
				   len   长度
* Return         : None
*******************************************************************************/
void ch395_send_data(uint8_t sockindex, uint8_t *databuf, uint16_t len)
{
    uint16_t i;
	
    ch395_write_cmd(CMD30_WRITE_SEND_BUF_SN);
    ch395_write_data((uint8_t)sockindex);
    ch395_write_data((uint8_t)len);
    ch395_write_data((uint8_t)(len >> 8));

    for (i = 0; i < len; i++)
    {
		#ifdef USE_SPI1_CTRL_CH395
		spi_data_write(*databuf++);
		#else
		ch395_write_data(*databuf++);
		#endif
    }
		delay_us(5);
    ch395_scs_hign;
}


/*******************************************************************************
* Function Name  : ch395_get_recv_length
* Description    : 获取接收缓冲区长度
* Input          : sockindex socket索引
* Return         : 返回接收缓冲区有效长度
*******************************************************************************/
uint16_t ch395_get_recv_length(uint8_t sockindex)
{
    uint16_t i;

    ch395_write_cmd(CMD12_GET_RECV_LEN_SN);
    ch395_write_data((uint8_t)sockindex);
    i = ch395_read_data();
    i = (uint16_t)(ch395_read_data() << 8) + i;
    ch395_scs_hign;
    return i;
}



/*******************************************************************************
* Function Name  : ch395_clear_recv_buf
* Description    : 清除接收缓冲区
* Input          : sockindex socket索引
* Return         : 无
*******************************************************************************/
void ch395_clear_recv_buf(uint8_t sockindex)
{
    ch395_write_cmd(CMD10_CLEAR_RECV_BUF_SN);
    ch395_write_data((uint8_t)sockindex);
    ch395_scs_hign;
}


/*******************************************************************************
* Function Name  : ch395_get_recv_data
* Description    : 读取接收缓冲区数据
* Input          : sockindex socket索引
				   len  长度
                   pbuf  缓冲区
* Return         : 无
*******************************************************************************/
void ch395_get_recv_data(uint8_t sockindex, uint16_t len, uint8_t *pbuf)
{
    uint16_t i;

    if (!len)return;

    ch395_write_cmd(CMD30_READ_RECV_BUF_SN);
    ch395_write_data(sockindex);
    ch395_write_data((uint8_t)len);
    ch395_write_data((uint8_t)(len >> 8));

    for (i = 0; i < len; i++)
    {
        *pbuf = ch395_read_data();
        pbuf++;
    }

    ch395_scs_hign;
}



/*******************************************************************************
* Function Name  : ch395_cmd_set_retry_count
* Description    : 设置重试次数
* Input          : count 重试值,最大为20次
* Return         : 无
*******************************************************************************/
void ch395_cmd_set_retry_count(uint8_t count)
{
    ch395_write_cmd(CMD10_SET_RETRAN_COUNT);
    ch395_write_data(count);
    ch395_scs_hign;
}


/*******************************************************************************
* Function Name  : ch395_cmd_set_retry_period
* Description    : 设置重试周期
* Input          : period 重试周期单位为毫秒,最大1000ms
* Return         : 无
*******************************************************************************/
void ch395_cmd_set_retry_period(uint16_t period)
{
    ch395_write_cmd(CMD10_SET_RETRAN_COUNT);
    ch395_write_data((uint8_t)period);
    ch395_write_data((uint8_t)(period >> 8));
    ch395_scs_hign;
}


/*******************************************************************************
* Function Name  : ch395_cmd_get_socket_status
* Description    : 获取socket
* Input          : sockindex socket索引
* Return         : socket n的状态信息,第1字节为socket 打开或者关闭,第2字节为tcp状态
*******************************************************************************/
void ch395_cmd_get_socket_status(uint8_t sockindex, uint8_t *status)
{
    ch395_write_cmd(CMD12_GET_SOCKET_STATUS_SN);
    ch395_write_data(sockindex);
    *status++ = ch395_read_data();
    *status++ = ch395_read_data();
    ch395_scs_hign;
}


/*******************************************************************************
* Function Name  : ch395_open_socket
* Description    : 打开socket,此命令需要等待执行成功
* Input          : sockindex socket索引
* Return         : 返回执行结果
*******************************************************************************/
uint8_t  ch395_open_socket(uint8_t sockindex)
{
    uint8_t i = 0;
    uint8_t s = 0;
    ch395_write_cmd(CMD1W_OPEN_SOCKET_SN);
    ch395_write_data(sockindex);
    ch395_scs_hign;

    while (1)
    {
        delay_ms(5);                          /* 延时查询,建议2MS以上 */
        s = ch395_get_cmd_status();           /* 不能过于频繁查询 */

        if (s != CH395_ERR_BUSY)
        {
            break;        /* 如果CH395芯片返回忙状态 */
        }

        if (i++ > 200)
        {
            return CH395_ERR_UNKNOW; /* 超时退出 */
        }
    }

    return s;
}



/*******************************************************************************
* Function Name  : ch395_close_socket
* Description    : 关闭socket,
* Input          : sockindex socket索引
* Return         : 返回执行结果
*******************************************************************************/
uint8_t  ch395_close_socket(uint8_t sockindex)
{
    uint8_t i = 0;
    uint8_t s = 0;
    ch395_write_cmd(CMD1W_CLOSE_SOCKET_SN);
    ch395_write_data(sockindex);
    ch395_scs_hign;

    while (1)
    {
        delay_ms(5);                            /* 延时查询,建议2MS以上 */
        s = ch395_get_cmd_status();             /* 不能过于频繁查询 */

        if (s != CH395_ERR_BUSY)
        {
            break;          /* 如果CH395芯片返回忙状态 */
        }

        if (i++ > 200)
        {
            return CH395_ERR_UNKNOW;  /* 超时退出 */
        }
    }

    return s;
}

/*******************************************************************************
* Function Name  : ch395_tcp_connect
* Description    : tcp连接,仅在tcp模式下有效,此命令需要等待执行成功
* Input          : sockindex socket索引
* Return         : 返回执行结果
*******************************************************************************/
uint8_t ch395_tcp_connect(uint8_t sockindex)
{
    uint8_t i = 0;
    uint8_t s = 0;
    ch395_write_cmd(CMD1W_TCP_CONNECT_SN);
    ch395_write_data(sockindex);
    ch395_scs_hign;

    while (1)
    {
        delay_ms(5);                            /* 延时查询,建议2MS以上 */
        s = ch395_get_cmd_status();             /* 不能过于频繁查询 */

        if (s != CH395_ERR_BUSY)
        {
            break;          /* 如果CH395芯片返回忙状态 */
        }

        if (i++ > 200)
        {
            return CH395_ERR_UNKNOW;  /* 超时退出 */
        }
    }

    return s;
}


/*******************************************************************************
* Function Name  : ch395_tcp_listen
* Description    : tcp监听,仅在tcp模式下有效,此命令需要等待执行成功
* Input          : sockindex socket索引
* Return         : 返回执行结果
*******************************************************************************/
uint8_t ch395_tcp_listen(uint8_t sockindex)
{
    uint8_t i = 0;
    uint8_t s = 0;
    ch395_write_cmd(CMD1W_TCP_LISTEN_SN);
    ch395_write_data(sockindex);
    ch395_scs_hign;

    while (1)
    {
        delay_ms(5);                           /* 延时查询,建议2MS以上 */
        s = ch395_get_cmd_status();            /* 不能过于频繁查询 */

        if (s != CH395_ERR_BUSY)
        {
            break;         /* 如果CH395芯片返回忙状态 */
        }

        if (i++ > 200)
        {
            return CH395_ERR_UNKNOW; /* 超时退出 */
        }
    }

    return s;
}


/*******************************************************************************
* Function Name  : ch395_tcp_disconnect
* Description    : tcp断开,仅在tcp模式下有效,此命令需要等待执行成功
* Input          : sockindex socket索引
* Return         : 返回执行结果
*******************************************************************************/
uint8_t ch395_tcp_disconnect(uint8_t sockindex)
{
    uint8_t i = 0;
    uint8_t s = 0;
    ch395_write_cmd(CMD1W_TCP_DISNCONNECT_SN);
    ch395_write_data(sockindex);
    ch395_scs_hign;

    while (1)
    {
        delay_ms(5);                           /* 延时查询,建议2MS以上 */
        s = ch395_get_cmd_status();               /* 不能过于频繁查询 */

        if (s != CH395_ERR_BUSY)
        {
            break;         /* 如果CH395芯片返回忙状态 */
        }

        if (i++ > 200)
        {
            return CH395_ERR_UNKNOW; /* 超时退出 */
        }
    }

    return s;
}

/*******************************************************************************
* Function Name  : ch395_get_socket_int
* Description    : 获取socket n的中断状态
* Input          : sockindex socket索引
* Return         : 中断状态
*******************************************************************************/
uint8_t ch395_get_socket_int(uint8_t sockindex)
{
    uint8_t intstatus;
    ch395_write_cmd(CMD11_GET_INT_STATUS_SN);
    ch395_write_data(sockindex);
	
//	delay_us(2);
	
    intstatus = ch395_read_data();
    ch395_scs_hign;
    return intstatus;
}

/*******************************************************************************
* Function Name  : ch395_crcret_6bit
* Description    : 对多播地址进行crc运算,并取高6位。
* Input          : mac_addr   mac地址
* Return         : 返回crc32的高6位
*******************************************************************************/
uint8_t ch395_crcret_6bit(uint8_t *mac_addr)
{
    signed long perbyte;
    signed long perbit;
    const uint32_t poly = 0x04c11db7;
    uint32_t crc_value = 0xffffffff;
    uint8_t c;

    for ( perbyte = 0; perbyte < 6; perbyte ++ )
    {
        c = *(mac_addr++);

        for ( perbit = 0; perbit < 8; perbit++ )
        {
            crc_value = (crc_value << 1) ^ ((((crc_value >> 31)^c) & 0x01) ? poly : 0);
            c >>= 1;
        }
    }

    crc_value = crc_value >> 26;
    return ((uint8_t)crc_value);
}


/*******************************************************************************
* Function Name  : ch395_dhcp_enable
* Description    : 启动/停止dhcp
* Input          : flag:0 / 1, 具体含义如下:
*   @arg        1: 启动dhcp
*   @arg        0:停止dhcp
* Return         : 返回crc32的高6位
*******************************************************************************/
uint8_t  ch395_dhcp_enable(uint8_t flag)
{
    uint8_t i = 0;
    uint8_t s;
    ch395_write_cmd(CMD10_DHCP_ENABLE);
    ch395_write_data(flag);
    ch395_scs_hign;

    while (1)
    {
        delay_ms(20);
        s = ch395_get_cmd_status();            /* 不能过于频繁查询 */

        if (s != CH395_ERR_BUSY)
        {
            break;         /* 如果CH395芯片返回忙状态 */
        }

        if (i++ > 200)
        {
            return CH395_ERR_UNKNOW; /* 超时退出 */
        }
    }

    return s;
}

/*******************************************************************************
* Function Name  : ch395_get_dhcp_status
* Description    : 获取dhcp状态
* Input          : None
* Return         : dhcp状态,0为成功,其他值表示错误
*******************************************************************************/
uint8_t ch395_get_dhcp_status(void)
{
    uint8_t status;
    ch395_write_cmd(CMD01_GET_DHCP_STATUS);
    status = ch395_read_data();
    ch395_scs_hign;
    return status;
}

/*******************************************************************************
* Function Name  : ch395_get_ipinf
* Description    : 获取ip,子网掩码和网关地址
* Input          : sockindex socket索引
* Return         : 12个字节的ip,子网掩码和网关地址
*******************************************************************************/
void ch395_get_ipinf(uint8_t *addr)
{
    uint8_t i;
    ch395_write_cmd(CMD014_GET_IP_INF);

    for (i = 0; i < 20; i++)
    {
        *addr++ = ch395_read_data();
    }

    ch395_scs_hign;
}


/*******************************************************************************
* Function Name  : ch395_write_gpio_addr
* Description    : 写gpio寄存器
* Input          : regadd   寄存器地址
									 regval   寄存器值
* Return         : None
*******************************************************************************/
void ch395_write_gpio_addr(uint8_t regadd, uint8_t regval)
{
    ch395_write_cmd(CMD20_WRITE_GPIO_REG);
    ch395_write_data(regadd);
    ch395_write_data(regval);
}


/*******************************************************************************
* Function Name  : ch395_read_gpio_addr
* Description    : 读gpio寄存器
* Input          : regadd   寄存器地址
* Return         : 寄存器的值
*******************************************************************************/
uint8_t ch395_read_gpio_addr(uint8_t regadd)
{
    uint8_t i;
    ch395_write_cmd(CMD10_READ_GPIO_REG);
    ch395_write_data(regadd);
    delay_ms(1);
    i = ch395_read_data();
    return i;
}

/*******************************************************************************
* Function Name  : ch395_eeprom_erase
* Description    : 擦除eeprom
* Input          : None
* Return         : 执行状态
*******************************************************************************/
uint8_t ch395_eeprom_erase(void)
{
    uint8_t i;
    ch395_write_cmd(CMD00_EEPROM_ERASE);

    while (1)
    {
        delay_ms(20);
        i = ch395_get_cmd_status();

        if (i == CH395_ERR_BUSY)
        {
            continue;
        }

        break;
    }

    return i;
}

/*******************************************************************************
* Function Name  : ch395_eeprom_write
* Description    : 写eeprom
* Input          : eepaddr  eeprom地址
									 buf      缓冲区地址
									 len      长度
* Return         : 执行状态
*******************************************************************************/
uint8_t ch395_eeprom_write(uint16_t eepaddr, uint8_t *buf, uint8_t len)
{
    uint8_t i;
    ch395_write_cmd(CMD30_EEPROM_WRITE);
    ch395_write_data((uint8_t)(eepaddr));
    ch395_write_data((uint8_t)(eepaddr >> 8));
    ch395_write_data(len);

    while (len--)ch395_write_data(*buf++);

    while (1)
    {
        delay_ms(20);
        i = ch395_get_cmd_status();

        if (i == CH395_ERR_BUSY)
        {
            continue;
        }

        break;
    }

    return i;
}

/*******************************************************************************
* Function Name  : ch395_eeprom_write
* Description    : 读eeprom
* Input          : eepaddr  eeprom地址
				   buf      缓冲区地址
				   len      长度
* Return         : None
*******************************************************************************/
void ch395_eeprom_read(uint16_t eepaddr, uint8_t *buf, uint8_t len)
{
    ch395_write_cmd(CMD30_EEPROM_READ);
    ch395_write_data((uint8_t)(eepaddr));
    ch395_write_data((uint8_t)(eepaddr >> 8));
    ch395_write_data(len);
    delay_ms(1);

    while (len--)
    {
        *buf++ = ch395_read_data();
    }
}


/*******************************************************************************
* Function Name  : ch395_set_tcpmss
* Description    : 设置tcp mss值
* Input          : tcpmss
* Return         : None
*******************************************************************************/
void ch395_set_tcpmss(uint16_t tcpmss)
{
    ch395_write_cmd(CMD20_SET_TCP_MSS);
    ch395_write_data((uint8_t)(tcpmss));
    ch395_write_data((uint8_t)(tcpmss >> 8));
	ch395_scs_hign;
}


/*******************************************************************************
* Function Name  : ch395_set_socket_recv_buf
* Description    : 设置socket接收缓冲区
* Input          : sockindex  socket索引,址,blknum
				   startblk   起始地址
				   单位缓冲区个数 ,单位为512字节
* Return         : None
*******************************************************************************/
void ch395_set_socket_recv_buf(uint8_t sockindex, uint8_t startblk, uint8_t blknum)
{
    ch395_write_cmd(CMD30_SET_RECV_BUF);
    ch395_write_data(sockindex);
    ch395_write_data(startblk);
    ch395_write_data(blknum);
	ch395_scs_hign;
//	delay_us(2);
}


/*******************************************************************************
* Function Name  : ch395_set_socket_send_buf
* Description    : 设置socket发送缓冲区
* Input          : sockindex  socket索引,址,blknum
				   startblk   起始地址
				   单位缓冲区个数 ,单位为512字节
* Return         : None
*******************************************************************************/
void ch395_set_socket_send_buf(uint8_t sockindex, uint8_t startblk, uint8_t blknum)
{
    ch395_write_cmd(CMD30_SET_SEND_BUF);
    ch395_write_data(sockindex);
    ch395_write_data(startblk);
    ch395_write_data(blknum);
	ch395_scs_hign;
//	delay_us(2);
}

/*******************************************************************************
* Function Name  : ch395_udp_send_data
* Description    : udp向指定的ip和端口发送数据
* Input          : buf     : 发送数据缓冲区
				   len     : 发送数据长度
				   ip      : 目标ip
				   port    : 目标端口
				   sockeid : socket索引值
* Return         : None
*******************************************************************************/
void ch395_udp_send_data(uint8_t *buf, uint32_t len, uint8_t *ip, uint16_t port, uint8_t sockindex)
{
    ch395_set_socket_desip(sockindex, ip);   /* 设置socket 0目标IP地址 */
    ch395_set_socket_desport(sockindex, port);
    ch395_send_data(sockindex, buf, len);
}

/*******************************************************************************
* Function Name  : ch395_set_start_para
* Description    : 设置CH395启动参数
* Input          : madata
* Return         : None
*******************************************************************************/
void ch395_set_start_para(uint32_t mdata)
{
    ch395_write_cmd(CMD40_SET_FUN_PARA);
    ch395_write_data((uint8_t)mdata);
    ch395_write_data((uint8_t)((uint16_t)mdata >> 8));
    ch395_write_data((uint8_t)(mdata >> 16));
    ch395_write_data((uint8_t)(mdata >> 24));
	  ch395_scs_hign;
}
/*******************************************************************************
* Function Name  : ch395_cmd_get_glob_int_status_all
* Description    : 获取全局中断状态,收到此命令CH395自动取消中断,0x44及以上版本使用
* Input          : None
* Return         : 返回当前的全局中断状态
*******************************************************************************/
uint16_t ch395_cmd_get_glob_int_status_all(void)
{
    uint16_t init_status;
	  uint8_t i,init[2];

//	  #ifdef USE_USART2_CTRL_CH395
//	  if(UART_WORK_BAUDRATE==9600)
//		{
//		  ch395_write_cmd(CMD02_GET_GLOB_INT_STATUS_ALL);
//      delay_ms(25);
//	    for (i = 0; i < 2; i++)
//      {
//        init[i] = ch395_read_data();
//      }
//			init_status = (uint16_t)(init[1] << 8) + init[0];
//		}  		
//		else
//		{
//      USART_DMA_Config();
//	    delay_ms(10);
//      ch395_write_cmd(CMD02_GET_GLOB_INT_STATUS_ALL);
//      delay_ms(2);	
//	    for (i = 0; i < 2; i++)
//      {
//        init[i] = ITDATA[i];
//      }
//      init_status = (uint16_t)(init[1] << 8) + init[0];
//		
//		  DMA_Cmd(DMA1_Channel6, DISABLE);
//      USART_DMACmd(USART2,USART_DMAReq_Rx,DISABLE);
//		}
//		#else
		ch395_write_cmd(CMD02_GET_GLOB_INT_STATUS_ALL); /* 获取全局中断状态,V44版本以后的程序由于增加了socket数量需要用此命令获取全部的中断 */
	  delay_us(2);
	    for (i = 0; i < 2; i++)
    {
        init[i] = ch395_read_data();
    }
		init_status = (uint16_t)(init[1] << 8) + init[0];
//    #endif

    ch395_scs_hign;
    return  init_status;
}
/*******************************************************************************
* Function Name  : ch395_set_keeplive
* Description    : 设置keepalive功能
* Input          : sockindex Socket号
				   cmd 0:关闭 1:开启
* Return         : None
*******************************************************************************/
void ch395_set_keeplive(uint8_t sockindex, uint8_t cmd)
{
    ch395_write_cmd(CMD20_SET_KEEP_LIVE_SN);
    ch395_write_data(sockindex);
    ch395_write_data(cmd);
}
/*******************************************************************************
* Function Name  : ch395_keeplive_cnt
* Description    : 设置keepalive重试次数
* Input          : cnt 重试次数
* Return         : None
*******************************************************************************/
void ch395_keeplive_cnt(uint8_t cnt)
{
    ch395_write_cmd(CMD10_SET_KEEP_LIVE_CNT);
    ch395_write_data(cnt);
}
/*******************************************************************************
* Function Name  : ch395_keeplive_idle
* Description    : 设置KEEPLIVE空闲
* Input          : idle 空闲时间(单位:ms)
* Return         : None
*******************************************************************************/
void ch395_keeplive_idle(uint32_t idle)
{
    ch395_write_cmd(CMD40_SET_KEEP_LIVE_IDLE);
    ch395_write_data((uint8_t)idle);
    ch395_write_data((uint8_t)((uint16_t)idle >> 8));
    ch395_write_data((uint8_t)(idle >> 16));
    ch395_write_data((uint8_t)(idle >> 24));
}
/*******************************************************************************
* Function Name  : ch395_keeplive_intvl
* Description    : 设置KeepLive间隔时间 
* Input          : intvl 间隔时间(单位:ms)
* Return         : None
*******************************************************************************/
void ch395_keeplive_intvl(uint32_t intvl)
{
    ch395_write_cmd(CMD40_SET_KEEP_LIVE_INTVL);
    ch395_write_data((uint8_t)intvl);
    ch395_write_data((uint8_t)((uint16_t)intvl >> 8));
    ch395_write_data((uint8_t)(intvl >> 16));
    ch395_write_data((uint8_t)(intvl >> 24));
}
/*******************************************************************************
* Function Name  : ch395_setttl_num
* Description    : 设置TTL
* Input          : sockindex Socket号
				   TTLnum:TTL数
* Return         : None
*******************************************************************************/
void ch395_setttl_num(uint8_t sockindex, uint8_t ttlnum)
{
    ch395_write_cmd(CMD20_SET_TTL);
    ch395_write_data(sockindex);
    ch395_write_data(ttlnum);
}

/*******************************************************************************
* Function Name  : USART_DMA_Config
* Description    : USART2DMA接收中断信息数据
* Input          : None
* Return         : None
*******************************************************************************/
//void USART_DMA_Config(void)
//{
//	DMA_InitTypeDef DMA_InitStructure;
//  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
//	
//	DMA_DeInit(DMA1_Channel6);  
//  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART2->DATAR);
//  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ITDATA;
//  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
//  DMA_InitStructure.DMA_BufferSize = 2;
//	 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
//  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
//  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
//  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
//  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
//  DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
//  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
//  DMA_Init(DMA1_Channel6, &DMA_InitStructure);

//	DMA_Cmd(DMA1_Channel6, ENABLE);
//	USART_DMACmd(USART2,USART_DMAReq_Rx,ENABLE);
//}


/******************************************************************************
Description        : CH395基本操作步骤
*******************************************************************************/ 

/* CH395本地配置 */
struct _CH395_SYS  ch395inf;      /* 保存CH395信息 */
extern uint8_t local_ip[];        /* CH395IP地址 */
extern uint8_t gateway_ip[] ;     /* CH395网关 */
extern uint8_t mask_ip[];         /* CH395子网掩码 */

/* CH395socket配置 */
extern uint16_t source_port[8];
extern uint16_t destination_port[8];
extern uint8_t socket_desip0[4];
extern uint8_t socket_desip1[4];
extern uint8_t socket_desip2[4];
extern uint8_t socket_desip3[4];
extern uint8_t socket_desip4[4];
extern uint8_t socket_desip5[4];
extern uint8_t socket_desip6[4];
extern uint8_t socket_desip7[4];
extern struct _SOCK_INF  sockinf[8];
/*******************************************************************************
* Function Name  : CH395_if_init
* Description    : CH32的硬件接口初始化
* Input          : None
* Return         : None
*******************************************************************************/
void CH395_if_init(void)
{
	
//#ifdef USE_USART2_CTRL_CH395
//	USART2_init();
//	control_UART_Init();    /* io口相关的初始化 */
//#else 
	SPI_FullDuplex_Init();/* SPI初始化和SPI相关的GPIO口初始化 */
	control_SPI_Init();    /* io口相关的初始化 */
//#endif
	
}

/*******************************************************************************
* Function Name  : CH395_init
* Description    : CH395初始化
* Input          : None
* Return         : 初始化状态
*******************************************************************************/
uint8_t CH395_init(void)
{
    uint8_t i;
		
	i=ch395_cmd_check_exist(0x65);
	if(i != 0x9a)return CH395_ERR_UNKNOW;
	delay_ms(10);
	i = ch395_cmd_get_ver();
    printf("版本号CH395VER : %2x\r\n",i);
	ch395_cmd_reset();                            /* 软复位命令 */
    delay_ms(50);                                /* 软复位之后起码延时50毫秒 */
	

    ch395_cmd_set_ipaddr(ch395inf.IPAddr);        /* 设置CH395的IP地址 */
    ch395_cmd_set_gw_ipaddr(ch395inf.GWIPAddr);   /* 设置网关地址 */
    ch395_cmd_set_maskaddr(ch395inf.MASKAddr);    /* 设置子网掩码,默认为255.255.255.0*/
	  delay_ms(300); 
    i = ch395_cmd_init();                         /* 初始化CH395芯片 */
	
    return i;
}
/*******************************************************************************
* Function Name  : ch395_inf_init
* Description    : CH395本地信息初始化
* Input          : None
* Return         : 初始化状态
*******************************************************************************/
void ch395_inf_init(void)
{
    memset(&ch395inf, 0, sizeof(ch395inf));        /* 将CH395Inf全部清零 */
    memcpy(ch395inf.IPAddr, local_ip, 4);          /* 将IP地址写入CH395Inf中 */
    memcpy(ch395inf.GWIPAddr, gateway_ip, 4);      /* 将网关IP地址写入CH395Inf中 */
    memcpy(ch395inf.MASKAddr, mask_ip, 4);         /* 将子网掩码写入CH395Inf中 */
}

/*******************************************************************************
* Function Name  : ch395_socket_init
* Description    : CH395socke信息初始化
* Input          : None
* Return         : None
*******************************************************************************/
void ch395_socket_init(void)
{
	memset(&sockinf[0],0,sizeof(sockinf[0]));                      /* 将SockInf[0]全部清零*/
  memcpy(&sockinf[0].IPAddr, &socket_desip0, 4);              /* 将目标IP写入结构体 */
	memcpy(&sockinf[0].SourPort, &source_port[0], 2);              /* 将本地端口写入 */
	memcpy(&sockinf[0].DesPort, &destination_port[0], 2);          /* 将目的端口写入 */
	sockinf[0].ProtoType = PROTO_TYPE_TCP;                         /* TCP模式 */
	sockinf[0].TcpMode = TCP_CLIENT_MODE;                            /* TCP客户端模式 */ 
}

/*******************************************************************************
* Function Name  : socket_open
* Description    : CH395socke开启
* Input          : None
* Return         : None
*******************************************************************************/
void socket_open(void)
{
	uint8_t rc;
 
	
	ch395_set_socket_desip(0,sockinf[0].IPAddr);
	ch395_set_socket_prot_type(0,sockinf[0].ProtoType);
    ch395_set_socket_desport(0,sockinf[0].DesPort);
	ch395_set_socket_sourport(0,sockinf[0].SourPort);
	rc=ch395_open_socket(0);
	stop_if_error(rc); 
	rc=ch395_tcp_connect(0);
    stop_if_error(rc); 
    delay_ms(500);
}

/*********************************************************************************
* Function Name  : Socket_R_S_Buf_Modify
* Description    : Socket收发缓冲区定义
* Input          : None
* Output         : None
* Return         : None
**********************************************************************************/
void Socket_R_S_Buf_Modify(void )
{

   ch395_set_socket_recv_buf(0,0,4);                                     /* Socket 0 ,接收缓冲区4*512 = 2K,发送缓冲区2*512 = 1K*/
   ch395_set_socket_send_buf(0,4,2);  
  
   ch395_set_socket_recv_buf(1,6,4);                                     /* Socket 1 */
   ch395_set_socket_send_buf(1,10,2);  
  
   ch395_set_socket_recv_buf(2,12,4);                                    /* Socket 2 */
   ch395_set_socket_send_buf(2,16,2);  
  
   ch395_set_socket_recv_buf(3,18,4);                                    /* Socket 3 */
   ch395_set_socket_send_buf(3,22,2);  
  
   ch395_set_socket_recv_buf(4,24,4);                                    /* Socket 4 */
   ch395_set_socket_send_buf(4,28,2);  
  
   ch395_set_socket_recv_buf(5,30,4);                                    /* Socket 5 */
   ch395_set_socket_send_buf(5,34,2);
  
   ch395_set_socket_recv_buf(6,36,4);                                    /* Socket 6 */
   ch395_set_socket_send_buf(6,40,2);  
  
   ch395_set_socket_recv_buf(7,42,4);                                    /* Socket 7 */
   ch395_set_socket_send_buf(7,46,2);  

}


/**********************************************************************************
* Function Name  : KeepLive_Set
* Description    : 保活定时器参数设置
* Input          : None
* Output         : None
* Return         : None
**********************************************************************************/
void KeepLive_Set(void)
{
	ch395_keeplive_cnt(DEF_KEEP_LIVE_CNT);

	ch395_keeplive_idle(DEF_KEEP_LIVE_IDLE);

	ch395_keeplive_intvl(DEF_KEEP_LIVE_PERIOD);
}








#define SPI1_SR   *(uint32_t*)(0x40013008)
#define SPI1_DR   *(uint32_t*)(0x4001300C)
DMA_InitTypeDef DMA_InitStructure;
SPI_InitTypeDef SPI_InitStructure;	

void control_SPI_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;

	/* CH395中断输入脚 PA0*/
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;	/* CH395中断配置:单片机引脚设为上拉输出 */
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   /* */
	GPIO_Init( GPIOA, &GPIO_InitStructure );
	
	/* 控制CH395硬件复位脚 PA1*/
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;	/* 硬件复位输出配置为开漏输出 */
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   /* */
	GPIO_Init( GPIOA, &GPIO_InitStructure );
	GPIO_SetBits(GPIOA,GPIO_Pin_1);

}

void control_UART_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	EXTI_InitTypeDef EXTI_InitStructure;
 	NVIC_InitTypeDef NVIC_InitStructure;

	/* CH395中断输入脚 PA0*/
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;	/* CH395中断配置:单片机引脚设为上拉输出 */
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   /* */
	GPIO_Init( GPIOA, &GPIO_InitStructure );
	
	/* 控制CH395硬件复位脚 PA1*/
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;	/* 硬件复位输出配置为开漏输出 */
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   /* */
	GPIO_Init( GPIOA, &GPIO_InitStructure );
	GPIO_SetBits(GPIOA,GPIO_Pin_1);
	
	/* PA0设为下降沿中断 */
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0); 
    EXTI_InitStructure.EXTI_Line=EXTI_Line0;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);	 	

    NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;			        
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;	
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;					
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;								
    NVIC_Init(&NVIC_InitStructure); 
}
/*
------------------------------------SPI接口相关---------------------------------
*/

/*******************************************************************************
* Function Name  : SPI_FullDuplex_Init
* Description    : Configuring the SPI for full-duplex communication.
* Input          : None
* Return         : None
*******************************************************************************/ 
#ifdef USE_SPI1_CTRL_CH395
void SPI_FullDuplex_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1, ENABLE );	
		
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;	
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init( GPIOA, &GPIO_InitStructure );	

	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init( GPIOA, &GPIO_InitStructure );	

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	
	GPIO_Init( GPIOA, &GPIO_InitStructure );	
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;		
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init( GPIOA, &GPIO_InitStructure );
	
	SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;	

	SPI_InitStructure.SPI_Mode = SPI_Mode_Master;	
	
	SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;	
	SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;	
	SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;	
	SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;	
	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;	
	SPI_InitStructure.SPI_CRCPolynomial = 7;
	SPI_Init( SPI1, &SPI_InitStructure );	
	
	SPI_Cmd( SPI1, ENABLE );
}

#else 
void USART2_init(void)
{
	USART_InitTypeDef USART_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	

	/* USART2 TX-->A.2   RX-->A.3 */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOA, &GPIO_InitStructure);	

	USART_InitStructure.USART_BaudRate = 9600;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;

	USART_Init(USART2, &USART_InitStructure); 
	USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);

	USART_Cmd(USART2, ENABLE); 
}

void set_usart2_bandrate(uint32_t bandrate)
{
	USART_InitTypeDef USART_InitStructure;
	
	USART_InitStructure.USART_BaudRate = bandrate;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;

	USART_Init(USART2, &USART_InitStructure); 
	USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);

	USART_Cmd(USART2, ENABLE);
}
#endif

/**
*描述:语句基本构成:写命令
 */
void ch395_write_cmd( uint8_t mCmd )
{
	ch395_scs_hign;                /* 防止CS原来为低,先将CS置高 */
    ch395_scs_low;                 /* 命令开始,CS拉低 */
#ifdef USE_USART2_CTRL_CH395
    ch395_write_data(0x57);

	ch395_write_data(0xab);

#endif
	
    ch395_write_data(mCmd);        /* SPI发送命令码 */
	delay_us(2);                   /* 必要延时,延时1.5uS确保读写周期不小于1.5uS */
 
}






#if 1
uint8_t SPI1_ReadWriteByte(uint8_t Tx_Data)
{			
	while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) ;
	
	SPI_I2S_SendData(SPI1, Tx_Data); 


	while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
		
	return SPI_I2S_ReceiveData(SPI1); 	
}
#endif

uint8_t SPI1_ReadByte(uint8_t Tx_Data)
{		
	u8 i=0;		
	while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET)
	{
		i++;
		if(i>200)return 0;
	}		
	return SPI_I2S_ReceiveData(SPI1); 	
	
}

#if SPI1_DMA_EN
void SPI_DMA_Read(u16 length)
{
	u16 i=0;

	DMA_InitStructure.DMA_BufferSize=length;
	DMA_Init( DMA1_Channel2, &DMA_InitStructure );	
	
	DMA_Cmd( DMA1_Channel2, ENABLE );
	SPI_I2S_DMACmd( SPI1, SPI_I2S_DMAReq_Rx, ENABLE );	
	for(i=0;i<length;i++)
	{
		SPI_I2S_SendData(SPI1,0xff);
	}
	Delay_Us(1);
	
	while( (DMA_GetFlagStatus(DMA1_FLAG_TC2)) == RESET)
	{
//		DMA_ClearFlag(DMA1_FLAG_TC2);//清除通道2传输完成标志
	}
	DMA_ClearFlag(DMA1_FLAG_TC2);//清除通道2传输完成标志
	SPI_I2S_DMACmd( SPI1, SPI_I2S_DMAReq_Rx, DISABLE );	
	DMA_Cmd( DMA1_Channel2, DISABLE );
	for( i=0; i<length; i++ )
	{	
		TxData[i]=RxData[i];
		
	}
	DMA_DeInit(DMA1_Channel2);
	SPI1_DMA_Rx_Init( DMA1_Channel2, (uint32_t)&SPI1->DATAR, (uint32_t)RxData, 20 );
}
#endif
/**
----------------------------------------  CH395硬件写取函数 -----------------------------------------
---------------------------------------  移植更换API入口位置 -----------------------------------------
 */
void ch395_write_data( uint8_t mData )
{	
#ifdef USE_SPI1_CTRL_CH395
	SPI1_ReadWriteByte(mData);
#else
	USART_SendData(USART2, mData); 
	while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);
#endif
}

void spi_data_write(uint8_t mData)
{
	while ((SPI1_SR & SPI_I2S_FLAG_TXE) == RESET) ;	
	
	SPI1_DR=mData;
}

/**
-----------------------------------------  CH395硬件读取函数 -----------------------------------------
----------------------------------------  移植更换API入口位置 -----------------------------------------
 */
uint8_t ch395_read_data( void )
{
#ifdef USE_SPI1_CTRL_CH395
	while((SPI1_SR & SPI_I2S_FLAG_TXE)==RESET);	
	SPI1_DR=0xff;
	while((SPI1_SR & SPI_I2S_FLAG_RXNE)==RESET);	
//	return (uint8_t)SPI1->DATAR;//沁恒单片机
	return (uint8_t)SPI1->DR;	
	
	
#else
	uint32_t x;
	for(x=0;x<500000;x++)
	{
		if(USART_GetFlagStatus(USART2,USART_IT_RXNE) == SET)
		{
			
			return (uint8_t)USART_ReceiveData(USART2);
		}
	}
	return (0);
#endif
}

/*
-------------------------------------------------------------------------------------------------------

                                        USART接口相关

-------------------------------------------------------------------------------------------------------
*/





/**********************************************************************************
* Function Name  : CH395SocketInterrupt
* Description    : CH395 socket 中断,在全局中断中被调用
* Input          : sockindex:socket索引号
* Output         : None
* Return         : None
**********************************************************************************/
void CH395SocketInterrupt(uint8_t sockindex)
{
   uint8_t  sock_int_socket,i;
   uint16_t len;
   uint16_t tmp;

   sock_int_socket = ch395_get_socket_int(sockindex);                /* 获取socket 的中断状态  获取不同的中断状态   处理不同的中断状态   */
	
	
   if(sock_int_socket & SINT_STAT_SENBUF_FREE)                       /* 发送缓冲区空闲,可以继续写入要发送的数据 */
   {
		  
	   delay_us(300);
		 
   }
	 
	 
   if(sock_int_socket & SINT_STAT_SEND_OK)                           /* 发送完成中断 */
   {
//	   printf("send ok!\n");
   }
	 
	 
	 
   if(sock_int_socket & SINT_STAT_RECV)                              /* 接收中断 */
   {
	   
       len = ch395_get_recv_length(sockindex);                        /* 获取当前缓冲区内数据长度 */
  
	   printf("接收到的字节数长度 = %d\r\n",len);
		 #ifdef USE_SPI1_CTRL_CH395 
	   delay_us(200);
		 #endif	
		 
	   if(len == 0)return;
       if(len > default_tcp_mss)len = default_tcp_mss;                /* MyBuffer缓冲区长度为512*/
	     ch395_get_recv_data(sockindex,len,socket_buff[sockindex]);     /* 读取数据 */
//		   delay_us(100);
//       ch395_send_data(sockindex,socket_buff[sockindex],len);        /* 发送数据  */
   }
	 
   if(sock_int_socket & SINT_STAT_CONNECT)                           /* 连接中断,仅在TCP模式下有效*/
   {
	   uint8_t target_inf[6];
	   
	   printf("*");
	   tcp_connect = 1;
       if(sockinf[sockindex].TcpMode == TCP_SERVER_MODE)             /* 如果socket 为服务器模式,用户可以获取远端的IP和端口*/
       {
           ch395_cmd_get_remoteipp(sockindex,target_inf);
           tmp = (uint16_t)(target_inf[5]<<8) + target_inf[4];
           printf("IP address = %d.%d.%d.%d\n",(uint16_t)target_inf[0],(uint16_t)target_inf[1],(uint16_t)target_inf[2],(uint16_t)target_inf[3]);    
           printf("Port = %d\n",tmp);    
       }
   }
   /*
   **产生断开连接中断和超时中断时,CH395默认配置是内部主动关闭,用户不需要自己关闭该Socket,如果想配置成不主动关闭Socket需要配置
   **SOCK_CTRL_FLAG_SOCKET_CLOSE标志位(默认为0),如果该标志为1,CH395内部不对Socket进行关闭处理,用户在连接中断和超时中断时调用
   **CH395CloseSocket函数对Socket进行关闭,如果不关闭则该Socket一直为连接的状态(事实上已经断开),就不能再去连接了。
   */
   /*SOCK_CTRL_FLAG_SOCKET_CLOSE被置位后,下面的中断需要关闭Socket,再进行其他操作。不置位则不需要CH395CloseSocket,CH395内部已经关闭。*/
   if(sock_int_socket & SINT_STAT_DISCONNECT)                        /* 断开中断,仅在TCP模式下有效 */
   {
	   
	   i = ch395_close_socket(sockindex); //关闭socket                            
	   stop_if_error(i);//打印出被关闭的Socket
	   delay_ms(2);
	   i = ch395_open_socket(sockindex);
	   stop_if_error(i);
   }
	 
	 
	 
	if(sock_int_socket & SINT_STAT_TIM_OUT)                           /* 超时中断,仅在TCP模式下有效 */
	{
		printf("SINT_STAT_TIM_OUT超时");
		i = ch395_close_socket(sockindex);                             
		stop_if_error(i);
		delay_ms(2);
		i = ch395_open_socket(sockindex);
		stop_if_error(i);
	}
}

/**********************************************************************************
* Function Name  : CH395GlobalInterrupt
* Description    : CH395全局中断函数
* Input          : None
* Output         : None
* Return         : None
**********************************************************************************/
void CH395GlobalInterrupt(void)
{
	uint16_t  init_status,tem_flag;
	uint8_t  i,buf[10]; 

	init_status = ch395_cmd_get_glob_int_status_all();
	printf("init_status = %x\r\n",init_status);
	if(init_status & GINT_STAT_UNREACH)                              /* 不可达中断,读取不可达信息 */
	{
		ch395_cmd_get_unreachippt(buf);                                
	}
	if(init_status & GINT_STAT_IP_CONFLI)                            /* 产生IP冲突中断,建议重新修改CH395的 IP,并初始化CH395*/
	{
	}
	if(init_status & GINT_STAT_PHY_CHANGE)                           /* 产生PHY改变中断*/
	{
		printf("Init status : GINT_STAT_PHY_CHANGE\r\n");
	}

	tem_flag=GINT_STAT_SOCK0;
	for(i=0;i<8;i++)
	{
		if(init_status & tem_flag)
		{
	   	CH395SocketInterrupt(i); 
		}
		     
		tem_flag=(1<<(4+1+i));
	}
}


      

CH395Q.h

#ifndef __CH395Q_H
#define __CH395Q_H	 

#include "sys.h"





#define default_tcp_mss   4096       /* 默认的MSS大小设置 */

#define DEF_KEEP_LIVE_IDLE                           (20*1000)        /* 空闲时间 */
#define DEF_KEEP_LIVE_PERIOD                         (15*1000)        /* 间隔15s,发送一次KEPPLIVE数据包 */                  
#define DEF_KEEP_LIVE_CNT                            200                /* 重试次数  */

/* CH32操作CH395的硬件接口选择 */

//#if 0
#define USE_SPI1_CTRL_CH395     1    /* 使用SPI口作为默认的控制H395的接口 */
//#else
//#define USE_USART2_CTRL_CH395        /* 使用USART2口作为默认的控制CH395的接口 */     
//#endif

#define UART_WORK_BAUDRATE  921600

#define stop_if_error(x)\
if(x!=0){printf("Error: %02x,@ line %d of \"%s\".\r\n", (uint16_t)x,__LINE__,__FILE__);while(1);}

#define server_port source_port[0]                 /* 服务器端口 */


#ifdef __cplusplus
extern "C" {
#endif

#ifndef     TRUE
#define     TRUE    1
#define     FALSE   0
#endif
#ifndef     NULL
#define     NULL    0
#endif

/* 命令代码:
 * 一个命令操作顺序包含:
 * 一个命令码(对于串口方式,命令码之前还需要两个同步码)
 * 若干个输入数据(可以是0个)
 * 若干个输出数据(可以是0个)
 * 命令码起名规则: CMDxy_NAME
 * 其中的x和y都是数字, x说明最少输入数据个数(字节数), y说明最少输出数据个数(字节数), y如果是W表示需要等待命令执行成功
 * 有些命令能够实现0到多个字节的数据块读写, 数据块本身的字节数未包含在上述x或y之内
 */
#define CMD01_GET_IC_VER                  0x01        /* 获取芯片以及固件版本号 */

#define CMD31_SET_BAUDRATE                0x02        /* 串口方式: 设置串口通讯波特率(上电或者复位后的默认波特率为9600bps */

#define CMD00_ENTER_SLEEP                 0x03        /* 进入睡眠状态 */

#define CMD00_RESET_ALL                   0x05        /* 执行硬件复位 */

#define CMD11_CHECK_EXIST                 0x06        /* 测试通讯接口以及工作状态 */

#define CMD02_GET_GLOB_INT_STATUS_ALL     0x19        /* 获取全局中断状态,V44版本以后的程序由于增加了socket数量需要用此命令获取全部的中断 */

#define CMD10_SET_PHY                     0x20        /* 设置PHY,默认为Auto,自动协商 */

#define CMD60_SET_MAC_ADDR                0x21        /* 设置MAC地址 必须在CMD00H_INIT_CH395之前设置完毕 */

#define CMD40_SET_IP_ADDR                 0x22        /* 设置IP地址 必须在CMD00H_INIT_CH395之前设置完毕 */

#define CMD40_SET_GWIP_ADDR               0x23        /* 设置网关IP地址 必须在CMD00H_INIT_CH395之前设置完毕 */

#define CMD40_SET_MASK_ADDR               0x24        /* 设置子网掩码, 必须在CMD00H_INIT_CH395之前设置完毕 */

#define CMD90_SET_MAC_FILT                0x25        /* 设置MAC过滤 可以进行广播,多播等过滤 */

#define CMD01_GET_PHY_STATUS              0x26        /* 获取PHY当前状态,如断开连接,10/100M FULL/HALF */

#define CMD0W_INIT_CH395                  0x27        /* 初始化CH395 */

#define CMD08_GET_UNREACH_IPPORT          0x28        /* 获取不可达信息 */

#define CMD01_GET_GLOB_INT_STATUS         0x29        /* 获取全局中断状态,最大值为1S,不可以设置为0 */

#define CMD10_SET_RETRAN_COUNT            0x2A        /* 重试次数,仅在TCP模式下有效 */

#define CMD20_SET_RETRAN_PERIOD           0x2B        /* 重试周期,最大值为20,仅在TCP模式下有效,不可以设置为0 */

#define CMD01_GET_CMD_STATUS              0x2C        /* 获取命令执行状态 */

#define CMD06_GET_REMOT_IPP_SN            0x2D        /* 获取远端的端口以及IP地址,该命令在TCP服务器模式下使用 */

#define CMD10_CLEAR_RECV_BUF_SN           0x2E        /* 清除接收缓冲区  */

#define CMD12_GET_SOCKET_STATUS_SN        0x2F        /* 获取socket n状态 */

#define CMD11_GET_INT_STATUS_SN           0x30        /* 获取socket n的中断状态 */

#define CMD50_SET_IP_ADDR_SN              0x31        /* 设置socket n的目的IP地址 */

#define CMD30_SET_DES_PORT_SN             0x32        /* 设置socket n的目的端口 */

#define CMD30_SET_SOUR_PORT_SN            0x33        /* 设置socket n的源端口 */

#define CMD20_SET_PROTO_TYPE_SN           0x34        /* 设置socket n的协议类型 */

#define CMD1W_OPEN_SOCKET_SN              0x35        /* 打开socket n */

#define CMD1W_TCP_LISTEN_SN               0x36        /* socket n监听,收到此命令,socket n进入服务器模式,仅对TCP模式有效 */

#define CMD1W_TCP_CONNECT_SN              0x37        /* socket n连接,收到此命令,socket n进入客户端模式,仅对TCP模式有效 */

#define CMD1W_TCP_DISNCONNECT_SN          0x38        /* socket n断开连接,收到此命令,socket n断开已有连接,仅对TCP模式有效 */

#define CMD30_WRITE_SEND_BUF_SN           0x39        /* 向socket n缓冲区写入数据 */

#define CMD12_GET_RECV_LEN_SN             0x3B        /* 获取socket n接收数据的长度 */

#define CMD30_READ_RECV_BUF_SN            0x3C        /* 读取socket n接收缓冲区数据 */

#define CMD1W_CLOSE_SOCKET_SN             0x3D        /* 关闭socket n */

#define CMD20_SET_IPRAW_PRO_SN            0x3E        /* 在IP RAW下,设置socket n的IP包协议类型 */

#define CMD01_PING_ENABLE                 0x3F        /* 开启/关闭PING */

#define CMD06_GET_MAC_ADDR                0x40        /* 获取MAC地址 */

#define CMD10_DHCP_ENABLE                 0x41        /* DHCP使能 */

#define CMD01_GET_DHCP_STATUS             0x42        /* 获取DHCP状态 */

#define CMD014_GET_IP_INF                 0x43        /* IP,子网掩码,网关 */

#define CMD00_PPPOE_SET_USER_NAME         0x44        /* 设置PPPOE用户名 */

#define CMD00_PPPOE_SET_PASSWORD          0x45        /* 设置密码 */

#define CMD10_PPPOE_ENABLE                0x46        /* PPPOE使能 */

#define CMD01_GET_PPPOE_STATUS            0x47        /* 获取pppoe状态 */

#define CMD20_SET_TCP_MSS                 0x50        /* 设置TCP MSS */

#define CMD20_SET_TTL                     0x51        /* 设置TTL,TTL最大值为128 */

#define CMD30_SET_RECV_BUF                0x52        /* 设置SOCKET接收缓冲区 */

#define CMD30_SET_SEND_BUF                0x53        /* 设置SOCKET发送缓冲区 */

#define CMD10_SET_MAC_RECV_BUF            0x54        /* 设置MAC接收缓冲区 */

#define CMD40_SET_FUN_PARA                0x55        /* 设置功能参数 */

#define CMD40_SET_KEEP_LIVE_IDLE          0x56        /* 设置KEEPLIVE空闲 */

#define CMD40_SET_KEEP_LIVE_INTVL         0x57        /* 设置间隔时间 */

#define CMD10_SET_KEEP_LIVE_CNT           0x58        /* 重试次数 */

#define CMD20_SET_KEEP_LIVE_SN            0X59        /* 设置socket nkeeplive功能*/

#define CMD00_EEPROM_ERASE                0xE9        /* 擦除EEPROM*/

#define CMD30_EEPROM_WRITE                0xEA        /* 写EEPROM */

#define CMD30_EEPROM_READ                 0xEB        /* 读EEPROM */

#define CMD10_READ_GPIO_REG               0xEC        /* 读GPIO寄存器 */

#define CMD20_WRITE_GPIO_REG              0xED        /* 写GPIO寄存器 */

/* 协议类型 */
#define PROTO_TYPE_IP_RAW                 0           /* IP层原始数据 */
#define PROTO_TYPE_MAC_RAW                1           /* MAC层原始数据 */
#define PROTO_TYPE_UDP                    2           /* UDP协议类型 */
#define PROTO_TYPE_TCP                    3           /* TCP协议类型 */

/* PHY 命令参数/状态 */
#define PHY_DISCONN                       (1<<0)      /* PHY断开 */
#define PHY_10M_FLL                       (1<<1)      /* 10M全双工 */
#define PHY_10M_HALF                      (1<<2)      /* 10M半双工 */
#define PHY_100M_FLL                      (1<<3)      /* 100M全双工 */
#define PHY_100M_HALF                     (1<<4)      /* 100M半双工 */
#define PHY_AUTO                          (1<<5)      /* PHY自动模式,CMD10H_SET_PHY */

/* CH395 MAC过滤 */
#define MAC_FILT_RECV_BORADPKT            (1<<0)      /* 使能接收广播包 */
#define MAC_FILT_RECV_ALL                 (1<<1)      /* 使能接收所有数据包 */
#define MAC_FILT_RECV_MULTIPKT            (1<<2)      /* 使能接收多播包 */
#define MAC_FILT_RECV_ENABLE              (1<<3)      /* 使能接收 */
#define MAC_FILT_SEND_ENABLE              (1<<4)      /* 使能发送 */

/* 中断状态 */
/* 以下为GLOB_INT会产生的状态 */
#define GINT_STAT_UNREACH                 (1<<0)      /* 不可达中断 */
#define GINT_STAT_IP_CONFLI               (1<<1)      /* IP冲突 */
#define GINT_STAT_PHY_CHANGE              (1<<2)      /* PHY状态改变 */
#define GINT_STAT_DHCP                    (1<<3)      /* PHY状态改变 */
#define GINT_STAT_SOCK0                   (1<<4)      /* socket0 产生中断 */
#define GINT_STAT_SOCK1                   (1<<5)      /* socket1 产生中断 */
#define GINT_STAT_SOCK2                   (1<<6)      /* socket2 产生中断 */
#define GINT_STAT_SOCK3                   (1<<7)      /* socket3 产生中断 */
#define GINT_STAT_SOCK4                   (1<<8)      /* scoket4 产生中断 */
#define GINT_STAT_SOCK5                   (1<<9)      /* scoket5 产生中断 */
#define GINT_STAT_SOCK6                   (1<<10)     /* scoket6 产生中断 */
#define GINT_STAT_SOCK7                   (1<<11)     /* scoket7 产生中断 */

/* 以下为Sn_INT会产生的状态 */
#define SINT_STAT_SENBUF_FREE             (1<<0)      /* 发送缓冲区空闲 */
#define SINT_STAT_SEND_OK                 (1<<1)      /* 发送成功 */
#define SINT_STAT_RECV                    (1<<2)      /* socket端口接收到数据或者接收缓冲区不为空 */
#define SINT_STAT_CONNECT                 (1<<3)      /* 连接成功,TCP模式下产生此中断 */
#define SINT_STAT_DISCONNECT              (1<<4)      /* 连接断开,TCP模式下产生此中断 */
#define SINT_STAT_TIM_OUT                 (1<<6)      /* ARP和TCP模式下会发生此中断 */

/* 获取命令状态 */
#define CMD_ERR_SUCCESS                   0x00        /* 命令操作成功 */
#define CMD_RET_ABORT                     0x5F        /* 命令操作失败 */
#define CH395_ERR_BUSY                    0x10        /* 忙状态,表示当前正在执行命令 */
#define CH395_ERR_MEM                     0x11        /* 内存错误 */
#define CH395_ERR_BUF                     0x12        /* 缓冲区错误 */
#define CH395_ERR_TIMEOUT                 0x13        /* 超时 */
#define CH395_ERR_RTE                     0x14        /* 路由错误*/
#define CH395_ERR_ABRT                    0x15        /* 连接停止*/
#define CH395_ERR_RST                     0x16        /* 连接复位 */
#define CH395_ERR_CLSD                    0x17        /* 连接关闭/socket 在关闭状态 */
#define CH395_ERR_CONN                    0x18        /* 无连接 */
#define CH395_ERR_VAL                     0x19        /* 错误的值 */
#define CH395_ERR_ARG                     0x1a        /* 错误的参数 */
#define CH395_ERR_USE                     0x1b        /* 已经被使用 */
#define CH395_ERR_IF                      0x1c        /* MAC错误  */
#define CH395_ERR_ISCONN                  0x1d        /* 已连接 */
#define CH395_ERR_OPEN                    0X20        /* 已经打开 */
#define CH395_ERR_UNKNOW                  0xFA        /* 未知错误 */

/* PPP状态 */
#define CH395_PPP_SUCCESS                 0           /* 成功 */
#define CH395_PPPERR_PARM                 1           /* 无效参数 */
#define CH395_PPPERR_OPEN                 2           /* 无法打开PPP会话 */
#define CH395_PPPERR_DEVICE               3           /* 无效的PPP设备 */
#define CH395_PPPERR_ALLOC                4           /* 资源分配失败 */
#define CH395_PPPERR_USER                 5           /* 用户中断 */
#define CH395_PPPERR_CONNECT              6           /* 连接断开 */
#define CH395_PPPERR_AUTHFAIL             7           /* 挑战鉴别失败 */
#define CH395_PPPERR_PROTOCOL             8           /* 握手协议失败 */
#define CH395_PPPERR_TIME_OUT             9           /* 超时失败 */
#define CH395_PPPERR_CLOSE                10          /* 关闭失败 */

/* 不可达代码 */
#define UNREACH_CODE_HOST                 0           /* 主机不可达 */
#define UNREACH_CODE_NET                  1           /* 网络不可达 */
#define UNREACH_CODE_PROTOCOL             2           /* 协议不可达 */
#define UNREACH_CODE_PROT                 3           /* 端口不可达 */
/* 其他值请参考RFC792文档 */

/* 命令包头 */
#define SER_SYNC_CODE1                    0x57        /* 串口命令同步码1 */
#define SER_SYNC_CODE2                    0xAB        /* 串口命令同步码2 */

/* TCP状态 */
#define TCP_CLOSED                        0
#define TCP_LISTEN                        1
#define TCP_SYN_SENT                      2
#define TCP_SYN_RCVD                      3
#define TCP_ESTABLISHED                   4
#define TCP_FIN_WAIT_1                    5
#define TCP_FIN_WAIT_2                    6
#define TCP_CLOSE_WAIT                    7
#define TCP_CLOSING                       8
#define TCP_LAST_ACK                      9
#define TCP_TIME_WAIT                     10

/* GPIO寄存器地址 */
#define GPIO_DIR_REG                     0x80        /* 寄存器方向寄存器,1:输出;0:输入 */
#define GPIO_IN_REG                      0x81        /* GPIO输入寄存器 */
#define GPIO_OUT_REG                     0x82        /* GPIO输出寄存器 */
#define GPIO_CLR_REG                     0x83        /* GPIO输出清除: 0=keep, 1=clear */
#define GPIO_PU_REG                      0x84        /* GPIO上拉使能寄存器 */
#define GPIO_PD_REG                      0x85        /* GPIO下拉使能寄存器 */

/* 功能参数 */
#define FUN_PARA_FLAG_TCP_SERVER         (1<<1)      /* tcp server 多连接模式标志,0X44版本及以后支持 */
#define FUN_PARA_FLAG_LOW_PWR            (1<<2)      /* 低耗能模式 */
#define SOCK_CTRL_FLAG_SOCKET_CLOSE      (1<<3)      /* CH395不主动关闭Socket */
#define SOCK_DISABLE_SEND_OK_INT         (1<<4)      /* send ok中断控制位,为1表示关闭send ok中断 */

#ifdef __cplusplus
}
#endif



#define TCP_CLIENT_MODE                                      0
#define TCP_SERVER_MODE                                      1

struct _CH395_SYS
{
    uint8_t   IPAddr[4];           /* CH395IP地址 32bit*/
    uint8_t   GWIPAddr[4];         /* CH395网关地址 32bit*/
    uint8_t   MASKAddr[4];         /* CH395子网掩码 32bit*/
    uint8_t   MacAddr[6];          /* CH395MAC地址 48bit*/
    uint8_t   PHYStat;             /* CH395 PHY状态码 8bit*/
    uint8_t   MackFilt;            /* CH395 MAC过滤,默认为接收广播,接收本机MAC 8bit*/
    uint32_t  RetranCount;         /* 重试次数 默认为10次*/
    uint32_t  RetranPeriod;        /* 重试周期,单位MS,默认200MS */
    uint8_t   IntfMode;            /* 接口模式 */
    uint8_t   UnreachIPAddr[4];    /* 不可到达IP */
    uint16_t  UnreachPort;         /* 不可到达端口 */
};

struct _SOCK_INF
{
    uint8_t  IPAddr[4];            /* socket目标IP地址 32bit*/
    uint8_t  MacAddr[6];           /* socket目标地址 48bit*/
    uint8_t  ProtoType;            /* 协议类型 */
    uint8_t  ScokStatus;           /* socket状态,参考scoket状态定义 */
    uint8_t  TcpMode;              /* TCP模式 */
    uint32_t IPRAWProtoType;       /* 协议类型 */
    uint16_t DesPort;              /* 目的端口 */
    uint16_t SourPort;             /* 目的端口 */
    uint16_t SendLen;              /* 发送数据长度 */
    uint16_t RemLen;               /* 剩余长度 */
    uint8_t  *pSend;               /* 发送指针 */
};


//

#ifndef uint8_t
typedef unsigned char uint8_t;
#endif

#ifndef uint16_t
typedef unsigned short uint16_t;
#endif

#ifndef uint32_t
typedef unsigned int uint32_t;
#endif

void ch395_cmd_reset(void);
void ch395_cmd_hard_reset(void);
uint8_t ch395_cmd_get_ver(void);
void ch395_write_cmd( uint8_t mCmd );
uint8_t ch395_cmd_check_exist(uint8_t testdata);
void ch395_cmd_set_ipaddr(uint8_t *ipaddr);
void ch395_cmd_set_gw_ipaddr(uint8_t *gwipaddr);
void ch395_cmd_set_maskaddr(uint8_t *maskaddr);
uint8_t ch395_get_cmd_status(void);
uint8_t ch395_cmd_init(void);
void ch395_set_socket_sourport(uint8_t sockindex, uint16_t surprot);
uint8_t ch395_open_socket(uint8_t sockindex);
uint8_t  ch395_close_socket(uint8_t sockindex);
uint8_t ch395_tcp_listen(uint8_t sockindex);
uint8_t ch395_get_socket_int(uint8_t sockindex);
uint16_t ch395_get_recv_length(uint8_t sockindex);
void ch395_get_recv_data(uint8_t sockindex, uint16_t len, uint8_t *pbuf);
uint16_t ch395_cmd_get_glob_int_status_all(void);
void ch395_cmd_get_unreachippt(uint8_t *list);
void ch395_cmd_get_remoteipp(uint8_t sockindex, uint8_t *list);
void ch395_set_start_para(uint32_t mdata);
void ch395_set_tcpmss(uint16_t tcpmss);
void ch395_send_data(uint8_t sockindex, uint8_t *databuf, uint16_t len);
void ch395_cmd_set_uart_baud_rate(uint32_t baudrate);
void ch395_keeplive_cnt(uint8_t cnt);
void ch395_set_keeplive(uint8_t sockindex, uint8_t cmd);
void ch395_keeplive_idle(uint32_t idle);
void ch395_keeplive_intvl(uint32_t intvl);
void ch395_set_socket_desip(uint8_t sockindex, uint8_t *ipaddr);
void ch395_set_socket_prot_type(uint8_t sockindex, uint8_t prottype);
void ch395_set_socket_desport(uint8_t sockindex, uint16_t desprot);
void ch395_set_socket_prot_type(uint8_t sockindex, uint8_t prottype);
uint8_t ch395_tcp_connect(uint8_t sockindex);
//void USART_DMA_Config(void);
void ch395_cmd_get_socket_status(uint8_t sockindex, uint8_t *status);


 
void CH395_if_init(void);
uint8_t CH395_init(void);
void ch395_inf_init(void);
uint8_t ch395_cmd_get_phy_status(void);
void ch395_set_socket_recv_buf(uint8_t sockindex, uint8_t startblk, uint8_t blknum);
void ch395_set_socket_send_buf(uint8_t sockindex, uint8_t startblk, uint8_t blknum);
void ch395_set_socket_prot_type(uint8_t sockindex, uint8_t prottype);
void socket_open(void);
void ch395_socket_init(void);
void Socket_R_S_Buf_Modify(void );

void KeepLive_Set(void);


void CH395GlobalInterrupt(void);
/* Global Variable */ 
void CH395GlobalInterrupt(void);
void CH395SocketInterrupt(uint8_t sockindex);


//#define ch395_scs_hign
//#define ch395_scs_low  

#ifdef USE_SPI1_CTRL_CH395
#define ch395_scs_hign (*(uint32_t*)(GPIOA_BASE+0x10))|=(1<<4)
#define ch395_scs_low  (*(uint32_t*)(GPIOA_BASE+0x14))|=(1<<4)
#else
#define ch395_scs_hign 
#define ch395_scs_low  
#endif

#define ch32_gpio_in_a (*(uint32_t*)(GPIOA_BASE+0x08))
#define ch395_exti_stat (ch32_gpio_in_a&0x0001)


void SPI_FullDuplex_Init(void);
void control_SPI_Init(void);
void ch395_write_cmd( uint8_t mCmd );
void ch395_write_data( uint8_t mData );
uint8_t ch395_read_data( void );
void USART2_init(void);
void set_usart2_bandrate(uint32_t bandrate);
void SPI1_DMA_Tx_Init(DMA_Channel_TypeDef* DMA_CHx,uint32_t cpar,uint32_t cmar,u16 bufsize);
void SPI1_DMA_Rx_Init( DMA_Channel_TypeDef* DMA_CHx, uint32_t ppadr, uint32_t memadr, u16 bufsize );
void SPI_DMA_Read(u16 length);
uint8_t SPI1_ReadByte(uint8_t TxData);
void spi_data_write(uint8_t mData);
void control_UART_Init(void);



#endif

                  

                        

猜你喜欢

转载自blog.csdn.net/weixin_47041339/article/details/129389654
今日推荐