Code: Select all
pi@raspberrypi ~/dht22spi $ cat dht22spi.c
/* dht22spi
* SPI device interface to read DHT22 sensor
*
* Copyright (c) February 2014 Daniel Perron
*
*
* Software inspire from
* http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob_plain;f=Documentation/spi/spidev_test.c
* Copyright (c) 2007 MontaVista Software, Inc.
* Copyright (c) 2007 Anton Vorontsov <avorontsov@ru.mvista.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License.
*
* Cross-compile with cross-gcc -I/path/to/cross-kernel/include
*/
#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <fcntl.h>
#include <malloc.h>
#include <string.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
static void pabort(const char *s)
{
perror(s);
abort();
}
static uint8_t mode;
static uint8_t bits = 8;
static uint32_t speed = 500000;
static uint16_t delay;
static unsigned char Bits[8]={128,64,32,16,8,4,2,1};
static void transfer(int fd, unsigned char *ArrayTx, unsigned char *ArrayRx, int ArraySize)
{
int ret;
ArrayRx[0]=0;
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)ArrayTx,
.rx_buf = (unsigned long)ArrayRx,
.len = ArraySize,
.delay_usecs = delay,
.speed_hz = speed,
.bits_per_word = bits,
};
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1)
pabort("can't send spi message");
}
int GetBit(unsigned char * Array, int bitIdx)
{
int ByteIdx = bitIdx/8;
if( (Array[ByteIdx] & Bits[bitIdx % 8]) == 0)
return 0;
return 1;
}
int GetNextDelay(unsigned char * Array, int * bitIdx, int MaxBit)
{
int index,Lastbit,delta;
if( *bitIdx >= MaxBit) return(0);
index = *bitIdx;
Lastbit = GetBit(Array,index);
while(index < MaxBit)
{
if(GetBit(Array,++index) != Lastbit)
{
delta = index - *bitIdx;
*bitIdx = index;
return( (int) (1000000.0 * delta / speed)); // return value in usec
}
}
return(0);
}
int DecodeArray(unsigned char *ArrayIn,unsigned char *ArrayOut, int TotalBit)
{
int ByteIdx,BitIdx;
int BitPointer=0;
int HighPulse;
//first get rid off start
GetNextDelay(ArrayIn,&BitPointer,TotalBit);
//get rid off wait
GetNextDelay(ArrayIn,&BitPointer,TotalBit);
//get rid off ACK
GetNextDelay(ArrayIn,&BitPointer,TotalBit);
//get rid off ACK
GetNextDelay(ArrayIn,&BitPointer,TotalBit);
for(ByteIdx=0;ByteIdx<5;ByteIdx++)
{
ArrayOut[ByteIdx]=0;
for(BitIdx=0;BitIdx<8;BitIdx++)
{
// get low level
GetNextDelay(ArrayIn,&BitPointer,TotalBit);
// get High level
HighPulse = GetNextDelay(ArrayIn,&BitPointer,TotalBit);
if(HighPulse < 5) return 0;
if(HighPulse > 80) return 0;
if(HighPulse > 43)
ArrayOut[ByteIdx]|= Bits[BitIdx];
}
}
return 1;
}
int main(int argc, char *argv[])
{
int ret = 0;
int fd;
int loop;
unsigned char checkSum;
unsigned char ArrayOut[5];
float Temperature,Humidity;
fd = open("/dev/spidev0.0", O_RDWR);
if (fd < 0)
pabort("can't open device");
/*
* spi mode
*/
mode = 0;
ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
if (ret == -1)
pabort("can't set spi mode");
ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
if (ret == -1)
pabort("can't get spi mode");
/*
* bits per word
*/
ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
if (ret == -1)
pabort("can't set bits per word");
ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
if (ret == -1)
pabort("can't get bits per word");
/*
* max speed hz
*/
ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
if (ret == -1)
pabort("can't set max speed hz");
ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
if (ret == -1)
pabort("can't get max speed hz");
// use a array size fpr 10ms;
int BitSize = (int) ( 0.010 * speed);
int ArraySize = BitSize / 8;
int TotalBit = ArraySize * 8;
unsigned char * Array= (unsigned char *) malloc(ArraySize);
// need to have the 1.5 ms to 0
int startOfRx = (int) (0.0015 * speed) / 8;
memset(Array,0, startOfRx);
memset(&Array[startOfRx],0xff, ArraySize-startOfRx);
transfer(fd,Array, Array,ArraySize);
if(DecodeArray(Array,ArrayOut,TotalBit))
{
checkSum=0;
for(loop=0;loop<4;loop++)
checkSum+=ArrayOut[loop];
if(checkSum!=ArrayOut[4])
printf("Checksum invalid\n");
else
{
Temperature = ((int) (ArrayOut[2]&0x7f) * 256 + ArrayOut[3])/10.0;
if((ArrayOut[2] & 0x80)== 0x80)
Temperature = -(Temperature);
Humidity = ((int) ArrayOut[0]*256 + ArrayOut[1])/10.0;
printf("Temperature = %5.1f Celsius\n",Temperature);
printf("Humidity = %5.1f %%\n",Humidity);
}
}
else
printf("Unable to read DHT22 sensor\n");
close(fd);
free(Array);
return ret;
}