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.

[参考译文] MSP430FR2433:如何向 FRAM 写入/读取长整型值

Guru**** 2535150 points
Other Parts Discussed in Thread: MSP430FR2433

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1175932/msp430fr2433-how-to-write-read-long-value-to-fram

器件型号:MSP430FR2433

各位专家:

目前、我正在使用 MSP430FR2433来制作 血氧仪等器件、我想检测中断并增加增量并将值存储到 FRAM 中、我已经完成了检测中断进入低功耗模式的操作、但我无法将数据写入/读取到 FRAM 中、  

我是 FRAM 低功耗微控制器的新手

我已遵循以下示例  

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/720929/ccs-msp430fr2433-how-to-write-to-and-read-from-fram

以上链接我无法理解为什么它们运行以下循环

对于(I = 0;I < 128;I++)
{
*FRAM_WRITE_PTR++=数据;
} 

以及为何将它们声明为 long 变量的位
数据+= 0x00010001; 

我的请求非常简单、我在触发中断时使 long 变量递增。
然后、我将该值存储到 FRAM 以避免中断计数器值、然后我读取 FRAM 以进行例程递增和存储
当控制器由于电源或其他故障而重新启动时、此方法将帮助我从旧值启动中断计数器。

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

    您好 Surya、

    这是查看您的应用的最佳示例、因此我将提供一些更多信息。 我不知道您对环路的哪个部分感到困惑、因此我将解释每一行内容。 首先是一些背景信息、MSP430是一款16位器件、这意味着一个字是2个字节、而一个长字是4个字节。 示例程序用于写入512字节的数据、等于128个长字。 循环是写入 FRAM 的过程。

    for(i = 0; i < 128; i++) // loops through 128 longs, which is 512 bytes
    {
        */ 
        *   assign the value of data to the current location of
        *   FRAM_write_ptr then increment the pointer
        *   because the ptr is a long, the increment will move
        *   the pointer over by the length of a long.
        /*
        *FRAM_write_ptr++ = data; /
    }
    
    //Increment data by hex 0x10001, or decimal 65,537. Completely arbitary choice.
    //data is a long variable so it is 4 bytes.
    data += 0x00010001; 

    此致、

    Luke

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

    您好 

    感谢您的快速响应和详细解释、

    好的、现在我已将变量更改为 int、因此我在这里解释了我的疑问、

     我有 类似的 int 值  

    #define FRAM_ADD_1 0x1800

    unsigned int *指针;

    unsigned int *FRAM_WRITE_ptr;

    FRAM_WRITE_PTR =(unsigned int *) FRAM_Add_1

    unsigned int data=2147483647、data1=0;


    SYSCFG0 = FRWPPW | PFWP;
    *FRAM_WRITE_PTR =数据;
    SYSCFG0 = FRWPPW | PFWP | DFWP;

    我使用它  

    指针=(unsigned int *) FRAM_Add_1;//要读取的地址
    Data1 =*指针;//要读取的数据

    在这里、我得到的值不正确、 请指导我将超过 long 的值写入 FRAM、以及如何检索 作为 long 的值。

    如果有任何指导可以将长值拆分为用于 MODBUS 通信的4字节(高字节和低字节),以将该4字节存储到 FRAM,并检索该4字节,并操纵变量转换为长,如下代码所示。

    以下代码只是假设未经测试。

    unsigned int data=2147483647、

    INT 测试[4];

    INT*指针;

    在这里、我将 int 值拆分为4字节  

    test[0](data&0xFF000000)>> 24.

    TEST[1]=(DATA&0x00FF0000)>> 16;

    test[2]=(data&0xFF00)>> 8;

    test[3]=(data&0xFF);

    将字节存储在单独的位置  

    SYSCFG0 = FRWPPW | PFWP;


    *FRAM_WRITE_PTR=测试[0];

    *FRAM_WRITE_PTR+=测试[1];

    *FRAM_WRITE_PTR+=测试[2];

    *FRAM_WRITE_PTR+=测试[3];


    SYSCFG0 = FRWPPW | PFWP | DFWP;

    在这里、我只读 存储的 address 中的每个字节

    Pointer=( int *) FRAM_Add_1;//要读取的地址

    Data1[0]=*指针;//要读取的数据

     Pointer=( int *) FRAM_Add_1_+;//要读取的地址

    Data1[1]=*指针;//要读取的数据

     Pointer=( int *) FRAM_Add_1_+;//要读取的地址

    Data1[2]=*指针;//要读取的数据

    Pointer=( int *) FRAM_Add_1_+;//要读取的地址

    Data1[3] =*指针;//要读取的数据

    在这里、我将该值作为十进制操作

    long data =((unsigned long) Data1[0])<< 24)|((unsigned long) Data1[1])<< 16)|((unsigned long) Data1[2])<< 8)|((unsigned long) Data1[3]);

    此致

    Surya

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

    您好 Surya、

    我建议使用调试器选项并在您的第一个预期写入中放置一个断点。 在调试过程中、您可以转到 View -> Memory Browser。 您可以在此处输入您希望写入数据的存储器地址。 如果您执行 View -> Expressions、则可以查看变量本身并查看其中的值及其存储器地址。  

    指针需要非常注意何时引用或取消引用某个内容、我希望这里会有一些不匹配。 因此、内存浏览器和表达式视图应该有助于解决不匹配问题。

    另一个注意事项是

    *FRAM_WRITE_PTR=测试[0];

    *FRAM_WRITE_PTR+=测试[1];

    *FRAM_WRITE_PTR+=测试[2];

    *FRAM_WRITE_PTR+=测试[3];

    将分配该值、然后进行增量计算。 前2行写入相同的位置。 如果您将第一行更改为 *FRAM_WRITE_PTR+= TEST[0],它将起作用。

    另一件事、即使我认为您的字节移位可行、但最好执行以下操作:

    TEST[0](DATA  >> 24)& 0xFF;

    TEST[1]=(数据>> 16) & 0xFF;

    TEST[2]=(数据>> 8)& 0xFF;

    TEST[3]=数据和0xFF;

    此致、

    Luke

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

    如果要读取和写入 long、请使用指向 long 的指针:

    unsigned long * FRAM_WRITE_ptr;

    这: pointer=( int *) FRAM_Add_1_+;//要读取的地址

    将不起作用。 事实上、编译器应该抱怨需要 lvalue。

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

    您好   

    感谢您的回答、现在我可以将我的十进制数写入 FRAM。

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

    您好   

    我对 MSP430fr2433有一个疑问、这里有512字节的信息存储器。我的疑问是、如何向该信息存储器写入多个值、如所示

    #define FRAM_ADD_1 0x1800

    unsigned long *指针;

    unsigned long  * FRAM_WRITE_ptr;

    FRAM_WRITE_PTR =(unsigned int *) FRAM_Add_1

    长数据1=1234567890、值1=0;

    long DATA2=9876543210、value2=0

    长 DATA3=6543278901、Value3=0;  

    我想将上述三个值存储/读取到 FRAM 中、我需要对以下代码进行哪些更改  

    SYSCFG0 = FRWPPW | PFWP;
    *FRAM_WRITE_PTR = Data1
    SYSCFG0 = FRWPPW | PFWP | DFWP;

    我使用它  

    指针=(unsigned long *) FRAM_Add_1;//要读取的地址
    Value1 =*指针;//要读取的数据

    此致

    Surya

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

    您好 Surya、

    我将在下面详细介绍每一行的目的

    SYSCFG0 = FRWPPW | PFWP; //Unlock the Data section, lock the rest of FRAM
    *FRAM_write_ptr++ = DATA1; //write data to the FRAM location specified by the pointer
    SYSCFG0 = FRWPPW | PFWP | DFWP; //Lock the FRAM to prevent unexpected writes

    因此、您可以通过几种方法来执行此操作、您可以进行硬编码、只需添加其他地址和数据即可  

    SYSCFG0 = FRWPPW | PFWP;
    *FRAM_write_ptr++ = DATA1;
    *FRAM_write_ptr++ = DATA2;
    *FRAM_write_ptr = DATA3;
    SYSCFG0 = FRWPPW | PFWP | DFWP;

    但我个人认为、最好创建一个新函数、然后传递您所需的值。

    void FRAMLongWrite (long* FRAM_write_ptr, long data)
    {
        SYSCFG0 = FRWPPW | PFWP;
        *FRAM_write_ptr++ = data;
        SYSCFG0 = FRWPPW | PFWP | DFWP;
    }

    希望这对您有所帮助!

    此致、

    Luke

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

    您好

    感谢您的快速回复、是的、以下代码必须能够用于写入数据  

    空 FRAMLongWrite (long* FRAM_WRITE_PTR、长数据)

    SYSCFG0 = FRWPPW | PFWP;
    *FRAM_WRITE_PTR++=数据;
    SYSCFG0 = FRWPPW | PFWP | DFWP;

    但是、如何从存储器中检索/读取这些数据????

    根据 的建议、吹扫代码显示错误、

    unsigned long * FRAM_WRITE_ptr;

    这:  pointer=( int *) FRAM_Add_1_+;//要读取的地址

    将不起作用。 实际上、编译器应该抱怨需要 lvalue。

    在这种情况下、我如何从 FRAM 读取数据、

    此致

    Surya

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

     您好 Surya、

    我继续将其放入我的 CCS 中、没有遇到任何问题。

    #define FRAM_ADD_1 (0x1800)
    unsigned char count = 0;
    unsigned long *pointer;
    unsigned long *FRAM_write_ptr;
    unsigned long data;
    
    #define FRAM_TEST_START 0x1800
    
    
    int main(void)
    {
        WDTCTL = WDTPW | WDTHOLD;               // Stop watchdog timer
    
        P1OUT &= ~BIT0;                         // Clear P1.0 output latch for a defined power-on state
        P1DIR |= BIT0;                          // Set P1.0 to output directionOUT
    
        PM5CTL0 &= ~LOCKLPM5;                   // Disable the GPIO power-on default high-impedance mode
                                                // to activate previously configured port settings
        data = 0x11111111;                      // Initialize dummy data
    
        FRAM_write_ptr = (unsigned long *)FRAM_ADD_1;
    
        volatile long DATA1=1234567890,VALUE1=0;
    
        volatile long DATA2=9876543210,VALUE2=0;
    
        volatile long DATA3=6543278901,VALUE3=0;
    
        SYSCFG0 &= ~DFWP;
        *FRAM_write_ptr = DATA1;
        SYSCFG0 |= DFWP;
    
        pointer = (unsigned long *)FRAM_ADD_1; // address to read
        VALUE1 = *pointer; // data to read

    我认为 Ivalue 只是投诉、因为 long 和 unsigned int 之间的类型不匹配。 下面是存储器视图、用于显示 Data1的值已正确写入列出的地址。

    此致、

    Luke

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

    否 lvalue 问题来自 POST 递增常量:

    Pointer=( int *) FRAM_Add_1_+;//要读取的地址

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

    没错、我误将 FRAM_ADD 读为 FRAM_WRITE_PTR。 原始分配应将 FRAM_WRITE_PTR 设置为 FRAM_ADD_1、然后可以使 FRAM_WRITE_PTR 递增、因为它是具有有效存储器地址的变量。  

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

    大家好、

    感谢您按照数据表所做的回复  

    01800h 至019FFh 是数据存储器、在这里、我想向不同的存储器地址写入3个不同的值、那么我可以按照如下方式定义3个不同的存储器地址

    FRAM_TEST_START 0x1800

    FRAM_TEST_MID 0x1809

    FRAM_TEST_final 0x1812

    它是否起作用??

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

    也许、但不像您所期望的那样。

    如果您尝试在0x1809处访问整数或 long、则不会将其存储在该处。 虽然某些 CPU 可以处理未对齐的访问、但 MSP430不是其中之一。 它将安静地忽略地址的 lsb 并使用0x1808。 如果该位置不用于其他任何用途、则没有问题。

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

    以扩展 David 的评论。

    我强烈建议在对地址进行硬编码时在 MSP430上执行偶数地址。  下面是一个有趣的视图、说明如果您将0x1809用于地址、将会发生什么情况。 下面是从示例代码 framwrite.c 中略微修改的代码

    #include <msp430.h>
    
    void FRAMWrite(void);
    
    unsigned char count = 0;
    unsigned long *FRAM_write_ptr;
    unsigned long data;
    volatile unsigned long test;
    #define FRAM_TEST_START 0x1809
    
    
    int main(void)
    {
        WDTCTL = WDTPW | WDTHOLD;               // Stop watchdog timer
    
        P1OUT &= ~BIT0;                         // Clear P1.0 output latch for a defined power-on state
        P1DIR |= BIT0;                          // Set P1.0 to output directionOUT
    
        PM5CTL0 &= ~LOCKLPM5;                   // Disable the GPIO power-on default high-impedance mode
                                                // to activate previously configured port settings
        data = 0x0;                      // Initialize dummy data
    
        while(1)
        {
            data += 0xAA;
            FRAM_write_ptr = (unsigned long *)FRAM_TEST_START;
            FRAMWrite();
            count++;
            if (count > 100)
            {
                P1OUT ^= 0x01;                  // Toggle LED to show 512K bytes
                count = 0;                      // ..have been written
                data = 0x00;
                FRAM_write_ptr = (unsigned long *)FRAM_TEST_START;
                test = *FRAM_write_ptr;
            }
        }
    }

    我在 TEST =* FRAM_WRITE_PTR 处放置了一个断点;然后单步执行、以便我可以看到测试变为什么值。 以下是 FRAM_WRITE_PTR 的值和 TEST 的值。

    这看起来是您想要的、但如果我们查看内存浏览器、我们可以看到实际发生了什么。

    该值实际上存储在0x1808。 因此、即使我们将地址和指针设置为0x1809、存储和读取的值也是在0x1808中。 这是因为 MSP430需要一个对齐的地址。 如果您的数据彼此相邻打包、这将导致问题、因为如果您不小心、您可以覆盖数据。

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

    大家好、

    感谢您的建议、我不在工作区、因此无法使用电路板检查代码。

    因此、请查看以下代码、如果我犯了任何错误、请指出这些错误。

    unsigned long *指针;
    unsigned long * FRAM_WRITE_ptr;

    #define  FRAM_TEST_START 0x1800

    #define  FRAM_TEST_MID 0x1808

    #define  FRAM_TEST_FINAL 0x1812


    int main (空)

    WDTCTL = WDTPW | WDTHOLD;//停止看门狗计时器

    P1OUT &=~BIT0;//清除 P1.0输出锁存器以实现定义的加电状态
    P1DIR |= BIT0;//将 P1.0设置为输出方向 OUT

    PM5CTL0 &=~LOCKLPM5;//禁用 GPIO 上电默认高阻抗模式
    //激活先前配置的端口设置

    FRAM_WRITE_PTR =(unsigned long *) FRAM_TEST_START

    volatile long Data1=1234567890、value1=0;

    volatile long DATA2=9876543210、value2=0;

    volatile long DATA3=6543278901、Value3=0;

    FRAM_WRITE_PTR =(unsigned long *) FRAM_TEST_START

    SYSCFG0 &=~DFWP;
    *FRAM_WRITE_PTR = Data1;
    SYSCFG0 |= DFWP;

    指针=(unsigned long *) FRAM_TEST_START;//要读取的地址
    Value1 =*指针;//要读取的数据

    P1OUT ^= BIT0;      //切换 LED

    FRAM_WRITE_PTR =(unsigned long *) FRAM_TEST_MID

    SYSCFG0 &=~DFWP;
    *FRAM_WRITE_PTR = DATA2;
    SYSCFG0 |= DFWP;

    指针=(无符号长整型*) FRAM_TEST_MID;//要读取的地址
    Value2 =* FRAM_WRITE_PTR;//要读取的数据

    P1OUT ^= BIT0;      //切换 LED

    FRAM_WRITE_PTR =(unsigned long *) FRAM_TEST_final

    SYSCFG0 &=~DFWP;
    *FRAM_WRITE_PTR = DATA3;
    SYSCFG0 |= DFWP;

    指针=(unsigned long *) FRAM_TEST_final;//要读取的地址
    Value3 =*指针;//要读取的数据

    P1OUT ^= BIT0;      //切换 LED

    此致

    Surya