This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] MSP430G2231:USI i2c 目标从器件地址

Guru**** 2387080 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1271315/msp430g2231-usi-i2c-target-slave-address

器件型号:MSP430G2231

你好。

我尝试按地址读取和写入 i2c 总线上的特定器件、因为总线上有多个器件。

目前、我正在使用 Kerry D. Wong 提供的 i2c.h 库、该库主要来自下面的示例: http://www.43oh.com/forum/viewtopic.php?f=9&t=139

如果链接不再工作、我在此处提供源代码:

#include "i2c.h"
#include <msp430g2231.h>

#define SDA  BIT7 //P1.7
#define SCL  BIT6 //P1.6
#define LED  BIT0 //P1.0

void i2c_init(void)
{
    P1DIR |= SCL | SDA | LED; // Set SCL, SDA and LED as Output
    P1REN |= SCL | SDA; // Set Pull-Ups on SCL and SDA


    // enable SDA, SCL, SCLK, i2c mode, MSB, output enabled, hold in reset
    USICTL0 = USIPE7 | USIPE6 | USIMST | USIOE | USISWRST;

    // USICTL0 Upper 8bit Register of 16bit USICTL Register
	// USIPE7   = P1.7 USI Mode, i2c SDA enabled
	// USIPE6   = P1.6 USI Mode, i2c SCL enabled
	// USIPE5   = P1.5 USI Mode, i2c Clock Input? (Not Set)
	// USILSB   = LSB Mode (Not Set = MSB)
	// USIMST   = Master Mode
	// USIGE    = Output Latch (Not Set = Clock Controlled)
	// USIOE    = Data Output Enable
	// USISWRST = USI Software Reset (Set to allow changing settings)


    // SMCLK / 4, and Reverse Clock Polarity
    USICKCTL = USIDIV_2 + USISSEL_2 + USICKPL;

    // USICKCTL 8bit USI Clock Control Register
	// USIDIVx  = Clock Divider (Bit7-5, USIDIV_2 = Divide by 4)
	// USISSELx = Clock Source (For Master Mode, Bit4-2, USISSEL_2 = SMCLK)
	// USICKPL  = Clock Polarity (0 = Inactive Low, 1 = Inactive High)
	// USISWCLK = Software Clock State

    // I2C Mode
    USICTL1 = USII2C;

    // USICTL1 Lower 8bit Register of 16bit USICTL Register
	// USICKPH   = Clock Phase (0 = Data Changed, then Captured, 1 = Data Captured, then Changed)
	// USII2C    = I2C mode
	// USISTTIE  = START condition Interrupt
	// USIIE     = USI Counter Interrupt
	// USIAL     = Arbitration Lost Notification
	// USISTP    = STOP condition Notification
	// USISTTIFG = START condition Int. Flag
	// USIIFG    = USI Counter Int. Flag

    // release from reset
    USICTL0 &= ~USISWRST;
}

void i2c_start(void)
{
    P1OUT |= LED;  // Turn P1.0 Led on

    // Send i2c START condition
    USISRL = 0x00; // Load USISRL Lower Byte Shift Register MSB with 0 for i2c START
    USICTL0 |= USIGE | USIOE; // Force Output Latch, And Enable Data Output Bit (High to Low SDA while SCL is High)
    USICTL0 &= ~USIGE; // Clear Output Latch (Return to Clock Control)
}

void i2c_stop(void)
{
	// Prepare i2c STOP condition
    USICTL0 |= USIOE; // Enable Data Output Bit (Turn SDA into Output)
    USISRL = 0x00; // Load USISRL Lower Byte Shift Register MSB with 0 for i2c STOP
    USICNT = 1; // Load USICNT Counter with number of Bits to Send. USIIFG Auto-Cleared
    // Data TXed by USI I2C
    while((USICTL1 & USIIFG) != 0x01); // Delay, Wait for USIIFG, Counter down to 0

    // Send i2c STOP condition
    USISRL = 0xFF; // Load USISRL Lower Byte Shift Register MSB with 1 for i2c STOP
    USICTL0 |= USIGE; // Force Output Latch (Low to High SDA while SCL is High)
    USICTL0 &= ~USIOE & ~USIGE ; // Clear Data Output Enable Bit and Output Latch (Release SCL)

    P1OUT &= ~LED; // Turn P1.0 Led off
}

unsigned char i2c_write8(unsigned char c)
{
// TX
    USICTL0 |= USIOE; // Enable Data Output Bit (Turn SDA into Output)
    USISRL = c; // Load USISRL Lower Byte Shift Register with 8 Bit data (Byte)
    USICNT = 8; // Load USICNT Counter with number of Bits to Send. USIIFG Auto-Cleared
    // Data TXed by USI I2C
    while((USICTL1 & USIIFG) != 0x01); // Delay, Wait for USIIFG, Counter down to 0

// RX
    // Data TXed. Ready to Receive (n)ACK from i2c Slave
    USICTL0 &= ~USIOE; // Clear Data Output Enable Bit (Turn SDA into Input)
    USICNT = 1; // Load USICNT Counter with number of Bits to Receive. USIIFG Auto-Cleared
    // Data RXed by USI I2C
    while((USICTL1 & USIIFG) != 0x01); // Delay, Wait for USIIFG, Counter down to 0

// Return Data
    c = USISRL; // LSB of USISRL Holds Ack Status of 0 = ACK (0x00) or 1 = NACK (0x01)
    return c;
}

unsigned char i2c_read8(unsigned char acknack)
{
// RX
    USICTL0 &= ~USIOE; // Clear Data Output Enable Bit (Turn SDA into Input)
    USISRL = 0x00; // Clear USISRL Lower Byte Shift Register (Byte)
    USICNT = 8; // Load USICNT Counter with number of Bits to Receive. USIIFG Auto-Cleared
    // Data RXed by USI I2C
    while((USICTL1 & USIIFG) != 0x01); // Delay, Wait for USIIFG, Counter down to 0

// Copy Data to c
    unsigned char c;
    c = USISRL; // USISRL Holds Received Data

// TX
    // Data RXed. Ready to Send (n)ACK to i2c Slave
    USICTL0 |= USIOE; // Enable Data Output Bit (Turn SDA into Output)
    USISRL = acknack; // Load USISRL Lower Byte Shift Register MSB with acknack (0x00 = Ack, 0xFF = Nack)
    USICNT = 1; // Load USICNT Counter with number of Bits to Send. USIIFG Auto-Cleared
    // Data TXed by USI I2C
    while((USICTL1 & USIIFG) != 0x01); // Delay, Wait for USIIFG, Counter down to 0

// Return Data
    return c;
}

我对使用 USI 寄存器进行 i2c 通信非常陌生、但由于我只有2K 的程序存储器、因此必须在寄存器级完成这一操作、无需太大的外部库。

到目前为止、这个库示例的唯一缺点是未能指定微控制器应该寻址总线上的哪一个器件。

对如何执行这种功能有何建议?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我从未使用过 USI、但通过查看文档、我发现没有像其他硬件串行实现那样针对从器件地址的特殊规定。这意味着在启动后发送的数据的第一个字节将是从器件地址和方向。

    您可以查看 SLAC463中的 I2C 代码示例。