历史上的今天
返回首页

历史上的今天

今天是:2024年12月05日(星期四)

正在发生

2019年12月05日 | STM8S存储器的读写操作

2019-12-05 来源:elecfans

/*

**********************************************************************************************************************************

* Name    : STM8S存储器的读写操作

* Author  : MingMing

* Release : 2014/1/2

* Update  : 2014/1/2

* E-mail  : clint.wang@foxmail.com

**********************************************************************************************************************************

*/

    在芯片中存储器一般分为两种:一种是EEPROM(数据存储器),另一种是FLASH ROM(程序存储器)。它们都是非易失性存储器,但是在特性上有一些差别。EEPROM读写最小单元为字节,在同一个地址重复写入数据时允许不进行擦除操作。FLASH ROM是按照扇区读写的,在同一个地址重复写入数据时需要擦除该地址才能再次写入。

    STM8S的芯片集成了EEPROM和FLASH ROM两种存储器,前者负责存储数据和Option Byte(选项字节),后者负责存储代码。

Stm8s_flash.h文件中代码如下所示:

/*

  ***************************************************************************

  * @file stm8s_flash.h

  * @brief This file is used to configure the Library.

  * @author clint.wang

  * @platform IAR For STM8S 1.31 + STM8S105C6

  * @date 12/27/2013

 ******************************************************************************

*/

#ifndef __STM8S_FLASH_H__

#define __STM8S_FLASH_H__

//

#include

#include "stm8s_type.h"

//

#define STM8S105

#ifdef STM8S105

  #define FLASH_PROG_PHYSICAL_ADDR_START   0x8000       /* 程序存储区首端地址 */

  #define FLASH_PROG_PHYSICAL_ADDR_END     0xFFFF       /* 程序存储区末端地址 */

  #define FLASH_PROG_BLOCKS_NUMBER         256          /* 程序存储区的块数 */

  #define FLASH_DATA_PHYSICAL_ADDR_START   0x4000       /* 数据存储区首端地址 */

  #define FLASH_DATA_PHYSICAL_ADDR_END     0x43FF       /* 数据存储区末端地址 */

  #define FLASH_DATA_BLOCKS_NUMBER         8            /* 数据存储区的块数 */

  #define OPTION_BYTE_PHYSICAL_ADDR_START  0x4800       /* 选项字节首端地址 */

  #define OPTION_BYTE_PHYSICAL_ADDR_END    0x487F       /* 选项字节末端地址 */

  #define OPTION_BYTE_NUMBER               15           /* 选项字节的长度 */

  #define FLASH_BLOCK_SIZE                 128          /* 每块存储所含的字节 */

#endif /* STM8S105 */

//

#define FLASH_RASS_KEY1     0x56                        /* FLASH解除写保护密钥 */

#define FLASH_RASS_KEY2     0xAE                        /* FLASH解除写保护密钥 */

#define FLASH_CLR_BYTE      0x00

#define FLASH_SET_BYTE      0xFF

//

typedef enum{

  FLASH_PROG = 0,

  FLASH_DATA = 1

}PLASH_TYPE;

//

#define ADDR_FLASH(addr)     *((INT8U*)addr)

#define ADDR_PROG(offset)    ADDR_FLASH(FLASH_PROG_PHYSICAL_ADDR_START + offset)  

#define ADDR_DATA(offset)    ADDR_FLASH(FLASH_DATA_PHYSICAL_ADDR_START + offset)

#define ADDR_OPTION(offset)  ADDR_FLASH(OPTION_BYTE_PHYSICAL_ADDR_START + offset)

//

/* Flash写操作的锁定和解除 */

void FLASH_WirteLock(PLASH_TYPE memoryType);

void FLASH_WirteUnlock(PLASH_TYPE memoryType);

//

/* Flash 程序存储器的读写和擦除 */

void FLASH_ProgWirteByte(INT16U addrOffset, INT8U iuData);

void FLASH_ProgEraseByte(INT16U addrOffset);

INT8U FLASH_ProgReadByte(INT16U addrOffset);

//

/* EEPROM 数据存储器的读写和擦除 */

void FLASH_DataWirteByte(INT16U addrOffset, INT8U iuData);

void FLASH_DataEraseByte(INT16U addrOffset);

INT8U FLASH_DataReadByte(INT16U addrOffset);

//

/* 选项字节的读写 */

void FLASH_OptionWirteByte(INT16U addrOffset, INT8U iuData);

INT8U FLASH_OptionReadByte(INT16U addrOffset);

//

/* Flash在halt状态下进入低功耗模式 */

void FLASH_LowPowerMode(void);

/* 擦除一块存储区 */

void FLASH_EraseBlock(INT8U BlockNum, PLASH_TYPE MemType);

//

#endif

Stm8s_flash.c文件中代码如下所示:


#include "stm8s_flash.h"

 

/*******************************************************************************

* 函数名:FLASH_WirteLock

* 描  述:Flash写保护使能

* 参  数:memoryType :写保护对象,程序存储器或者数据存储器

* 返回值:无

*******************************************************************************/

void FLASH_WirteLock(PLASH_TYPE memoryType)

{

  if (memoryType == FLASH_DATA)

     FLASH_IAPSR &= ~MASK_FLASH_IAPSR_DUL;

  else

     FLASH_IAPSR &= ~MASK_FLASH_IAPSR_PUL; 

}

/*******************************************************************************

* 函数名:FLASH_WirteUnlock

* 描  述:Flash写保护解锁

* 参  数:memoryType :解保护对象,程序存储器或者数据存储器

* 返回值:无

*******************************************************************************/

void FLASH_WirteUnlock(PLASH_TYPE memoryType)

{

  if(memoryType == FLASH_DATA)

  {

    do{

    FLASH_DUKR = FLASH_RASS_KEY2;                   /* 写入第二个密钥 */

    FLASH_DUKR = FLASH_RASS_KEY1;                   /* 写入第一个密钥 */ 

    }while(!(FLASH_IAPSR & MASK_FLASH_IAPSR_DUL));  /* 判断解锁是否成功 */  

  }

  else

  {

    do{

    FLASH_PUKR = FLASH_RASS_KEY1;                   /* 写入第一个密钥 */

    FLASH_PUKR = FLASH_RASS_KEY2;                   /* 写入第二个密钥 */ 

    }while(!(FLASH_IAPSR & MASK_FLASH_IAPSR_PUL));  /* 判断解锁是否成功 */    

  }

}

/*******************************************************************************

* 函数名:FLASH_ProgWirteByte

* 描  述:写一个字节到程序存储区

* 参  数:addrOffset :相对程序存储区首地址的偏移量,从0开始

          iuData :写入存储区的数据

* 返回值:无

*******************************************************************************/

void FLASH_ProgWirteByte(INT16U addrOffset, INT8U iuData)

{

  if(FLASH_IAPSR & MASK_FLASH_IAPSR_PUL)            /* 是否处于解锁状态 */

  {

    if(addrOffset < ((INT16U)FLASH_PROG_BLOCKS_NUMBER * 128))

    {

      ADDR_PROG(addrOffset) = iuData;

      while(!(FLASH_IAPSR & MASK_FLASH_IAPSR_EOP));

    }    

  }

}

/*******************************************************************************

* 函数名:FLASH_ProgEraseByte

* 描  述:擦除程序存储区指定地址的数据,写入0x00即可

* 参  数:addrOffset :相对程序存储区首地址的偏移量,从0开始

* 返回值:无

*******************************************************************************/

void FLASH_ProgEraseByte(INT16U addrOffset)

{

  

  FLASH_ProgWirteByte(addrOffset,FLASH_CLR_BYTE );//FLASH_CLR_BYTE  

}

/*******************************************************************************

* 函数名:FLASH_ProgReadByte

* 描  述:读取程序存储区指定地址的数据

* 参  数:addrOffset :相对程序存储区首地址的偏移量,从0开始

* 返回值:偏移地址存储的数据

*******************************************************************************/

INT8U FLASH_ProgReadByte(INT16U addrOffset)

{

  if(addrOffset < ((INT16U)FLASH_PROG_BLOCKS_NUMBER * FLASH_BLOCK_SIZE))  

    return (ADDR_PROG(addrOffset));

  return 0;

}

/*******************************************************************************

* 函数名:FLASH_DataWirteByte

* 描  述:写一个字节到数据存储区

* 参  数:addrOffset :相对数据存储区首地址的偏移量,从0开始

          iuData :写入存储区的数据

* 返回值:无

*******************************************************************************/

void FLASH_DataWirteByte(INT16U addrOffset, INT8U iuData)

{

  if(FLASH_IAPSR & MASK_FLASH_IAPSR_DUL)            /* 是否处于解锁状态 */

  {  

    if(addrOffset < (FLASH_DATA_BLOCKS_NUMBER*FLASH_BLOCK_SIZE))

    {

      ADDR_DATA(addrOffset) = iuData;

      while(!(FLASH_IAPSR & MASK_FLASH_IAPSR_EOP));

    }

  }

}

/*******************************************************************************

* 函数名:FLASH_DataEraseByte

* 描  述:擦除数据存储区指定地址的数据,写入0x00即可

* 参  数:addrOffset :相对程序存储区首地址的偏移量,从0开始

* 返回值:无

*******************************************************************************/

void FLASH_DataEraseByte(INT16U addrOffset)

{

  FLASH_DataWirteByte(addrOffset, FLASH_CLR_BYTE);

}

/*******************************************************************************

* 函数名:FLASH_DataReadByte

* 描  述:读取数据存储区指定地址的数据

* 参  数:addrOffset :相对数据存储区首地址的偏移量,从0开始

* 返回值:偏移地址存储的数据

*******************************************************************************/

INT8U FLASH_DataReadByte(INT16U addrOffset)

{

  if(addrOffset < (FLASH_DATA_BLOCKS_NUMBER*FLASH_BLOCK_SIZE))  

  {  return (ADDR_DATA(addrOffset));}

  return 0;

}

/*******************************************************************************

* 函数名:FLASH_OptionWirteByte

* 描  述:写一个字节到选项字节存储区

* 参  数:addrOffset :相对选项字节存储区首地址的偏移量,从0开始

          iuData :写入存储区的数据

* 返回值:无

*******************************************************************************/

void FLASH_OptionWirteByte(INT16U addrOffset, INT8U iuData)

{

  if(addrOffset < OPTION_BYTE_NUMBER)

  {

    FLASH_CR2  |= MASK_FLASH_CR2_OPT;          /* 解除OPT写保护 */ 

    FLASH_NCR2 &=~MASK_FLASH_CR2_OPT;          /* 解除OPT写保护 */

    

    ADDR_OPTION(addrOffset)   |= iuData;       /* 写入选项字节 */

    ADDR_OPTION(addrOffset+1) &=~iuData;       /* 写入选项字节 */

    

    while(!(FLASH_IAPSR & MASK_FLASH_IAPSR_EOP));

    

    FLASH_CR2  &=~MASK_FLASH_CR2_OPT;          /* 锁定OPT写保护 */ 

    FLASH_NCR2 |= MASK_FLASH_CR2_OPT;          /* 锁定OPT写保护 */    

  }

}

/*******************************************************************************

推荐阅读

史海拾趣

D3 Semiconductor公司的发展小趣事

在不断发展壮大的过程中,D3 Semiconductor逐渐将业务拓展至电机控制领域。公司开发的功率MOSFET产品,在电机控制应用和电源中表现出色,提供了更高的效率、集成和性能。这一领域的拓展不仅丰富了D3 Semiconductor的产品线,也进一步巩固了公司在电子行业中的地位。

FREESCALE (NXP)公司的发展小趣事

为了更好地拓展市场,D3 Semiconductor与全球知名的电子元件分销商贸泽电子(Mouser Electronics)建立了合作伙伴关系。根据协议,贸泽电子储备了D3 Semiconductor的完整650伏额定电压超结MOSFET产品线,并将其推向全球市场。这一合作不仅加强了D3 Semiconductor在全球市场的竞争力,也为公司带来了更多的商业机会。

Boyd Corporation公司的发展小趣事

随着公司规模的扩大和市场需求的增长,Boyd Corporation积极拓展全球业务版图。公司在多个国家和地区设立了生产基地和研发中心,以便更好地服务全球客户。通过全球化布局,Boyd Corporation不仅提升了生产效率,还加强了与全球客户的合作关系,进一步巩固了其在电子行业的领导地位。

Cadeka公司的发展小趣事

在电子行业的初期,Cadeka公司凭借一项革命性的半导体技术突破,迅速崭露头角。公司研发团队经过数年的努力,成功开发出一种新型的集成电路,大大提高了电子设备的性能和效率。这一技术突破迅速吸引了市场的关注,Cadeka公司的订单量激增,公司规模迅速扩大。

广州奥松公司的发展小趣事

奥松电子拥有一支近200名工程师组成的专职研发团队,并配备了超过7000㎡的研发实验室。实验室中配置了步进式投影光刻机、双面光刻机等先进设备,为公司的产品研发提供了有力的支持。这些设备不仅满足了产品研发、小试以及中试各个阶段的试验条件,也为公司的技术创新提供了坚实的基础。

FUJITSU(富士通)公司的发展小趣事

奥松电子自成立以来,一直致力于MEMS特色半导体芯片的研发与生产。公司凭借其国内领先的生产线技术,成功打造了一条高效、稳定的芯片生产线。这不仅提升了公司的生产效率,也为公司在电子行业中树立了良好的口碑。随着技术的不断进步,奥松电子的芯片性能也得到了显著提升,满足了市场对于高质量、高性能芯片的需求。

问答坊 | AI 解惑

  先进控制软件与DCS 的人机界面设计

从先进控制软件实际应用出发,阐述了如何解决先进控制软件和 DCS之间操作界面的设计问题。由于先进控制软件与DCS处在不同的运行环境,DCS面向过程,其控制功能在过程控制单元中实现;而先进控制软件是在基本控制的基础上实现生产过程的“卡边”或先进控 ...…

查看全部问答>

【晒电路】麦克风放大电路

前几天发过一个电路,有噪声.但没人给解答.后来又重新用TDA2822做了一个麦克风放大的,用在对讲电路中,效果很好,没有一点噪声. 因为开始自己寻找这方面的电路找了很久,但照图弄出来效果都不理想.所以就想把自己的贴出来,给需要的同行一点帮助. 本电 ...…

查看全部问答>

串口通讯时断时续

主板rs232连接程序,过几个小时程序就会挂起。和硬件有关吗?(对通讯不太懂,麻烦说详细点可能原因)谢谢!…

查看全部问答>

PB编译时发生错误

想用VT6656 USB网卡,但安装驱动后编译出错,错误如图: 网上搜索了一下,毫无头绪,请问各位有没有碰到过类似的问题啊? 我用的是ATMEL 9261的bsp。…

查看全部问答>

请问Windows Embedded CE 6.0 为什么只有评估版?

我在网上到处找Windows Embedded CE 6.0的正式版,但是没有。全都是评估版。请问各位哪里有正式版下载?谢谢。…

查看全部问答>

WinCE程序移植问题

我在原来的VC程序中用到了ltoa函数,把long型数据存在字符数组中,但是在WinCE中不支持,有什么其它的办法实现这个功能吗?请教各位了…

查看全部问答>

请教各位前辈,32位变量被中断骚扰??

uint16 moniliangruanjianjizhun(uint16 a,uint16 b) //模拟量软件基准计算 { unsigned long int c,d; if(a>=b) a=0xffff; else {   //_asm("sim"); //禁止中断后计算正常   c=a; d=c<<16; d-=c; //==d ...…

查看全部问答>

一个在linux2.6.26下关于加入devfs的奇怪问题。

本人在linux2.6.26下想加入devfs。在fs/Kconfig里更改了编译选项,即定义了CONFIG_DEVFS_FS,但是在编译内核的时候,出现错误: driver/built-in.o:In function \'at91_spidev_init\'; hid-debug.c:undefined reference&nb ...…

查看全部问答>

STM32中SPI数据传输问题

我在STM32外面接了一个ADC-TLC2543,用STM32的SPI传输ADC转换之后的结果。现在我用示波器观察STM32中MOSI(PA7)的输出,示波器中没有波形(片选信号和时钟信号正常),把MOSI接到ADC中,ADC的输出用示波器看有波形,但输入STM32中读出的数据很小, ...…

查看全部问答>

关于数模模数转换的问题?可能是我对单片机理解还不够深,请问谁能解答一下?

比如用单片机时我直接置高电平是外接发光二极管点亮,与我用数模转换后输出一个电压点亮发光二极管   请问这两个过程有区别么,为什么要加数模转换?…

查看全部问答>