Recepción de datos por un socket UDP - CCS

Buenas tardes, despues de buscar y leer todos los posts relacionados, abro este tema para realizarles unas consultas de mi proyecto.
La idea es, mediante un PIC 18F252 y un ENC28J60, enviar comandos UDP con visual basic y que el micro tome deciciones y me encienda salidas, datos x usart, etc.
Comence con el famoso ejemplo "11 Ethernet" lo dejo adjuntado.
Ya pude migrar el codigo al 18F252, y me anda realmente bien, puedo hacer ping y hasta meterme por http y ver algun texto ahi escrito.
Por lo que estuve leyendo e investigando debo usar las sig. funciones:

UDPOpen()
UDPIsGetReady()
UDPGet()
UDPDiscard()
UDPClose()

Se que ese debe ser el orden de utilizacion, pero no se como usar exactamente esas funciones, existe algun manual donde esten bien explicadas?
Aclaro que tengo conociminetos de PICs, he hecho muchas cosas, pero nada de red, es mi primer proyecto ethernet.

Si alguien tiene algun codigo de donde me pueda guir o alguna ayuda realmente se lo agradeceria.
 

Adjuntos

  • 11 Ethernet.rar
    730.2 KB · Visitas: 43
Si puedes hacer ping, te comento que has dado un gran paso ya que estas garantizando el acceso a capa 3 (capa de red) (modelo OSI). Ahora para escalar a CAPA 4 (CAPA DE TRANSPORTE (UDP O TCP) solo te falta la utilización de unas pocas funciones.

Antes de ayudarte con código me gustaría que me indicaras si estas trabajando con el stack tcp-ip de microchip en c18 (MPLAB) o en CCS.(stack tcp-ip de microchip modificado para CCS).

Te comento que yo solo he trabajado este aspecto en CCS, no con Mplab c18 y aunque esencialmente es lo mismo, existen ligeras diferencias para que se pueda hacer funcionar el pic..



Disculpa, olvidé que habías adjuntado el archivo y efectivamente ese es CCS. ok

te anexo un código ejemplo.. para que te guíes...

Está con el 18f4550... pero en fin, puedes adaptarlo

Código:
#include <18f4550.h>
#fuses XT,MCLR,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOPBADEN, NOLVP,NOCPD,NODEBUG,NOWRT,NOVREGEN
#use delay(clock=4000000)


// Conexión entre el PIC18F4550 y el Modulo ENC28J60 (Se conecta directamente sin adaptador de voltajes).


#define ON output_high //SE DEFINE ESTADO ALTO COMO ON
#define OFF output_low //SE DEFINE ESTADO BAJO COMO OFF

#define LedR PIN_B4 //SE DEFINE LED ROJO EN EL PIN RB4



#define PIN_ENC_MAC_SO PIN_C7 // Conectar con PIN MISO del ENC28J60.
#define PIN_ENC_MAC_SI PIN_B0 // Conectar con PIN MOSI del ENC28J60.
#define PIN_ENC_MAC_CLK PIN_B1 // Conectar con PIN SCK del ENC28J60.
#define PIN_ENC_MAC_CS PIN_B3 // Conectar con PIN CS del ENC28J60.
#define PIN_ENC_MAC_RST PIN_B5 // Conectar con PIN RST del ENC28J60.

#define PIN_ENC_MAC_INT PIN_D2 // Conectar con PIN INT del ENC28J60.
#define PIN_ENC_MAC_WOL PIN_D3 // Conectar con PIN WOL del ENC28J60.




//Protocolos a utilizar.

#define STACK_USE_MCPENC TRUE
#define STACK_USE_ARP TRUE
#define STACK_USE_ICMP TRUE
#define STACK_USE_UDP TRUE


#include "tcpip/stacktsk.c"

NODE_INFO inforemota; //nombre nuevo de la estructura NODE_INFO
UDP_SOCKET s; //define el socket s


void MAC_REMOTA (void) //MAC DE MI PC= 00 19 66 16 CF 26
{

inforemota.MACAddr.v[0]=0x00;
inforemota.MACAddr.v[1]=0x19;
inforemota.MACAddr.v[2]=0x66;
inforemota.MACAddr.v[3]=0x16;
inforemota.MACAddr.v[4]=0xCF;
inforemota.MACAddr.v[5]=0x26;

}

void IP_REMOTA (void) //*aquí escribo la IP de destino, que corresponde a la de mi PC

{
inforemota.IPAddr.v[0]=192;
inforemota.IPAddr.v[1]=168;
inforemota.IPAddr.v[2]=1;
inforemota.IPAddr.v[3]=111;


}


// Microchip VendorID, MAC: 00-04-A3-XX-XX-XX
void MACAddrInit(void) //SE DEFINE MAC DEL DISPOSITIVO
{
MY_MAC_BYTE1=0x00;
MY_MAC_BYTE2=0x04;
MY_MAC_BYTE3=0xA3;
MY_MAC_BYTE4=0x00;
MY_MAC_BYTE5=0x00;
MY_MAC_BYTE6=0x01;
}

void IPAddrInit(void) //SE DEFINE LA IP del PIC
{
//Direccion IP
MY_IP_BYTE1=192;
MY_IP_BYTE2=168;
MY_IP_BYTE3=1;
MY_IP_BYTE4=111;

//Mascara de Subred //SE DEFINE LA MÁSCARA DE SUB RED
MY_MASK_BYTE1=255;
MY_MASK_BYTE2=255;
MY_MASK_BYTE3=255;
MY_MASK_BYTE4=0;

//Puerta de Enlace //SE DEFINE EL GATEWAY O PUERTA DE ENLACE
MY_GATE_BYTE1=192;
MY_GATE_BYTE2=168;
MY_GATE_BYTE3=0;
MY_GATE_BYTE4=1;
}

void envio_datos(void) // esta función será llamada en el main
{

int8 Dato; //defino una variable intermedia

{
if (UDPIsPutReady(s))
{
OFF(LedR); /*cambio los leds para detectar el envio
de datos en la placa*/
delay_ms(500);
Dato=0xff;
UDPPut(Dato);

//printf(UDPPut, "%i", TMPC); /*no sé cual de las dos instrucciones me sirve
// realmente para ver los datos que envío, no sé
//bien la diferencia entre ambas, he probado a
// poner las dos para asegurar que se envían los
//datos, si alguien sabe la diferencia lo agradecería*/

delay_ms(100);
}

}
UDPFlush(); //envío los datos que están en el buffer de transmisión
ON(LedR);
}


void main(void) //FUNCIÓN PRINCIPAL
{


OFF(LedR); //APAGA EL LED ROJO

MAC_REMOTA();
IP_REMOTA();
MACAddrInit(); //CARGA EL VALOR DE LA MAC
IPAddrInit(); //CARGA EL VALOR DE LA IP


ON(LedR); //ENCIENDE EL LED ROJO
delay_ms(1000); //DURANTE 1 SEG
OFF(LedR); //APAGALO
delay_ms(1000); //DURANTE 1 SEGUNDO
ON(LedR); //VUELVE A ENCENDERLO
delay_ms(1000); //DURANTE OTRO SEGUNDO
OFF(LedR); //VUELVE A APAGARLO
delay_ms(1000); //DURANTE OTRO SEGUNDO
ON(LedR);

StackInit(); //INICIALIZA LA PILA

//ENCIENDELO INDEFINIDAMENTE

s=UDPOpen( 1234, &inforemota, 2345);


if (s !=INVALID_UDP_SOCKET)
{

while(TRUE)
{
StackTask();
envio_datos();
}
}


UDPClose(s);

}

///saludos, cualquier cosa, me preguntas.....
 
Última edición por un moderador:
Buenisimo! ya mando datos y los leo con un monitor desde una PC!!!!!.
:D:D:D:D:D
Ahora 2 consultas:
1. Necesito ayuda con la sintaxis para recibir
2. La IP y MAC de destino (en este caso mi PC monitor remoto), la tengo fija por codigo, como hago para que funcione con cualquier PC que se quiera conectar???

muchas gracias
 
Me alegra mucho que ya estes recibiendo datos... Con respecto a lo que me preguntas¡ Si quieres conectar el dispositivo a cualquier maquina y que funcione de igual manera, te comento que en ese caso necesitarías incorporar el protocolo DHCP CLIENTE en tu código. El protocolo DHCP(DINAMIC HOST CONTROL PROTOCOL) permite que el router de la red donde estes conectado, le asigne una IP automática al dispositivo, tal como lo hace con un computador, telefono o cualquier otro aparato que utilize protocolo Ethernet, ya sea inalámbrico (wi-fi IEEE 802.11) o alámbrico (IEEE-802.3).. Te comento que en los proyectos que he realizado nunca he utilizado DHCP por lo que en este caso, creo que deberas investigar un poco más sobre como incorporar ese protocolo en el código. Lo que si te puedo asegurar es que no es tán dificil, ojala que lo logres y me puedas comentar tu experiencia para ver si yo me animo y se lo adapto tambien a mis propotipos...

Saludos.....
 
Buenisimo! ya mando datos y los leo con un monitor desde una PC!!!!!.
:D:D:D:D:D
Ahora 2 consultas:
1. Necesito ayuda con la sintaxis para recibir
2. La IP y MAC de destino (en este caso mi PC monitor remoto), la tengo fija por codigo, como hago para que funcione con cualquier PC que se quiera conectar???

muchas gracias
Hola, estoy con el mismo problema que vos, conseguiste hacer andar el dhcp?
Gracias
 
Saludos..

Tengo un buen tiempo sin realizarle modificaciones al código por estar ocupado en otras cosas.

Sin embargo, hoy mismo me voy a poner a trabajar al respecto para poder compartir la experiencia.

De todas maneras, sugiero que vayas trabajando para ver si se logra hacer funcionar el DHCP pronto.
 
Buenas, he estado trabajando en un proyecto similar. PIC18F4550+ENC28J60 con un programa en PC (Aplicación en C#). Enviar datos del PIC a la PC funciona perfecto, mi problema es al recibir datos de la PC al PIC, aparentemente no lee nada.

Estoy usando el Stack TCP-IP para CCS; me he guiado de los manuales de microchip:
- http://www.egr.msu.edu/classes/ece480/capstone/fall11/group03/TCPIP Stack Help.pdf (pag 548 -UDP)
-http://ww1.microchip.com/downloads/en/AppNotes/00833b.pdf (pag61 -UDP)

El Stack TCP-IP en CCS lo conseguí del siguiente foro:
http://www.todopic.com.ar/foros/index.php?topic=44465.0 (gracias al usuario jonathanPIC888 que colgó un rar con ejemplos, me guié del EJEMPLO9 que es UDP).

He simulado en PROTEUS + HERCULES e igual que con los dispositivos reales la transmisión del PIC al HERCULES funciona bien y en la recepción es mi dolor de cabeza, para debugear use un mensaje por comunicación serial como flag, el cual nunca llega:
if (UDPIsGetReady(rx_socket_1)) {
fprintf(DEBUG,"RECIBI ALGO");
while(UDPGet(&c)) {
}
UDPDiscard();
}

En la condicional UDPIsGetReady(rx_socket_1) siempre me devuelve el valor de False, pese a que le mando datos por el hercules.
Lo que note fue que en Pproteus me salia un aviso de deshabilitar el checksum del IP cada vez que enviaba datos del Hercules.
Captura.PNG

Lo que hice fue deshabiliar eso en mi tarjeta de red de mi PC:
Captura2.PNG

Pero ni así logro que se lean los datos

Agradecería si tuvieran algún código del cual guiarme. Voy a centrarme en solo la recepción por ahora.
 
Hola, este proyecto lo hice hace mucho, ya no me acuerdo nada, pero trato de copiarte aca los pedazos de mi codigo que use para recibir:
Primero tengo una funcion llamada recibo_datos:
Código:
int8 ()
{
   int8 rx;
   if (UDPIsGetReady(s))
   {
      while(UDPGet(&rx))
      {
         return rx;
      }
   }
}

Luego en mi codigo principal tengo:
Código:
if (s !=INVALID_UDP_SOCKET)
   {   
      while(TRUE)
      {
         StackTask();
         dato=recibo_datos();
         bla bla bla mucho mas codigo de otras cosas
      }
   }
Ojala pueda destrabarte con tu problema. cualquier cosa volve a escribir y veo si te puedo ayudar.
:)
 
Gracias por el código. Había realizado un código similar siguiendo el modelo de una máquina de estados para la función de recibir datos, y encontré que mi error era que no estaba enviando datos por el hércules (de la PC al PIC real y PIC de proteus en ambos casos no obtenía nada). Eso lo pude ver recién cuando analice las tramas en la red con el uso de WireShark.
Lo que hice fue reiniciar mi PC y probé con el PIC real y por fin pude recibir datos, y podía entrar a la condicional del UDPIsGetReady(s), ahora solo me centraré en trabajar la trama.

Una pregunta aparte de esto, he estado viendo muchos ejemplos de recibir datos por UDP, pero no lo trabajan como interrupción como sucede en otros tipos de comunicación como SPI o Serial. En este caso ponen la función de recibir datos dentro de un "WHILE(true)" que esta corriendo en el Main.c. ¿Es posible hacer que la recepción de datos se de por interrupción? Mi pregunta es porque aveces dentro de la lógica se toma tiempos de mili-segundos por ejemplo para escribir en un LCD y si en ese lapso llegan varios paquetes de datos como haria para recibirlos todos.
 
Una pregunta aparte de esto, he estado viendo muchos ejemplos de recibir datos por UDP, pero no lo trabajan como interrupción como sucede en otros tipos de comunicación como SPI o Serial. En este caso ponen la función de recibir datos dentro de un "WHILE(true)" que esta corriendo en el Main.c. ¿Es posible hacer que la recepción de datos se de por interrupción? Mi pregunta es porque aveces dentro de la lógica se toma tiempos de mili-segundos por ejemplo para escribir en un LCD y si en ese lapso llegan varios paquetes de datos como haria para recibirlos todos.
Normalmente, las implementaciones del stack TCP/IP dispone de buffers mas o menos grandes donde colocan los paquetes con la información recibida. Si ajustás correctamente el buffer (o el dispositivo que usés lo permite), eso es todo de lo que tenés que preocuparte.
Analizá la documentación del ENC28J60 para saber como hace las cosas...
 
Última edición:
Atrás
Arriba