elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Usando Git para manipular el directorio de trabajo, el índice y commits (segunda parte)


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  Problema con descriptores de ficheros
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Problema con descriptores de ficheros  (Leído 2,163 veces)
iapellaniz

Desconectado Desconectado

Mensajes: 2


Ver Perfil
Problema con descriptores de ficheros
« en: 15 Octubre 2014, 19:01 pm »

Hola a todos:

Lo primero es agradecer las posibles respuestas que me podáis dar.

Os cuento mi problema. Estoy desarrollando un programa en C++, para la Raspberry, que hace uso de un LCD (Kit Adafruit LCD 16x2 ). Este LCD hace uso de un chip MCP23017 y se comunica con la Rasp mediante i2c. El caso es que existe una librería en Python para este LCD y lo que estoy intentando es traducirlo a C++.

La comunicación del sistema operativo (Raspbian) con i2c es mediante el uso de descriptores de ficheros. Compruebo que abro bien el fichero, pero a la hora de hacer operaciones con él me cambia el descriptor de fichero y no encuentro la causa.

Este es el resultado que obtengo:
root@raspberrypi:/liquidcrystal# ./prueba
openI2C - File Descriptor: 3
i2c_smbus - File Descriptor: 0

Os copio la clase que controla el acceso a i2c.

#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <string>

#include "i2c8Bit.h"

using namespace std;

/*****************************************************************
 * This is the default constructor for the class. It assigns
 * all private variables to default values and calls the openI2C()
 * function to open the default I2C device "/dev/i2c-0".
 *****************************************************************/
i2c8Bit::i2c8Bit(uint8_t dev_addr){
   int revision = this->piBoardRev();
   if (revision == 1) i2c8Bit(dev_addr, string("/dev/i2c-0"));
   else if (revision == 2) i2c8Bit(dev_addr, string("/dev/i2c-1"));
   else {printf("Error"); exit(1);}
}
 
/*******************************************************************
 * This is the overloaded constructor. It allows the programmer to
 * specify a custom I2C device & device address
 * The device descriptor is determined by the openI2C() private member
 * function call.
 * *****************************************************************/
 
i2c8Bit::i2c8Bit(uint8_t dev_addr, string i2c_file_name){
   this->i2cFileName = i2c_file_name;
    this->deviceAddress = dev_addr;
    this->i2cDescriptor = 0;

   this->openI2C();
}
/**********************************************************************
 * This is the class destructor it simply closes the open I2C device
 * by calling the closeI2C() which in turn calls the close() system call
 * *********************************************************************/
 
i2c8Bit::~i2c8Bit(void){
    //cout << " Closing I2C Device" << endl;
    this->closeI2C();
}
 
/**********************************************************************
 * This function opens the I2C device by simply calling the open system
 * call on the I2C device specified in the i2cFileName string. The I2C
 * device is opened for writing and reading. The i2cDescriptor private
 * variable is set by the return value of the open() system call.
 * This variable will be used to reference the opened I2C device by the
 * ioctl() & close() system calls.
 * ********************************************************************/
 
int i2c8Bit::openI2C(){
   
   if (this->i2cDescriptor)  this->closeI2C();

   this->i2cDescriptor = open(this->i2cFileName.c_str(), O_RDWR);
   if (this->i2cDescriptor < 0) {
      perror("Could not open file");
        exit(1);
   }

   if (ioctl(this->i2cDescriptor, I2C_SLAVE, this->deviceAddress) < 0)
      {
         perror("Unable to select I2C device");
         exit(1);
      }

   printf("openI2C - File Descriptor: %i \n", this->i2cDescriptor);
   return 0;
}
 
/*********************************************************************
 * This function closes the I2C device by calling the close() system call
 * on the I2C device descriptor.  
 * *******************************************************************/
 
int i2c8Bit::closeI2C(){
    int retVal = -1;

    if (this->i2cDescriptor)
     {
      retVal = close(this->i2cDescriptor);
      if(retVal < 0){
         perror("Could not close file (1)");
         exit(1);
      }
      this->i2cDescriptor = 0;
    }   
   
return retVal;
}
 
int i2c8Bit::piBoardRev (void)
{
  FILE *cpuFd ;
  char line [120] ;
  char *c ;
  static int  boardRev = -1 ;

  if (boardRev != -1)   // No point checking twice
    return boardRev ;

  if ((cpuFd = fopen ("/proc/cpuinfo", "r")) == NULL)
   { perror("Unable to open /proc/cpuinfo"); exit(1); }

  while (fgets (line, 120, cpuFd) != NULL)
    if (strncmp (line, "Revision", 8) == 0)
      break ;

  fclose (cpuFd) ;

  if (strncmp (line, "Revision", 8) != 0)
   { perror("No \"Revision\" line"); exit(1); }

// Chomp trailing CR/NL

  for (c = &line [strlen (line) - 1] ; (*c == '\n') || (*c == '\r') ; --c)
    *c = 0 ;
  
// Scan to first digit

  for (c = line ; *c ; ++c)
    if (isdigit (*c))
      break ;

  if (!isdigit (*c))
   { perror("No numeric revision string"); exit(1); }
    

// Make sure its long enough

  if (strlen (c) < 4)
    { perror("Bogus \"Revision\" line (too small)"); exit(1); }
  

// Isolate  last 4 characters:

  c = c + strlen (c) - 4 ;

  if ( (strcmp (c, "0002") == 0) || (strcmp (c, "0003") == 0))
   boardRev = 1 ;
  else
   boardRev = 2 ;

  return boardRev ;
}

uint8_t i2c8Bit::i2cRead()
{
   union i2c_smbus_data data ;
   
   if (this->i2c_smbus_operation(I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, &data)) return -1;
   
   return data.byte & 0xFF;
}

uint8_t i2c8Bit::i2cReadReg8(uint8_t reg)
{
  union i2c_smbus_data data;

  if (this->i2c_smbus_operation(I2C_SMBUS_READ, reg, I2C_SMBUS_BYTE_DATA, &data)) return -1 ;
  
  return data.byte & 0xFF;
}

uint16_t i2c8Bit::i2cReadReg16(uint8_t reg)
{
  union i2c_smbus_data data;

  if (this->i2c_smbus_operation(I2C_SMBUS_READ, reg, I2C_SMBUS_WORD_DATA, &data)) return -1 ;
  
  return data.word & 0xFFFF;
}

int i2c8Bit::i2cWrite(uint8_t data)
{
  return this->i2c_smbus_operation(I2C_SMBUS_WRITE, data, I2C_SMBUS_BYTE, NULL) ;
}

int i2c8Bit::i2cWriteList(uint8_t reg, uint8_t *value, int lenghtValue)
{
  union i2c_smbus_data data;
  
  data.block[0] = lenghtValue;
  
  for(int i = 0; i < lenghtValue; i++)
    data.block[i+1] = value;
  
//  return this->i2c_smbus_operation(I2C_SMBUS_WRITE, reg, I2C_SMBUS_BLOCK_DATA, &data);
  return this->i2c_smbus_operation(I2C_SMBUS_WRITE, reg, I2C_SMBUS_I2C_BLOCK_DATA, &data);
  
}

int i2c8Bit::i2cWriteReg8 (uint8_t reg, uint8_t value)
{
  union i2c_smbus_data data;

  data.byte = value ;
  return this->i2c_smbus_operation(I2C_SMBUS_WRITE, reg, I2C_SMBUS_BYTE_DATA, &data) ;
  //return this->writeReg(reg, value);
}

int i2c8Bit::i2cWriteReg16 (uint8_t reg, uint16_t value)
{
  union i2c_smbus_data data ;

  data.word = value ;
  return this->i2c_smbus_operation(I2C_SMBUS_WRITE, reg, I2C_SMBUS_WORD_DATA, &data) ;
}


int i2c8Bit::i2c_smbus_operation(char rw, uint8_t command, int size, union i2c_smbus_data *data)
{
  struct i2c_smbus_ioctl_data args ;
  int operation;

  args.read_write = rw ;
  args.command    = command ;
  args.size       = size ;
  args.data       = data ;
  printf("i2c_smbus - File Descriptor: %i \n", this->i2cDescriptor);

  operation = ioctl(this->i2cDescriptor, I2C_SMBUS, &args);
  if (operation < 0)
   {
       perror("Unable to make operation"); exit(1);
   }
  
  return operation;
}

De nuevo, gracias a todos.

Saludos.



Hola de nuevo:

He seguido investigando y he descubierto que en cuanto creo el objeto en el programa principal, automáticamente se destruye. Por eso cambia el descriptor de fichero.

Lo que no sé es porque se destruye el objeto antes de la finalización del programa.

Os dejo la cabecera del objeto y el fichero de prueba.

#ifndef I2C8BIT_H
#define I2C8BIT_H
 
#include <string>
#include <stdint.h>
#include <linux/i2c.h>

class i2c8Bit {
    private:
        std::string i2cFileName; //i2c device name e.g."/dev/i2c-0" or "/dev/i2c-1"
        int i2cDescriptor;  // i2c device descriptor
        uint8_t deviceAddress; // i2c device address

        //private member functions
        int openI2C(); //open an I2C device. Called only in constructors
        int closeI2C(); // close an I2C device. Called only in destructor

        int piBoardRev();
      int i2c_smbus_operation(char, uint8_t, int, union i2c_smbus_data *);

    public:
        i2c8Bit(uint8_t); // default constructor
        i2c8Bit(uint8_t, std::string); //over loaded constructor
        ~i2c8Bit(); // destructor
       
      uint8_t i2cRead();
      uint8_t i2cReadReg8(uint8_t);
      uint16_t i2cReadReg16(uint8_t);

      int i2cWrite(uint8_t);
      int i2cWriteList(uint8_t, uint8_t *, int);
      int i2cWriteReg8(uint8_t, uint8_t);
      int i2cWriteReg16(uint8_t, uint16_t);

};
 
#endif



///========

Fichero main:

#include "i2c8Bit.h"

i2c8Bit *smbus;

int main()
{
    smbus = new i2c8Bit(0x20);
   
    smbus->i2cWriteReg8(0x0A,0x28);
   
   return 0;
}

El comando de compilación es: g++-4.8 prueba.c i2c8Bit.cpp -o prueba


Saludos.


« Última modificación: 17 Octubre 2014, 19:19 pm por Eternal Idol » En línea

Eternal Idol
Kernel coder
Moderador
***
Desconectado Desconectado

Mensajes: 5.958


Israel nunca torturó niños, ni lo volverá a hacer.


Ver Perfil WWW
Re: Problema con descriptores de ficheros
« Respuesta #1 en: 17 Octubre 2014, 19:15 pm »

El codigo de los constructores no concuerda con el comentario. ¿Lo cambiaste vos? Lo que estas haciendo al llamar al constructor de esa manera es crear un objeto temporario, podes comprobarlo con un depurador o imprimiendo en pantalla (en el constructor por defecto observa this, en el constructor sobrecargado tambien y finalmente en el destructor, despues cuando hagas delete en el main del objeto veras la direccion del this en el constructor por defecto), es es el que se destruye y es el unico que llama al metodo openI2C. Solucion sencilla llama al metodo openI2C desde el constructor ...


En línea

La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón
iapellaniz

Desconectado Desconectado

Mensajes: 2


Ver Perfil
Re: Problema con descriptores de ficheros
« Respuesta #2 en: 17 Octubre 2014, 23:31 pm »

Hola Eternal Idol:

Efectívamente, el constuctor lo modifiqué yo, me pareció más optimo. Sin embargo ha causado el efecto que dices. Dentro del constuctor por defecto, creaba un objeto temporal que era destruido inmediatamente.

Siguiendo tu consejo, este es el código que ha quedado en el constructor por defecto:

Código
  1. i2c8Bit::i2c8Bit(uint8_t dev_addr)
  2. {
  3. int revision = this->piBoardRev();
  4. this->deviceAddress = dev_addr;
  5.  
  6. if (revision == 1){
  7. this->i2cFileName ="/dev/i2c-0";
  8. }
  9. else if (revision == 2){
  10. this->i2cFileName ="/dev/i2c-1";
  11. }
  12. else {printf("Error"); exit(1);}
  13.  
  14.    this->i2cDescriptor = 0;
  15.  
  16. this->openI2C();
  17.  
  18. }
  19.  

Ahora funciona perfectamente. Muchísimas gracias.

Saludos.
En línea

Eternal Idol
Kernel coder
Moderador
***
Desconectado Desconectado

Mensajes: 5.958


Israel nunca torturó niños, ni lo volverá a hacer.


Ver Perfil WWW
Re: Problema con descriptores de ficheros
« Respuesta #3 en: 17 Octubre 2014, 23:35 pm »

De nadas  ::)
En línea

La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón
Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Problema con envio de ficheros
Java
Debci 4 2,682 Último mensaje 26 Agosto 2009, 10:03 am
por Debci
problema con programa de ficheros en c
Programación C/C++
Quake-man 1 2,523 Último mensaje 10 Septiembre 2010, 18:39 pm
por nicolas_cof
[C] Problema con nombres de ficheros
Programación C/C++
JJShadiw 3 2,718 Último mensaje 24 Diciembre 2010, 00:22 am
por dooque
iDStore lista ficheros y directorios ocultos de ficheros .DS_Store
Nivel Web
MichBukana 0 3,514 Último mensaje 29 Agosto 2013, 09:21 am
por MichBukana
Redireccion de descriptores de archivo supuestamente ambigua (bash)
GNU/Linux
4v1dy4 2 3,865 Último mensaje 29 Diciembre 2022, 13:15 pm
por 4v1dy4
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines