i2c.asm

来自「DSP中用MCBSP模拟I2C接口的程序.其中DSP的型号是C5416」· 汇编 代码 · 共 679 行 · 第 1/2 页

ASM
679
字号
		.mmregs          	   
      	.include "time.inc"
      	.include "i2c.inc"
  		.include "bsp.inc"  
  		.include "i2creg.inc"      
  		
  		.def TIMER_INT
  		.def _I2CSTATUS,_ODBYTECTR,_IDBYTECTR,_ODPTR,_SLAVE_ADDR            
      	.def _init_gpio,_init_i2c,_write_i2c,_read_i2c
      	.ref _USER_FUNCTION
      	 
      	 ;***字节位屏蔽
		.sect "constant"
MASK    .int 01h			;Bit 0 
        .int 02h            ;Bit 1
        .int 04h            ;Bit 2
        .int 08h            ;Bit 3
        .int 10h            ;Bit 4
        .int 20h            ;Bit 5
        .int 40h            ;Bit 6 
        .int 80h            ;Bit 7 (MSB)
		
		.sect "program"				
;***************************************************************************
; 定时中断服务函数
;***************************************************************************
TIMER_INT:								

;***寄存器压栈***
	  NOP
	  NOP
	  PSHM	ST0
	  PSHM	ST1
	  PSHM	AR1
	  PSHM	AR2
	  PSHM	AR3
	  PSHM  AR4
	  PSHM  AR5
	  PSHM	AR6
	  NOP
	  NOP                  
	  RSBX	SXM                 		
	  RSBX	CPL                         
	  RSBX	HM                          
      LD	#_I2C_DP,DP      			 
      NOP
      NOP
      LD	_I2CSTATUS,A	    		;加载I2C状态
      LD	A,B							;乘2
  	  AND   #K_DISABLE_I2C,B            ;检测I2C是否使能
      BC    tint_disable_tint,BNEQ		;如果 =1, 结束
;***更新 前位SDA和SCL***      
      AND   #3H,A	 					
      LD    A,2,B 						
      ANDM  #0FFF0H,_I2CSTATUS       	
      LD	_I2CSTATUS,A	    		
      ADD	B,A								
      STL   A,_I2CSTATUS				
;***更新当前 SDA 和 SCL***
	  STM   #SPSA,AR2                	
	  ST	#PCR_SUB,*AR2+          	
  	  LD	#(K_DR_STAT_1|K_FSXP_1),B 	
  	  AND   #0FFFFH,A                 	
   	  AND	*AR2-,B					
  	  OR    B,-3,A						
  	  STL   A,_I2CSTATUS             
;***检测开始/结束条件或操作模式 ***
  	  LD	A,B							
  	  AND   #K_CLKH_1,B					
  	  BC    tint_clk_go_high,BNEQ		
  	  LD	A,B							
  	  AND   #K_CLKL_1,B					
  	  BC    tint_clk_go_low,BNEQ		      
  	  LD	A,B							;乘2左移
  	  AND   #K_ACK_1,B 		   			
  	  BC	tint_ack,BNEQ				;应答?
  	  LD	A,B							;左移
  	  AND   #K_START_1,B    			;起始状态?
  	  BC	tint_start,BNEQ				
  	  AND   #K_STOP_1,A   	 			;结束?
  	  BC	tint_stop,ANEQ				
  	  MVDK	_I2CSTATUS,TEMP_REG		
	  ANDM	#01100000B, TEMP_REG	 	
	  CMPM	TEMP_REG,#K_READ_FROM_SLAVE	
	  BC	tint_read_slave, TC         
	  									      
  	  CMPM  TEMP_REG,#K_WRITE_TO_SLAVE      
  	  BC	tint_write_slave, TC        
  	  									      
  	  B		tint_busy					


;**************************************************************************
;**************************************************************************    

;*****起始条件预处理*****
tint_start:  	                                                   
	  ;***读当前或前一 SDA/SCL 幅值***
	  MVDK	_I2CSTATUS,TEMP_REG			
	  ANDM	#0FH, TEMP_REG	 			
	  CMPM	TEMP_REG,#1111B			    
	  BC	tint_start_start,TC         
	  CMPM	TEMP_REG,#1110B				
	                 ;1~~~              
	                 ;~1~~              
	                 ;~~1~              
	                 ;~~~0              
	  BC	tint_start_finish,TC        
	  B	    tint_start_invalid  		
;***开始起始条件***      
tint_start_start:
      CALL  pullSDA						;SDA->0 当 SCL=1
      ;***计时5us
      STM	#STOP_TIMER,TCR     		
      STM	#K_START_HOLD_TIME,PRD    	
      STM	#START_TIMER,TCR    		;开始计时
      B		tint_end_isr
;***结束起始条件***
tint_start_finish: 
	  CALL	pullSCL						
	  ANDM	#K_START_0,_I2CSTATUS		
	  ST	#1,TEMP_REG					   
      B		tint_end_isr				
;***状态未知***
tint_start_invalid:
      CALL	releaseSDA					;释放数据时钟线,重新开始
      CALL	releaseSCL                                                
      B		tint_end_isr			    


;**************************************************************************
;**************************************************************************    


;******开始应答位部分*****      
tint_ack:
      ;***是否主接收模式?(read slave)
	  MVDK	_I2CSTATUS,TEMP_REG			
	  ANDM	#01100000B, TEMP_REG	 	
	  CMPM	TEMP_REG,#K_READ_FROM_SLAVE	
	  BC	tint_ack_not_rs, NTC       

      LD    _I2CSTATUS,A                
      AND	#K_ADDR_1,A                 
      BC	tint_ack_end_slave_addr,ANEQ

	  LD	POINTER,B					
	  BC	tint_ack_rs_first,BEQ				
	  CALL	releaseSDA
	  ANDM	#K_ACK_0,_I2CSTATUS		   
	  B		tint_end_isr	
tint_ack_rs_first:	  	  
	  ST	#1,POINTER      			  
	  LD	_I2CSTATUS,A				
	  AND   #K_STOP_1,A   	 			
  	  BC	tint_ack_stop,ANEQ			
  	  CALL	pullSDA					
  	  B		tint_ack_end                
tint_ack_stop:
	  CALL	releaseSDA					
	  B		tint_ack_end                
  	  
tint_ack_end_slave_addr:
      ANDM	#K_ADDR_0,_I2CSTATUS			 
                                        
  	  ;***主机发送模式 (write slave)***									
tint_ack_not_rs:	  
	  CALL	releaseSDA				                                               
      ST	#0,TEMP_REG						  
tint_ack_end:
      ORM	#K_CLKH_1,_I2CSTATUS	                                                                      	  
      B		tint_end_isr	
;***是否从给主应答***
tint_ack_test:                                   
      
	  ;ST    SPSA,AR2                	
	  ST	#PCR_SUB,*AR2+              
  	  LD	#K_FSXP_1,A   	            
      AND	*AR2-,A    
      BC	tint_ack_sda_low,AEQ        
      ;***从机没应答***      
      ORM	#K_ERR_1,_I2CSTATUS			
      ST	#K_ERR_NOACK,ERRORCODE	
tint_ack_sda_low:      
      ;***从机应答***        
      ORM	#K_CLKL_1,_I2CSTATUS		
      ANDM	#(K_ACK_0&K_ADDR_0),_I2CSTATUS   
      STM	#STOP_TIMER,TCR     	
      STM	#K_SCL_HIGH,PRD    			
      STM	#START_TIMER,TCR    		
	  B		tint_end_isr    	       
	  

;**************************************************************************
;**************************************************************************    

      
;*****停止条件部分*****      
tint_stop:                              
	 
	  LD	TEMP1_REG,A					 
	  BC	tint_stop_continue,ANEQ	
	  CALL  pullSDA	                    
	  ST	#1,TEMP1_REG			     
      STM	#STOP_TIMER,TCR     		
      STM	#K_STOP_SETUP_TIME,PRD    
      STM	#START_TIMER,TCR    	
	  B		tint_end_isr	            
tint_stop_continue:	
	  MVDK	_I2CSTATUS,TEMP_REG		
	  ANDM	#03H,TEMP_REG	 			
	  ;***SCL=1 , SDA=0***  
	  CMPM	TEMP_REG,#10B				
	                 ;1~    	        
	                 ;~0        	              
	  BC	tint_stop_finish,TC        
	  ;*** SCL/SDA=0/0***
	  CMPM	TEMP_REG,#00B			
	                 ;0~    	       
	                 ;~0				
	  BC	tint_stop_invalid,NTC		
	 
      CALL  releaseSCL				
      NOP                 				
	  NOP                               
	  NOP                               
      ;***同步***
	  ;ST    SPSA,AR2                	
	  ST	#PCR_SUB,*AR2+              
  	  LD	#K_DR_STAT_1,A            
      AND	*AR2-,A    
      BC	tint_stop_scl_go_high_yes,ANEQ	

	  ;***定时 1us***
      B		tint_stop_invalid		
      
tint_stop_scl_go_high_yes:      
      ;***定时5us保持时间***
      STM	#STOP_TIMER,TCR     	
      STM	#K_STOP_SETUP_TIME,PRD    
      STM	#START_TIMER,TCR    		
      B		tint_end_isr
	  ;***SDA=0 ***
tint_stop_finish: 
	  CALL	releaseSDA				
	  ANDM	#K_STOP_0,_I2CSTATUS	
      ORM	#K_SUCC_1,_I2CSTATUS        
      NOP
      CALL  _USER_FUNCTION				
      NOP 
      B		tint_end_isr			
tint_stop_invalid:
      CALL	pullSDA   					
      CALL  releaseSCL                                              
	  STM	#STOP_TIMER,TCR     		
      STM	#K_PRD_VAL,PRD    			
      STM	#START_TIMER,TCR    		
      B		tint_end_isr	                
      
      
;**************************************************************************
;**************************************************************************      
      

;*****读从机*****      
tint_read_slave:                                             
	  LD	_I2CSTATUS,A	    		
  	  AND   #K_ADDR_1,A					
      BC    tint_clk_go_high,AEQ		
      B		tint_write_slave			
;***当 SCL=1读数据***      
tint_rs_mode:                                                      
	  ;***SETUP POINTERS TO CORRECT LOCATION***
	  LD    #IDPTR,B					;Load addr of out-data to B
      LD    _IDBYTECTR, -8,A			;Move current byte pointer
      STL	A,POINTER					;Store it to POINTER (1ST= BYTE 0)
      ADD   A,B							;Update current btye pointer
      STLM  B,AR4						;AR4 points to current byte
      
      CMPM	IDBITCTR,#7                 ;If IDBITCTR == 7, then it is new byte
      BC	tint_rs_not_new_byte,NTC	;else not new byte
      ST	#0,*AR4						;Clear the memory location
tint_rs_not_new_byte:      
	  ST	#PCR_SUB,*AR2+          	;Check current line status of SDA
  	  LD	#K_FSXP_1,B 				;Mask FSXP bit (bit 3) 
  	  AND	*AR2-,B						;check FSXP bit
      LD	B,-3,A	  					;Store to bit 0 of A
      
      LD	IDBITCTR,B   				;Check if end of byte,ie. bit ctr=0
      BC	tint_rs_bit_0,BEQ			;If bit ctr=0, goto new_byte
      SUB   #1,B                        ;else decrement bit ctr
      STL	B,TEMP1_REG                 ;Store to TEMP1 register

      RPT	TEMP1_REG                   ;Shift A (bitctr-1) times
      SFTL	A,1                         ;Result in A         
      ;***LSB NO NEED TO SHIFT***
tint_rs_bit_0:                          ;If bit 0, no need to shift
      LD	*AR4,B                      ;Load B with current read byte
      OR	A,B                         ;Combine and store to B
      AND   #0FFH,B                     ;Allows only byte
      STL	B,*AR4                      ;Store back to memory

      LD	IDBITCTR,A	                ;If BITCTR=0(LSB) ie. end of byte
      BC    tint_rs_next_byte,AEQ		;goto next byte
      SUB	#1,A,B						;Decrement A and store to B
      STL	B,IDBITCTR					;Store back to register
	  B	    tint_rs_next            	;Next bit
	  ;***TEST IF COME TO LAST BYTE***
tint_rs_next_byte:
	  ORM	#K_ACK_1,_I2CSTATUS			;Enable ACK flag
      ST	#7,IDBITCTR					;Start from MSB (initiate next byte)
      ADDM	#1,POINTER					;Increment POINTER
      ANDM	#0FFH,_IDBYTECTR			;Prepare num of btye to receive

	  LD	POINTER,B					;Load the incremental POINTER to B
      LD    _IDBYTECTR,A                ;Load num of byte to A
      SUB   B,A							;A=(Num of byte) - (current byte POINTER)     
      BC	tint_rs_no_more_byte,AEQ	;If=0,no more to receive
      LD	POINTER,8,A                 ;Shift 8 places forward
      LD	_IDBYTECTR,B				;
      OR	B,A							;Combine POINTER and num of btye to send                                                                 
      STL	A,_IDBYTECTR				;Update IDBYTECTR
      B		tint_rs_next				;Goto next byte
tint_rs_no_more_byte:
      ORM	#K_STOP_1,_I2CSTATUS		;Enable STOP condition
tint_rs_next:
	  ST	#0,POINTER					;Extra flag use in ack_rs
	  ORM	#K_CLKL_1,_I2CSTATUS		;Next TINT,enable releaseSCL	
      STM	#STOP_TIMER,TCR     		;stop timer
      STM	#K_SCL_HIGH,PRD    			;load PRD (interrupt at 5us)
      STM	#START_TIMER,TCR    		;start timer
      B		tint_end_isr				;

      
;**************************************************************************
;**************************************************************************      
 
      
;*****WRITE TO SLAVE SEQUENCES*****
tint_write_slave:                       

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?