一、硬件介绍
USR-C210 硬件上集成了 MAC、基频芯片、射频收发单元,尺寸小,易于焊接在客户的单板电路上,且模块可选择内置或外置天线的应用,方便客户多重选择,模块内置低功耗运行机制,可以有效实现模块的低功耗运行。
GD32F427系列高性能MCU产品系列提供了丰富的外设和大存储容量,可广泛应用于高级计算,云服务器,人工智能、工业控制、电机变频、图形显示、安防监控、传感器网络、无人机、机器人、物联网等创新领域。
二、硬件连接
从图中可以看到,只需将GD32F427开发板上的3.3V供给模块,然后UART口与WIFI模块连接,最后再使用一个GPIO作为WIFI模块的重启和复位控制,即可实现该模块完整控制。
三、程序初始化
本文使用USART3与WIFI模块进行连接,因此将对该部分进行初始化。
`void USART3_GpioInit(void)
{
/* enable GPIO clock */
rcu_periph_clock_enable(BSP_USART3_GPIO_RCU);
/* configure the USART0 TX pin and USART0 RX pin */
gpio_af_set(BSP_USART3_TX_PORT, GPIO_AF_7, BSP_USART3_TX_PIN);
gpio_af_set(BSP_USART3_RX_PORT, GPIO_AF_7, BSP_USART3_RX_PIN);
/* configure USART0 TX as alternate function push-pull */
gpio_mode_set(BSP_USART3_TX_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, BSP_USART3_TX_PIN);
gpio_output_options_set(BSP_USART3_TX_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, BSP_USART3_TX_PIN);
/* configure USART0 RX as alternate function push-pull */
gpio_mode_set(BSP_USART3_RX_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, BSP_USART3_RX_PIN);
gpio_output_options_set(BSP_USART3_RX_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, BSP_USART3_RX_PIN);
}`
串口波特率配置函数:
`void USART3_BoudRateConfig(uint32_t boud)
{
/* enable USART clock */
rcu_periph_clock_enable(BSP_USART3_RCU);
/* USART configure */
usart_deinit(BSP_USART3_USART);
usart_baudrate_set(BSP_USART3_USART, boud);
usart_receive_config(BSP_USART3_USART, USART_RECEIVE_ENABLE);
usart_transmit_config(BSP_USART3_USART, USART_TRANSMIT_ENABLE);
usart_enable(BSP_USART3_USART);
}`
Wifi模块初始化
`void USRC210_Init(void)
{
uint8_t strBuf[200];
uint8_t i,status;
while(1)
{
i=0;
status=1;
//1. Reset the UsrC210
Wifi_Reset();
//2.1 Send +++ Wake UsrC210
if(UsrC210SendCmd("+++")!=3)
{
continue;
}
//2.2 Send a Wake UsrC210 Into CMD Mode
if(UsrC210SendCmd("a")!=1)
{
continue;
}
//3. Set WIFI Mode
while(UsrC210SendCmd("AT+WMODE=APSTA\r\n")!=1)
{
if(i++>CmdRepeatCount)
{
status=0;
break;
}
}
if(!status)continue;
//4. Set STA
i=0;
sprintf((char*)strBuf,"AT+WSTA=%s\r\n",STAMSG);
while(UsrC210SendCmd((char*)strBuf)!=1)
{
if(i++>CmdRepeatCount)
{
status=0;
break;
}
}
if(!status)continue;
//5. Set AP
i=0;
sprintf((char*)strBuf,"AT+WAP=%s\r\n",APMSG);
while(UsrC210SendCmd((char*)strBuf)!=1)
{
if(i++>CmdRepeatCount)
{
status=0;
break;
}
}
if(!status)continue;
//6. Set WEB LOGIN
i=0;
sprintf((char*)strBuf,"AT+WEBU=%s\r\n",LOGINMSG);
while(UsrC210SendCmd((char*)strBuf)!=1)
{
if(i++>CmdRepeatCount)
{
status=0;
break;
}
}
if(!status)continue;
//7. Set MID
i=0;
sprintf((char*)strBuf,"AT+MID=%s\r\n",MID);
while(UsrC210SendCmd((char*)strBuf)!=1)
{
if(i++>CmdRepeatCount)
{
status=0;
break;
}
}
if(!status)continue;
//8. SET TCP CLIENT
i=0;
sprintf((char*)strBuf,"AT+SOCKA=%s\r\n",SERVERMSG);
while(UsrC210SendCmd((char*)strBuf)!=1)
{
if(i++>CmdRepeatCount)
{
status=0;
break;
}
}
if(!status)continue;
//9. Reset The UsrC210
i=0;
while(UsrC210SendCmd("AT+Z\r\n")!=1)
{
if(i++>CmdRepeatCount)
{
status=0;
break;
}
}
if(!status)continue;
else
{
delay_ms(5000);
break;
}
}
}`
在Wifi模块初始化中,需要定义一些参数,这样初始化后的模块就能拥有连接到以太网的信息。
`uint8_t STAMSG[60]="CMCC-sct3,45mnbqdb"; //连接的网络名字和密码
uint8_t APMSG[40]="WG-0001,WG123456";//模块作为AP的名字和密码
uint8_t LOGINMSG[40]="WG-0001,WG123456";//登录模块的名字和密码
uint8_t SERVERMSG[72]="TCPC,47.103.12.149,8181";//远程服务器端口
uint8_t ServerName[20]="test.usr.cn,80"; //可以随便配置
uint8_t UrlName[12]="/1.php[3F]";
char OKMSG[4]={0x10,0xAA,0xBB,0xCC};//接收到正确信号返回信息
char PLSMSG[4]={0x10,0xCC,0xDD,0xEE};//发送心跳信号,如每秒连接
char RESMSG[4]={0xFF,0xFF,0xFF,0xFF};//返回保留信息`
四、定义通信协议
协议解析代码
`void Decode_Packet(void)
{
u8 packet_len;
u8 relay_status[4];
u16 crc_get, crc_cal;
if(UartRecvMessage())
{
packet_len = uart1receBuf[0];
if(packet_len==0x10)
{
crc_get = uart1receBuf[packet_len - 2];
crc_get = (crc_get<< 8) | uart1receBuf[packet_len -1];
crc_cal = crc16(uart1receBuf,packet_len-2);
if(crc_get!=crc_cal)
{
return;
}
else
{
ic_address=uart1receBuf[1];
R=uart1receBuf[2];
B=uart1receBuf[3];
G=uart1receBuf[4];
W=uart1receBuf[5];
relay_status[0] = uart1receBuf[6];
relay_status[1] = uart1receBuf[7];
relay_status[2] = uart1receBuf[8];
relay_status[3] = uart1receBuf[9];
reserved_data = (uart1receBuf[10]<<24)|(uart1receBuf[11]<<16)|(uart1receBuf[12]<<8)|(uart1receBuf[13]);
DMX512_Buf_Init(0xf0);
Update_Led();
LedFlag = 1;
Relay_Operation(1,relay_status[0]);
Relay_Operation(2,relay_status[0]);
Relay_Operation(3,relay_status[0]);
Relay_Operation(4,relay_status[0]);
SendOK();
}
}
UartFlushRecvBuf();
}
}`
软件CRC解析
`unsigned short crc16(unsigned char *src, unsigned long sizes) {
unsigned char *ptr = NULL;
unsigned short i, j, n, ccitt;
unsigned short c = 0;
unsigned short tabccitt[256];
unsigned short crc = 0;
unsigned short tmp = 0;
unsigned short sc = 0;
for (i = 0; i < 256; i++) {
ccitt = 0;
c = i << 8;
for (j = 0; j < 8; j++) {
if ( (ccitt ^ c) & 0x8000 ){
ccitt = ( ccitt << 1 ) ^ 0x1021;
}
else{
ccitt = ccitt << 1;
}
c = c << 1;
}
tabccitt[i] = ccitt;
}
ptr = src;
crc = 0xFFFF;
if (ptr != NULL) for (n = 0; n < sizes; n++) {
sc = 0X00FF & (unsigned short) *ptr;
tmp = (crc >> 8) ^ sc;
crc = (crc << 8) ^ tabccitt[tmp];
ptr++;
}
return crc;
}`
定时发送心跳连接函数
`void SendPulse(void)
{
u8 buf[16];
u16 i, crc;
for(i = 0; i <= 13; i++)
{
if(i<=3)
buf[i]=PLSMSG[i];
else if(i<=9)
buf[i]=MID[i-4];
else
buf[i]=RESMSG[i-10];
}
crc = crc16(buf,14);
buf[14] = crc>>8;
buf[15] = (crc&0x00ff);
Send_Data_Uart3((char *)buf,16);
}
`
主函数While循环的操作
`while(1)
{
Decode_Packet();
if(TimerCmdFlag>=PULSE_TIME)
{
TimerCmdFlag = 0;
Send_Pulse();
LED0 = !LED0;
}
}`