[C con Clase] Comunicación serie.

raul castelar raulcastelar en hotmail.com
Mie Ene 23 22:43:47 CET 2013


Hola a todos.Que tal?
Aquí expongo mi primer mensaje como nuevo usuario.El tema es el siguiente:Estoy intentando comunicar un microcontrolador con un PC a través del puerto serie, y lo estoy haciendo en windows xp, asi que utilizo las API, la cuestión es que envía estupendamente utilizando WriteFile, pero  y ClearComError, ReadFile me dan problemas ; no entra en estas funciones y me devuelven un  FALSE; he miado el error con GetlastError y lo identifica como 998 "Acceso no válido a ubicación de memoria".Estoy seguro que es por falta de experiencia con estas funciones, si alguien se ha encontrado con ese error, me gustaría saber que hago mal.  Aquí os dejo el código con comentarios es fácil de entender, seguro¡¡ lo he sacado de aquí: http://articulos.conclase.net/serie/Por supuesto yo lo he retocado para mi finalidad.
Para empezar, lo único que quiero es apuntar  dos vectores a los datos de entrada y salida, y en principio solo me bastaría con recibir un ACK 0x06 en hexadecimal y enviar ENQ un 0x05 en hexadecimal. Aquí os lo pongo con comentarios.
#include <stdio.h>#include <stdlib.h>#include <windows.h>#define ENQ 0x05;#define ACK 0X06;

DCB dcb;         //declaraciones glogales estructuras punteros etc...HANDLE canal;   HGLOBAL hCadena, hSalida;char *dato_t,*dato_r;char datos_recibidos[100];int accion=1;
DWORD dwEvtMask;void LeeSerie();void escribir_serie (char *buf);BOOL abrir_canal();void FinComunicacion(void);
int main( ) {                                                //dentro del main el código no esta terminado, utilizo un switch case para primero recibir y luego enviar                                                //la comunicacion es semiduplex pues no envia y recibe al mismo tiempo. dependiendo de "accion"                                                                                                                            
    if (abrir_canal()==0)                 //si retorna un 1 se ha abierto canal "CreatefFile"    {return (EXIT_SUCCESS);}    while(1){    switch (accion)            case  1:                {                 WaitCommEvent(canal, &dwEvtMask, NULL);         if(dwEvtMask & EV_RXCHAR)            {LeeSerie();                                     datos_recibidos[100]=*dato_r;         }            accion=2;                        case 2:                             	dato_t = (char *) malloc (1*sizeof (byte));             *dato_t=ENQ;             escribir_serie(dato_t);             //free (dato);             accion=1;                      }                         FinComunicacion();       return (EXIT_SUCCESS);    }}
/*void IniciarBuffers()  //esta parte de aqui estoy pensando en quitarla, y reservar memoria para los puntero con malloc{                             //no le hagais caso iniciar buffer   hCadena = GlobalAlloc(GMEM_MOVEABLE, 4096);//reserva memoria   dato_r = (char *)GlobalLock(hCadena);//castin tranforma la variable a tipo int   hSalida = GlobalAlloc(GMEM_MOVEABLE, 4096);//reserva memoria   dato_t = (char *)GlobalLock(hSalida); }*/void escribir_serie (char *buf)   //esta función funciona estupendamente{   char Buffer[1024];   DWORD n, l, p, err;      strcpy(Buffer, buf);   l = strlen(Buffer);//Calcula el número de caracteres de la cadena apuntada por s.   p = 0;   while(l) {      if(!WriteFile(canal, &Buffer[p], l-p, &n, NULL))//Escribe datos a un fichero      {                                               //La función empieza escribiendo datos al fichero en la posición indicada por el puntero del fichero. Después de que la operación de escritura ha sido completada, el puntero del fichero se ajusta en el número de bytes escritos actualmente      	 err = GetLastError();      	 if(err != ERROR_IO_PENDING)printf ("datos enviados incorrectamente");       	    return;      }      l -= n;      p += n;   }}      /*   void LiberarBuffers()  //esto tampoco vale         {            GlobalUnlock(hCadena);            GlobalFree(hCadena);              GlobalUnlock(hSalida);            GlobalFree(hSalida);             }*/

void  FinComunicacion(void){   // Liberar máscara de eventos del puerto serie:   SetCommMask(canal, 0);   // Cerrar el puerto serie:   CloseHandle(canal);   // Comunicación interrumpida:   }BOOL abrir_canal()           //esto funciona por que consigo enviar datos por lo que el fichero esta abierto{BOOL bit_copia;    canal = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE,0, NULL, OPEN_EXISTING, 0 , NULL);   if(canal ==INVALID_HANDLE_VALUE)    {printf("ERROR: CreateFile. Inicialización puerto serie");  //Devuelve un manipulador que puede ser usado para acceder al objeto      return 0;}       dcb.BaudRate = 4800;   dcb.ByteSize = 8;   dcb.Parity = ODDPARITY;   dcb.StopBits = ONESTOPBIT;      bit_copia = GetCommState(canal, &dcb);    if(!bit_copia)     {printf ("ERROR: GetCommState. Inicialización puerto serie");      return 0;}        if(!SetCommMask(canal, EV_RXCHAR))    { printf ("No se pudo activar la el evento de lectura.");      return 0; }return 1;}
void LeeSerie()   //el problema está aquí en leerserie{   COMSTAT cs;     DWORD x,err;    DWORD *y;   y=&x;        if( ! ClearCommError (canal, y,cs));            err = GetLastError();            if (err=ERROR_NOACCESS) printf ("\n998 (0x3E6)Acceso no válido a ubicación de memoria\n");        if(!ReadFile (canal, dato_r, cs.cbInQue, &x, NULL));            err = GetLastError();            if (err=ERROR_NOACCESS)     printf ("\n998 (0x3E6)Acceso no válido a ubicación de memoria\n");                       return;}
Gracias de ante mano por vuestro tiempo. 		 	   		  
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://listas.conclase.net/pipermail/cconclase_listas.conclase.net/attachments/20130123/678e0b84/attachment.html>


Más información sobre la lista de distribución Cconclase