请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
器件型号:MSP430F6720 工具/软件:Code Composer Studio
您好!
我正在尝试将 slaa208a 从 MSP430F1/2xxx 移植到 MSP430F67XX。 我能够在某种程度上使代码正常工作、但遇到了一些奇怪的问题。 从 EEPROM 读取似乎正常、但写入 EEPROM 总是会出现问题:
1) 1)逐一写入256字节需要几十秒。
2) 2)这些字节中的很多字节未成功写入 EEPROM。 当从这些地址读回时、其中许多地址为默认值0xFF。
下面随附了我的代码。 我应该如何进行故障排除?
提前感谢。
i2ceeprom.h
#define I2C_PORT_SEL P2SEL #define I2C_PORT_OUT P2OUT #define I2C_PORT_REN P2REN #define I2C_PORT_DIR P2DIR #define SDA_PIN BIT1 // UCB0SDA 引脚 #define SCL_PIN BIT0 // UCB.S 引脚 #define SCL_CLOCK _DIV 0x0050 // SCL 时钟分频 器 void InitI2C (unsigned char EEPROM_i2c_address); void EEPROM_ByteWrite (unsigned int Address、unsigned char StartAddress、unsigned char * Data、unsigned char Size); unsigned char EEPROM_RandomRead (unsigned char int Address);// unsigned char eeproM_CurrentRefad (unsigned char)、unsigned char Reset_Reset_Resize*、void *、unsigned char Data) void EEPROM_AckPolling (void); void resetI2C (void);
i2ceeprom.c
#include "msp430.h"
#include "i2ceeprom.h"
#define MAXPAGEWRITE 8
int PtrTransmit;
unsigned char I2CBufferArray[16];
unsigned char I2CBuffer;
/*--------------- */
//说明:
// I2C 模块的初始化
/*--------------- */
void InitI2C (unsigned char EEPROM_i2c_address)
{
I2C_PORT_SEL |= SDA_PIN | SCL_PIN; //将 I2C 引脚分配给 USCI_B0
//设置 eUSCI_B0
UCB0CTLW0 |= UCSWRST; //启用 SW 复位
UCB0CTLW0 |= UCMST | UCMODE_3 | UCSSEL_SMCLK | UCSYNC; // I2C 主设备,使用 SMCLK
// UCB0BRW = SCL_Cock_DIV; // fSCL = SMCLK/40 =~100kHz
UCB0BRW_L = 40; // fSCL = SMCLK/12 =~100kHz
UCB0BRW_H = 0;
UCB0I2CSA = EEPROM_i2c_address; //从器件地址
UCB0CTLW0 &=~UCSWRST; //清除 SW 复位、
如果(UCB0STATW 和 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 引脚
};
}
void resetI2C()
{
I2C_PORT_SEL &=~(SDA_PIN + SCL_PIN); //将 I2C 引脚分配给 GPIO
I2C_PORT_DIR &=~(SDA_PIN + SCL_PIN);//将 I2C 引脚设置为输入
I2C_PORT_REN &=~(SDA_PIN + SCL_PIN);//没有上拉或下拉电阻
器}
/*--- //
说明:
//初始化 I2C 模块以执行写操作。
/*------------------ */
void I2CWriteInit (void)
{
UCB0CTLW0 |= UCTR; // UCTL=1 =>发送模式(R/W 位= 0)
UCB0IFG &&~UCTXIFG0;
UCB0IE &&~UCRXIE0; //禁用接收就绪中断
UCB0IE |= UCTXIE0; //启用发送就绪中断}/--><!--kadov_tag{{</spaces>}/--><!--kadov_tag{</spaces>}}-->
*/
/说明:
// I2C 模块初始化以执行读取操作。
/*------------------ *
/ void I2CReadInit (void)
{
UCB0CTLW0 &&~UCTR; // UCTL=0 =>接收模式(R/W 位= 1)
UCB0IFG &&~UCRXIFG0;
UCB0IE &&~UCTXIE0; //禁用发送就绪中断
UCB0IE |= UCRXIE0; //启用接收就绪中断}/--><!--kadov_tag{{</spaces>}/--><!--kadov_tag{</spaces>}}-->
*/
//说明:
//字节写入操作。 通过 I2C 总线与 EEPROM
//(2465)进行通信。 一个数据字节被写入一个用户定义的地址。
/*------------------ //
void EEPROM_ByteWrite (unsigned int Address、unsigned char Data)
{
unsigned char ADR_hi;
unsigned char ADR_lo;
while (UCB0STATW 和 UCBUSY); //等待 I2C 模块完成所有操作。
ADR_HI =地址>> 8; //计算高字节
ADR_LO =地址和0xFF; //和地址
I2CBufferArray[2]的低字节= ADR_HI; //低字节地址。
I2CBufferArray[1]= ADR_lo; //高字节地址。
I2CBufferArray[0]=数据;
PtrTransmit = 2; //设置 I2CBufferArray 指针
I2CWriteInit();
UCB0CTLW0 |= UCTR | UCTXSTT; //开始条件生成 I2C 通信
__bis_SR_register (LPM0_bits + GIE); //通过中断 UCB0CTLW0输入 LPM0
|= UCTXSTP; // I2C 停止条件
while (UCB0CTLW0 & UCTXSTP); //确保已发送停止条件}/*--><!--kadov_tag{{</spaces>}--><!--kadov_tag{</spaces>}--><!--kadov_tag{</spaces>}--><!--kadov_tag{</spaces>}--><!--kadov_tag{</spaces>}}-->
//
//说明:
//当前地址读取操作。 从 EEPROM 读取数据。
使用来自 EEPROM 的当前//地址。
/*------------------ //
unsigned char EEPROM_CurrentAddressRead (void)
{
while (UCB0STATW & UCBUSY); //等待 I2C 模块具有
//完成所有操作
I2CReadInit();
UCB0CTLW0 |= UCTXSTT; // I2C 启动条件
while (UCB0CTLW0 & UCTXSTT); //起始条件是否已发送?
UCB0CTLW0 |= UCTXSTP; // I2C 停止条件
_ bis_SR_register (LPM0_bits + GIE); //通过中断
while (UCB0CTLW0 & UCTXSTP)输入 LPM0; //确保停止条件已发送
返回 I2CBuffer;
}-->---------------
*/
//说明:
//随机读取操作。 从 EEPROM 读取数据。 EEPROM
//地址由参数 Address 定义。
/*------------------ //
unsigned char EEPROM_RandomRead (unsigned int Address)
{
unsigned char ADR_hi;
unsigned char ADR_lo;
while (UCB0STATW 和 UCBUSY); //等待 I2C 模块完成所有操作
ADR_HI =地址>> 8; //计算高字节
ADR_LO =地址和0xFF; //和地址
I2CBufferArray[1]的低字节= ADR_HI; //存储必须
包含 I2CBufferArray[0]= ADR_lo 的单字节; //在 I2CBuffer 中发送。
PtrTransmit = 1;
//写入地址优先
I2CWriteInit();
UCB0CTLW0 |= UCTXSTT; //开始条件生成=> I2C 通信开始
__bis_SR_register (LPM0_Bits + GIE); //输入带中断的 LPM0
//读取数据字节
I2CReadInit();
UCB0CTLW0 |= UCTXSTT; // I2C 启动条件
while (UCB0CTLW0 & UCTXSTT); //起始条件是否已发送?
UCB0CTLW0 |= UCTXSTP; // I2C 停止条件
_ bis_SR_register (LPM0_bits + GIE); //通过中断
while (UCB0CTLW0 & UCTXSTP)输入 LPM0; //确保停止条件已发送
返回 I2CBuffer;
}-->---------------
//
//说明:
//确认轮询。 如果写入周期为
//正在进行、EEPROM 将不会应答。 它可用于确定写入周期何时完成。
/*------------------ */
void EEPROM_AckPolling (void)
{
while (UCB0STATW 和 UCBUSY); //等待 I2C 模块具有
//完成所有操作
都执行
{
UCB0STATW = 0x00; //清除 I2C 中断标志
UCB0CTLW0 |= UCTR; // I2CTRX=1 =>发送模式(R/W 位= 0)
UCB0CTLW0 &=~UCTXSTT;
UCB0CTLW0 |= UCTXSTT; //起始条件已生成
while (UCB0CTLW0和 UCTXSTT) //等待 I2CSTT 位被清零
{
if (!(UCNACKIFG & UCB0STATW)) //如果收到 ACK 则分接
中断;
}
UCB0CTLW0 |= UCTXSTP; //停止条件在之后生成
//发送从器件地址=> I2C 通信开始
while (UCB0CTLW0和 UCTXSTP); //等待停止位被复位
_delay_cycles (500); //软件延迟
}while (UCNACKIFG & UCB0STATW);
}//---------------
// USCIAB0_ISR 的结构使其可用于通过
预加载带有字节计数的 TXByteCtr 来发送任何//字节数。
///----------------------------------
// USCI_B0中断服务例程
#if defined (__TI_Compiler_version__)|| Defined (__IAR_systems_ICC__)
#pragma vector = USCI_B0_Vector
__interrupt void USCI_B0_ISR (void)
#Elif defined (__GSCI__)
void __attribute_(nvoid USCI_B0_bvector)(nuc1_b0_isr)#interrupt BUC0!
#endif
{
开关(_偶数_在范围内(UCB0IV、30))
{
USCI_NONE 案例:中断;//无中断
USCI_I2C_UCALIFG 案例:中断;// ALIFG
案例 USCI_I2C_UCNACKIFG:中断;// NACKIFG
案例 USCI_I2C_UCSTTIFG:中断;// STTIFG
案例 USCI_I2C_UCSTPIFG:中断;// STPIFG
USCI_I2C_UCRXIFG3案例:中断;// RXIFG3
USCI_I2C_UCTXIFG3案例:中断;// TXIFG3
USCI_I2C_UCRXIFG2案例:中断;// RXIFG2
USCI_I2C_UCTXIFG2案例:中断;// TXIFG2
USCI_I2C_UCRXIFG1案例:中断;// RXIFG1
USCI_I2C_UCTXIFG1案例:中断;// TXIFG1
USCI_I2C_UCRXIFG0案例:// RXIFG0
I2CBuffer = UCB0RXBUF;//将接收到的数据存储在缓冲区中
_BIC_SR_REGISTER_ON_EXIT (LPM0_BITS);//退出 LPM0
中断;
USCI_I2C_UCTXIFG0案例:// TXIFG0
UCB0TXBUF = I2CBufferArray[PtrTransmit];//加载 TX 缓冲区
PtrTransmit ----;//测量 TX 字节计数器
if (PtrTransmit < 0)
{
while (!(UCB0IFG & UCTXIFG0));
UCB0IE &=~UCTXIE0;//禁用中断。
UCB0IFG &=~UCTXIFG0;//清除 USCI_B0 TX int 标志
_BIC_SR_REGISTER_ON_EXIT (LPM0_BITS);//退出 LPM0
}
中断;
案例 USCI_I2C_UCBCNTIFG:break;// CNTIFG
USCI_I2C_UCCLTOIFG 案例:中断;// LTOIFG
USCI_I2C_UCBIT9IFG 案例:中断;// BIT9IFG
默认值:break;
}
}
main.c
//WDTCTL = WDTPW | WDTHOLD;//停止看门狗计时器sysinit (); WDTCTL = WDTPW | WDTSSEL_ACLK | WDTIS_3;//启用看门狗计时器:ACLK、4分钟和16秒 initSystem ();// Init i2c UART 和其他 int eepromAddr = 0; 字符 eepromCont = 0; for (eepromAddr = 0;eepromAddr < 256;eepromAddr++){ EEPROM_ByteWrite (eepromAddr、++eepromCont); EEPROM_AckPolling(); WDTCTL = WDTPW | WDTSSEL_ACLK | WDTIS_3 | WDTCNTCL; } eepromAddr = 0; while (1){ eepromCont = EEPROM_RandomRead (eepromAddr); eepromAddr++; if (eepromAddr > 256){ eepromAddr = 0; } while (!(UCA1IFG&UCTXIFG));// USCI_A0 TX 缓冲器准备就绪? UCA1TXBUF = eepromAddr; while (!(UCA1IFG&UCTXIFG));// USCI_A0 TX 缓冲器准备就绪? UCA1TXBUF = eepromCont; while (!(UCA1IFG&UCTXIFG));// USCI_A0 TX 缓冲器准备就绪? UCA1TXBUF = 0x0D; WDTCTL = WDTPW | WDTSSEL_ACLK | WDTIS_3 | WDTCNTCL; _bis_SR_register (LPM3_bits | GIE); }