1 \ name : msp430FR5xxx_I2C_Soft_MultiMaster.f
3 \ I2C MASTER Standard Mode software driver without interrupt, with detection collision
4 \ Target: MSP430FR5xxx, tested @ 8,16,24 MHz and adjusted @ 16,24 MHz
5 \ SDA = P1.2, SCL = P1.3, with 3k3 pullup resistors
7 \ version 1.0 2016-04-10
10 \ ========================================================================================================
11 \ ========================================================================================================
13 \ ### ##### ##### ##### # # # #
14 \ # # # # # # # #### ###### ##### ## ## ## ## ## #### ##### ###### #####
15 \ # # # # # # # # # # # # # # # # # # # # # # #
16 \ # ##### # ##### # # ##### # # # # # # # # # #### # ##### # #
17 \ # # # # # # # # # # # # ###### # # # #####
18 \ # # # # # # # # # # # # # # # # # # # # # #
19 \ ### ####### ##### ##### #### # # # # # # # # #### # ###### # #
21 \ ========================================================================================================
22 \ ========================================================================================================
24 \ P1.2 = SDA, P1.3 = SCL
25 \ use Px.0 to Px.3 for good timing at 8 MHz (immediate addressing is less of one cycle)
27 \ tested with P1.6 SDA, P1.7 SCL @ 8MHz :
28 \ Start + Adr + Write 3 bytes + Stop + Start + adr + read 2 bytes + stop = 628us ==> 100 kHz
29 \ See MSP430FR5xxx_I2C_Soft_MultiMaster.png
31 VARIABLE I2CS_ADR \ low(I2CS_ADR) = slave I2C address with RW flag, high(I2CS_ADR) = RX buffer,data0
33 VARIABLE I2CM_BUF \ low(I2CM_BUF) = RX or TX lentgh, high(I2CM_BUF) = TX buffer,data0
37 \ ------------------------------\
38 ASM T_I2C \ 4 init first once !!!
39 \ ------------------------------\
43 MOV #1,Y \ 2 set I2C tHIGH time @ 8MHz
44 \ MOV #9,Y \ 2 set I2C tHIGH time @ 16MHz
45 \ MOV #20,Y \ 2 set I2C tHIGH time @ 24MHz
51 \ ------------------------------\
52 ASM I2C_PLS \ SCL Pulse
53 \ ------------------------------\
54 CALL #R11_I2C \ _ wait tLOW
55 BIC.B #SMMSCL,&I2CSMM_DIR \ _^ release SCL (high)
57 BIT.B #SMMSCL,&I2CSMM_IN \ test if SCL is released
59 CALL #R11_I2C \ wait tHIGH
60 BIT.B #SMMSDA,&I2CSMM_IN \ _ get SDA
61 BIS.B #SMMSCL,&I2CSMM_DIR \ v_ force SCL low
66 \ ------------------------------\
67 ASM I2C_BTX \ MASTER TX \ one bit shared code for address and TX data
68 \ ------------------------------\
69 ADD.B X,X \ 1 l shift one left
70 U>= IF \ 2 l carry set ?
71 BIC.B #SMMSDA,&I2CSMM_DIR \ 4 l yes : SDA as input ==> SDA high because pull up resistor
73 BIS.B #SMMSDA,&I2CSMM_DIR \ 4 l no : SDA as output ==> SDA low
75 JMP I2C_PLS \ SCL _| |_ pulse
79 \ ==================================\
80 ASM I2C_MM \ soft I2C_MultiMaster driver
81 \ ==================================\
82 \ \ in : I2CS_ADR pointer
83 \ \ : I2CM_BUF pointer
84 \ \ used: S datas pointer
85 \ \ T count of I2C datas exchanged
89 \ \ SR(10) collision flag
90 \ \ out : I2CS_ADR(0) unchanged
91 \ \ I2CM_BUF(0) = count of data not exchanged (normally = 0)
92 \ \ I2CM_BUF(0) = -1 <==> Nack on address
93 \ ----------------------------------\
94 \ I2CMM_Stop_UCBxI2CSlave \ if SDA SCL of I2C_MultiMaster are hard wired onto SDA SCL of I2C_Slave under interrupt...
95 \ ----------------------------------\
96 \ BIS #1,&UCB0CTLW0 \ set eUSCI_B0 in reset state, reset StartCond int in UCB0IFG
97 \ BIC.B #I2CM_BUS,&I2CSMM_SEL1 \ disable I2C I/O
98 \ ----------------------------------\
99 \ I2C_MR_DC_ListenBeforeStart: \ test if SCL & SDA lines are idle (high)
100 \ ----------------------------------\
102 BIC.B #SMM_BUS,&I2CSMM_DIR \ SDA & SCL pins as input
103 BIC.B #SMM_BUS,&I2CSMM_OUT \ preset output LOW for SDA & SCL pins
106 MOV #2,T \ I2C_MR_DC_Wait_Start_Loop = 8 µs @ 8 MHz
107 \ MOV #4,T \ I2C_MR_DC_Wait_Start_Loop = 8 µs @ 16 MHz
108 \ MOV #6,T \ I2C_MR_DC_Wait_Start_Loop = 8 µs @ 24 MHz
110 BIT.B #SMMSCL,&I2CSMM_IN \ 3 P1DIR.3 SCL high ?
112 BIT.B #SMMSDA,&I2CSMM_IN \ 3 P1IN.2 SDA high ?
115 0= UNTIL \ 2 here the I2C bus is idle
116 \ --------------------------------\
117 \ I2CMR_DC_Shutdown_Slave_Int \ if SDA SCL of I2C_MultiMaster are hard wired onto SDA SCL of I2C_Slave under interrupt...
118 \ --------------------------------\
119 \ BIS #1,&$640 \ ...set eUSCI_B0 in reset state, that allows I/O use for SDA & SCL...
120 \ BIC.B #SMM_BUS,&PI2CSSEL1 \ disable I2C I/O
121 \ --------------------------------\
122 \ I2C_Master_Start_Cond: \ here, SDA and SCL are in idle state
123 \ --------------------------------\
124 BIS.B #SMMSDA,&I2CSMM_DIR \ 4- force SDA output (low)
125 MOV #I2CS_ADR,S \ 2 l
126 MOV.B @S+,X \ 3 l X = slave address, S = RX buffer
127 MOV #I2CM_BUF,W \ 2 l
128 MOV.B @W+,T \ 2 l T = count of datas, W = TX buffer
129 ADD.B #1,T \ to include address in count
130 BIT.B #1,X \ 1 l test I2C R/w flag
131 0= IF \ 2 l write flag
132 MOV W,S \ 3 l TX buffer
134 MOV #5,Y \ 2 tHD\STA time 8 MHz complement
135 \ MOV #14,Y \ 2 tHD\STA time 16MHz complement
136 \ MOV #25,Y \ 2 tHD\STA time 24MHz complement
137 CALL #R11_I2C \ wait 4 us
138 BIS.B #SMMSCL,&I2CSMM_DIR \ 4- force SCL output (low)
139 \ --------------------------------\
140 \ I2C_Master_Start_EndOf: \
141 \ --------------------------------\
142 \ I2C_Master_Send_address \
143 \ --------------------------------\
144 MOV.B #8,W \ 1 l prepare 8 bit Master writing
146 MOV #1,Y \ 2 tHD\STA time =8MHz complement
147 \ MOV #2,Y \ 2 tHD\STA time =16MHz complement
148 \ MOV #13,Y \ 2 tHD\STA time =24MHz complement
149 CALL #I2C_BTX \ l send one bit
150 \ ----------------------------\
151 \ collision detection \
152 \ ----------------------------\
154 BIT.B #SMMSDA,&I2CSMM_DIR \ 3
155 0= ?GOTO BW1 \ 2 collision : IN(MMSDA=0) XOR DIR(MMSDA=0) = 0
157 SUB #1,W \ 3 dec count of bits
159 BIC.B #SMMSDA,&I2CSMM_DIR \ 5 release SDA high before 9th bit
160 \ ----------------------------------\
162 \ ----------------------------------\
164 \ --------------------------------\
165 \ Master TX/RX ACK/NACK \
166 \ --------------------------------\
167 MOV #1,Y \ 2 tLOW time complement @ 8MHz
168 \ MOV #7,Y \ 2 tLOW time complement @ 16MHz
169 \ MOV #18,Y \ 2 tLOW time complement @ 24MHz
170 CALL #I2C_PLS \ _| |_ SCL pulse with SDA bit test
171 0<> IF BIS #2,SR \ l if Nack, force Z=1 ==> StopCond
172 ELSE SUB.B #1,T \ else dec count
174 \ --------------------------------\
175 \ I2C_Master_CheckCountDown \ count=0 or Nack received
176 \ --------------------------------\
177 0= IF \ count reached or Nack
178 \ --------------------------------\
179 \ I2C_Master_StopCond \
180 \ --------------------------------\ before releasing SCL
181 BIS.B #SMMSDA,&I2CSMM_DIR \ l force SDA low
182 MOV #1,Y \ 2 l tLOW time complement @ 8MHz
183 \ MOV #7,Y \ 2 tLOW time complement @ 16MHz
184 \ MOV #18,Y \ 2 tLOW time complement @ 24MHz
185 CALL #R11_I2C \ _ wait 4 us
186 BIC.B #SMMSCL,&I2CSMM_DIR \ _| release SCL (high with pull up resistor)
187 SUB.B T,&I2CM_BUF \ 4 refresh buffer length
188 MOV #5,Y \ 2 tSU:STO time 8 MHz complement
189 \ MOV #15,Y \ 2 tSU:STO time 16MHz complement
190 \ MOV #25,Y \ 2 tSU:STO time 24MHz complement
191 CALL #R11_I2C \ _ wait tSU:STO
192 BIC.B #SMMSDA,&I2CSMM_DIR \ _| release SDA (high with pull up resistor)
193 \ ----------------------------\
195 \ ----------------------------\
196 \ Restart I2C_Slave_Int \ if any
197 \ ----------------------------\
198 \ BIC #1,&UCB0CTLW0 \ restart eUSCI_B
199 \ BIS.B #SMM_BUS,&I2CSMM_SEL1 \ reenable I2C I/O
200 \ ----------------------------\
202 \ --------------------------------\
204 \ --------------------------------\
205 MOV.B #8,W \ 1 l prepare 8 bits transaction
206 BIT.B #1,&I2CS_ADR \ 3 l I2C_Master Read/write bit test
207 0= IF \ 2 l write flag test
208 \ ============================\
210 \ ============================\
211 MOV.B @S+,X \ 2 l next byte to TX
213 MOV #1,Y \ 2 tHD\STA time =8MHz complement
214 \ MOV #2,Y \ 2 tHD\STA time =16MHz complement
215 \ MOV #13,Y \ 2 tHD\STA time =24MHz complement
216 CALL #I2C_BTX \ l send one bit
217 SUB.B #1,W \ l count of bits
219 BIC.B #SMMSDA,&I2CSMM_DIR \ 5 l release SDA high before 9th bit
221 \ ============================\
222 \ I2C_Master_RX: \ here, SDA is indetermined, SCL is strech low by master
223 \ ============================\
224 BIC.B #SMMSDA,&I2CSMM_DIR \ 5 l _ After ACK we must release SDA
226 MOV #3,Y \ 2 tLOW time complement @ 8 MHz
227 \ MOV #15,Y \ 2 tLOW time complement @ 16MHz
228 \ MOV #24,Y \ 2 tLOW time complement @ 24MHz
229 CALL #I2C_PLS \ _| |_ SCL pulse with SDA bit test
230 ADDC.B X,X \ 1 l C <-- X <--- C ; C flag = SDA
231 SUB #1,W \ 1 l count of bits
233 MOV.B X, 0(S) \ 3 l store RX byte in buffer
235 \ ----------------------------\
236 \ Compute RX Ack/Nack \
237 \ ----------------------------\
238 CMP #1,T \ 1 l here, SDA is released by slave = Nack
240 BIS.B #SMMSDA,&I2CSMM_DIR \ 4 l send Ack if byte count <> 1
247 \ ------------------------------\
249 \ ------------------------------\
250 \ init PORTA (P2:P1) (complement) when reset occurs all I/O are set in input with resistors pullup
251 BIC.B #SMM_BUS,&I2CSMM_OUT \ preset SDA + SCL output low
252 BIC.B #SMM_BUS,&I2CSMM_REN \ SDA + SCL pullup/down disable
253 \ ------------------------------\
255 ." Type STOP to stop :-)"
256 LIT RECURSE IS WARM \ insert this starting routine between COLD and WARM...
257 ['] WARM >BODY EXECUTE \ ...and continue with WARM (very, very usefull after COLD or RESET !:-)
260 : STOP \ stops multitasking, must to be used before downloading app
261 ['] WARM >BODY IS WARM \ remove START app from FORTH init process
262 ECHO COLD \ reset CPU, interrupt vectors, and start FORTH
267 \ ---------------------------------------------------------------------------------------------------------------------\
268 \ SCL clock generation, timing, and test of data(s) number are made by I2C_Master.
269 \ slave can strech SCL low after Start Condition and after any bit.
271 \ address Ack/Nack is generated by the slave on SDA line (released by the master)
272 \ Two groups of eight addresses (000xxxy and 1111xxxy) are not allowed (reserved)
273 \ after address or data is sent, the transmitter (Master or Slave) must release SDA line to allow (N)Ack by the receiver
274 \ data Ack/Nack are generated by the receiver (master or slave) on SDA line
275 \ a master receiver must signal the end of data to the slave transmitter by sending a Nack bit
276 \ Stop or restart conditions must be generated by master after a Nack bit.
277 \ after Ack bit is sent, Slave must release SDA line to allow master to do stop or restart conditions
279 \ __ _____ _____ _..._ _____ _____ _NACK _____ _____ _..._ _____ _____ _NACK _
280 \ SDA \____/_MSB_X_____X_..._X_LSB_X_R/Wx_ACK_x_MSB_X_____X_..._X_____X_LSB_X_ACK_X___/
281 \ _____ _ _ _ _ _ _ _ _ _ _ ___
282 \ SCL \___/1\___/2\___...___/7\___/8\___/9\___/1\___/2\___...___/7\___/8\___/9\___/
284 \ | |Slave Stretch Low |SSL |SSL |SSL |SSL |
286 \ |Start Condition |stoP Condition
288 \ __ _____ _____ _..._ _____ _____ _NACK _____ _____ _..._ _____ _____ _NACK ___
289 \ SDA \____/_MSB_X_____X_..._X_LSB_X_R/W_x_ACK_x_MSB_X_____X_..._X_____X_LSB_X_ACK_X \____...
290 \ _____ _ _ _ _ _ _ _ _ _ _ ____
291 \ SCL \___/1\___/2\___...___/7\___/8\___/9\___/1\___/2\___...___/7\___/8\___/9\___/ \_...
293 \ | |Slave Stretch Low |SSL |SSL |SSL |SSL |
295 \ |Start Condition |reStart Condition
297 \ tHIGH : SCL high time
298 \ tLOW : SCL low time
299 \ tBUF : SDA high time between Stop and Start conditions
300 \ tHD:STA : Start_Condition SCL high time after SDA is low
301 \ tSU:STO : Stop_Condition SCL high time before SDA rise
302 \ tSU:STA : Start_Condition SCL high time before SDA fall
303 \ tHD:DAT : SDA data change time after SCL is low
304 \ the SDA line must be strobe just after SCL is high
305 \ the SDA data must be change just after SCL is low
306 \ standard mode (up to 100 kHz) : tHIGH = tHD:STA = tSU:STO = 4µs
307 \ tLOW = tSU:STA = tBUF = 4,7µs
309 \ -------------------------------------------------------------------------------------------------------------------\