Advertisement
Guest User

Untitled

a guest
Apr 5th, 2017
72
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.81 KB | None | 0 0
  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
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement