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.

[参考译文] CCS/MSP430G2553:写入/读取信息存储器-正确的方式

Guru**** 2535140 points


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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/575471/ccs-msp430g2553-write-read-into-information-memory---the-right-way

部件号:MSP430G2553

工具/软件:Code Composer Studio

大家好,

关于信息存储器。存储器是字节可寻址的(我想是)

它有4个数据段,每个数据段有64个字节(总共256个字节)。

它以地址0x1000 (段D)开头。 因此,如果 我在此地址中输入一个字符(字节大小),则下一个可用的地址是0x1001

如果之后我输入一个短(2个字节),则下一个可用地址是 0x1003

如果我说的是正确的,那么为什么我下面的代码不能正常工作?

#include <msp430g2553.h>

#define end_of_flash 0x0FFFF

void WriteCharToFlash(Char Flashptr,char val);
void WriteLongToFlash(Long* Flashptr,Long val);
void ReadCharFromFlash(Char地址, CHAR* val);
void ReadLongFromFlash (Long*地址,Long* val);
void ClearAllFlash();

int main (void){
	WDTCTL = WDTPW + WDTHOLD;
	BCSCTL1 = CALC1_1MHz; //将DCO设置为1MHz
	DCOCTL = CALDCO_1MHz;
	FCTL2 = FWKEY + FSSEL0 + FN1;

	长val;
	char val2;
	ClearAllFlash();
	WriteCharToFlash((Char *) 0x0.1万, '2');
	ReadCharFromFlash((Char *) 0x0.1万,&val2);
	WriteLongToFlash((((Long*) 0x0.1001万, 123.4567万);
	ReadLongFromFlash((Long*) 0x0.1001万,&val);

	ReadLongFromFlash((Long*) 0x0.1001万,&val);
	ReadCharFromFlash((Char *) 0x0.1万, &val2);
	返回0;
}


void WriteLongToFlash(long* address, long val)
{
	long* flash_ptr;
	flash_ptr =地址;//初始化Flash指针
	FCTL1 = FWKEY + erase; //设置擦除位
	FCTL3 = FWKEY; //清除锁定位
	*FLASH_PTR =0;
	WHITE(FCTL3 & BUSY);
	FCTL1 = FWKEY + WRT;
	*FLASH_PTR = val;
	WHITE(FCTL3 & BUSY);
	FCTL1 = FWKEY; //清除WRT位
	FCTL3 = FWKEY + LOCK; //设置锁定位
}

void ReadLongFromFlash(long* address,long* val)
{
	long* flash_ptr;
	flash_ptr =地址;
	*val =*flash_ptr;
}

void WriteCharToFlash(Char地址,char val)
{
	char* flash_ptr;
	flash_ptr =地址;//初始化Flash Pointer
	FCTL1 = FWY + erase; //设置擦除位
	FCTL3 = FWKEY; //清除锁定位
	*FLASH_PTR = 0;
	FCTL1 = FWKEY + WRT;
	*FLASH_PTR = val;
	FCTL1 = FWKEY; //清除WRT位
	FCTL3 = FWKEY + LOCK; // set lock bit
}

void ReadCharFromFlash(Char* address, char* val)
{
	char* flash_ptr;
	flash_ptr =地址;
	*val =*flash_ptr;
}

void ClearAllFlash()
{
	char *flash_ptr; //段D指针
	flash_ptr =(char *) 0x1000; //初始化闪存段D指针
	FCTL1 = FWKEY + MERAS; //设置大量擦除位
	FCTL3 = FWKEY; //清除锁定位
	*FLASH_PTR =0; //虚拟写入以擦除闪存段D
	FCTL1 = FWKEY + WRT; //设置写入操作的WRT位
	FCTL1 = FWKEY; //清除WRT位
	FCTL3 = FWKEY + LOCK;
}

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

    写入闪存的数据应该对齐。 您可以将字节写入/读取到0x1000,0x1001,0x1002...字写入到0x1000,0x1002,0x1004...
    当然,您可以通过换档将您的功能更新为在0x1001之间正确写入/读取长距离,但看不到任何点/原因。
    写入功能将在写入前擦除所有块(0xFFFF值)。 功能ClearAllFlash将擦除所有主闪光灯,包括您的程序。

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

    感谢您的帮助,

    根据我的理解,如果我不想擦除我的程序(代码和数据),不要使用ClearAllFlash

    根据您的说法,我将数据放在正确的位置

    那么为什么我得到错误的值呢?

    在代码中,我将char 2写入0x0.1万并读取,它返回2  

    之后,我将长123.4567万写入0x0.1001万并读取,它返回123.4567万

    到目前为止,它应该是这样的。

    但是,如果我再次读取地址0x0.1万,我没有得到2,而是得到其他内容。

    我不明白为什么

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    MSP430不允许未对齐的内存访问。 当您尝试将大于8位的值写入0x1001地址时,会发生不可预测的情况。 (在您的情况下,CPU显然会访问0x1000。)

    请注意,您的所有写入函数都会擦除整个句段,因此它们还会擦除任何早期写入调用放入同一句段的任何值。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您的回复,

    在char和long的写入部分,我擦除擦除行并设置一个新的main,下面是代码的一部分:

    INT MAIN (void){
    	WDTCTL = WDTPW + WDTHOLD;
    	BCSCTL1 = CALC1_1MHz; //将DCO设置为1MHz
    	DCOCTL = CALDCO_1MHz;
    	FCTL2 = FWKEY + FSSEL0 + FN1;
    
    	长val;
    	char val2;
    	char val3;
    	ClearAllFlash();
    	WriteCharToFlash ((CHAR *) 0x0.104万,'2');
    	WriteLongToFlash ((Long *) 0x0.1039万,1234567);
    	WriteCharToFlash ((CHAR *) 0x0.1035万, '5');
    
    	ReadCharFromFlash((Char *) 0x0.104万,&val2);
    	ReadLongFromFlash((((Long*) 0x0.1039万,&val);
    	ReadCharFromFlash((Char *) 0x0.1035万,&val3);
    
    	返回0;
    }
    
    
    void WriteLongToFlash(long* address,long val)
    {
    	long* flash_ptr;
    	flash_ptr =地址;//初始化闪存指针
    	while (FCTL3 & busy);
    	FCTL1 = FWKEY + WRT;
    	*FLASH_PTR = while
    	(FCTL3 & Busy
    	);FWCTL1 = FWCTL3; //清除WRT位
    	FCTL3 = FWKEY + LOCK; //设置锁定位
    } 

    我从C段开始

    将Charon 0x0.104万置于以下地址: 0x0.104万
    将long置于0x0.1039万 将采用以下地址: 0x0.1039万, 0x0.1038万, 0x0.1037万, 0x0.1036万
    将CHAR置于0x0.1036万 上采用以下地址: 0x0.1035万

    但只有最后一个参数获得正确的值。

    所以我不知道我错过了什么

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您读的值是什么?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    十六进制 (12月)
    阀2 = 0xFF (255)
    Val = 0xFFFFFFFF (-1)
    阀3 = 0x35 (5)
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    其他值被擦除。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我不明白怎么做? 我是否写信给无法访问的地址?
    可能是因为ClearAllFlash? 但它是代码的开头
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    显示整个代码。 更改值以确保正在运行新代码。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我更改了值,但当我运行代码时,数据未写入或读取

    下面是完整的代码,感谢您的帮助

    #include <msp430g2553.h>
    
    void WriteCharToFlash(CharTmFlashptr,char val);
    void WriteLongToFlash(Long* Flashptr,Long val);
    void ReadCharFromFlash(CharTm地址, CHAR* val);
    void ReadLongFromFlash (Long*地址,Long* val);
    void ClearAllFlash();
    
    int main (void){
    	WDTCTL = WDTPW + WDTHOLD;
    	BCSCTL1 = CALC1_1MHz; //将DCO设置为1MHz
    	DCOCTL = CALDCO_1MHz;
    	FCTL2 = FWKEY + FSSEL_3 + FN1;
    
    	长val;
    	char val2;
    	char val3;
    	//ClearAllFlash();
    	WriteCharToFlash ((CHAR *) 0x0.104万,'4');
    	WriteLongToFlash ((Long *) 0x0.1039万,5.4321万);
    	WriteCharToFlash ((CHAR *) 0x0.1035万, '7');
    
    	ReadCharFromFlash((Char *) 0x0.104万,&val2);
    	ReadLongFromFlash((((Long*) 0x0.1039万,&val);
    	ReadCharFromFlash((Char *) 0x0.1035万,&val3);
    
    	返回0;
    }
    
    
    void WriteLongToFlash(long* address,long val)
    {
    	long* flash_ptr;
    	flash_ptr =地址;//初始化闪存指针
    	while (FCTL3 & busy);
    	FCTL1 = FWKEY + WRT;
    	*FLASH_PTR = while
    	(FCTL3 & Busy
    	);FWCTL1 = FWCTL3; //清除WRT位
    	FCTL3 = FWKEY + LOCK; // set lock bit
    }
    
    void ReadLongFromFlash(long* address, long* val)
    {
    	while (FCTL3 & busY);
    	long* flash_ptr;
    	flash_ptr =地址;
    	*val =*flash_ptr;
    }
    
    void WriteCharToFlash(Char* address, char val){
    
    	Initialize* flash_rt;
    	flash_ptr =地址;// fwctl=
    	待
    	
    	处理;*FWCTL1 & ptr =待处理;FWCTFLASH =待处理;FWCTFLT = FLASH =待处理;FWCTFLT = FLASH
    	While (FCTL3 & Busy);
    	FCTL1 = FWKEY; //清除WRT位
    	FCTL3 = FWKEY + LOCK; // set lock bit
    }
    
    void ReadCharFromFlash(Char* address, char* val){
    
    	while (FCTL3 & busy);
    	char* flash_ptr;
    	flash_ptr =地址;
    	*val =*flash_ptr;
    }
    
    void ClearAllFlash()
    {
    	char *flash_ptr; //段D指针
    	flash_ptr =(char *) 0x1000; //初始化闪存段D指针
    	FCTL1 = FWKEY + MERAS; //设置大量擦除位
    	FCTL3 = FWKEY; //清除锁定位
    	*FLASH_PTR =0; //虚拟写入以擦除闪存段D
    	FCTL1 = FWKEY + WRT; //设置写入操作的WRT位
    	FCTL1 = FWKEY; //清除WRT位
    	FCTL3 = FWKEY + LOCK;
    }
    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    擦除将所有位设置为1。 编程(写入)将某些位设置为0。 如果根本不清除,则不能将任何位更改为1。

    MERAS位表示“大量擦除”,并擦除所有主内存段。 您可能需要使用擦除位。

    (请参阅《用户指南》的7.3 章节2。)
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [报价用户="Joe Shoshana"]

    我更改了值,但当我运行代码时,数据未写入或读取

    下面是完整的代码,感谢您的帮助

    	//ClearAllFlash();
    	WriteCharToFlash ((CHAR *) 0x0.104万,'4');
    	WriteLongToFlash (((Long *) 0x0.1039万,5.4321万);
    	WriteCharToFlash ((char *) 0x0.1035万,'7');
    
    	ReadCharFromFlash ((char *) 0x0.104万,&val2);
    	ReadLongFromFlash ((Long *) 0x0.1039万, &val);
    	ReadCharFromFlash ((char *) 0x0.1035万,&val3);
     
    您不能将长值写入0x1039 (闪存或RAM,任何内容)。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我做了一些更改:

    1.在写入功能中,我忘记解锁FWKEY,所以我添加了它。

    2.我添加了擦除功能:

    void EraseSegment(Char* flash_PTR)
    {
    	FCTL3 = FWKEY; //清除锁定位
    	FCTL1 = FWKEY +擦除; //设置擦除位
    	*FLASH_PTR =0;
    	FCTL1 = FWKEY; //清除WRT位
    	FCTL3 = FWKEY + LOCK; //设置锁定位
    } 

    我从long更改为char并重新排列地址以使其对齐以下是主要内容:

    INT MAIN (void){
    	WDTCTL = WDTPW + WDTHOLD;
    	BCSCTL1 = CALC1_1MHz; //将DCO设置为1MHz
    	DCOCTL = CALDCO_1MHz;
    	FCTL2 = FWKEY + FSSEL_3 + FN1;
    
    	char val;
    	char val2;
    	char val3;
    	EraseSegment((Char *) 0x1040);
    	WriteCharToFlash((char *) 0x0.104万,'1');
    	WriteCharToFlash((char *) 0x0.1039万,'3');
    	WriteCharToFlash((char *) 0x0.1038万, '5');
    
    	ReadCharFromFlash((Char *) 0x0.104万,&val2);
    	ReadCharFromFlash((Char *) 0x0.1039万,&val);
    	ReadCharFromFlash((Char *) 0x0.1038万,&val3);
    
    	返回0;
    }
    

    但仍不保存val 3和val 5

    另一件事,您建议如何节省长期价值? 分为两个词?

    那么,短呢? 是否可以写入2字节(字)?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您正在擦除包含地址0x1040的信息存储器段,即0x1040到0x107F的段。 您正在将其他两个值写入未擦除的闪存。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [报价用户="Joe Shoshana"]

    另一件事,您建议如何节省长期价值? 分为两个词?

    那么,短呢? 是否可以写入2字节(字)?

    [/引述]
    如果(由于某些特殊原因)需要将单词/长字符写入未对齐的地址,则可以将其拆分为字节,并使用具有地址增量的多字节写入。
    标准方法是将单词写入0x1040,0x1042,0x1044...并将长字拆分为两个单词,然后使用双地址增量进行写入。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    … 并将长分为两个单词

    编译器会自动执行此操作。 只有当两次写入的顺序很重要时,才需要注意这一点。

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

    感谢您的帮助,

    在过去的一周里,我尝试写入主内存,成功写入主内存, 但是我总是需要一个2字节的地址来写入(无论字符还是短)。但是当我尝试在运行时更改它时,它不会更改任何内容。每次调用saveparameters函数时,我都会调用loadparameters来查看参数是否已保存。

    我尝试在信息存储器中执行相同操作,但在运行时仍无法更改。

    以下是信息存储器中仅有一个参数的代码(主存储器中的代码相同)

    void LoadParameters()
    {
    	Short M1,m2;
    	ReadFromFlash((car*)0x1040,(car*)&cnt_By_idx);// Count_by
    	IF( cnt_By_idx < 0|| cnt_by_idx > count_by_arr_LEN -1)
    		cnt_by_idx =3;cnt_by_whar*
    
    
    Write*( fvoid
    
    	
    
    
    
    
    	
    	
    	)符号=1040_flash; ftr_flash={+格列数) //初始化闪存指针
    	While (FCTL3 & Busy);
    	FCTL1 = FWKEY + WRT;
    	*FLASH_PTR = val;
    	While (FCTL3 & Busy);
    	FCTL1 = FWKEY; //清除WRT位
    	FCTL3 = FWKEY + LOCK; // set lock bit
    }
    
    void ReadFromFlash(Char* address, char* val)
    {
    	char* flash_ptr;
    	flash_ptr =地址;
    	while (FCTL3 & busy);
    	*val =*flash_ptr;
    } 

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

    在这里,您可以找到仅用于写入一个字节的源代码...

    https://www.embeddedrelated.com/showthread/msp430/2.0061万-1.php

    如果这不是您想要的,请搜索。 我相信Google会找到100个闪存写入工作示例。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    请检查您的内存地址:
    段D从0x1000变为0x103F
    Segmend C从0x1040变为0x 107F

    您正在擦除句段D (但在上面的代码中已删除注)

    可变val位于段C中(0x1040!)
    变量val2经过段D和段D之间的边界(0x1039..0x1042,1042,地址向上计数)
    D段中的变量val3是正确的(0x1035),因此这是您可以读取的唯一值。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    一般而言,使用硬编码地址不是很好。 我发现了一个更好的使徒来使用信息内存,因为链接程序知道信息内存位于何处。

    尝试执行以下操作(我假设您使用CCS):

     #pragma data_section (myValue,".infoD")

     int myValue;

    或者,如果您有多个值要存储:

    #pragma set_data_section(".infoD") 
    int myValue_1;
    长myValue_2;
    char myValue_3;
    //...不超过64个字节,允许每个数据类型
    #pragma set_data_section("")

    如果要写入这些值,可以按以下方式使用写函数:

    WriteCharToFlash (&myValue3,char_value_to_write) 

    您需要为每个数据类型使用不同的写入功能,
    但您不需要任何读取函数,只需使用该变量即可。

    我做得稍微短一点:

    void writeWord(void *Flash_ptr, int value)
    {
    	unsigned int *tmp_ptr;//要写入,只需更改此行,您必须为每个数据类型
    	FCTL3 = FWKEY;//清除锁定位
    	FCTL1 = FWKEY + WRTR;//为写入操作设置WRT位
    	PTR_PTR = Flash_PTR;//转换为void*至uint*
    	值 //将值写入闪存
    	FCTL1 = FWKEY;//清除WRT位
    	FCTL3 = FWKEY + LOCK;//设置锁定位
    } 

    如果要擦除此句段,只需选择其中一个变量:
    eraseSegment (&val_1); 

    void eraseSegment (void *指针)

       char *seg_pointer;

       SEG_POINTER =指针;
       FCTL1 = FWKEY + ERASE;//设置Erase bit
       FCTL3 = FWKEY;//清除锁定位
       *seg_pointer = 0;//虚拟写入以擦除闪存段
       FCTL1 = FWKEY;//清除位
       FCTL3 = FWKEY + LOCK;//设置锁定位
    }

    我用于此目的的信息来自
    www.ti.com/.../getliterature.tsp