Ver Mensaje Individual
  #1 (permalink)  
Antiguo 13/10/2014, 11:45
iapellaniz
 
Fecha de Ingreso: octubre-2014
Ubicación: Torrejón de Ardoz
Mensajes: 4
Antigüedad: 10 años
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