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.

[参考译文] MSP430FR6877:与 W25Q16JV 的通信

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/945832/msp430fr6877-communication-with-w25q16jv

器件型号:MSP430FR6877

我将 MSP430FR6877与外部闪存 W25Q16JV 搭配使用、

我正在使用 UCA0 SPI 进行通信、通信已启动并正在运行、我可以读取/写入状态寄存器和读取制造商 ID、例如、

但在存储器中读取/写入数据/代码仍然不起作用、

我尝试通过将5个字节写入闪存中的地址0来测试它、但是当我读取它们时、我会找到复位值"0xFF"、

代码如下所示:

1-初始化:

void flashInit (void)
{
//初始化与闪存
spiInit()的 SPI 通信;

//硬复位
GPIO_setOutputLowOnPin (port_flash_RST、PIN_flash_RST);
// configResetPin ();
__delay_cycles (100000);
GPIO_setOutputHighOnPin (port_flash_RST、 PIN_FLASH_RST);
__DELAY_CYLES (100000);
GPIO_setOutputHighOnPin (PORT_FLASH_WP、PIN_FLASH_WP);
GPIO_setOutputHighOnPin (PORT_FLASH_CS、 PIN_FLASH_CS);

//软复位:命令0x66,然后是0x99
复位();

////*测试:读取制造商 ID */
uint8_t command[4]={0};
uint8_t data[2]={0};
命令[0]= 0x90;
命令[1]= 0;
命令[2]= 0;
命令[3]= 0;

spiTxRx (command、4、data、2、1);

WriteEnable();
WriteUnprotect();

/*芯片擦除*/
COMMAN[0]= 0x60; //写入命令
spiTxRx (命令、1、数据、0、1);

_DELAY_CYCLES (160000);

命令[0]= 0x01;
命令[1]= 0x00;
spiTxRx (command、2、data、 0、1);

命令[0]= 0x31;
命令[1]= 0x00;
spiTxRx (command、2、data、 0、1);

命令[0]= 0x11;
命令[1]= 0x00;
spiTxRx (command、2、data、 0、1);

// command[0]= 0x05;
// spiTxRx (command、1、data、2、 1);

//闪存加电前延迟10ms
__DELAY_CYCLES (160000);
} 

2-写入:

void flashWrite (uint32_t address、uint8_t*数据、uint16_t size)
{
//清除写保护
uint8_t command[4];
uint8_t dummy = 0;

WriteEnable();
WriteUnprotect();

/*此部分写入数据。 第一个字符是 WRITE 命令*/
COMMAN[0]= 0x02; //写入命令
命令命令[1]=(无符号字符)(地址>> 16);
命令[2]=(无符号字符)(地址>> 8);
命令[3]=(无符号字符)(地址>> 0);

GPIO_setOutputLowOnPin (port_flash_CS、PIN_flash_CS);
__delay_cycles (8800);

spiTxRx (命令、4、&dummy、0、0); //发送写入命令
spiTxRx (data、size、&dummy、0、0); //写入数据

_DELAY_CYCLES (8800);
GPIO_setOutputHighOnPin (PORT_FLASH_CS、PIN_FLASH_CS);

while (FlashReadStatus ()= 0x03); //这确保读取操作完成

__delay_cycles (3200);
} 

3-读:

void flashRead (uint32_t address、uint8_t* data、uint16_t size)
{
uint8_t command[4];

/*本节回读数据。 第一个字符是读取命令*/
命令[0]= 0x03; //send 读取命令
命令[1]=(uint8_t)(地址>> 16);
命令[2]=(uint8_t)(地址>> 8);
命令[3]=(uint8_t)(地址>> 0);

spiTxRx (命令、4、数据、大小、 1); //发送读取命令和读取数据
} 

4-其他使用的功能:

静态空 spiInit (void)
{
UCA0CTLW0 = UCSWRST; //**将状态机复位**
UCA0CTLW0 |= UCMST + UCSYNC + UCCKPL + UCMSB;// 3引脚8位 SPI 主器件 MSB

UCA0CTLW0 |= UCSSEL_2; // SMCLK 特定于器件

的 UCA0BR0 = 4; // CLK / 1
UCA0BR1 = 0;
UCA0CTL1 &&~UCSWRST;

return;
}

静态空 spiTxRx (uint8_t * addr、uint32_t addlen、uint8_t *数据、uint32_t datalen、uint8_t csEn)
{
=0、
unsigned int char;i = 0;unsigned int

if (csEn = 1)
{
GPIO_setOutputLowOnPin (PORT_FLASH_CS、PIN_FLASH_CS);
_DELAY_CYCLES (8800);
}

while (addlen-i){
while (!(UCA0IFG & UCTXIFG));
UCA0IFG &=~UCRXIFG;
UCA0TXBUF=addr[i++];
while (!(UCA0IFG & UCRXIFG));
虚拟= UCA0RXBUF;
}

虚拟= 0;

while (datalen-j){
while (!(UCA0IFG & UCTXIFG));
UCA0TXBUF=虚拟;
while (!(UCA0IFG & UCRXIFG));//等待字节被接收
DATA[j++]=UCA0RXBUF;
}

if (csEn = 1)
{
_delay_cycles (8800);
GPIO_setOutputHighOnPin (PORT_FLASH_CS、PIN_FLASH_CS);
}

return;
}

static void GlobalBlockProtectionUnlock (void)
{
//发送 global block unlock 命令*/
uint8_t 命令= 0x98;
uint8_t dummy = 0;

spitxRx (&command、1、&dummy、0、 1);
}

静态空复位(void)
{
//发送 global 块解锁命令*/
uint8_t 命令= 0x66;
uint8_t dummy = 0;

spitxRx (&command、1、&dummy、0、 1);

命令= 0x99;
spitxRx (&command、1、&dummy、0、 1);
}

静态空 WriteUnprotect (void)
{
GlobalBlockProtectionUnlock();

__delay_cycles (160000);
}

静态空 WriteEnable (void)
{
//*发送写入启用命令*/
uint8_t 命令= 0x06;
uint8_t dummy = 0;

spitTxRx (&command、1、&dummy、&0、 1);
}

静态 uint8_t FlashReadStatus (void)
{
/*读取状态 reg-1 */
uint8_t 命令= 0x05;
uint8_t 数据= 0;

spitxRx (&command、1、&data、1、 1);

返回(uint8_t)数据;
}

静态空 configResetPin (void)
{
//发送写入启用命令*/
uint8_t 命令[2];
uint8_t dummy = 0;

命令[0]= 0x11;
命令[1]= 0x80;

spiTxRx (command、2、&dummy、 0、1);
} 

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

     当我在读取之前使用 flashWrite()两次时,它就能工作。

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

    我在 INIT 函数的末尾向闪存写入了1个字节、并且工作正常。 我不是第一次写的那样做! 不管怎样、它现在正在工作。

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

    根据数据表[Rev D、08122016]第8.3.23节、软件复位(tRST)需要30uS。 第9.3节说明硬件复位(tPUW)需要大于5ms。 第9.6节说明芯片擦除(Tce)需要5-25秒(!)。

    我看不到这些时序反映在您的代码中。 累积延迟可能会增加、以便第二次写入成功、但我怀疑在此期间忽略了一些请求。

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

    可能是的、我删除了芯片擦除、因为我不想在每次初始化时擦除它。

    但我还有另一个问题:闪存可写入一次、当我尝试再次写入时、它会复位为0、并且不会更新。 尽管我在尝试再次写入之前确实擦除了。

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

    被擦除的是0xFF、而不是0x00。 如果您继续写入同一个字节、它最终将变为0x00。 (他们似乎不会说您是否可以多次写入相同的字节、因此我假设您可以写入。)

    擦除之前是否启用了写入? 您是否等待擦除完成?

    您是否相当确定失败的是写入、而不是读取? 我通常做的第一件事是读取芯片 ID、以确保我正在正确读取。

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

    正是我错过的、我刚刚修复了它:根据数据表、块擦除的等待时间可高达1600ms、我正在执行一个更少的值。

    非常感谢。