위즈네트 아카데미

TUTORIAL

튜토리얼

Home  > 튜토리얼

W5500 W5500-EVB활용 Chat Client 구현하기 - 2

WIZnet Academy 2015.04.09 09:18 조회 수 : 5

지난 포스팅(W5500-EVB 활용 Chat Client 구현하기 - 1)에 구현된 Chat Client 를 업그레이드 해보겠습니다. 아래의 2가지로 업그레이드 합니다.

  1. “Socket Status Register”의 상태에 따라 해당 동작 진행

  2. Serial로 입력 받은 값을 버퍼에 저장을 하다가, CR과 LF 값을 입력 받으면 저장된 버퍼의 값을 TCP로 전송


첫번째 수정,

main 함수의 while문에서 “Socket Status Register”의 상태를 계속 확인을 하고, 그 상태에 따라 동작하게 됩니다.

SOCK_CLOSED 상태일때, 소켓을 생성함.

SOCK_INIT 상태일때, 서버에 접속 시도함.

SOCK_ESTABLISHED 상태일때, 데이터를 주고 받음.
while(1) {
switch(getSn_SR(sn)) {
case SOCK_CLOSED:
/* Socket Closed State */
//Socket Creation
if(socket(sn, Sn_MR_TCP, port, 0x00)==sn){
printf("%d:Socket Openedrn",sn);
}
else{
printf("%d:Socket Errorrn",sn);
while(1);
}
break;

case SOCK_INIT:
/* TCP Socket Creatation */
printf("%d:Connecting, ip[%d.%d.%d.%d] port [%d]rn", sn, ip[0], ip[1], ip[2], ip[3], port);
//Connent TCP Server
if(connect(sn,ip,port)==SOCK_OK);
else {
printf("%d:Connect Errorrn",sn);
while(1);
}
break;
case SOCK_LISTEN:
/* TCP Server Mode */

break;
case SOCK_ESTABLISHED:
/* TCP ESTABLISHED */
//Connect Interrupt Check
if(getSn_IR(sn) & Sn_IR_CON) {
printf("%d:Connectedrn",sn);
setSn_IR(sn,Sn_IR_CON);
Board_LED_Set(0, false);
Board_LED_Set(1, true);
}
//Receive Data Check
if((size = getSn_RX_RSR(sn)) > 0) {
if(size > DATA_BUF_SIZE) size = DATA_BUF_SIZE;
recv(sn,gDATABUF,size);
EtherToSerial(gDATABUF, size);
}
SerialToEther(sn);
break;

case SOCK_CLOSE_WAIT:
/* Disconnect request */

break;
}
}

 

두번째 수정,

기존에는 수신된 Serial 데이터를 1바이트씩 TCP로 전송을 했지만, 수정된 코드에서는 수신된 Serial 데이터를 버퍼에 계속 쌓으면서 CR과 LF 값이 입력되면 TCP로 지금까지 수신한 Serial 데이터를 전송하도록 수정했고, UART를 인터럽트 처리했습니다

아래 코드는 UART 인터럽트를 Enable 시켜주는 부분으로 main 문에 추가합니다.
<p style="margin-left: 2em;">// Enable UART interrupt
Chip_UART_IntEnable(LPC_USART, (UART_IER_RBRINT | UART_IER_RLSINT));
// Start UART interrupt
NVIC_EnableIRQ(UART0_IRQn);
</p>

아래코드는 UART 인터럽트가 발생되면, UART로 입력된 데이터를 sr_rx_data 버퍼에 계속 쌓아 나가다가  CR과 LF 값이 입력되면 TCP로 지금까지 수신한 Serial 데이터를 전송하도록 한는 부분입니다.
// Serial => Ethernet
int SerialToEther(uint8_t sn)
{
if(sr_rx_data[sr_rx_size-2]==CR && sr_rx_data[sr_rx_size-1]==LF){
send(sn, sr_rx_data, sr_rx_size);
sr_rx_size = 0;
}
/*if((Chip_UART_ReadLineStatus(LPC_USART) & UART_LSR_RDR) == 1){
sr_rx_data[sr_rx_size]=Chip_UART_ReadByte(LPC_USART);
sr_rx_size++;
// Serial CR LF Check
if(sr_rx_data[sr_rx_size-2]==CR && sr_rx_data[sr_rx_size-1]==LF){
send(sn, sr_rx_data, sr_rx_size);
sr_rx_size = 0;
}
//Chip_UART_SendBlocking(LPC_USART, &sr_rx_data, 1);
}*/
return 0 ;
}
//UART interrupt function
void UART_IRQHandler(void)
{
sr_rx_data[sr_rx_size]=Chip_UART_ReadByte(LPC_USART);
sr_rx_size++;
}

 

보완점

  1. uart 수신단 보완

  2. TCP Disconnect 처리

  3. 예외 처리 및 에러 처리


아래는 전체 코드 입니다.
#if defined (__USE_LPCOPEN)
#if defined(NO_BOARD_LIB)
#include "chip.h"
#else
#include "board.h"
#endif
#endif

#include "socket.h"
#include "spi_handler.h"
#include "w5500_init.h"

// TODO: insert other include files here

// TODO: insert other definitions and declarations here
#define SOCK_TCPS0 0
#define DATA_BUF_SIZE 2048
uint8_t gDATABUF[DATA_BUF_SIZE];

#define CR 0x0D
#define LF 0x0A
#define SR_RX_BUF_SIZE 2048
uint8_t sr_rx_data[SR_RX_BUF_SIZE];
uint16_t sr_rx_size = 0;
uint8_t sn=SOCK_TCPS0;

// Ethernet => Serial
int EtherToSerial(uint8_t* buf,uint16_t size)
{
uint8_t i;
for(i=0 ; i < size ; i++){
putchar(buf[i]);
}
putchar('r');
putchar('n');
//Chip_UART_Send(LPC_USART, buf, size);
return 0 ;
}
// Serial => Ethernet
int SerialToEther(uint8_t sn)
{
if(sr_rx_data[sr_rx_size-2]==CR && sr_rx_data[sr_rx_size-1]==LF){
send(sn, sr_rx_data, sr_rx_size);
sr_rx_size = 0;
}
/*if((Chip_UART_ReadLineStatus(LPC_USART) & UART_LSR_RDR) == 1){
sr_rx_data[sr_rx_size]=Chip_UART_ReadByte(LPC_USART);
sr_rx_size++;
// Serial CR LF Check
if(sr_rx_data[sr_rx_size-2]==CR && sr_rx_data[sr_rx_size-1]==LF){
send(sn, sr_rx_data, sr_rx_size);
sr_rx_size = 0;
}
//Chip_UART_SendBlocking(LPC_USART, &sr_rx_data, 1);
}*/
return 0 ;
}
//UART interrupt function
void UART_IRQHandler(void)
{
sr_rx_data[sr_rx_size]=Chip_UART_ReadByte(LPC_USART);
sr_rx_size++;
}


int main(void) {

uint8_t ip[4]={192,168,1,218};
uint16_t port=23;
uint16_t size=0;

#if defined (__USE_LPCOPEN)
#if !defined(NO_BOARD_LIB)
// Read clock settings and update SystemCoreClock variable
SystemCoreClockUpdate();
// Set up and initialize all required blocks and
// functions related to the board hardware
Board_Init();
// Set the LED to the state of "On"
Board_LED_Set(0, true);
#endif
#endif
SPI_Init();
W5500_Init();
Net_Conf();

// Enable UART interrupt
Chip_UART_IntEnable(LPC_USART, (UART_IER_RBRINT | UART_IER_RLSINT));
// Start UART interrupt
NVIC_EnableIRQ(UART0_IRQn);


while(1) {
switch(getSn_SR(sn)) {
case SOCK_CLOSED:
/* Socket Closed State */
//Socket Creation
if(socket(sn, Sn_MR_TCP, port, 0x00)==sn){
printf("%d:Socket Openedrn",sn);
}
else{
printf("%d:Socket Errorrn",sn);
while(1);
}
break;

case SOCK_INIT:
/* TCP Socket Creatation */
printf("%d:Connecting, ip[%d.%d.%d.%d] port [%d]rn", sn, ip[0], ip[1], ip[2], ip[3], port);
//Connent TCP Server
if(connect(sn,ip,port)==SOCK_OK);
else {
printf("%d:Connect Errorrn",sn);
while(1);
}
break;
case SOCK_LISTEN:
/* TCP Server Mode */

break;
case SOCK_ESTABLISHED:
/* TCP ESTABLISHED */
//Connect Interrupt Check
if(getSn_IR(sn) & Sn_IR_CON) {
printf("%d:Connectedrn",sn);
setSn_IR(sn,Sn_IR_CON);
Board_LED_Set(0, false);
Board_LED_Set(1, true);
}
//Receive Data Check
if((size = getSn_RX_RSR(sn)) > 0) {
if(size > DATA_BUF_SIZE) size = DATA_BUF_SIZE;
recv(sn,gDATABUF,size);
EtherToSerial(gDATABUF, size);
}
SerialToEther(sn);
break;

case SOCK_CLOSE_WAIT:
/* Disconnect request */

break;
}
}
return 0 ;
}

W5500-EVB 활용 Chat Client 구현하기 – 1

W5500-EVB 활용 Chat Client 구현하기 – 3

W5500-EVB 활용 Chat Client 구현하기 – 4

W5500-EVB 활용 Chat Client 구현하기 – 5

 출처 : OSHW Alchemist