历史上的今天
今天是: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写保护 */ } } /*******************************************************************************
史海拾趣
|
从先进控制软件实际应用出发,阐述了如何解决先进控制软件和 DCS之间操作界面的设计问题。由于先进控制软件与DCS处在不同的运行环境,DCS面向过程,其控制功能在过程控制单元中实现;而先进控制软件是在基本控制的基础上实现生产过程的“卡边”或先进控 ...… 查看全部问答> |
|
前几天发过一个电路,有噪声.但没人给解答.后来又重新用TDA2822做了一个麦克风放大的,用在对讲电路中,效果很好,没有一点噪声. 因为开始自己寻找这方面的电路找了很久,但照图弄出来效果都不理想.所以就想把自己的贴出来,给需要的同行一点帮助. 本电 ...… 查看全部问答> |
|
请问Windows Embedded CE 6.0 为什么只有评估版? 我在网上到处找Windows Embedded CE 6.0的正式版,但是没有。全都是评估版。请问各位哪里有正式版下载?谢谢。… 查看全部问答> |
|
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外面接了一个ADC-TLC2543,用STM32的SPI传输ADC转换之后的结果。现在我用示波器观察STM32中MOSI(PA7)的输出,示波器中没有波形(片选信号和时钟信号正常),把MOSI接到ADC中,ADC的输出用示波器看有波形,但输入STM32中读出的数据很小, ...… 查看全部问答> |
|
关于数模模数转换的问题?可能是我对单片机理解还不够深,请问谁能解答一下? 比如用单片机时我直接置高电平是外接发光二极管点亮,与我用数模转换后输出一个电压点亮发光二极管 请问这两个过程有区别么,为什么要加数模转换?… 查看全部问答> |




