Advertisement
Guest User

Untitled

a guest
Feb 19th, 2018
96
0
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             1           // SDA Port D, Pin 4  
  42. #define SCL             0           // SCL Port D, Pin 5
  43. #define SDA_PORT        PORTB       // SDA Port D
  44. #define SCL_PORT        PORTB       // SCL Port D        
  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.  
  58. #ifndef __tmp_reg__
  59. #define __tmp_reg__ 0
  60. #endif
  61.  
  62.  
  63.     .section .text
  64.  
  65. ;*************************************************************************
  66. ; delay half period
  67. ; For I2C in normal mode (100kHz), use T/2 > 5us
  68. ; For I2C in fast mode (400kHz),   use T/2 > 1.25us
  69. ;*************************************************************************
  70.     .stabs  "",100,0,0,i2c_delay_T2
  71.     .stabs  "i2cmaster.S",100,0,0,i2c_delay_T2
  72.     .func i2c_delay_T2  ; delay 5.0 microsec with 4 Mhz crystal
  73. i2c_delay_T2:        ; 3 cycles
  74. #if F_CPU <= 4000000UL
  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          ; 4   "  total 20 cyles = 5.0 microsec with 4 Mhz crystal
  83. #elif F_CPU <= 8000000UL
  84.     push r24     ; 2 cycle
  85.     ldi  r24, 7  ; 1 cycle
  86.     nop          ; 1 cycle
  87. 1:  sbiw r24, 1  ; 2 cycle
  88.     brne 1b      ; 2 or 1 cycle, 4 cycles per loop
  89.     pop  r24     ; 2 ycle
  90.     ret          ; 4 cycle = total 60 cycles = 5.0 microsec with 12 Mhz crystal
  91. #elif F_CPU <= 12000000UL
  92.     push r24     ; 2 cycle
  93.     ldi  r24, 12 ; 1 cycle
  94.     nop          ; 1 cycle
  95. 1:  sbiw r24, 1  ; 2 cycle
  96.     brne 1b      ; 2 or 1 cycle, 4 cycles per loop
  97.     pop  r24     ; 2 ycle
  98.     ret          ; 4 cycle = total 60 cycles = 5.0 microsec with 12 Mhz crystal
  99. #elif F_CPU <= 16000000UL
  100.     push r24     ; 2 cycle
  101.     ldi  r24, 17 ; 1 cycle
  102.     nop          ; 1 cycle
  103. 1:  sbiw r24, 1  ; 2 cycle
  104.     brne 1b      ; 2 or 1 cycle, 4 cycles per loop
  105.     pop  r24     ; 2 ycle
  106.     ret          ; 4 cycle = total 80 cycles = 5.0 microsec with 16 Mhz crystal
  107. #else
  108.     push r24     ; 2 cycle
  109.     ldi  r24, 22 ; 1 cycle
  110.     nop          ; 1 cycle
  111. 1:  sbiw r24, 1  ; 2 cycle
  112.     brne 1b      ; 2 or 1 cycle, 4 cycles per loop
  113.     pop  r24     ; 2 ycle
  114.     ret          ; 4 cycle = total 100 cycles = 5.0 microsec with 20 Mhz crystal
  115. #endif 
  116.     .endfunc     ;
  117.  
  118.  
  119. ;*************************************************************************
  120. ; Initialization of the I2C bus interface. Need to be called only once
  121. ;
  122. ; extern void i2c_init(void)
  123. ;*************************************************************************
  124.     .global i2c_init
  125.     .func i2c_init
  126. i2c_init:
  127.     cbi SDA_DDR,SDA     ;release SDA
  128.     cbi SCL_DDR,SCL     ;release SCL
  129.     cbi SDA_OUT,SDA
  130.     cbi SCL_OUT,SCL
  131.     ret
  132.     .endfunc
  133.  
  134.  
  135. ;************************************************************************* 
  136. ; Issues a start condition and sends address and transfer direction.
  137. ; return 0 = device accessible, 1= failed to access device
  138. ;
  139. ; extern unsigned char i2c_start(unsigned char addr);
  140. ;   addr = r24, return = r25(=0):r24
  141. ;*************************************************************************
  142.  
  143.     .global i2c_start
  144.     .func   i2c_start
  145. i2c_start:
  146.     sbi     SDA_DDR,SDA ;force SDA low
  147.     rcall   i2c_delay_T2    ;delay T/2
  148.    
  149.     rcall   i2c_write   ;write address
  150.     ret
  151.     .endfunc       
  152.  
  153.  
  154. ;*************************************************************************
  155. ; Issues a repeated start condition and sends address and transfer direction.
  156. ; return 0 = device accessible, 1= failed to access device
  157. ;
  158. ; extern unsigned char i2c_rep_start(unsigned char addr);
  159. ;   addr = r24,  return = r25(=0):r24
  160. ;*************************************************************************
  161.  
  162.     .global i2c_rep_start
  163.     .func   i2c_rep_start
  164. i2c_rep_start:
  165.     sbi SCL_DDR,SCL ;force SCL low
  166.     rcall   i2c_delay_T2    ;delay  T/2
  167.     cbi SDA_DDR,SDA ;release SDA
  168.     rcall   i2c_delay_T2    ;delay T/2
  169.     cbi SCL_DDR,SCL ;release SCL
  170.     rcall   i2c_delay_T2    ;delay  T/2
  171.     sbi     SDA_DDR,SDA ;force SDA low
  172.     rcall   i2c_delay_T2    ;delay  T/2
  173.    
  174.     rcall   i2c_write   ;write address
  175.     ret
  176.     .endfunc
  177.  
  178.  
  179. ;************************************************************************* 
  180. ; Issues a start condition and sends address and transfer direction.
  181. ; If device is busy, use ack polling to wait until device is ready
  182. ;
  183. ; extern void i2c_start_wait(unsigned char addr);
  184. ;   addr = r24
  185. ;*************************************************************************
  186.  
  187.     .global i2c_start_wait
  188.     .func   i2c_start_wait
  189. i2c_start_wait:
  190.     mov __tmp_reg__,r24
  191. i2c_start_wait1:
  192.     sbi     SDA_DDR,SDA ;force SDA low
  193.     rcall   i2c_delay_T2    ;delay T/2
  194.     mov r24,__tmp_reg__
  195.     rcall   i2c_write   ;write address
  196.     tst r24     ;if device not busy -> done
  197.     breq    i2c_start_wait_done
  198.     rcall   i2c_stop    ;terminate write operation
  199.     rjmp    i2c_start_wait1 ;device busy, poll ack again
  200. i2c_start_wait_done:
  201.     ret
  202.     .endfunc   
  203.  
  204.  
  205. ;*************************************************************************
  206. ; Terminates the data transfer and releases the I2C bus
  207. ;
  208. ; extern void i2c_stop(void)
  209. ;*************************************************************************
  210.  
  211.     .global i2c_stop
  212.     .func   i2c_stop
  213. i2c_stop:
  214.     sbi SCL_DDR,SCL ;force SCL low
  215.     sbi SDA_DDR,SDA ;force SDA low
  216.     rcall   i2c_delay_T2    ;delay T/2
  217.     cbi SCL_DDR,SCL ;release SCL
  218.     rcall   i2c_delay_T2    ;delay T/2
  219.     cbi SDA_DDR,SDA ;release SDA
  220.     rcall   i2c_delay_T2    ;delay T/2
  221.     ret
  222.     .endfunc
  223.  
  224.  
  225. ;*************************************************************************
  226. ; Send one byte to I2C device
  227. ; return 0 = write successful, 1 = write failed
  228. ;
  229. ; extern unsigned char i2c_write( unsigned char data );
  230. ;   data = r24,  return = r25(=0):r24
  231. ;*************************************************************************
  232.     .global i2c_write
  233.     .func   i2c_write
  234. i2c_write:
  235.     sec         ;set carry flag
  236.     rol     r24     ;shift in carry and out bit one
  237.     rjmp    i2c_write_first
  238. i2c_write_bit:
  239.     lsl r24     ;if transmit register empty
  240. i2c_write_first:
  241.     breq    i2c_get_ack
  242.     sbi SCL_DDR,SCL ;force SCL low
  243.     brcc    i2c_write_low
  244.     nop
  245.     cbi SDA_DDR,SDA ;release SDA
  246.     rjmp    i2c_write_high
  247. i2c_write_low:
  248.     sbi SDA_DDR,SDA ;force SDA low
  249.     rjmp    i2c_write_high
  250. i2c_write_high:
  251.     rcall   i2c_delay_T2    ;delay T/2
  252.     cbi SCL_DDR,SCL ;release SCL
  253.     rcall   i2c_delay_T2    ;delay T/2
  254.     rjmp    i2c_write_bit
  255.    
  256. i2c_get_ack:
  257.     sbi SCL_DDR,SCL ;force SCL low
  258.     cbi SDA_DDR,SDA ;release SDA
  259.     rcall   i2c_delay_T2    ;delay T/2
  260.     cbi SCL_DDR,SCL ;release SCL
  261. i2c_ack_wait:
  262.     sbis    SCL_IN,SCL  ;wait SCL high (in case wait states are inserted)
  263.     rjmp    i2c_ack_wait
  264.    
  265.     clr r24     ;return 0
  266.     sbic    SDA_IN,SDA  ;if SDA high -> return 1
  267.     ldi r24,1
  268.     rcall   i2c_delay_T2    ;delay T/2
  269.     clr r25
  270.     ret
  271.     .endfunc
  272.  
  273.  
  274.  
  275. ;*************************************************************************
  276. ; read one byte from the I2C device, send ack or nak to device
  277. ; (ack=1, send ack, request more data from device
  278. ;  ack=0, send nak, read is followed by a stop condition)
  279. ;
  280. ; extern unsigned char i2c_read(unsigned char ack);
  281. ;   ack = r24, return = r25(=0):r24
  282. ; extern unsigned char i2c_readAck(void);
  283. ; extern unsigned char i2c_readNak(void);
  284. ;   return = r25(=0):r24
  285. ;*************************************************************************
  286.     .global i2c_readAck
  287.     .global i2c_readNak
  288.     .global i2c_read       
  289.     .func   i2c_read
  290. i2c_readNak:
  291.     clr r24
  292.     rjmp    i2c_read
  293. i2c_readAck:
  294.     ldi r24,0x01
  295. i2c_read:
  296.     ldi r23,0x01    ;data = 0x01
  297. i2c_read_bit:
  298.     sbi SCL_DDR,SCL ;force SCL low
  299.     cbi SDA_DDR,SDA ;release SDA (from previous ACK)
  300.     rcall   i2c_delay_T2    ;delay T/2
  301.    
  302.     cbi SCL_DDR,SCL ;release SCL
  303.     rcall   i2c_delay_T2    ;delay T/2
  304.    
  305. i2c_read_stretch:
  306.     sbis SCL_IN, SCL        ;loop until SCL is high (allow slave to stretch SCL)
  307.     rjmp    i2c_read_stretch
  308.        
  309.     clc         ;clear carry flag
  310.     sbic    SDA_IN,SDA  ;if SDA is high
  311.     sec         ;  set carry flag
  312.    
  313.     rol r23     ;store bit
  314.     brcc    i2c_read_bit    ;while receive register not full
  315.    
  316. i2c_put_ack:
  317.     sbi SCL_DDR,SCL ;force SCL low 
  318.     cpi r24,1
  319.     breq    i2c_put_ack_low ;if (ack=0)
  320.     cbi SDA_DDR,SDA ;      release SDA
  321.     rjmp    i2c_put_ack_high
  322. i2c_put_ack_low:                ;else
  323.     sbi SDA_DDR,SDA ;      force SDA low
  324. i2c_put_ack_high:
  325.     rcall   i2c_delay_T2    ;delay T/2
  326.     cbi SCL_DDR,SCL ;release SCL
  327. i2c_put_ack_wait:
  328.     sbis    SCL_IN,SCL  ;wait SCL high
  329.     rjmp    i2c_put_ack_wait
  330.     rcall   i2c_delay_T2    ;delay T/2
  331.     mov r24,r23
  332.     clr r25
  333.     ret
  334.     .endfunc
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement