大家好、我正在尝试 使用 MSP430FR2433读取 I2C 上的 DS1621温度传感器。
批量读取代码行会导致 I2C 总线“挂起”,并且不会生成 ACK 确认位!!!
BIS.w #UCTXSTT、&UCB0CTLW0 ;I2C start+address
MOV.w #0x00AA、UCB0TXBUF ;命令 DS1621 (读取温度)
BIS.w #UCTXSTP,&UCB0CTLW0 ;I2C 停止
如果我在步骤中有一个程序、那么 I2C 总线工作!
I2C 总线在两个阶段有一个“部分”写入周期
BIS.w #UCTXSTT、&UCB0CTLW0;I2C start+address
MOV.w #0x00AA、UCB0TXBUF;命令 DS1621 (读取温度)
BIS.w #UCTXSTP,&UCB0CTLW0;I2C 停止
或
BIS.w #UCTXSTT、&UCB0CTLW0;I2C start+address
MOV.w #0x00AA、UCB0TXBUF;命令 DS1621 (读取温度)
BIS.w #UCTXSTP,&UCB0CTLW0;I2C 停止
然后、在开始+地址之后、无论波特率如何、ACK + TX_DATA 都以50ms 的间隔出现。
I2C 总线上的几个字节的周期记录不能分两个阶段进行部分分步调试。
BIS.w #UCTXSTT、&UCB0CTLW0;start+address
MOV.w #0x00AA、UCB0TXBUF;ACK+命令 DS1621 (读取温度)
MOV.w #0x00EE、UCB0TXBUF;ACK+命令 DS1621 (启动温度转换)
MOV.w #0x0022、UCB0TXBUF;ACK+命令 DS1621 (暂停温度转换)
MOV.w #0x00AA、UCB0TXBUF;ACK+命令 DS1621 (读取温度)
BIS.w #UCTXSTP,&UCB0CTLW0;ACK+STOP
或
BIS.w #UCTXSTT、&UCB0CTLW0;I2C start+address
MOV.w #0x00AA、UCB0TXBUF;ACK+命令 DS1621 (读取温度)
MOV.w #0x00EE、UCB0TXBUF;ACK+命令 DS1621 (启动温度转换)
MOV.w #0x0022、UCB0TXBUF;ACK+命令 DS1621 (暂停温度转换)
MOV.w #0x00AA、UCB0TXBUF;ACK+命令 DS1621 (读取温度)
BIS.w #UCTXSTP,&UCB0CTLW0;ACK+STOP
在 NACK + STOP 总线上、仅以相同的50ms 间隔发送 ACK + 1个数据字节+
如果您在寄存器 UCB0TXBUF 中预先设置数据、然后在一个命令中设置开始+停止位
MOV.w #0x00AA、UCB0TXBUF;命令 DS1621 (读取温度)
BIS.w #UCTXSTT+UCTXSTP、&UCB0CTLW0;I2C start+address
START + ADRESS + ACK + STOP 出现在总线 I2C 上。
- 为什么主器件在每8位数据传输一次后不会生成 ACK、这是 I2C 协议所规定的、并在传输下一个状态(TX_DATA 和 STOP)之前形成 ACK?
- I2C 为什么会自动"挂起"50ms?
- 为什么 I2C 自动拒绝在没有分步模式的情况下执行总线周期(UCBBUSY 位的分析没有导致结果)?
- 如何在从器件的1个写入周期内传输多个数据字节?
批量代码执行只会导致读取第一个字节!
BIS.w #UCTXSTT、&UCB0CTLW0;I2C start+address+RX_data
MOV.w UCB0RXBUF、R7
BIS.w #UCTXSTP、&UCB0CTLW0
MOV.w UCB0RXBUF、R8;ACK + NACK + STOP
分步执行中
BIS.w #UCTXSTT、& UCB0CTLW0
命令、它会调用 START + addres + ACK + RX_DATA (16位)、而 UCB0RXBUF 寄存器(slau445h.pdf 第655页)只接受8个低位!
读取寄存器 UCB0RXBUF 会在总线上产生 ACK + RX_DATA (8位)
MOV.w UCB0RXBUF、R7
当#UCTXSTP 位置位时、读取寄存器命令 UCB0RXBUF 会导致 ACK + NACK + STOP
BIS.w #UCTXSTP 和 UCB0CTLW0
MOV.w UCB0RXBUF、R7 ; ACK + NACK + STOP
运行
BIS.w # UCTXSTT + UCTXSTP、& UCB0CTLW0
导致一个读周期、8个数据位开始+地址+ ACK + RX_DATA + NACK + STOP
如何读取几个字节的数据?
IAR Workbench ASM 代码:
;------------------------------------------------------------------
;CPU:MSP430FR2433IRGER
;------------------------------------------------------------------
; I2C 地址:
;#090h - DS1621 (W)
;#091h - DS1621 (R)
;UCB0I2CSA =#048h
;------------------------------------------------------------------
#include "msp430.h" ;#define controlled include 文件
RSEG CSTACK ;定义堆栈段
RSEG 代码
;------------------------------------------------------------------
重置 mov.w #SFE (CSTACK),SP ;初始化 stackpointer
StopWDT mov.w #WDTPW+WDTHOLD、&WDTCTL ;停止看门狗计时器
//配置 GPIO
BIS.b #BIT2+BIT3、P1SEL0 ;I2C 引脚
BIC.b #BIT2+BIT3、&P1DIR
BIC.w #LOCKLPM5、PM5CTL0 ;解锁 I/O 引脚
//将 USCI_B0配置为 I2C 模式
BIS.w #UCSWRST、&UCB0CTLW0
BIS.w #UCMST、 &UCB0CTLW0 ;I2C 主机模式
BIS.w #UCMODE_3、&UCB0CTLW0 ;eUSCI_B 模式= I2C
MOV.w #0x0100、 UCB0BRW ;波特率= SMCLK / 100
BIC.w #UCSWRST、&UCB0CTLW0 ;
wait1 bit.w #UCBBUSY、和 UCB0STATW ;等待 I2C 模块完成所有操作
JC wait1
// WIRITE I2C
MOV.w #0x0048、 UCB0I2CSA ;I2C 从器件地址= DS1621
BIS.w #UCTR、 &UCB0CTLW0 ;I2C=TX
BIS.w #UCTXSTT、&UCB0CTLW0 ;start+address
MOV.w #0x00AA、 UCB0TXBUF ;ACK+命令 DS1621 (读取温度)
MOV.w #0x00EE、 UCB0TXBUF ;ACK+命令 DS1621 (启动温度转换)
//暂停
NOP
//--
MOV.w #0x0022、 UCB0TXBUF ;ACK+命令 DS1621 (暂停温度转换)
MOV.w #0x00AA、 UCB0TXBUF ;ACK+命令 DS1621 (读取温度)
BIS.w #UCTXSTP,&UCB0CTLW0 ;ACK+STOP
//读取 I2C
BIC.w #UCTR、 &UCB0CTLW0 ;I2C=RX
BIS.w #UCTXSTT+UCTXSTP、&UCB0CTLW0 ;start+address+RX_data
MOV.w UCB0RXBUF、R7
BIS.w #UCTXSTT、&UCB0CTLW0 ;I2C start+address+RX_data
MOV.w UCB0RXBUF、R7
BIS.w #UCTXSTP、&UCB0CTLW0
MOV.w UCB0RXBUF、R8 ;ACK + NACK + STOP
JMP $ ;跳转至当前位置'$'
;(无限循环)
;------------------------------------------------------------------
常见的 INTVEC ;中断矢量
;------------------------------------------------------------------
org reset_vector ;Reset Vector
DW 复位
结束