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.

[参考译文] 编译器/MSP430F67791A:F6779和 I2C EEPROM

Guru**** 2535750 points
Other Parts Discussed in Thread: MSP430F67791A, MSPDRIVERLIB

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/712492/compiler-msp430f67791a-f6779-and-i2c-eeprom

器件型号:MSP430F67791A
主题中讨论的其他器件: MSPDRIVERLIB

工具/软件:TI C/C++编译器

您好、先生、

       我已经为 msp430f67791a 的 EEPROM 通信 i2c 编写了代码、这里我们使用了 EEPROM 24c02c 微芯片。

我在这里附加代码在 EEPROM 中写入数据时遇到问题、因为当我使用 EEPROM 读取数据时、我会得到"0xFF"。

请建议我更改代码、以便在 EEPROM 中正确写入数据、并从 EEPROM 读取给定地址上的数据。

//=================== main.C=================================================================

#include "msp430.h"
#include "i2c f67791a.c"


unsigned char read_val[100];
unsigned char write_val[100];
unsigned int 地址;

int main (空)

unsigned int i;
WDTCTL = WDTPW + WDTHOLD;//停止看门狗计时器

InitI2C (0x50);//初始化 I2C 模块

EEPROM_ByteWrite (0x0000,0x05);
EEPROM_AckPolling();//等待 EEPROM 写入周期
//完成
EEPROM_ByteWrite (0x0001、0x34);
EEPROM_AckPolling();//等待 EEPROM 写入周期
//完成
EEPROM_ByteWrite (0x0002、0x56);
EEPROM_AckPolling();//等待 EEPROM 写入周期
//完成
EEPROM_ByteWrite (0x0003、0x78);
EEPROM_AckPolling();//等待 EEPROM 写入周期
//完成
EEPROM_ByteWrite (0x0004、0x9A);
EEPROM_AckPolling();//等待 EEPROM 写入周期
//完成
EEPROM_ByteWrite (0x0005、0xBC);
EEPROM_AckPolling();//等待 EEPROM 写入周期
//完成
READ_VAL[0]= EEPROM_RandomRead (0x0000);//从地址0x0000读取
Read_val[1]= EEPROM_CurrentAddressRead ();//从地址0x0001读取
Read_val[2]= EEPROM_CurrentAddressRead ();//从地址0x0002读取
Read_val[3]= EEPROM_CurrentAddressRead ();//从地址0x0003读取
Read_val[4]= EEPROM_CurrentAddressRead ();//从地址0x0004读取
Read_val [5]= EEPROM_CurrentAddressRead ();//从地址0x0005读取

//使用计数器值填充 write_val 数组
for (i = 0;i <= sizeof (write_val);i++)

write_val[i]= i;


地址= 0x0000;//将起始地址设置为0

//写入数据数组序列
EEPROM_PageWrite (address、write_val、sizeof (write_val));

//从 EEPROM 读取一系列数据
EEPROM_SequentialRead (address、read_val、sizeof (read_val));

_bis_SR_register (GIE);

__no_operation();

//======================================== I2C f67791a.c================================================ //

#include "msp430f67791a.h"
#include "I2Croutines.h"

#define MAXPAGEWRITE 64

Int PtrTransmit;
unsigned char I2CBufferArray[66];
unsigned char I2CBuffer;

/*------------------ *
//描述:
// I2C 模块的初始化
/*------------------ *
空 InitI2C (unsigned char EEPROM_i2c_address)

I2C_PORT_DIR |= SDA_PIN + SCL_PIN;
I2C_PORT_SEL |= SDA_PIN + SCL_PIN;//将 I2C 引脚分配给 USCI_B0

//用户指南中显示的 I2C 模块的建议初始化步骤:
UCB0CTL1 |= UCSWRST;//启用 SW 复位
UCB0CTLW0 |= UCMST + UCMODE_3 + UCSYNC + UCSSEL_2;// I2C 主设备、同步模式
//UCB0CTL1 = UCSSEL_2 + UCTR + UCSWRST;//使用 SMCLK、TX 模式、保持软件复位
UCB0BRW_L = 12;// fSCL = SMCLK/12 =~100kHz
UCB0BRW_H = 0;
UCB0I2CSA = EEPROM_i2c_address;//定义从地址
//在本例中为从地址
//定义控制字节
//发送到 EEPROM。
//UCB0I2COA = 0x01A5;//自有地址。
// UCB0IE|=UCTXIE+UCRXIE;
UCB0CTLW0 &=~UCSWRST;//清除软件复位,恢复操作

IF (UCB0STAT 和 UCBBUSY)//测试是否总线为空
{//否则、手动时钟打开
//生成
I2C_PORT_SEL &=~SCL_PIN;//为 SCL 选择端口功能
I2C_PORT_OUT &=~SCL_PIN;//
I2C_PORT_DIR |= SCL_PIN;//将 SCL 驱动为低电平
I2C_PORT_SEL |= SDA_PIN + SCL_PIN;//为选择模块功能
//使用的 I2C 引脚
};
_enable_interrupt ();

/*------------------ *
//描述:
//初始化 I2C 模块以执行写操作。
/*------------------ *
空 I2CWriteInit (空)

UCB0CTLW0 |= UCTR;// UCTL=1 =>发送模式(R/W 位= 0)
UCB0IFG &=~UCTXIFG;
UCB0IE &=~UCRXIE0;//禁用接收就绪中断
UCB0IE|= UCTXIE0;//启用发送就绪中断

/*------------------ *
//描述:
//为读取操作初始化 I2C 模块。
/*------------------ *
空 I2CReadInit (空)

UCB0CTLW0 &=~Ω UCTR;// UCTL=0 =>接收模式(R/W 位= 1)
UCB0IFG |= UCRXIFG;
//UCB0IE &=~UCTXIE0;//禁用发送就绪中断
UCB0IE |= UCRXIE0;//启用接收就绪中断

/*------------------ *
//描述:
//字节写入操作。 通过 I2C 总线与 EEPROM 进行通信
//(2465)已实现。 一个数据字节被写入一个用户定义的地址。
/*------------------ *
空 EEPROM_ByteWrite (unsigned int 地址、unsigned char 数据)

unsigned char adr_hi;
unsigned char adr_lo;

while (UCB0STAT 和 UCBUSY);//等待 I2C 模块具有
//完成所有操作。

ADR_HI =地址>> 8;//计算高字节
ADR_lo =地址和0xFF;//和低字节地址

I2CBufferArray[2]= ADR_HI;//低字节地址。
I2CBufferArray[1]= ADR_lo;//高字节地址。
I2CBufferArray[0]=数据;
PtrTransmit = 2;//设置 I2CBufferArray 指针

I2CWriteInit();
UCB0CTLW0 |= UCTXSTT;//开始条件生成
//=> I2C 通信开始
//_ bis_SR_register (LPM0_bits + GIE);//输入 LPM0、带中断
while (UCB0CTLW0 & UCTXSTP);//确保发送了 STOP 条件

/*------------------ *
//描述:
//页写操作。 通过 I2C 总线与 EEPROM 进行通信
//(24xx65)已实现。 一个数据字节被写入一个用户定义的地址。
/*------------------ *
void EEPROM_PageWrite (unsigned int StartAddress、unsigned char * Data、unsigned char size)

volatile unsigned int i = 0;
volatile unsigned char counterI2cBuffer;
unsigned char adr_hi;
unsigned char adr_lo;
unsigned int currentAddress = StartAddress;
unsigned char currentSize = size;
unsigned char bufferPtr = 0;
unsigned char moreDataToRead = 1;

while (UCB0STAT 和 UCBUSY);//等待 I2C 模块具有
//完成所有操作。

//执行,直到数据缓冲区中没有更多数据
while (moreDataToRead)

ADR_HI =电流地址>> 8;//计算高字节
ADR_lo =当前地址和0xFF;//和低字节地址

//一次发送低至64字节数据包的斩波数据
//保持当前起始地址的指针
if (currentSize > MAXPAGEWRITE)

bufferPtr = bufferPtr + MAXPAGEWRITE;
counterI2cBuffer = MAXPAGEWRITE - 1;
PtrTransmit = MAXPAGEWRITE + 1;//设置 I2CBufferArray 指针
currentSize = currentSize - MAXPAGEWRITE;
currentAddress = currentAddress + MAXPAGEWRITE;

//获取起始地址
I2CBufferArray[MAXPAGEWRITE + 1]= ADR_HI;//高字节地址。
I2CBufferArray[MAXPAGEWRITE]= ADR_LO;//低字节地址。

其他

bufferPtr = bufferPtr + currentSize;
counterI2cBuffer =当前大小-1;
PtrTransmit = currentSize + 1;//设置 I2CBufferArray 指针。
MoreDataToRead = 0;
currentAddress = currentAddress + currentSize;

//获取起始地址
I2CBufferArray[currentSize + 1]= ADR_HI;//高字节地址。
I2CBufferArray[电流大小]= ADR_lo;//低字节地址。

//将数据复制到 I2CBufferArray
unsigned char temp;
for (i;i < bufferPtr;i++)

temp = Data[i];//必需、否则 IAR 抛出
//警告[Pa082]
I2CBufferArray[counterI2cBuffer]= temp;
counterI2c 缓冲器--;

I2CWriteInit();
UCB0CTLW0 |= UCTXSTT;//开始条件生成
//=> I2C 通信开始
//_ bis_SR_register (LPM0_bits + GIE);//输入 LPM0、带中断
while (UCB0CTLW0 & UCTXSTP);//确保发送了 STOP 条件

EEPROM_AckPolling();//确保数据写入 EEPROM 中

/*------------------ *
//描述:
//当前地址读取操作。 从 EEPROM 读取数据。 电流
使用来自 EEPROM 的//地址。
/*------------------ *
unsigned char EEPROM_CurrentAddressRead (空)

while (UCB0STAT 和 UCBUSY);//等待 I2C 模块具有
//完成所有操作
I2CReadInit();

UCB0CTLW0 |= UCTXSTT;// I2C 启动条件
while (UCB0CTLW0 & UCTXSTT);//是否发送了启动条件?
UCB0CTLW0 |= UCTXSTP;// I2C 停止条件
//_bis_SR_register (LPM0_bits + GIE);//输入 LPM0、带中断
while (UCB0CTLW0 & UCTXSTP);//确保发送了 STOP 条件
返回 I2CBuffer;

/*------------------ *
//描述:
//随机读取操作。 从 EEPROM 读取数据。 EEPROM
//地址由参数 Address 定义。
/*------------------ *
unsigned char EEPROM_RandomRead (unsigned int Address)

unsigned char adr_hi;
unsigned char adr_lo;

while (UCB0STAT 和 UCBUSY);//等待 I2C 模块具有
//完成所有操作

ADR_HI =地址>> 8;//计算高字节
ADR_lo =地址和0xFF;//和低字节地址

I2CBufferArray[1]= ADR_HI;//存储必须的单个字节
I2CBufferArray[0]= ADR_lo;//在 I2CBuffer 中发送。
PtrTransmit = 1;//设置 I2CBufferArray 指针

//首先写入地址
I2CWriteInit();
UCB0CTLW0 |= UCTXSTT;//开始条件生成
//=> I2C 通信开始
//_bis_SR_register (LPM0_bits + GIE);//输入 LPM0、带中断
while (UCB0CTLW0 & UCTXSTP);//确保发送了 STOP 条件

//读取数据字节
I2CReadInit();

UCB0CTLW0 |= UCTXSTT;// I2C 启动条件
while (UCB0CTLW0 & UCTXSTT);//是否发送了启动条件?
UCB0CTLW0 |= UCTXSTP;// I2C 停止条件
//_bis_SR_register (LPM0_bits + GIE);//输入 LPM0、带中断
while (UCB0CTLW0 & UCTXSTP);//确保发送了 STOP 条件
返回 I2CBuffer;

/*------------------ *
//描述:
//顺序读取操作。 数据按顺序从 EEPROM 读取
//从参数地址作为起点。 指定要的大小
//被读取并填充到数据缓冲区。
/*------------------ *
void EEPROM_SequentialRead (unsigned int Address、unsigned char * Data、unsigned int size)

unsigned char adr_hi;
unsigned char adr_lo;
unsigned int counterSize;

while (UCB0STAT 和 UCBUSY);//等待 I2C 模块具有
//完成所有操作

ADR_HI =地址>> 8;//计算高字节
ADR_lo =地址和0xFF;//和低字节地址

I2CBufferArray[1]= ADR_HI;//存储必须的单个字节
I2CBufferArray[0]= ADR_lo;//在 I2CBuffer 中发送。
PtrTransmit = 1;//设置 I2CBufferArray 指针

//首先写入地址
I2CWriteInit();
UCB0CTLW0 |= UCTXSTT;//开始条件生成
//=> I2C 通信开始
//_bis_SR_register (LPM0_bits + GIE);//输入 LPM0、带中断
while (UCB0CTLW0 & UCTXSTP);//确保发送了 STOP 条件

//读取数据字节
I2CReadInit();

UCB0CTLW0 |= UCTXSTT;// I2C 启动条件
while (UCB0CTLW0 & UCTXSTT);//是否发送了启动条件?

for (counterSize = 0;counterSize < size;counterSize++)((counterSize = 0;counterSize < Size <;

//_bis_SR_register (LPM0_bits + GIE);//输入 LPM0、带中断
DATA[counterSize]= I2CBuffer;

UCB0CTLW0 |= UCTXSTP;// I2C 停止条件
//_bis_SR_register (LPM0_bits + GIE);//输入 LPM0、带中断
while (UCB0CTLW0 & UCTXSTP);//确保发送了 STOP 条件

/*------------------ *
//描述:
//确认轮询。 如果写入周期为、EEPROM 将不会应答
//正在处理。 它可用于确定写入周期何时完成。
/*------------------ *
void EEPROM_AckPolling (void)

while (UCB0STAT 和 UCBUSY);//等待 I2C 模块具有
//完成所有操作
操作

UCB0STAT = 0x00;//清除 I2C 中断标志
UCB0CTLW0 |= UCTR;// I2CTRX=1 =>发送模式(R/W 位= 0)
UCB0CTLW0 &=~UCTXSTT;
UCB0CTLW0 |= UCTXSTT;//开始条件被生成
while (UCB0CTLW0 & UCTXSTT)//等待 I2CSTT 位被清零

if (!(UCNACKIFG & UCB0STAT))//如果收到 ACK 则中断
中断;

UCB0CTLW0 |= UCTXSTP;//停止条件在之后生成
//发送从器件地址=> I2C 通信开始
while (UCB0CTLW0 & UCTXSTP);//等待停止位复位
__DELAY_CYCLES (500);//软件延迟
} while (UCNACKIFG & UCB0STAT);

/*------------------ *
/*中断服务例程*/
/*请注意,编译器版本将在以下代码和*/中进行检查
/*根据编译器版本、正确的中断服务*/
使用了/*例程定义。 *
//#if __VER__< 200
//中断[USCIAB0TX_Vector] void TX_ISR_I2C (void)
//#else
#pragma vector = USCI_B0_vector
_interrupt void USCI_B0_ISR (void)
//#endif

IF (UCTXIFG 和 UCB0IFG)

UCB0TXBUF = I2CBufferArray[PtrTransmit];//加载 TX 缓冲区
PtrTransmit--;//减量 TX 字节计数器
if (PtrTransmit < 0)

while (!(UCB0IFG & UCTXIFG));
UCB0CTLW0 |= UCTXSTP;// I2C 停止条件
UCB0IE &=~UCTXIE0;//禁用中断。
UCB0IFG &=~UCTXIFG;//清除 USCI_B0 TX 内部标志
//__BIC_SR_REGISTER_ON_EXIT (LPM0_BITS);//退出 LPM0


否则 IF (UCRXIFG 和 UCB0IFG)

I2CBuffer = UCB0RXBUF;//将接收到的数据存储在缓冲区中
//_BIC_SR_REGISTER_ON_EXIT (LPM0_BITS);//退出 LPM0

此致、

扭结

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

    您好!

    您是否已通读 MSP430TmMCU 上常见 eUSCI 和 USCI 串行通信问题解决 方案应用手册中的第5节常见 I2C 通信问题(以及第5节中的子部分)? 至于代码建议、由于您已经创建了自己的函数并且有许多注释代码、因此很难通读代码。 我建议您在尝试创建自己的函数之前、先在 CCS 中使用我们的 I2C 代码示例、等等 我们还提供 MSP 驱动程序(MSPDRIVERLIB)、该驱动程序具有用于 I2C 通信的易于使用的 API。 您是否了解过此库?

    为了供将来发布代码时参考、请勿发布过多代码、否则社区可能不想花时间浏览代码。 此外,请使用语法高亮显示工具(如下所示:" ")找到"插入代码、附加文件等..." 单击"回复"按钮后显示的链接。 它使代码更具可读性。

    此致、

    James

    MSP 客户应用