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 ; }
