Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Otros entornos y lenguajes > .NET
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 06-12-2023
REHome REHome is offline
Miembro
 
Registrado: jul 2003
Ubicación: España
Posts: 454
Poder: 21
REHome Va por buen camino
ERROR: Referencia a objeto no establecida como instancia de un objeto.

Hola:

En este código me sale un error y no se como corregirlo, ya que me interesa mostrar datos en pantalla y no me sale.

Ver error.

Código hecho hasta ahora.
Código:
using System;
using System.IO.Ports;

namespace Almacenar_byte_puerto_serie_Consola_01
{
    internal class Program
    {
        static SerialPort puertoSerie;
        static byte[] datoRecibido;
        static void Main(string[] args)
        {
            #region Configuración ventana.
            // Título de la ventana.
            Console.Title = "Almacenar byte[] desde el puerto serie.";

            // Tamaño de la ventana, x, y, o ancho y alto.
            const byte ANCHO_X = 70, ALTO_Y = 25;
            Console.SetWindowSize(ANCHO_X, ALTO_Y);

            // Color de fondo.
            Console.BackgroundColor = ConsoleColor.Black;

            // Color de las letras.
            Console.ForegroundColor = ConsoleColor.Yellow;

            // Limpiar pantalla y dejarlo todo en color de fondo.
            Console.Clear();

            // Visible el cursor.
            Console.CursorVisible = true;
            #endregion

            puertoSerie = new SerialPort()
            {
                // Configuración del puerto serie.
                PortName = "COM4",           // Nombre del puerto serie.
                BaudRate = 2400,             // Velocidad en baudios.
                Parity = Parity.None,        // Esquema para comprobar la paridad de cada byte recibido.
                StopBits = StopBits.One,     // Número de bits de parada por byte.
                DataBits = 8,                // Número de bits de datos por byte.
                Handshake = Handshake.None,  // Protocolo de establecimiento.
                DtrEnable = true,            // Línea de terminal de datos.
                RtsEnable = true,            // Línea de solicitud.

                // Establecer los tiempos de espera de lectura / escritura.
                ReadTimeout = 500,           // Tiempo de espera de escritura en ms.
                WriteTimeout = 500,          // Tiempo de espera de escritura en ms.

                // Más configuraciones.
                DiscardNull = false,         // Descartar bytes nulos recibidos.
                ParityReplace = 63,          // Reemplaza los bytes recibidos con errores de paridad.
                ReadBufferSize = 4096,       // Tamaño del búfer de lectura en bytes.
                WriteBufferSize = 2018,      // Tamaño del búfer de escritura en bytes.
                ReceivedBytesThreshold = 1   // Número de bytes que se necesitan.
            };

            puertoSerie.DataReceived += SerialPort_DataReceived;
            puertoSerie.Open();

            Console.WriteLine("Presiona cualquier tecla para detener la captura...");
            Console.ReadKey();

            puertoSerie.Close();

            Console.WriteLine("Datos recibidos:");
            MostrarBytes(datoRecibido);
        }
        static void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPort sp = (SerialPort)sender;
            int bytesToRead = sp.BytesToRead;
            byte[] buffer = new byte[bytesToRead];
            sp.Read(buffer, 0, bytesToRead);

            if (datoRecibido == null)
            {
                datoRecibido = buffer;
            }
            else
            {
                Array.Resize(ref datoRecibido, datoRecibido.Length + bytesToRead);
                Array.Copy(buffer, 0, datoRecibido, datoRecibido.Length - bytesToRead, bytesToRead);
            }
        }

        static void MostrarBytes(byte[] dato)
        {
            for (int i = 0; i < dato.Length; i++)
            {
                Console.Write($"{dato[i]} ");
            }
            Console.WriteLine();
        }
    }
}
Se trata de obtener bytes puro y duro desde el RS232 o puerto serie, almacenarlo en un array tipo byte[] y mostrarlo en pantalla.

¿Alguna idea?

Saludos.
__________________
http://electronica-pic.blogspot.com....n-arduino.html Manuales de electrónica general, PIC y Arduino.
Responder Con Cita
  #2  
Antiguo 07-12-2023
Avatar de delphi.com.ar
delphi.com.ar delphi.com.ar is offline
Federico Firenze
 
Registrado: may 2003
Ubicación: Buenos Aires, Argentina *
Posts: 5.932
Poder: 26
delphi.com.ar Va por buen camino
Son errores distintos el del título del hilo y el de la captura de pantalla. En la captura se ve que estás accediendo a un elemento del array "numeros", por el índice almacenado en la variable "contador", y este contador esta fuera del intervalo del array. O sea es menor que el mínimo o mayor al máximo. Fíjate en la captura que "numeros" tiene una dimensión de 6, y dado que las posiciones son en base cero, estas van de 0 a 5. Por otro lado la variable "contador" tiene el valor 6, o sea está intentando acceder al séptimo elemento de un array de seis.

Por otro lado veo seguidos tus posts, y espero que no suene mal lo que digo, pero creo que debes aprender las bases del lenguaje que estás usando. Me parece que te estás peleando con lo más básico sin poder abstraer el problema. Te recomiendo ver algún curso del lenguaje online, que sin lugar a dudas te hará ahorrar mucho tiempo. Lo primero que me aparece al buscar "C# básico": https://www.youtube.com/watch?v=6W2wYwHQNT4

Saludos!
__________________
delphi.com.ar

Dedique el tiempo suficiente para formular su pregunta si pretende que alguien dedique su tiempo en contestarla.

Última edición por delphi.com.ar fecha: 07-12-2023 a las 22:11:48.
Responder Con Cita
  #3  
Antiguo 07-12-2023
REHome REHome is offline
Miembro
 
Registrado: jul 2003
Ubicación: España
Posts: 454
Poder: 21
REHome Va por buen camino
Gracias por el vídeo.

Y... Perdón., me equivoqué de enlace sobre la imagen que en realidad es esta.



Saludos.
__________________
http://electronica-pic.blogspot.com....n-arduino.html Manuales de electrónica general, PIC y Arduino.
Responder Con Cita
  #4  
Antiguo 08-12-2023
Avatar de delphi.com.ar
delphi.com.ar delphi.com.ar is offline
Federico Firenze
 
Registrado: may 2003
Ubicación: Buenos Aires, Argentina *
Posts: 5.932
Poder: 26
delphi.com.ar Va por buen camino
Ok, según esa imagen dato es NULL, o sea no tiene un valor asignado, por ese motivo el NullReferenceException.
No puedes acceder a propiedades de objetos no asignados, es como averiguar la edad de un perro que no existe.

El error seguramente está en la llamada a la función, y suele ser correcto que la función falle, pero deberías evaluar la asignación del parámetro y fallar con NullArgumentException detallando el parámetro no asignado.

Saludos.
__________________
delphi.com.ar

Dedique el tiempo suficiente para formular su pregunta si pretende que alguien dedique su tiempo en contestarla.
Responder Con Cita
  #5  
Antiguo 08-12-2023
tsk tsk is offline
Miembro
 
Registrado: dic 2017
Posts: 52
Poder: 7
tsk Va por buen camino
Me da la impresión de que tu función SerialPort_DataReceived no se está ejecutando. Esa función, se ejecuta en un Thread aparte, y en tu código no veo el "using System.Threading;" después de "using System.IO.Ports;"
Responder Con Cita
  #6  
Antiguo 08-12-2023
REHome REHome is offline
Miembro
 
Registrado: jul 2003
Ubicación: España
Posts: 454
Poder: 21
REHome Va por buen camino
Buenas:

El programa se trata de que si le entra datos desde el puerto serie, que sea natural y almacenarlo en una variable tipo Byte[].

Luego mostrarlo en pantalla.

Hablando lo del Thread pongo un ejemplo en un mini chat que si lo usa, me imagino que te refieres a esto:
Código:
using System;
using System.IO;
using System.IO.Ports;
using System.Text;
using System.Threading;

namespace Chat_Consola_05
{
    class Program
    {
        static bool _continua;
        static SerialPort Puerto_serie;

        static void Main(string[] args)
        {
            const int MAXIMA_LONGITUD = 40000;
            string COM = "";
            string nombre;
            string mensaje;
            string titulo = "Mini chat C# " + typeof(string).Assembly.ImageRuntimeVersion;

            StringComparer comparaString = StringComparer.OrdinalIgnoreCase;
            Thread readThread = new Thread(Leer);

            #region Configuración ventana.
            // Título de la ventana.
            Console.Title = titulo;

            // Tamaño de la ventana, x, y, o ancho y alto.
            const byte ANCHO_X = 70, ALTO_Y = 25;
            Console.SetWindowSize(ANCHO_X, ALTO_Y);

            // Color de fondo.
            Console.BackgroundColor = ConsoleColor.Green;

            // Color de las letras.
            Console.ForegroundColor = ConsoleColor.Black;

            // Limpiar pantalla y dejarlo todo en color de fondo.
            Console.Clear();

            // Visible el cursor.
            Console.CursorVisible = true;
            #endregion

            #region Configuración puerto serie.
            // Crear un nuevo objeto SerialPort con la configuración predeterminada.
            Puerto_serie = new SerialPort();

            // Codificar a UTF-8 para que se vean bien las tildes, ñ y otros caracteres.
            Puerto_serie.Encoding = Encoding.UTF8;

            // Obtenga una lista de nombres de puertos serie.
            string[] puertos = SerialPort.GetPortNames();

            Console.WriteLine("Se encontraron los siguientes puertos series:");

            // Muestre el nombre de cada puerto en la consola.
            foreach (string puerto in puertos)
            {
                Console.WriteLine(puerto);
            }

            // Configuración.
            Console.Write(@"
Introduzca un número para seleccionar puerto COM.
Por ejemplo el 4, sería COM4.

Puerto: ");
            COM = Console.ReadLine(); // Escribir el número del puerto.
            Console.Clear(); // Limpiar pantalla.

            Puerto_serie.PortName = "COM" + COM; // Número del puerto serie.

            // Configuración del puerto serie.
            Puerto_serie.BaudRate = 2400;     // 115200
            Puerto_serie.Parity = Parity.None;
            Puerto_serie.StopBits = StopBits.One;
            Puerto_serie.DataBits = 8;
            Puerto_serie.Handshake = Handshake.None;
            Puerto_serie.DtrEnable = true;
            Puerto_serie.RtsEnable = true;

            // Establecer los tiempos de espera de lectura / escritura.
            Puerto_serie.ReadTimeout = 500; // 500 Milisegundos.
            Puerto_serie.WriteTimeout = 500; // 500

            // Más configuraciones.
            Puerto_serie.DiscardNull = false;
            Puerto_serie.ParityReplace = 63;
            Puerto_serie.ReadBufferSize = 4096;
            Puerto_serie.WriteBufferSize = 2018;
            Puerto_serie.ReceivedBytesThreshold = 1;

            // Comprueba si puede abrir el puerto serie.
            try
            {
                Puerto_serie.Open(); // Abrir el puerto serie.
            }

            // En caso que diera algún error como que no encuentra el puerto seleccionado
            // muestra una excepción.
            catch (IOException)
            {
                Console.ForegroundColor = ConsoleColor.Red; // Texto en rojo.
                Console.CursorVisible = false;
                Console.SetCursorPosition(16, 6);
                Console.WriteLine(@"El puerto " + Puerto_serie.PortName + @" no existe
                o no lo encuentra.");
                Console.ReadKey();   // Pulse cualquier tecla.
                Environment.Exit(1); // Salir de la aplicación.
            }

            // Se ha denegado el acceso al puerto.
            catch (UnauthorizedAccessException)
            {
                Console.ForegroundColor = ConsoleColor.Red; // Texto en rojo.
                Console.CursorVisible = false;
                Console.SetCursorPosition(16, 6);
                Console.WriteLine(@"Se ha denegado el acceso al puerto " + Puerto_serie.PortName +
                                "" +
                                "\nPuede estar el puerto escogido en uso.\n" +
                                "Elija un puerto diferente o desactiva el que está en uso.");
                Console.ReadKey();   // Pulse cualquier tecla.
                Environment.Exit(1); // Salir de la aplicación.
            }
            #endregion

            _continua = true;
            readThread.Start();

            // Mostrar texto Nombre y se
            Console.Write("Nombre: ");

            // guarda en la variable nombre.
            nombre = Console.ReadLine();

            // Se muestra el nombre o nick y el puerto seleccionado al final del título de la ventana.
            Console.Title = titulo + "- Nick: " + nombre + " - COM: " + COM;

            Console.WriteLine("Escriba /salir para salir.");

            while (_continua)
            {
                // Cualquier caracter recibido se guarda en la variable mensaje.
                //mensaje = Console.ReadLine();

                #region Enviar más de 255 caracteres.
                // #########################################################################
                Stream entradaDeDatos = Console.OpenStandardInput();
                byte[] buffer = new byte[MAXIMA_LONGITUD];
                int numerosBytesLeidos = entradaDeDatos.Read(buffer, 0, MAXIMA_LONGITUD);

                char[] chars = Console.InputEncoding.GetChars(buffer, 0, numerosBytesLeidos);
                mensaje = new string(chars);
                // #########################################################################
                #endregion

                // Compara /salir con el mensaje /salir si lo haz escrito igual.
                // ¿Escribiste la palabra /salir?
                if (comparaString.Equals("/salir\r\n", mensaje))
                {
                    // Sí. Entonces, pone esta variable _continue en false.
                    _continua = false;
                }
                // No. Entonces, envía por el puerto serie tu nick
                // y mensaje que haz escrito.
                else
                {
                    Puerto_serie.WriteLine(String.Format("<{0}>: {1}", nombre, mensaje));
                }
            }

            // Bloquea el subproceso.
            readThread.Join();

            // Cierra el puerto serie.
            Puerto_serie.Close();
        }

        // Lee mensaje recibido.
        public static void Leer()
        {
            // Si _continua es true se ejecuta todas las instrucciones dentro de while.
            while (_continua)
            {
                try
                {
                    // Almacena en la variable mensaje cualquier caracter o mensaje recibido.
                    string mensaje = Puerto_serie.ReadLine();

                    // Muestra en pantalla mensaje recibido.
                    Console.WriteLine(mensaje);
                }
                catch (TimeoutException) { }
            }
        }
    }
}
Saludos.
__________________
http://electronica-pic.blogspot.com....n-arduino.html Manuales de electrónica general, PIC y Arduino.

Última edición por REHome fecha: 08-12-2023 a las 07:48:14.
Responder Con Cita
  #7  
Antiguo 08-12-2023
Avatar de delphi.com.ar
delphi.com.ar delphi.com.ar is offline
Federico Firenze
 
Registrado: may 2003
Ubicación: Buenos Aires, Argentina *
Posts: 5.932
Poder: 26
delphi.com.ar Va por buen camino
Insisto, debes abstraer los problemas de la lógica general del programa. Si miras el código como todo uno, no podrás llegar a desarrollar algo extenso, la programación se trata de dividir un problema, en muchos problemas pequeños.

Viendo tu código (el del inicio del post, este último no se que es), abres el puerto en la línea 58, y en la línea 66 llamas a MostrarBytes, sin ningúna garantía de que el buffer datoRecibido haya recibido datos. Simplemente si no tenías nada conectado en el puerto serie, el código producirá inevitablemente un NullReferenceException. Y si hubiera un dispositivo conectado, puede suceder una condición de carrera donde primero evalúas el buffer y luego recibes los datos.

Una simple solución puede ser tener la variable datoRecibido inicializada con un array vacío a la espera de datos, total la estas extendiendo cada vez que recibes datos. Pese a esto que te digo, lo único que lograrás es no generar excepciones, dado que el programa fallará pq no resultará lo que espera el usuario.

Saludos.
__________________
delphi.com.ar

Dedique el tiempo suficiente para formular su pregunta si pretende que alguien dedique su tiempo en contestarla.
Responder Con Cita
  #8  
Antiguo 09-12-2023
REHome REHome is offline
Miembro
 
Registrado: jul 2003
Ubicación: España
Posts: 454
Poder: 21
REHome Va por buen camino
El código del primer post no es mio en absoluto, lo saqué en Internet pero no funciona. Como nadie responde en esa Web, lo pregunto aquí.

Y si, hay que resolver partes por partes.

La idea es, que el puerto abre cuando inicio el programa, a la espera que lleguen datos por el puerto serie cuando desde el otro lado envíe tramas de bytes, se almacene en un arrray y lo muestre en pantalla.
__________________
http://electronica-pic.blogspot.com....n-arduino.html Manuales de electrónica general, PIC y Arduino.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
referencia a un objeto no establecida como instancia de un objeto Beare MySQL 4 30-12-2015 15:49:54
Como puedo asignar una copia de una instancia sin que sea una referencia. TecnoBestia Varios 15 08-11-2011 19:58:13
Compartir instancia de un objeto _cero_ C++ Builder 10 05-10-2011 04:57:16
Instancia de un objeto dao_ar OOP 1 25-06-2011 09:53:04
Referencia al objeto desde la interfaz marto OOP 2 19-01-2004 22:29:26


La franja horaria es GMT +2. Ahora son las 11:56:17.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi