Fox ds1621.c

De MicElectroLinGenMet.

Page liée: Carte Linux Acme Fox: Test_bus_I2C

//***************************************************
// 	Test DS1621 par Dan (Domos)
//
// through I2C using bit banging method in user space
// http://www.acmesystems.it/?id=10
//***************************************************

// Modif.
// Change bus SDA/SDL sur port B
// Change nom des fonctions, écriture adresse slave.

// Rajout fonctions i2c_write / i2c_read / i2c_writeread
// Fonctions DS1621
// Test OK avec DS121

/*
[root@fox /root]# /tmp/i2ctest 
Temp DS1621_1: 24.5°
*/

#include "stdio.h"     
#include <stdlib.h>
#include "unistd.h"    
#include "sys/ioctl.h"
#include "fcntl.h"     
#include "time.h"     
#include "linux/gpio_syscalls.h"

//#define I2C_SDA_LINE  1<<24   // IOG24 J7.21
//#define I2C_SCL_LINE  1<<25   //  OG25 J7.13
//#define I2C_DATA_PORT   PORTG
//#define I2C_CLOCK_PORT  PORTG

#define I2C_SDA_LINE  1<<4   //  PB4 J6.36
#define I2C_SCL_LINE  1<<7   //  PB7 J6.37
#define I2C_DATA_PORT   PORTB
#define I2C_CLOCK_PORT  PORTB

/*------------------------------------------------------------------------------*/
/* Fonctions I2C bas niveau							*/
/*------------------------------------------------------------------------------*/
// Get the SDA line state
int  i2c_get_sda_bit( void ) 
{
	 return  (gpiogetbits(I2C_DATA_PORT,I2C_SDA_LINE)?( 1 ):( 0 ));
} 

// Set the SDA line as output
void  i2c_set_sda_out( void ) 
{
	gpiosetdir(I2C_DATA_PORT,DIROUT,I2C_SDA_LINE);
}

// Set the SDA line as input
void  i2c_set_sda_in( void ) 
{
	gpiosetdir(I2C_DATA_PORT,DIRIN,I2C_SDA_LINE);
}

// Set the SDA line state
void  i2c_set_sda_bit( int  state) 
{
	 if  (state== 1 ) 
	{
		i2c_set_sda_in(); 
	} 
	 else  
	{  
		i2c_set_sda_out();  
		gpioclearbits(I2C_DATA_PORT, I2C_SDA_LINE);  
	} 
}

// Set the SCL line state
void  i2c_set_scl_bit( int  state) 
{
	 if  (state== 1 ) gpiosetbits(I2C_CLOCK_PORT, I2C_SCL_LINE);
	 else  gpioclearbits(I2C_CLOCK_PORT, I2C_SCL_LINE); 
}

// Initializate the I2C bus
void  i2c_init( void ) 
{
	i2c_set_sda_in();
	i2c_set_scl_bit( 1 );
}

// Send a start sequence to I2C bus
void  i2c_start( void )
{
	i2c_set_scl_bit( 0 );
	i2c_set_sda_bit( 1 );
	i2c_set_scl_bit( 1 );
	i2c_set_sda_bit( 0 );
}

// Send a stop sequence to I2C bus
void  i2c_stop( void ) 
{
	i2c_set_scl_bit( 0 );
	i2c_set_sda_bit( 0 );
	i2c_set_scl_bit( 1 );
	i2c_set_sda_bit( 1 );
}

// Read a byte from I2C bus and send the ack sequence
// Put islast = 1 is this is the last byte to receive from the slave
unsigned   char  i2c_read_byte( int  islast) 
{
	 unsigned   char  value =  0 ;
	 int  bitvalue;
	 int  i;

	 // Read data byte

	i2c_set_scl_bit( 0 );
	i2c_set_sda_in();

	 for  (i= 0 ;i< 8 ;i++) 
	{
		i2c_set_scl_bit( 1 );
		bitvalue = i2c_get_sda_bit();
		value |= bitvalue;
		 if  (i< 7 ) value <<=  1 ;	
		i2c_set_scl_bit( 0 );
	}
  
	 if  (islast== 0 ) 
	{
		 // Send Ack if is not the last byte to read
  
		i2c_set_sda_out();
		i2c_set_sda_bit( 0 );
		i2c_set_scl_bit( 1 );
		i2c_set_scl_bit( 0 );
		i2c_set_sda_in();
  	} 
	 else  
	{
    		 // Doesn't send Ack if is the last byte to read
    		i2c_set_sda_in();
    		i2c_set_scl_bit( 1 );
    		i2c_set_scl_bit( 0 );
	}

	 return  value;
}

// Send a byte to the I2C bus and return the ack sequence from slave
// rtc
//  0 = Nack, 1=Ack
int  i2c_write_byte( unsigned   char  x) 
{
	 int  i;
	 int  ack;

	i2c_set_scl_bit( 0 );

	 for  (i= 0 ;i< 8 ;i++) 
	{
		 if  (x &  0x80 ) i2c_set_sda_bit( 1 );
		 else   i2c_set_sda_bit( 0 );
		i2c_set_scl_bit( 1 );
		i2c_set_scl_bit( 0 );
		x <<=  1 ;
	}

	i2c_set_sda_in();
	i2c_set_scl_bit( 1 );
	ack=i2c_get_sda_bit();
	i2c_set_scl_bit( 0 );
  
	 if  (ack== 0 )  return   1 ;
	 else   return   0 ;
}

/*------------------------------------------------------------------------------*/
/* Fonctions trames I2C								*/
/*------------------------------------------------------------------------------*/
// Ecriture d'une trame i2c.
int  i2c_write( unsigned   char  i2cadr,  unsigned   char  *buff,  unsigned   char  wrlen) 
{
	 int  i ;

    	i2c_start();
	 if  (i2c_write_byte(i2cadr| 0 )== 0 )  return  - 1  ;	 // i2cadr|0 => ecriture.

	 for  (i= 0 ; i < wrlen; i++) i2c_write_byte(buff[i]) ; 

    	i2c_stop();
	 return   0  ;
}

// Lecture d'une trame i2c.
int  i2c_read( unsigned   char  i2cadr,  unsigned   char  *buff,  int  rdlen)
{
	 int  i ;

    	i2c_start();
	 if  (i2c_write_byte(i2cadr| 1 )== 0 )  return  - 1  ;	 // i2cadr|1 => lecture.

	 for  (i= 0 ; i < rdlen; i++)
		 if  (i != rdlen -  1 ) buff[i] = i2c_read_byte( 0 ) ;
			 else  buff[i] = i2c_read_byte( 1 ) ; 

	i2c_stop() ;
      	 return   0  ;
}

// Lecture d'une trame i2c aprés écriture d'un octet (registre).
int  i2c_writeread( unsigned   char  i2cadr,  unsigned   char  *buff,  int  rdlen)
{
	 int  i ;

    	i2c_start();
	 if  (i2c_write_byte(i2cadr| 0 )== 0 )  return  - 1  ;	 // i2cadr|0 => ecriture.
	i2c_write_byte(buff[ 0 ]) ; 			 // Octet à écrire (registre) dans buff[0].

    	i2c_start();					 // Repeated start.
	 if  (i2c_write_byte(i2cadr| 1 )== 0 )  return  - 1  ;	 // i2cadr|1 => lecture.

	 for  (i= 0 ; i < rdlen; i++)
		 if  (i != rdlen -  1 ) buff[i] = i2c_read_byte( 0 ) ;
			 else  buff[i] = i2c_read_byte( 1 ) ; 

	i2c_stop() ;
      	 return   0  ;
}

/*------------------------------------------------------------------------------*/
/* Fonctions DS1621 								*/
/*------------------------------------------------------------------------------*/
int  i2c_init_ds1621( unsigned   char  addr)
{
	 int  ack ;
	 char  buff[ 10 ] ;
	
  	buff[ 0 ] =  0xAC  ;
  	buff[ 1 ] =  0x01  ;
	ack = i2c_write(addr, buff,  2 ) ;
	 if  (ack !=  0 )
	{
		printf( "NACK received (write ds1621) ! \n " );
		i2c_stop();
		exit(- 1 ) ;
	}

	 /* start temperature conversion */
	buff[ 0 ] =  0xEE  ;
	ack = i2c_write(addr, buff,  1 ) ;
	sleep( 1 ) ;
	 return  ack ;
}

//-----------------------------------------------------------------------------
double  i2c_gettemp_ds1621( unsigned   char  addr)
{
  	 int  k, count, slope, temp;
	 char  buff[ 10 ] ;
	 int  ack ;
	
    	 /* stop conversion */
	errno =  0  ;	
  	buff[ 0 ] =  0x22  ;
	ack = i2c_write(addr, buff,  1 ) ;
         if  ( ack !=  0  )	 return   255  ;			 // 255 car retourne normalement la t°.
	 else
	{
    		 /* Temperature reading (1 Celsius degree precision) */
  		buff[ 0 ] =  0xAA  ;
		i2c_writeread(addr, buff,  1 ) ;		 // Ecrit buff[0] avant lecture.
    		temp = buff[ 0 ] ;

    		 /* Counter reading (fraction of degree) ) */
  		buff[ 0 ] =  0xA8  ;
		i2c_writeread(addr, buff,  1 ) ;
    		count = buff[ 0 ] ;

    		 /* slope reading */
  		buff[ 0 ] =  0xA9  ;
		i2c_writeread(addr, buff,  1 ) ;
    		slope = buff[ 0 ] ;
   		k = temp;

   		 if  (slope !=  0 ) 
   		{
       			k = temp* 100 - 25 +( 100 *(slope-count))/slope;
   		}
		 //printf("Temp DS1621_1: %2.1f°\n", (float)k/100) ;
	  	 /* start temperature conversion */
  		buff[ 0 ] =  0xEE  ;
		i2c_write(addr, buff,  1 ) ;
		 return  ( float )k/ 100  ;
	}
}

// MAIN
int  main( void ) 
{
	 unsigned   char  	ds1621_addr  =  0x9E  ;	 // DS1621

	 double 		temp ;

  	i2c_init();

	i2c_init_ds1621(ds1621_addr) ;
	temp = i2c_gettemp_ds1621(ds1621_addr) ;
	 //printf("Temp DS1621: %2.1f° (V2.09062255)\n", temp) ;
	printf( "%2.1f \n " , temp) ;

	 return   0 ;
} 


Outils personnels
Administration wiki