Foros del Web » Programación para mayores de 30 ;) » C/C++ »

[SOLUCIONADO] Descriptores de ficheros.

Estas en el tema de Descriptores de ficheros. en el foro de C/C++ en Foros del Web. 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 ...
  #1 (permalink)  
Antiguo 13/10/2014, 11:45
 
Fecha de Ingreso: octubre-2014
Ubicación: Torrejón de Ardoz
Mensajes: 4
Antigüedad: 10 años, 1 mes
Puntos: 0
Descriptores de ficheros.

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
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.

Última edición por iapellaniz; 15/10/2014 a las 11:00
  #2 (permalink)  
Antiguo 17/10/2014, 05:16
 
Fecha de Ingreso: octubre-2014
Ubicación: Torrejón de Ardoz
Mensajes: 4
Antigüedad: 10 años, 1 mes
Puntos: 0
Respuesta: Descriptores de ficheros.

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.
  #3 (permalink)  
Antiguo 17/10/2014, 05:26
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 10 años, 1 mes
Puntos: 204
Respuesta: Descriptores de ficheros.

Podrías probar a ver si editando tus mensajes para poner el código entre las etiquetas "highlight" de C++ consigues que el código sea un poco más legible :)

Además, no hace falta que plantes todo el programa del tirón... para que la ayuda sea lo más eficaz posible tienes que ser capaz de presentar la menor cantidad de código posible que permita reconocer y trazar el error... si plantas un código fuente de mil líneas creo que pocos te van a contestar.
  #4 (permalink)  
Antiguo 18/10/2014, 10:36
Avatar de Eternal Idol  
Fecha de Ingreso: mayo-2004
Ubicación: Lucentum
Mensajes: 6.192
Antigüedad: 20 años, 6 meses
Puntos: 74
Respuesta: Descriptores de ficheros.

Lo que estas haciendo al llamar al constructor de esa manera es crear un objeto temporario, es es el que se destruye y es el unico que llama al metodo openI2C. Solucion sencilla llama al metodo openI2C desde el constructor ...
__________________
¡Peron cumple, Evita dignifica! VIVA PERON CARAJO

Etiquetas: clase, int, programa
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta

SíEste tema le ha gustado a 1 personas




La zona horaria es GMT -6. Ahora son las 09:11.