Autor Tema: Tema: Librería para manejo de EEPROM externa en AVR - GCC  (Leído 3702 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado jonathanPIC888

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 320
Tema: Librería para manejo de EEPROM externa en AVR - GCC
« en: 30 de Septiembre de 2010, 01:26:01 »
Hola a todos , bueno luego de dar algunas vueltas y hacer varios ejemplos con WInAVR me embarque en la tarea de hacer funcionar una memoria eeprom 24C256, con resultados por el momento negativos.
Quisiera saber si alguien ha tenido experiencias con el bus I2C por software.
Les dejo la librería y el programa para un ATTINY2313.
1º - La librería I2C:
Código: C
  1. /*************************************************
  2.  LIBRERÍA DE CONTROL PARA BUS I2C EN MODO MASTER.
  3.  PROGRAMADOR: Moyano Jonathan.
  4.  Fecha: Setiembre del 2010.
  5.  Compilador: WinAVR
  6.  ************************************************/
  7.  
  8. // Acá definimos el puerto y los pines involucrados en la comunicación I2C.
  9. // Puerto SCL.
  10. #define SCLPORT    PORTD    // PUERTO RELOG I2C.
  11. #define SCLDDR    DDRD    // DIRECCIÓN PUERTO RELOG.
  12. // Puerto SDA.
  13. #define SDAPORT    PORTD    // PUERTO DATOS I2C.
  14. #define SDADDR    DDRD    // DIRECCIÓN PUERTO DATOS.
  15. #define SDAPIN    PIND    // PUERTO DE ENTRADA DE DATOS.
  16. // Asignaciones de pines.
  17. #define SCL    PD4     // PUERTO DE RELOG SCL I2C.
  18. #define SDA    PD3    // PUERTO DE DATOS SDA I2C.
  19.  
  20. // i2c 1/4 bit delay. (5uS)
  21. #define QDEL    asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop");
  22. // i2c 1/2 bit delay. (10uS)
  23. #define HDEL    asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop");
  24.  
  25. #define I2C_SDA_LO      SDAPORT &= ~(1<<SDA); // Pone la línea SDA, en bajo nivel.
  26. #define I2C_SDA_HI      SDAPORT |= 1<<SDA;    // Pone la línea SDA, en nivel alto.
  27.  
  28. #define I2C_SCL_LO      SCLPORT &= ~(1<<SCL); // Pone la línea SCL, en bajo nivel.
  29. #define I2C_SCL_HI      SCLPORT |= 1<<SCL;    // Pone la línea SCL, en nivel alto.
  30.  
  31. #define I2C_SCL_TOGGLE  HDEL I2C_SCL_HI HDEL I2C_SCL_LO
  32. #define I2C_START       I2C_SDA_LO QDEL I2C_SCL_LO      // Condición de START.
  33. #define I2C_STOP        HDEL I2C_SCL_HI QDEL I2C_SDA_HI HDEL // Condición de STOP.
  34.  
  35. // Definición de funciones:
  36.  
  37. // Iniciamos las comunicaciones.
  38. static void i2c_start(void);
  39.  
  40. // Paramos las comunicaciones;
  41. static void i2c_stop(void);
  42.  
  43. // Enviamos datos por el bus I2C.
  44. int i2c_write(int data);
  45.  
  46. // Recibimos datos por el bus I2C.
  47. int i2c_read(void);
  48. /*****************************************************************************************/
  49.  
  50. // FUNCIONES PARA TRABAJAR CON EL BUS I2C.
  51. static void i2c_start(void) {
  52.  I2C_START
  53.  }
  54. static void i2c_stop(void) {
  55.  I2C_SDA_LO // Limpiamos la línea de datos.
  56.  I2C_STOP
  57.  }
  58.  
  59. int i2c_write(int data) {
  60.  
  61.   uint8_t mascara = 0x80;
  62.   uint8_t i = 8;
  63.    
  64.     while(i--) {
  65.  
  66.         if(data & mascara)  //Si es 1.....
  67.          
  68.          I2C_SDA_HI // Pone a nivel alto la salida SDA.
  69.          else       // Si no es 1....
  70.          I2C_SDA_LO // Pone a nivel bajo la salida SDA.
  71.        
  72.       mascara >>= 1;
  73.            
  74.        I2C_SCL_TOGGLE // Cambio de flanco en el pin SCL.
  75.    }
  76.  
  77.  I2C_SDA_HI           // Dejamos SDA en alto.
  78.  SDADDR &= ~(1<<SDA);    // Configuramos SDA como entrada.        
  79.  HDEL                 // Esperamos 10us.
  80.  I2C_SCL_HI          // Dejamos SCL en alto.
  81.  
  82.       i = SDAPIN & (1<<SDA);    // Obtenemos el bit ACK.
  83.  
  84.  HDEL                 // Esperamos 10us.
  85.  I2C_SCL_LO          // Dejamoslínea SCL en bajo.
  86.  SDADDR |= 1<<SDA;    // Configuramos nuevamente SDA como salida.
  87.  HDEL                 // Esperamos 10us.
  88.  return i;     // Retornamos el valor de ACK.
  89.  
  90.           }
  91.      
  92. int i2c_read(void) {
  93.  
  94.   uint8_t datos = 0;
  95.   uint8_t i = 8;
  96.  
  97.    I2C_SDA_HI          // Dejamos SDA en alto.
  98.    SDADDR &= ~(1<<SDA);     // Configuramos SDA como entrada.    
  99.  
  100.    while (i--)
  101.     {
  102.         HDEL                 // Esperamos 10us.
  103.         I2C_SCL_HI         // Dejamos SCL en alto.
  104.         datos <<= 1;         // Rotamos el resultado a la izquierda.
  105.         if (SDAPIN & (1<<SDA))
  106.             datos += 1;      // Si hay un uno en la línea de datos lo agregamos
  107.                              // al arreglo.
  108.  
  109.         HDEL                 // Esperamos 10us.
  110.         I2C_SCL_LO           // Dejamoslínea SCL en bajo.
  111.     }
  112.  
  113.    SDADDR |= 1<<SDA;    // Configuramos nuevamente SDA como salida.
  114.    I2C_SCL_TOGGLE       // Cambio de flanco en el pin SCL.
  115.    I2C_SDA_HI           // Dejamos SDA en alto.
  116.    return datos;      // retornamos con el dato leido.
  117. }


y 2º el programa que implementé...me compila bien pero no me está funcionando , en la salida siempre obtengo 0xFF .. :(

Código: C
  1. /*************************************************
  2.  PROGRAMAS DE EJEMPLO PARA EL ATTINY2313 - 20PU.
  3.  PROGRAMADOR: Moyano Jonathan.
  4.  Fecha: Setiembre del 2010.
  5.  Programa: Graba 4 datos en una memoria EEPROM 24CL256. Luego
  6.            lee las memorias y muestra los valores guardados en
  7.            el puerto B.
  8.  Cristal:  8Mhz.
  9.  Programador: PK2-ISP.
  10.  ************************************************/
  11. #include <avr/io.h>     // Definiciones de hardware.
  12. #include <util/delay.h> // Librería para generar retardos.
  13. #include <util/i2c_software.c> // Librería para el manejo de I2C por
  14.                                // software.
  15.  
  16. void init_ext_eeprom()
  17. {
  18.    SDAPORT |= 1<<SDA;    // Pone la línea SDA, en nivel alto.
  19.    SCLPORT |= 1<<SCL;    // Pone la línea SCL, en nivel alto.
  20. }
  21.  
  22. void write_ext_eeprom(uint32_t address, uint8_t valor)
  23. {
  24.    int status;
  25.    i2c_start();
  26.    i2c_write(0xa0);
  27.    i2c_write((address>>8)&0x1f);
  28.    i2c_write(address);
  29.    i2c_write(valor);
  30.    i2c_stop();
  31.    i2c_start();
  32.    status=i2c_write(0xa0);
  33.    while(status==1)
  34.    {
  35.       i2c_start();
  36.       status=i2c_write(0xa0);
  37.    }
  38. }
  39.  
  40. uint8_t read_ext_eeprom(uint32_t address) {
  41.         uint8_t _datos;
  42.         i2c_start();
  43.         i2c_write(0xa0);
  44.         i2c_write((address>>8)&0x1f);
  45.         i2c_write(address);
  46.         i2c_start();
  47.         i2c_write(0xa1);
  48.         _datos =i2c_read();
  49.         i2c_stop();
  50.         return(_datos);
  51. }
  52. int main(void)
  53. {
  54.     DDRB = 0x1F;  // PB0-PB4 salidas.
  55.     PORTB = 0x00; // Ponemos todas las salidas a 0.
  56.  
  57.     uint8_t k; // Variable auxiliar.
  58.  
  59.         init_ext_eeprom();
  60.         write_ext_eeprom(0x01,0x01);
  61.         write_ext_eeprom(0x02,0x02);
  62.         write_ext_eeprom(0x03,0x03);
  63.         write_ext_eeprom(0x04,0x04);
  64.    
  65.     while(1) // Loop infinito.
  66.     {
  67.         for(k=0; k<=4; k++){
  68.         PORTB = read_ext_eeprom(k);
  69.         _delay_ms(250);
  70.     }
  71. }
  72. }

Desconectado jonathanPIC888

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 320
Re: Tema: Librería para manejo de EEPROM externa en AVR - GCC
« Respuesta #1 en: 03 de Octubre de 2010, 22:18:21 »
Bueno después de unos días de lectura sobre el protocolo I2C, encontré una librería hecha en ASM para el control a bajo nivel por software del puerto I2C de cualquier micro AVR.
Mediante una aplicación sencilla muestro como trabajar con dicha librería en WINAVR.
Código: C
  1. /*************************************************
  2.  PROGRAMAS DE EJEMPLO PARA EL ATTINY2313 - 20PU.
  3.  Fecha: Setiembre del 2010.
  4.  Programa: Guarda 1 dato en la EEPROM y luego lo lee.
  5.  Cristal:  8Mhz.
  6.  Programador: PK2-ISP.
  7.  ************************************************/
  8. #include <avr/io.h>
  9. #include "i2cmaster.h"
  10. #include <util/delay.h>
  11.  
  12. char i,status;
  13.  
  14. int main(void)
  15. {
  16.         DDRB = 0x07;  // PB0-PB2 salidas.
  17.         PORTB = 0x00; // Ponemos todas las salidas a 0.
  18.        
  19.     i2c_init(); // Iniciamos I2C.
  20.        
  21.         i2c_start_wait(0xA0+I2C_WRITE);
  22.         i2c_write(0x00); // Dirección ALTA.
  23.         i2c_write(0x01); // Dirección BAJA.
  24.         i2c_write(0x05); // Datos.
  25.         i2c_stop();
  26.        
  27.        
  28.         i2c_start_wait(0xA0+I2C_WRITE);
  29.         i2c_write(0x00); // Dirección ALTA.
  30.         i2c_write(0x01); // Dirección BAJA.
  31.        
  32.         status = i2c_rep_start(0XA0+I2C_READ);
  33.         if(status != 0) {
  34.           i2c_stop();
  35.             PORTB = 0x04;
  36.                  _delay_ms(2000);
  37.                    }
  38.              else
  39.  
  40.         i = i2c_readNak(); // Leemos dato.
  41.         PORTB = i;
  42.         _delay_ms(2000);
  43.         i2c_stop();
  44.        
  45.        
  46.  
  47. }

La librería con la definición de funciones:

Código: C
  1. #ifndef _I2CMASTER_H
  2. #define _I2CMASTER_H   1
  3. /*************************************************************************
  4. * Title:    C include file for the I2C master interface
  5. *           (i2cmaster.S or twimaster.c)
  6. * Author:   Peter Fleury <pfleury@gmx.ch>  http://jump.to/fleury
  7. * File:     $Id: i2cmaster.h,v 1.10 2005/03/06 22:39:57 Peter Exp $
  8. * Software: AVR-GCC 3.4.3 / avr-libc 1.2.3
  9. * Target:   any AVR device
  10. * Usage:    see Doxygen manual
  11. **************************************************************************/
  12.  
  13. #ifdef DOXYGEN
  14. /**
  15.  @defgroup pfleury_ic2master I2C Master library
  16.  @code #include <i2cmaster.h> @endcode
  17.  
  18.  @brief I2C (TWI) Master Software Library
  19.  
  20.  Basic routines for communicating with I2C slave devices. This single master
  21.  implementation is limited to one bus master on the I2C bus.
  22.  
  23.  This I2c library is implemented as a compact assembler software implementation of the I2C protocol
  24.  which runs on any AVR (i2cmaster.S) and as a TWI hardware interface for all AVR with built-in TWI hardware (twimaster.c).
  25.  Since the API for these two implementations is exactly the same, an application can be linked either against the
  26.  software I2C implementation or the hardware I2C implementation.
  27.  
  28.  Use 4.7k pull-up resistor on the SDA and SCL pin.
  29.  
  30.  Adapt the SCL and SDA port and pin definitions and eventually the delay routine in the module
  31.  i2cmaster.S to your target when using the software I2C implementation !
  32.  
  33.  Adjust the  CPU clock frequence F_CPU in twimaster.c or in the Makfile when using the TWI hardware implementaion.
  34.  
  35.  @note
  36.     The module i2cmaster.S is based on the Atmel Application Note AVR300, corrected and adapted
  37.     to GNU assembler and AVR-GCC C call interface.
  38.     Replaced the incorrect quarter period delays found in AVR300 with
  39.     half period delays.
  40.    
  41.  @author Peter Fleury pfleury@gmx.ch  http://jump.to/fleury
  42.  
  43.  @par API Usage Example
  44.   The following code shows typical usage of this library, see example test_i2cmaster.c
  45.  
  46.  @code
  47.  
  48.  #include <i2cmaster.h>
  49.  
  50.  
  51.  #define Dev24C02  0xA2      // device address of EEPROM 24C02, see datasheet
  52.  
  53.  int main(void)
  54.  {
  55.      unsigned char ret;
  56.  
  57.      i2c_init();                             // initialize I2C library
  58.  
  59.      // write 0x75 to EEPROM address 5 (Byte Write)
  60.      i2c_start_wait(Dev24C02+I2C_WRITE);     // set device address and write mode
  61.      i2c_write(0x05);                        // write address = 5
  62.      i2c_write(0x75);                        // write value 0x75 to EEPROM
  63.      i2c_stop();                             // set stop conditon = release bus
  64.  
  65.  
  66.      // read previously written value back from EEPROM address 5
  67.      i2c_start_wait(Dev24C02+I2C_WRITE);     // set device address and write mode
  68.  
  69.      i2c_write(0x05);                        // write address = 5
  70.      i2c_rep_start(Dev24C02+I2C_READ);       // set device address and read mode
  71.  
  72.      ret = i2c_readNak();                    // read one byte from EEPROM
  73.      i2c_stop();
  74.  
  75.      for(;;);
  76.  }
  77.  @endcode
  78.  
  79. */
  80. #endif /* DOXYGEN */
  81.  
  82. /**@{*/
  83.  
  84. #if (__GNUC__ * 100 + __GNUC_MINOR__) < 304
  85. #error "This library requires AVR-GCC 3.4 or later, update to newer AVR-GCC compiler !"
  86. #endif
  87.  
  88. #include <avr/io.h>
  89.  
  90. /** defines the data direction (reading from I2C device) in i2c_start(),i2c_rep_start() */
  91. #define I2C_READ    1
  92.  
  93. /** defines the data direction (writing to I2C device) in i2c_start(),i2c_rep_start() */
  94. #define I2C_WRITE   0
  95.  
  96.  
  97. /**
  98.  @brief initialize the I2C master interace. Need to be called only once
  99.  @param  void
  100.  @return none
  101.  */
  102. extern void i2c_init(void);
  103.  
  104.  
  105. /**
  106.  @brief Terminates the data transfer and releases the I2C bus
  107.  @param void
  108.  @return none
  109.  */
  110. extern void i2c_stop(void);
  111.  
  112.  
  113. /**
  114.  @brief Issues a start condition and sends address and transfer direction
  115.  
  116.  @param    addr address and transfer direction of I2C device
  117.  @retval   0   device accessible
  118.  @retval   1   failed to access device
  119.  */
  120. extern unsigned char i2c_start(unsigned char addr);
  121.  
  122.  
  123. /**
  124.  @brief Issues a repeated start condition and sends address and transfer direction
  125.  
  126.  @param   addr address and transfer direction of I2C device
  127.  @retval  0 device accessible
  128.  @retval  1 failed to access device
  129.  */
  130. extern unsigned char i2c_rep_start(unsigned char addr);
  131.  
  132.  
  133. /**
  134.  @brief Issues a start condition and sends address and transfer direction
  135.    
  136.  If device is busy, use ack polling to wait until device ready
  137.  @param    addr address and transfer direction of I2C device
  138.  @return   none
  139.  */
  140. extern void i2c_start_wait(unsigned char addr);
  141.  
  142.  
  143. /**
  144.  @brief Send one byte to I2C device
  145.  @param    data  byte to be transfered
  146.  @retval   0 write successful
  147.  @retval   1 write failed
  148.  */
  149. extern unsigned char i2c_write(unsigned char data);
  150.  
  151.  
  152. /**
  153.  @brief    read one byte from the I2C device, request more data from device
  154.  @return   byte read from I2C device
  155.  */
  156. extern unsigned char i2c_readAck(void);
  157.  
  158. /**
  159.  @brief    read one byte from the I2C device, read is followed by a stop condition
  160.  @return   byte read from I2C device
  161.  */
  162. extern unsigned char i2c_readNak(void);
  163.  
  164. /**
  165.  @brief    read one byte from the I2C device
  166.  
  167.  Implemented as a macro, which calls either i2c_readAck or i2c_readNak
  168.  
  169.  @param    ack 1 send ack, request more data from device<br>
  170.                0 send nak, read is followed by a stop condition
  171.  @return   byte read from I2C device
  172.  */
  173. extern unsigned char i2c_read(unsigned char ack);
  174. #define i2c_read(ack)  (ack) ? i2c_readAck() : i2c_readNak();
  175.  
  176.  
  177. /**@}*/
  178. #endif

Funciones en ASM:

Código: ASM
  1. ;*************************************************************************
  2. ; Title :    I2C (Single) Master Implementation
  3. ; Author:    Peter Fleury <pfleury@gmx.ch>  http://jump.to/fleury
  4. ;            based on Atmel Appl. Note AVR300
  5. ; File:      $Id: i2cmaster.S,v 1.12 2008/03/02 08:51:27 peter Exp $
  6. ; Software:  AVR-GCC 3.3 or higher
  7. ; Target:    any AVR device
  8. ;
  9. ; DESCRIPTION
  10. ;       Basic routines for communicating with I2C slave devices. This
  11. ;       "single" master implementation is limited to one bus master on the
  12. ;       I2C bus.
  13. ;  
  14. ;       Based on the Atmel Application Note AVR300, corrected and adapted
  15. ;       to GNU assembler and AVR-GCC C call interface
  16. ;       Replaced the incorrect quarter period delays found in AVR300 with
  17. ;       half period delays.
  18. ;
  19. ; USAGE
  20. ;       These routines can be called from C, refere to file i2cmaster.h.
  21. ;       See example test_i2cmaster.c
  22. ;       Adapt the SCL and SDA port and pin definitions and eventually
  23. ;       the delay routine to your target !
  24. ;       Use 4.7k pull-up resistor on the SDA and SCL pin.
  25. ;
  26. ; NOTES
  27. ;       The I2C routines can be called either from non-interrupt or
  28. ;       interrupt routines, not both.
  29. ;
  30. ;*************************************************************************
  31.  
  32. #if (__GNUC__ * 100 + __GNUC_MINOR__) < 303
  33. #error "This library requires AVR-GCC 3.3 or later, update to newer AVR-GCC compiler !"
  34. #endif
  35.  
  36.  
  37. #include <avr/io.h>
  38.  
  39.  
  40.  
  41. ;***** Adapt these SCA and SCL port and pin definition to your target !!
  42. ;
  43. #define SDA             3               // SDA Port B, Pin 3  
  44. #define SCL             4               // SCL Port B, Pin 4
  45. #define SDA_PORT        PORTB           // SDA Port B
  46. #define SCL_PORT        PORTB           // SCL Port B        
  47.  
  48. ;******
  49.  
  50. ;-- map the IO register back into the IO address space
  51. #define SDA_DDR         (_SFR_IO_ADDR(SDA_PORT) - 1)
  52. #define SCL_DDR         (_SFR_IO_ADDR(SCL_PORT) - 1)
  53. #define SDA_OUT         _SFR_IO_ADDR(SDA_PORT)
  54. #define SCL_OUT         _SFR_IO_ADDR(SCL_PORT)
  55. #define SDA_IN          (_SFR_IO_ADDR(SDA_PORT) - 2)
  56. #define SCL_IN          (_SFR_IO_ADDR(SCL_PORT) - 2)
  57.  
  58.  
  59. #ifndef __tmp_reg__
  60. #define __tmp_reg__ 0
  61. #endif
  62.  
  63.  
  64.         .section .text
  65.  
  66. ;*************************************************************************
  67. ; delay half period
  68. ; For I2C in normal mode (100kHz), use T/2 > 5us
  69. ; For I2C in fast mode (400kHz),   use T/2 > 1.3us
  70. ;*************************************************************************
  71.         .stabs  "",100,0,0,i2c_delay_T2
  72.         .stabs  "i2cmaster.S",100,0,0,i2c_delay_T2
  73.         .func i2c_delay_T2      ; delay 5.0 microsec with 4 Mhz crystal
  74. i2c_delay_T2:        ; 4 cycles
  75.         rjmp 1f      ; 2   "
  76. 1:      rjmp 2f      ; 2   "
  77. 2:      rjmp 3f      ; 2   "
  78. 3:      rjmp 4f      ; 2   "
  79. 4:      rjmp 5f      ; 2   "
  80. 5:      rjmp 6f      ; 2   "
  81. 6:      nop          ; 1   "
  82.         ret          ; 3   "
  83.         .endfunc     ; total 20 cyles = 5.0 microsec with 4 Mhz crystal
  84.  
  85.  
  86. ;*************************************************************************
  87. ; Initialization of the I2C bus interface. Need to be called only once
  88. ;
  89. ; extern void i2c_init(void)
  90. ;*************************************************************************
  91.         .global i2c_init
  92.         .func i2c_init
  93. i2c_init:
  94.         cbi SDA_DDR,SDA         ;release SDA
  95.         cbi SCL_DDR,SCL         ;release SCL
  96.         cbi SDA_OUT,SDA
  97.         cbi SCL_OUT,SCL
  98.         ret
  99.         .endfunc
  100.  
  101.  
  102. ;*************************************************************************     
  103. ; Issues a start condition and sends address and transfer direction.
  104. ; return 0 = device accessible, 1= failed to access device
  105. ;
  106. ; extern unsigned char i2c_start(unsigned char addr);
  107. ;       addr = r24, return = r25(=0):r24
  108. ;*************************************************************************
  109.  
  110.         .global i2c_start
  111.         .func   i2c_start
  112. i2c_start:
  113.         sbi     SDA_DDR,SDA     ;force SDA low
  114.         rcall   i2c_delay_T2    ;delay T/2
  115.        
  116.         rcall   i2c_write       ;write address
  117.         ret
  118.         .endfunc               
  119.  
  120.  
  121. ;*************************************************************************
  122. ; Issues a repeated start condition and sends address and transfer direction.
  123. ; return 0 = device accessible, 1= failed to access device
  124. ;
  125. ; extern unsigned char i2c_rep_start(unsigned char addr);
  126. ;       addr = r24,  return = r25(=0):r24
  127. ;*************************************************************************
  128.  
  129.         .global i2c_rep_start
  130.         .func   i2c_rep_start
  131. i2c_rep_start:
  132.         sbi     SCL_DDR,SCL     ;force SCL low
  133.         rcall   i2c_delay_T2    ;delay  T/2
  134.         cbi     SDA_DDR,SDA     ;release SDA
  135.         rcall   i2c_delay_T2    ;delay T/2
  136.         cbi     SCL_DDR,SCL     ;release SCL
  137.         rcall   i2c_delay_T2    ;delay  T/2
  138.         sbi     SDA_DDR,SDA     ;force SDA low
  139.         rcall   i2c_delay_T2    ;delay  T/2
  140.        
  141.         rcall   i2c_write       ;write address
  142.         ret
  143.         .endfunc
  144.  
  145.  
  146. ;*************************************************************************     
  147. ; Issues a start condition and sends address and transfer direction.
  148. ; If device is busy, use ack polling to wait until device is ready
  149. ;
  150. ; extern void i2c_start_wait(unsigned char addr);
  151. ;       addr = r24
  152. ;*************************************************************************
  153.  
  154.         .global i2c_start_wait
  155.         .func   i2c_start_wait
  156. i2c_start_wait:
  157.         mov     __tmp_reg__,r24
  158. i2c_start_wait1:
  159.         sbi     SDA_DDR,SDA     ;force SDA low
  160.         rcall   i2c_delay_T2    ;delay T/2
  161.         mov     r24,__tmp_reg__
  162.         rcall   i2c_write       ;write address
  163.         tst     r24             ;if device not busy -> done
  164.         breq    i2c_start_wait_done
  165.         rcall   i2c_stop        ;terminate write operation
  166.         rjmp    i2c_start_wait1 ;device busy, poll ack again
  167. i2c_start_wait_done:
  168.         ret
  169.         .endfunc       
  170.  
  171.  
  172. ;*************************************************************************
  173. ; Terminates the data transfer and releases the I2C bus
  174. ;
  175. ; extern void i2c_stop(void)
  176. ;*************************************************************************
  177.  
  178.         .global i2c_stop
  179.         .func   i2c_stop
  180. i2c_stop:
  181.         sbi     SCL_DDR,SCL     ;force SCL low
  182.         sbi     SDA_DDR,SDA     ;force SDA low
  183.         rcall   i2c_delay_T2    ;delay T/2
  184.         cbi     SCL_DDR,SCL     ;release SCL
  185.         rcall   i2c_delay_T2    ;delay T/2
  186.         cbi     SDA_DDR,SDA     ;release SDA
  187.         rcall   i2c_delay_T2    ;delay T/2
  188.         ret
  189.         .endfunc
  190.  
  191.  
  192. ;*************************************************************************
  193. ; Send one byte to I2C device
  194. ; return 0 = write successful, 1 = write failed
  195. ;
  196. ; extern unsigned char i2c_write( unsigned char data );
  197. ;       data = r24,  return = r25(=0):r24
  198. ;*************************************************************************
  199.         .global i2c_write
  200.         .func   i2c_write
  201. i2c_write:
  202.         sec                     ;set carry flag
  203.         rol     r24             ;shift in carry and out bit one
  204.         rjmp    i2c_write_first
  205. i2c_write_bit:
  206.         lsl     r24             ;if transmit register empty
  207. i2c_write_first:
  208.         breq    i2c_get_ack
  209.         sbi     SCL_DDR,SCL     ;force SCL low
  210.         brcc    i2c_write_low
  211.         nop
  212.         cbi     SDA_DDR,SDA     ;release SDA
  213.         rjmp    i2c_write_high
  214. i2c_write_low:
  215.         sbi     SDA_DDR,SDA     ;force SDA low
  216.         rjmp    i2c_write_high
  217. i2c_write_high:
  218.         rcall   i2c_delay_T2    ;delay T/2
  219.         cbi     SCL_DDR,SCL     ;release SCL
  220.         rcall   i2c_delay_T2    ;delay T/2
  221.         rjmp    i2c_write_bit
  222.        
  223. i2c_get_ack:
  224.         sbi     SCL_DDR,SCL     ;force SCL low
  225.         cbi     SDA_DDR,SDA     ;release SDA
  226.         rcall   i2c_delay_T2    ;delay T/2
  227.         cbi     SCL_DDR,SCL     ;release SCL
  228. i2c_ack_wait:
  229.         sbis    SCL_IN,SCL      ;wait SCL high (in case wait states are inserted)
  230.         rjmp    i2c_ack_wait
  231.        
  232.         clr     r24             ;return 0
  233.         sbic    SDA_IN,SDA      ;if SDA high -> return 1
  234.         ldi     r24,1
  235.         rcall   i2c_delay_T2    ;delay T/2
  236.         clr     r25
  237.         ret
  238.         .endfunc
  239.  
  240.  
  241.  
  242. ;*************************************************************************
  243. ; read one byte from the I2C device, send ack or nak to device
  244. ; (ack=1, send ack, request more data from device
  245. ;  ack=0, send nak, read is followed by a stop condition)
  246. ;
  247. ; extern unsigned char i2c_read(unsigned char ack);
  248. ;       ack = r24, return = r25(=0):r24
  249. ; extern unsigned char i2c_readAck(void);
  250. ; extern unsigned char i2c_readNak(void);
  251. ;       return = r25(=0):r24
  252. ;*************************************************************************
  253.         .global i2c_readAck
  254.         .global i2c_readNak
  255.         .global i2c_read               
  256.         .func   i2c_read
  257. i2c_readNak:
  258.         clr     r24
  259.         rjmp    i2c_read
  260. i2c_readAck:
  261.         ldi     r24,0x01
  262. i2c_read:
  263.         ldi     r23,0x01        ;data = 0x01
  264. i2c_read_bit:
  265.         sbi     SCL_DDR,SCL     ;force SCL low
  266.         cbi     SDA_DDR,SDA     ;release SDA (from previous ACK)
  267.         rcall   i2c_delay_T2    ;delay T/2
  268.        
  269.         cbi     SCL_DDR,SCL     ;release SCL
  270.         rcall   i2c_delay_T2    ;delay T/2
  271.        
  272. i2c_read_stretch:
  273.     sbis SCL_IN, SCL        ;loop until SCL is high (allow slave to stretch SCL)
  274.     rjmp        i2c_read_stretch
  275.        
  276.         clc                     ;clear carry flag
  277.         sbic    SDA_IN,SDA      ;if SDA is high
  278.         sec                     ;  set carry flag
  279.        
  280.         rol     r23             ;store bit
  281.         brcc    i2c_read_bit    ;while receive register not full
  282.        
  283. i2c_put_ack:
  284.         sbi     SCL_DDR,SCL     ;force SCL low 
  285.         cpi     r24,1
  286.         breq    i2c_put_ack_low ;if (ack=0)
  287.         cbi     SDA_DDR,SDA     ;      release SDA
  288.         rjmp    i2c_put_ack_high
  289. i2c_put_ack_low:                ;else
  290.         sbi     SDA_DDR,SDA     ;      force SDA low
  291. i2c_put_ack_high:
  292.         rcall   i2c_delay_T2    ;delay T/2
  293.         cbi     SCL_DDR,SCL     ;release SCL
  294. i2c_put_ack_wait:
  295.         sbis    SCL_IN,SCL      ;wait SCL high
  296.         rjmp    i2c_put_ack_wait
  297.         rcall   i2c_delay_T2    ;delay T/2
  298.         mov     r24,r23
  299.         clr     r25
  300.         ret
  301.         .endfunc


 

anything