硬件是PIC16F1936/PIC16F1503使用MSSP模块I2C主模式发数据给TM1650数显模块,问题是I2C时序启动条件无法发起。
如对照TM1650手册采用位操作软件模拟100kHz时序可以正常点亮数显模块。
之所以判断是启动条件无法发起,测试方法是在发起启动条件前后(断点1或断点2)插入测试代码BANKSEL PORTA/BSF PORTA,X,指示灯会亮;如改为插入在发起启动条件后,检测启动条件是否完成的环节(断点3),则指示灯不亮,说明程序在此进入死循环,即开始启动条件后一直未完成,不论是检测中断标志:BTFSS PIR1,SSPIF或检测启动条件使能位BTFSC SSPCON2,SEN(启动条件正常完成后SEN由硬件自动清零)都是一样无法执行到断点3。
我的疑问是:
1、是否遗漏了哪个步骤使模块工作不正常,置位启动条件使能位(BSF SSPCON2,SEN)后不是应该就开始发送启动时序了吗?还望“旁观者”指点迷津。
注:IO有配置为输入,SCL、SDA线有4.7K上拉,各种中断允许、串行端口使能有置位,MCU内部4M时钟,SSPADD写入09H即设定为100kHz。程序用MPLAB X IDE正常编译无报错。
2、发送完两个字节数据(如1字节地址+1字节数据)收到ACK后,应该:先发起停止条件,再发起启动条件,然后继续发送下一个数据(通常为地址)?
还是:收到ACK后直接发起重复启动条件,继续发送下一个数据(通常为地址)?
以下是16F1503测试程序:
ORG 0000H
NOP
GOTO START ;
ORG 0004H
GOTO INT_IN
ORG 0005H
START
CLRF STATUS
BANKSEL IOCAN
MOVLW B'00000000'
MOVWF IOCAN
BANKSEL WPUA
MOVLW B'00001111'
MOVWF WPUA
BANKSEL ANSELA
MOVLW B'00000000'
MOVWF ANSELA
MOVLW B'00000000'
MOVWF ANSELC
BANKSEL LATA
CLRF LATA
CLRF LATC
BANKSEL TRISA
MOVLW B'01101000' ;配置时钟为4M
MOVWF OSCCON
MOVLW B'10000100' ;TIMER0 32分频
MOVWF OPTION_REG
MOVLW B'00001000' ;允许SSPIF中断
MOVWF PIE1
MOVLW B'00000000'
MOVWF TRISA
MOVLW B'00000011' ;配置RC0/SCL、RC1/SDA配置为输入
MOVWF TRISC
MOVLW B'00000000'
MOVWF PIR1
MOVLW B'00010000' ;
MOVWF PORTA
MOVLW 0FH
MOVWF PORTC
MOVLW B'11000000' ;开中断
MOVWF INTCON
BANKSEL SSP1STAT
MOVLW B'10000000' ;初始化I2C
MOVWF SSP1STAT
MOVLW 09H ;设置波特率
MOVWF SSP1ADD
CLRF SSP1CON2
MOVLW B'00001000' ;配置为I2C主模式,时钟=Fosc/(4*(SSPADD+1))
MOVWF SSP1CON1
MOVLW B'01100000' ;允许停止条件、启动条件中断
MOVWF SSP1CON3
BANKSEL PIR1
BCF PIR1,SSP1IF
BCF PIR2,BCL1IF
BANKSEL SSP1STAT
BSF SSP1CON1,SSPEN ;使能同步串行端口
;CLRF SSPBUF
MAIN
CALL I2C_IDLE ;检测总线空闲 (断点1)
BANKSEL SSP1CON2
BSF SSP1CON2,SEN
(断点2)
BANKSEL PIR1 ;或BANKSEL SSP1CON2
BTFSS PIR1,SSP1IF ;或BTFSC SSP1CON2,SEN
GOTO $-1
(断点3)
BCF PIR1,SSP1IF
SENDWRTCOMM1
MOVLW B'01001000' ;模式命令48H
BANKSEL SSP1BUF
MOVWF SSP1BUF
BANKSEL PIR1
BTFSS PIR1,SSP1IF
GOTO $-1
BCF PIR1,SSP1IF
SENDWRTCOMM2
BANKSEL SSP1STAT
BTFSC SSP1STAT,BF
GOTO $-1
MOVLW B'01010001' ;5级亮度,7段显示,开显示
BANKSEL SSP1BUF
MOVWF SSP1BUF
BANKSEL PIR1
BTFSS PIR1,SSP1IF
GOTO $-1
BCF PIR1,SSP1IF
CALL WRTSTOP
CALL WRTSTART
BANKSEL SSP1CON2
BSF SSP1CON2,SEN
BANKSEL PIR1
BTFSS PIR1,SSP1IF
GOTO $-1
BCF PIR1,SSP1IF
SENDADDRESS
BANKSEL SSP1STAT
BTFSC SSP1STAT,BF
GOTO $-1
MOVLW 6CH ;DIG3
MOVWF SSP1BUF
BANKSEL PIR1
BTFSS PIR1,SSP1IF
GOTO $-1
BCF PIR1,SSP1IF
SENDDATA
BANKSEL SSP1STAT
BTFSC SSP1STAT,BF
GOTO $-1
MOVLW 6DH ;5
MOVWF SSP1BUF
BANKSEL PIR1
BTFSS PIR1,SSP1IF
GOTO $-1
BCF PIR1,SSP1IF
CALL WRTSTOP
GOTO MAIN
I2C_IDLE
BANKSEL SSP1STAT
BTFSC SSP1STAT,R_NOT_W
GOTO $-1
MOVF SSP1CON2,W
ANDLW 1FH
BTFSS STATUS,Z
GOTO $-3
RETURN
WRTSTART
BANKSEL SSP1STAT
BSF SSP1CON2,SEN
BANKSEL PIR1
BTFSS PIR1,SSP1IF
GOTO $-1
BCF PIR1,SSP1IF
RETURN
WRTSTOP
BANKSEL SSP1CON2
BSF SSP1CON2,PEN
BANKSEL PIR1
BTFSS PIR1,SSP1IF
GOTO $-1
BCF PIR1,SSP1IF
RETURN
INT_IN
RETFIE
END
|