I am building a Weather Station on a Raspberry Pi from scratch in C. I have a file with the code to get the temperature and I also have another file to call these functions. I have written code before to do this but the quality of the code was very poor and I am trying to re-write it better.
I believe I am having my issue is understanding how to pass around the reference to the file descriptor pointing to the sensor.
Please consider this code snippet from my software. (I am certain the error exists in this section).
#include "readTemp.h"
#include <stdio.h>
int main() {
int fd;
fd = initGPIO(0, 0x76);
getTemp(fd);
return(0);
}
and the file readTemp.C
int * initGPIO(int i2cBus, int i2cAddr){
int *addr = malloc(sizeof(int));
int fd;
//Initialise GPIO
if(gpioInitialise() < 0) {
perror("Initialisation failed\n");
exit(EXIT_FAILURE);
}
//Open the I2C bus
fd = i2cOpen(i2cBus, i2cAddr, 0);
if(fd < 0) {
perror("Device failed to open\n");
exit(EXIT_FAILURE);
}
//Send Reset
if(i2cWriteByte(fd, CMD_RESET) != 0){
perror("Error sending reset---\n");
}
addr = &fd;
printf("3-%d\n", &addr);
return(addr);
}
/*
* Reads the calibration data from the PROMs on the sensor
* Parameters - fd - File Descriptor of the i2c device
* *proms - Pointer to an array of 8 unsigned 16-bit integers
*/
static int getCalibData(int *fd, u_int16_t *proms) {
const int bytesToRead = 2;
char buf[2] = {0};
printf("2-%d\n", &fd);
// Populate for each prom (7)
for(int i = PROM_START; i < PROM_STOP; i = i + 2){
// Write PROM read commands
if(i2cWriteByte(*fd, i) != 0) {
perror("Error writing PROM command!!\n");
exit(EXIT_FAILURE);
}
// Read result from PROM
if(i2cReadDevice(*fd, buf, bytesToRead) <= 0) {
perror("Error reading from PROM\n");
exit(EXIT_FAILURE);
}
// Store result in array
proms[(i - PROM_START) / 2] = (buf[0] << 8) | (buf[1]);
}
return(0);
}
int getTemp(int *fd){
u_int16_t proms[8];
u_int32_t rawTemp = getRawTemp(fd);
printf("%d\n", rawTemp);
getCalibData(fd, proms);
for(int i = 0; i < 8; i++){
printf("%d-%d\n", i, proms[i]);
}
int temp = calcTemp(rawTemp, proms);
printf("---%d\n", temp);
return 0;
}
The code compiles but when run I get my "Error writing PROM Command"
error.
I think my error might lie in the small section of code where I am assigning the result of initGPIO()
to an int
where it should be to a pointer. But, when I do that my code seg faults.
You should get a compiler warning at the line
fd = initGPIO(0, 0x76);
because fd
is of type int
and initGPIO
returns and int*
.
Change initGPIO
as follows
int initGPIO(int i2cBus, int i2cAddr){
int fd;
//Initialise GPIO
if(gpioInitialise() < 0) {
perror("Initialisation failed\n");
exit(EXIT_FAILURE);
}
//Open the I2C bus
fd = i2cOpen(i2cBus, i2cAddr, 0);
if(fd < 0) {
perror("Device failed to open\n");
exit(EXIT_FAILURE);
}
//Send Reset
if(i2cWriteByte(fd, CMD_RESET) != 0){
perror("Error sending reset---\n");
}
return fd;
}
Explanation:
A file descriptor is a number that identifies an open file. As initGPIO
will return the file descriptor and you assign it in main
you can simply return the number. You don't need a pointer.
You would need to pass a pointer if you would want to pass fd
from main
to a function that is expected to modify the value of fd
.
You have two more errors in initGPIO
:
int *addr = malloc(sizeof(int)); /* Now addr points to the allocated memory for an int. */
int fd;
/* ... */
addr = &fd; /* Now you overwrite addr with the address of the local variable fd.
This creates a memory leak. Using the address in main() would be
undefined behavior because the address of the local variable fd will
become invalid when the function returns.
To put the fd value into the allocated memory you would have to use
*addr = fd, but this is not necessary here as explained above. */
There is no reference mechanism in the C language. By using pointers and indirection, it is somewhat mimicked.
In the above code, what you are returning is the address of the variable that holds fd value. Since fd is a local variable, dereferencing it through its address outside of the function it is declared will lead to SEGFAULT. It manyn't have happened now, but definitely happen eventually. Instead, just return the fd itself.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.