SHARE
TWEET

Untitled

a guest Apr 5th, 2017 3 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ;*************************************************************************
  2. ; Title :    I2C (Single) Master Implementation
  3. ; Author:    Peter Fleury <pfleury@gmx.ch>
  4. ;            based on Atmel Appl. Note AVR300
  5. ; File:      $Id: i2cmaster.S,v 1.13 2015/09/16 11:21:00 peter Exp $
  6. ; Software:  AVR-GCC 4.x
  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.  
  33. #include <avr/io.h>
  34.  
  35. #undef SCL_PORT
  36. #undef SCL_DDR
  37.  
  38.  
  39. ;******----- Adapt these SCA and SCL port and pin definition to your target !!
  40. ;
  41. #define SDA             7           // SDA Port A, Pin 7 (PA7)  
  42. #define SCL             2           // SCL Port B, Pin 2 (PB2)
  43. #define SDA_PORT        PORTA       // SDA Port A
  44. #define SCL_PORT        PORTB       // SCL Port B        
  45.  
  46. ;******----------------------------------------------------------------------
  47.  
  48.  
  49. ;-- map the IO register back into the IO address space
  50. #define SDA_DDR     (_SFR_IO_ADDR(SDA_PORT) - 1)
  51. #define SCL_DDR     (_SFR_IO_ADDR(SCL_PORT) - 1)
  52. #define SDA_OUT     _SFR_IO_ADDR(SDA_PORT)
  53. #define SCL_OUT     _SFR_IO_ADDR(SCL_PORT)
  54. #define SDA_IN      (_SFR_IO_ADDR(SDA_PORT) - 2)
  55. #define SCL_IN      (_SFR_IO_ADDR(SCL_PORT) - 2)
  56.  
  57. #define F_CPU 16000000UL
  58.  
  59.  
  60. #ifndef __tmp_reg__
  61. #define __tmp_reg__ 0
  62. #endif
  63.  
  64.  
  65.     .section .text
  66.  
  67. ;*************************************************************************
  68. ; delay half period
  69. ; For I2C in normal mode (100kHz), use T/2 > 5us
  70. ; For I2C in fast mode (400kHz),   use T/2 > 1.25us
  71. ;*************************************************************************
  72.     .stabs  "",100,0,0,i2c_delay_T2
  73.     .stabs  "i2cmaster.S",100,0,0,i2c_delay_T2
  74.     .func i2c_delay_T2  ; delay 5.0 microsec with 4 Mhz crystal
  75. i2c_delay_T2:        ; 3 cycles
  76. #if F_CPU <= 4000000UL
  77.     rjmp 1f      ; 2   "
  78. 1:  rjmp 2f      ; 2   "
  79. 2:  rjmp 3f      ; 2   "
  80. 3:  rjmp 4f      ; 2   "
  81. 4:  rjmp 5f      ; 2   "
  82. 5:  rjmp 6f      ; 2   "
  83. 6:  nop          ; 1   "
  84.     ret          ; 4   "  total 20 cyles = 5.0 microsec with 4 Mhz crystal
  85. #elif F_CPU <= 8000000UL
  86.     push r24     ; 2 cycle
  87.     ldi  r24, 7  ; 1 cycle
  88.     nop          ; 1 cycle
  89. 1:  sbiw r24, 1  ; 2 cycle
  90.     brne 1b      ; 2 or 1 cycle, 4 cycles per loop
  91.     pop  r24     ; 2 ycle
  92.     ret          ; 4 cycle = total 60 cycles = 5.0 microsec with 12 Mhz crystal
  93. #elif F_CPU <= 12000000UL
  94.     push r24     ; 2 cycle
  95.     ldi  r24, 12 ; 1 cycle
  96.     nop          ; 1 cycle
  97. 1:  sbiw r24, 1  ; 2 cycle
  98.     brne 1b      ; 2 or 1 cycle, 4 cycles per loop
  99.     pop  r24     ; 2 ycle
  100.     ret          ; 4 cycle = total 60 cycles = 5.0 microsec with 12 Mhz crystal
  101. #elif F_CPU <= 16000000UL
  102.     push r24     ; 2 cycle
  103.     ldi  r24, 17 ; 1 cycle
  104.     nop          ; 1 cycle
  105. 1:  sbiw r24, 1  ; 2 cycle
  106.     brne 1b      ; 2 or 1 cycle, 4 cycles per loop
  107.     pop  r24     ; 2 ycle
  108.     ret          ; 4 cycle = total 80 cycles = 5.0 microsec with 16 Mhz crystal
  109. #else
  110.     push r24     ; 2 cycle
  111.     ldi  r24, 22 ; 1 cycle
  112.     nop          ; 1 cycle
  113. 1:  sbiw r24, 1  ; 2 cycle
  114.     brne 1b      ; 2 or 1 cycle, 4 cycles per loop
  115.     pop  r24     ; 2 ycle
  116.     ret          ; 4 cycle = total 100 cycles = 5.0 microsec with 20 Mhz crystal
  117. #endif 
  118.     .endfunc     ;
  119.  
  120.  
  121. ;*************************************************************************
  122. ; Initialization of the I2C bus interface. Need to be called only once
  123. ;
  124. ; extern void i2c_init(void)
  125. ;*************************************************************************
  126.     .global i2c_init
  127.     .func i2c_init
  128. i2c_init:
  129.     cbi SDA_DDR,SDA     ;release SDA
  130.     cbi SCL_DDR,SCL     ;release SCL
  131.     cbi SDA_OUT,SDA
  132.     cbi SCL_OUT,SCL
  133.     ret
  134.     .endfunc
  135.  
  136.  
  137. ;************************************************************************* 
  138. ; Issues a start condition and sends address and transfer direction.
  139. ; return 0 = device accessible, 1= failed to access device
  140. ;
  141. ; extern unsigned char i2c_start(unsigned char addr);
  142. ;   addr = r24, return = r25(=0):r24
  143. ;*************************************************************************
  144.  
  145.     .global i2c_start
  146.     .func   i2c_start
  147. i2c_start:
  148.     sbi     SDA_DDR,SDA ;force SDA low
  149.     rcall   i2c_delay_T2    ;delay T/2
  150.    
  151.     rcall   i2c_write   ;write address
  152.     ret
  153.     .endfunc       
  154.  
  155.  
  156. ;*************************************************************************
  157. ; Issues a repeated start condition and sends address and transfer direction.
  158. ; return 0 = device accessible, 1= failed to access device
  159. ;
  160. ; extern unsigned char i2c_rep_start(unsigned char addr);
  161. ;   addr = r24,  return = r25(=0):r24
  162. ;*************************************************************************
  163.  
  164.     .global i2c_rep_start
  165.     .func   i2c_rep_start
  166. i2c_rep_start:
  167.     sbi SCL_DDR,SCL ;force SCL low
  168.     rcall   i2c_delay_T2    ;delay  T/2
  169.     cbi SDA_DDR,SDA ;release SDA
  170.     rcall   i2c_delay_T2    ;delay T/2
  171.     cbi SCL_DDR,SCL ;release SCL
  172.     rcall   i2c_delay_T2    ;delay  T/2
  173.     sbi     SDA_DDR,SDA ;force SDA low
  174.     rcall   i2c_delay_T2    ;delay  T/2
  175.    
  176.     rcall   i2c_write   ;write address
  177.     ret
  178.     .endfunc
  179.  
  180.  
  181. ;************************************************************************* 
  182. ; Issues a start condition and sends address and transfer direction.
  183. ; If device is busy, use ack polling to wait until device is ready
  184. ;
  185. ; extern void i2c_start_wait(unsigned char addr);
  186. ;   addr = r24
  187. ;*************************************************************************
  188.  
  189.     .global i2c_start_wait
  190.     .func   i2c_start_wait
  191. i2c_start_wait:
  192.     mov __tmp_reg__,r24
  193. i2c_start_wait1:
  194.     sbi     SDA_DDR,SDA ;force SDA low
  195.     rcall   i2c_delay_T2    ;delay T/2
  196.     mov r24,__tmp_reg__
  197.     rcall   i2c_write   ;write address
  198.     tst r24     ;if device not busy -> done
  199.     breq    i2c_start_wait_done
  200.     rcall   i2c_stop    ;terminate write operation
  201.     rjmp    i2c_start_wait1 ;device busy, poll ack again
  202. i2c_start_wait_done:
  203.     ret
  204.     .endfunc   
  205.  
  206.  
  207. ;*************************************************************************
  208. ; Terminates the data transfer and releases the I2C bus
  209. ;
  210. ; extern void i2c_stop(void)
  211. ;*************************************************************************
  212.  
  213.     .global i2c_stop
  214.     .func   i2c_stop
  215. i2c_stop:
  216.     sbi SCL_DDR,SCL ;force SCL low
  217.     sbi SDA_DDR,SDA ;force SDA low
  218.     rcall   i2c_delay_T2    ;delay T/2
  219.     cbi SCL_DDR,SCL ;release SCL
  220.     rcall   i2c_delay_T2    ;delay T/2
  221.     cbi SDA_DDR,SDA ;release SDA
  222.     rcall   i2c_delay_T2    ;delay T/2
  223.     ret
  224.     .endfunc
  225.  
  226.  
  227. ;*************************************************************************
  228. ; Send one byte to I2C device
  229. ; return 0 = write successful, 1 = write failed
  230. ;
  231. ; extern unsigned char i2c_write( unsigned char data );
  232. ;   data = r24,  return = r25(=0):r24
  233. ;*************************************************************************
  234.     .global i2c_write
  235.     .func   i2c_write
  236. i2c_write:
  237.     sec         ;set carry flag
  238.     rol     r24     ;shift in carry and out bit one
  239.     rjmp    i2c_write_first
  240. i2c_write_bit:
  241.     lsl r24     ;if transmit register empty
  242. i2c_write_first:
  243.     breq    i2c_get_ack
  244.     sbi SCL_DDR,SCL ;force SCL low
  245.     brcc    i2c_write_low
  246.     nop
  247.     cbi SDA_DDR,SDA ;release SDA
  248.     rjmp    i2c_write_high
  249. i2c_write_low:
  250.     sbi SDA_DDR,SDA ;force SDA low
  251.     rjmp    i2c_write_high
  252. i2c_write_high:
  253.     rcall   i2c_delay_T2    ;delay T/2
  254.     cbi SCL_DDR,SCL ;release SCL
  255.     rcall   i2c_delay_T2    ;delay T/2
  256.     rjmp    i2c_write_bit
  257.    
  258. i2c_get_ack:
  259.     sbi SCL_DDR,SCL ;force SCL low
  260.     cbi SDA_DDR,SDA ;release SDA
  261.     rcall   i2c_delay_T2    ;delay T/2
  262.     cbi SCL_DDR,SCL ;release SCL
  263. i2c_ack_wait:
  264.     sbis    SCL_IN,SCL  ;wait SCL high (in case wait states are inserted)
  265.     rjmp    i2c_ack_wait
  266.    
  267.     clr r24     ;return 0
  268.     sbic    SDA_IN,SDA  ;if SDA high -> return 1
  269.     ldi r24,1
  270.     rcall   i2c_delay_T2    ;delay T/2
  271.     clr r25
  272.     ret
  273.     .endfunc
  274.  
  275.  
  276.  
  277. ;*************************************************************************
  278. ; read one byte from the I2C device, send ack or nak to device
  279. ; (ack=1, send ack, request more data from device
  280. ;  ack=0, send nak, read is followed by a stop condition)
  281. ;
  282. ; extern unsigned char i2c_read(unsigned char ack);
  283. ;   ack = r24, return = r25(=0):r24
  284. ; extern unsigned char i2c_readAck(void);
  285. ; extern unsigned char i2c_readNak(void);
  286. ;   return = r25(=0):r24
  287. ;*************************************************************************
  288.     .global i2c_readAck
  289.     .global i2c_readNak
  290.     .global i2c_read       
  291.     .func   i2c_read
  292. i2c_readNak:
  293.     clr r24
  294.     rjmp    i2c_read
  295. i2c_readAck:
  296.     ldi r24,0x01
  297. i2c_read:
  298.     ldi r23,0x01    ;data = 0x01
  299. i2c_read_bit:
  300.     sbi SCL_DDR,SCL ;force SCL low
  301.     cbi SDA_DDR,SDA ;release SDA (from previous ACK)
  302.     rcall   i2c_delay_T2    ;delay T/2
  303.    
  304.     cbi SCL_DDR,SCL ;release SCL
  305.     rcall   i2c_delay_T2    ;delay T/2
  306.    
  307. i2c_read_stretch:
  308.     sbis SCL_IN, SCL        ;loop until SCL is high (allow slave to stretch SCL)
  309.     rjmp    i2c_read_stretch
  310.        
  311.     clc         ;clear carry flag
  312.     sbic    SDA_IN,SDA  ;if SDA is high
  313.     sec         ;  set carry flag
  314.    
  315.     rol r23     ;store bit
  316.     brcc    i2c_read_bit    ;while receive register not full
  317.    
  318. i2c_put_ack:
  319.     sbi SCL_DDR,SCL ;force SCL low 
  320.     cpi r24,1
  321.     breq    i2c_put_ack_low ;if (ack=0)
  322.     cbi SDA_DDR,SDA ;      release SDA
  323.     rjmp    i2c_put_ack_high
  324. i2c_put_ack_low:                ;else
  325.     sbi SDA_DDR,SDA ;      force SDA low
  326. i2c_put_ack_high:
  327.     rcall   i2c_delay_T2    ;delay T/2
  328.     cbi SCL_DDR,SCL ;release SCL
  329. i2c_put_ack_wait:
  330.     sbis    SCL_IN,SCL  ;wait SCL high
  331.     rjmp    i2c_put_ack_wait
  332.     rcall   i2c_delay_T2    ;delay T/2
  333.     mov r24,r23
  334.     clr r25
  335.     ret
  336.     .endfunc
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top