Skip to content

Instantly share code, notes, and snippets.

@user890104
Last active September 5, 2017 08:06
Show Gist options
  • Save user890104/60110bcb6272d0e5e177 to your computer and use it in GitHub Desktop.
Save user890104/60110bcb6272d0e5e177 to your computer and use it in GitHub Desktop.
Si7021 Linux app
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/i2c-dev.h>
#define BYTES2SHORT(X) (X[0] << 8 | X[1])
enum cmd_id {
MEAS_HUM,
MEAS_TEMP,
READ_TEMP,
RESET,
WRITE_USER_REG,
READ_USER_REG,
WRITE_HEATER_REG,
READ_HEATER_REG,
READ_SN_1,
READ_SN_2,
READ_FWREV,
CMDS_COUNT
};
char **cmd;
unsigned int i2c_rw(int file, const char *wdata, size_t wlen, char *rdata, size_t rlen) {
if (wlen) {
if (write(file, wdata, wlen) != wlen) {
perror("write");
return 1;
}
}
if (rlen) {
int retries = 10;
int result = read(file, rdata, rlen);
while (
result == -1 && // read error
errno == ENXIO && // NACK
(--retries > 0)
) {
result = read(file, rdata, rlen); // retry
usleep(5000); // wait 5 ms
}
if (result != rlen) {
perror("read");
return 2;
}
}
return 0;
}
int si7021_print_part(int file) {
unsigned char resp[6];
if (i2c_rw(file, cmd[READ_SN_2], 2, resp, 1)) {
return 1;
}
printf("PART: ");
switch (resp[0]) {
case 0x00:
case 0xFF:
puts("Engineering sample");
break;
case 0x0D:
puts("Si7013");
break;
case 0x14:
puts("Si7020");
break;
case 0x15:
puts("Si7021");
break;
default:
puts("UNKNOWN");
break;
}
return 0;
}
int si7021_print_sn(int file) {
unsigned char resp[8];
if (i2c_rw(file, cmd[READ_SN_1], 2, resp, 8)) {
return 1;
}
printf("SN: %02x%02x%02x%02x\n", resp[0], resp[2], resp[4], resp[6]);
return 0;
}
int si7021_print_fwrev(int file) {
unsigned char resp;
if (i2c_rw(file, cmd[READ_FWREV], 2, &resp, 1)) {
return;
}
printf("FWREV: ");
switch (resp) {
case 0xFF:
puts("1.0");
break;
case 0x20:
puts("2.0");
break;
default:
puts("UNKNOWN");
break;
}
return 0;
}
int si7021_print_env(int file) {
unsigned char resp[3];
if (i2c_rw(file, cmd[MEAS_HUM], 1, resp, 3)) {
return 1;
}
float hum = 125.0 * BYTES2SHORT(resp) / 65536 - 6;
if (i2c_rw(file, cmd[READ_TEMP], 1, resp, 2)) {
return 1;
}
float temp = 175.72 * BYTES2SHORT(resp) / 65536 - 46.85;
printf("T: %f\nH: %f\n", temp, hum);
return 0;
}
int main(int argc, char **argv) {
cmd = calloc(CMDS_COUNT, sizeof(char *));
cmd[MEAS_HUM] = "\xF5";
cmd[MEAS_TEMP] = "\xF3";
cmd[READ_TEMP] = "\xE0";
cmd[RESET] = "\xFE";
cmd[WRITE_USER_REG] = "\xE6";
cmd[READ_USER_REG] = "\xE7";
cmd[WRITE_HEATER_REG] = "\x51";
cmd[READ_HEATER_REG] = "\x11";
cmd[READ_SN_1] = "\xFA\x0F";
cmd[READ_SN_2] = "\xFC\xC9";
cmd[READ_FWREV] = "\x84\xB8";
int file;
char *filename;
int addr = 0x40;
filename = strdup("/dev/i2c-1");
if ((file = open(filename, O_RDWR)) < 0) {
perror("open");
exit(1);
}
if (ioctl(file, I2C_SLAVE, addr) < 0) {
perror("ioctl I2C_SLAVE");
exit(1);
}
si7021_print_part(file);
si7021_print_sn(file);
si7021_print_fwrev(file);
si7021_print_env(file);
close(file);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment