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.

[参考译文] MSP430F5438A:如何使用一个 MSP430与 I2C 通信?

Guru**** 2540460 points
Other Parts Discussed in Thread: MSP430F5438A

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1125383/msp430f5438a-how-to-communicate-i2c-using-one-msp430

器件型号:MSP430F5438A
主题中讨论的其他器件:MSP-TS430PZ5X100

大家好。

我不熟悉 I2C 协议、没有编程经验。

我已经在 David John 的 MSP430微控制器基础手册中阅读了 I2C 通信。 我还查看了 CCS 示例代码。

但是、我无法与 MCU 建立连接。  

我的电路板是使用 MSP430F5438A 的 MSP-TS430PZ5x100。

我想使用板与 I2C 通信。 因此、我已经将 USCI_B0设置为主器件并进行传输、并将 USCI_B1设置为从器件并编写一个代码来接收它。

我的代码开始在21行中重复。

 

void USCI_B_I2C_masterSendSingleByte (uint16_t baseAddress,
    uint8_t txData
    )
{
    //Store current TXIE status
    uint8_t txieStatus = HWREG8(baseAddress + OFS_UCBxIE) & UCTXIE;

    //Disable transmit interrupt enable
    HWREG8(baseAddress + OFS_UCBxIE) &= ~(UCTXIE);

    //Send start condition.
    HWREG8(baseAddress + OFS_UCBxCTL1) |= UCTR + UCTXSTT;

    //Poll for transmit interrupt flag.
    while (!(HWREG8(baseAddress + OFS_UCBxIFG) & UCTXIFG)) ;

    //Send single byte data.
    HWREG8(baseAddress + OFS_UCBxTXBUF) = txData;

    //Poll for transmit interrupt flag.
    while (!(HWREG8(baseAddress + OFS_UCBxIFG) & UCTXIFG)) ;

    //Send stop condition.
    HWREG8(baseAddress + OFS_UCBxCTL1) |= UCTXSTP;

    //Clear transmit interrupt flag before enabling interrupt again
    HWREG8(baseAddress + OFS_UCBxIFG) &= ~(UCTXIFG);

    //Reinstate transmit interrupt enable
    HWREG8(baseAddress + OFS_UCBxIE) |= txieStatus;
}

这是我使用 driverlib.h 的代码

#include <MSP430.h>
#include <MSP430F5xx_6xx/driverlib.h>

uint8_t transmitData = 0x52;
uint8_t receiveData;
/**
 * main.c
 */
void main(void)
{
	WDT_A_hold(WDT_A_BASE);// stop watchdog timer

	initGPIO();
	initClock();
	initI2C();

	while(1)
	{
		USCI_B_I2C_masterSendSingleByte(USCI_B0_BASE, transmitData);

		while(USCI_B_I2C_isBusBusy(USCI_B0_BASE));

		__delay_cycles(50);

		transmitData++;
	}
}
#pragma vector = USCI_B1_VECTOR
__interrupt void USCI_B1_ISR(void)
{
	switch(__even_in_range(UCB1IV, 0x0C)){
		case 0x0C:
			receiveData = USCI_B_I2C_slaveGetData(USCI_B1_BASE);
			break;
	default: //__never_executed();
	break;
	}
}

#include <MSP430F5xx_6xx/driverlib.h>


uint32_t myACLK, mySMCLK, myMCLK;


void initGPIO(void)
{
	//Configurate oscillator 
	GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P7, GPIO_PIN0 + GPIO_PIN1);

	//Configurate I2C
	GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P3, GPIO_PIN1 + GPIO_PIN2 + GPIO_PIN6 + GPIO_PIN7);
}

	

void initClock(void)
{
	PMM_setVCore(PMM_CORE_LEVEL_3);

	UCS_setExternalClockSource(XT1CLK_HZ, XT2CLK_HZ);
	UCS_turnOnLFXT1(XT1DRIVE_0, XCAP_3);

	UCS_initClockSignal(UCS_ACLK, UCS_XT1CLK_SELECT, UCS_CLOCK_DIVIDER_1);

	//Configurate FLL
	/*
	UCS_initClockSignal(UCS_FLLREF, UCS_XT1CLK_SELECT, UCS_CLOCK_DIVIDER_1);
	UCS_initFLL(DESIREDMCLK_KHZ, MCLKXT1CLKRATIO);
	*/
	myACLK = UCS_getACLK();
	mySMCLK = UCS_getSMCLK();
	myMCLK = UCS_getMCLK();
}

void initI2C(void)
{
	USCI_B_I2C_initMasterParam I2cParam0 = {0,};
	I2cParam0.selectClockSource = USCI_B_I2C_CLOCKSOURCE_SMCLK;
	I2cParam0.i2cClk = UCS_getSMCLK();
	I2cParam0.dataRate = USCI_B_I2C_SET_DATA_RATE_400KBPS;

	USCI_B_I2C_initMaster(USCI_B0_BASE, &I2cParam0);
	USCI_B_I2C_initSlave(USCI_B1_BASE, SLAVEADDRESS);

	USCI_B_I2C_setSlaveAddress(USCI_B0_BASE, SLAVEADDRESS);

	USCI_B_I2C_setMode(USCI_B0_BASE, USCI_B_I2C_TRANSMIT_MODE);
	USCI_B_I2C_setMode(USCI_B1_BASE, USCI_B_I2C_RECEIVE_MODE);

	USCI_B_I2C_enable(USCI_B0_BASE);
	USCI_B_I2C_enable(USCI_B1_BASE);

	USCI_B_I2C_clearInterrupt(USCI_B0_BASE, USCI_B_I2C_TRANSMIT_INTERRUPT);
	USCI_B_I2C_clearInterrupt(USCI_B1_BASE, USCI_B_I2C_RECEIVE_INTERRUPT);

	USCI_B_I2C_enableInterrupt(USCI_B0_BASE, USCI_B_I2C_TRANSMIT_INTERRUPT);
	USCI_B_I2C_enableInterrupt(USCI_B1_BASE, USCI_B_I2C_RECEIVE_INTERRUPT);
}

我在 USCI_B_I2C_masterSendSingleByte 上拍摄了有关 I2C SCL 和 SDA 的图片。 (Yello 为 SCL、Sky Blue 为 SDA)

我在哪里找不到?  

谢谢。

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

    示波器显示的是从器件侧拉伸时钟、因为您尚未获取其 Rx 字节。由于从器件 SCL 未连接、因此是一个 NACK。 查看位置:

    1) 1)我看不到您在哪里启用中断(GIE)。 在 main()中的某个位置添加此项:

    >_enable_interrupt ();// GIE=1

    2) 2)在从 ISR 中:

    > 案例0x0C:

    这是发送(TXIFG)未接收(RXIFG)的 IV 代码[参考用户指南(SLAU208Q)表38-14]。 尝试:

    > 案例0x0A:  // RXIFG:从主器件接收到内容

    您最终可能还需要 TXIFG 案例、但在当前实验中不需要

    3) 3)未经请求:

    > USCI_B_I2C_enableInterrupt (USCI_B0_BASE、USCI_B_I2C_Transmit _INTERRUPT);

    在使用 masterSendSingleByte()时,无需为主器件启用 TXIE。 它现在不会引起问题、但最终可能会导致问题。

    [编辑:根据数据表(SLAS655H)表9-45、UCB.S 不在 P3.6上、而是在 P5.4上[参考表9-49]、因此现在我想您会得到一个 NACK、这是 masterSendSingleByte 处理不是很好的。 因此、除了上面的(1)-(3)、您可能应该移至 P5.4并添加:

    > GPIO_setPeripheralModuleFunctionInputPin (GPIO_PORT_P5、GPIO_PIN4); // UCB.S 在这里

    ]

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

    您的建议 对我有所帮助!

    我错过了全局中断和 UCB.S.(P5.4)。 我错误地将 UCA1CLK (P3.6)用于 UCB.S。并且我已将0x0C 更改为0x0A。