> 文章列表 > STM8S208MB -> 寄存器方式实现对Flash的连续读写操作(IAR)

STM8S208MB -> 寄存器方式实现对Flash的连续读写操作(IAR)

STM8S208MB -> 寄存器方式实现对Flash的连续读写操作(IAR)

代码

File: STM8S208MB_Flash_Op.c

/*@file: STM8S208MB_Flash_Op.c@brief: 读写Flash@data: 2023-04-14@author: ArcherQAQ
*/#include "STM8S208MB_Flash_Op.h"
#include "stdio.h"u8 dataBuf[] = {0xFF, 0xFF}; // 写入Flash的数据
u8 Rec_Buf[100] = {0x00}; // 接收读取的数据, 设有100个元素/*
/*@brief: 读写Flash@data: 2023-04-14@author: ArcherQAQ
*/#include "STM8S208MB_Flash_Op.h"u8 dataBuf[] = {0xFF, 0xFF}; // 写入Flash的数据
u8 Rec_Buf[100] = {0x00}; // 接收读取的数据, 设有100个元素/*@brief      参考数据手册Flash的Memory access security system部分实现写入Flash功能@param      Addr: Flash中需要被写入的地址@param      Buf:  需要写入的数据buffer@return     None
*/
// High density的stm8s的Flash地址范围为0x00 8000 ~ 0x02 7FFF即20个bit所以这里用u32来存放地址
void Flash_WriteNByte(u32 Addr, u8 *Buf)
{u8 i = 0;// 解锁Main Program area,连续往FLASH_PUKR写入两个MASS keys(查看Flash的MASS部分)// 该两个keys会与硬件keys值比对// 如果相同则解锁FLASH_PUKR = 0x56;FLASH_PUKR = 0xAE;// 成功解锁后IAPSR寄存器的PUL(Program memory Unlocked Flag)会置位// 表示Flash解锁,允许写while (!(FLASH_IAPSR | (1 << 1))){};// 将Buf中的数据写入经过PointerAttr修饰的指针变量for (i = 0; i < sizeof(Buf); i++){*(PointerAttr u8*)Addr = Buf[i];Addr++;}// 完成写操作后重新给Flash上锁,防止Flash的内容corrupution// 通过软件清空FALSH_IAPSR的PUl即可将Flash重新上锁FLASH_IAPSR &= ~(1 << 1);
}/*@brief      参考数据手册Flash的Memory access security system部分实现读取Flash功能@param      Addr: Flash中需要被读取的地址@param      Len:  需要读的地址的长度@param      Rec_Buf: 接收返回字节的缓存数组@return     None
*/
void Flash_ReadNByte(u32 Addr, u16 Len, u8 *Rec_Buf)
{u8 i;for(i = 0; i < Len; i++){Rec_Buf[i] = *(PointerAttr u8*)Addr; // 将读到相应地址的字节返回给Rec_BufAddr++; // Addr地址+1}
}

File: STM8S208MB_Flash_Op.h

/*@file: STM8S208MB_Flash_Op.h@brief: 读写Flash@data: 2023-04-14@author: ArcherQAQ
*/
#ifndef __STM8S208MB_FLASH_OP_H__
#define __STM8S208MB_FLASH_OP_H__#include "iostm8s208mb.h"
#include "STM8S208MB_General.h" /*@note: 坑中坑,stm8s中普通指针变量的长度只有16bit但是Flash中的地址能最大能到地址为0x02 7FFF的内存单元这就意味着使用类型为u8*的指针变量无法指向64K(2^16)以后的地址单元然后通过在官方库函数查看 void  FLASH_ProgramByte (uint32_t Address, uint8_t Data) 函数,发现其通过 PointerAttr 标识来解锁Flash访问空间的限制可通过 printf("%d\\n", sizeof(PointerAttr u8*)); 验证,输出为3表示被PointerAttr修饰的u8*型指针变量长度为3个字节
*//*!< Used with memory Models for code higher than 64K */
#define FAR  __far
#define PointerAttr FAR#define FLASH_ADDR 0x27FF1 // 需要操作的Flash地址void Flash_WriteNByte(u32 Addr, u8 *Buf);
void Flash_ReadNByte(u32 Addr, u16 Len, u8 *Rec_Buf);#endif

File: STM8S208MB_General.h

/   @file: STM8S208MB_General.h*   @brief: STM8S208MB项目通用头文件*   @date: 2023-04-11*   @author: ArcherQAQ*/
#ifndef __STM8S208MB_General_H__
#define __STM8S208MB_General_H__
/*包含头文件*//*常用数据类型定义*/
/*!< Signed integer types  */
typedef   signed char     int8_t;
typedef   signed short    int16_t;
typedef   signed long     int32_t;
/*!< Unsigned integer types  */
typedef unsigned char     uint8_t;
typedef unsigned short    uint16_t;
typedef unsigned long     uint32_t;/*!< STM8 Standard Peripheral Library old types (maintained for legacy purpose) */
typedef int32_t  s32;
typedef int16_t s16;
typedef int8_t  s8;typedef uint32_t  u32;
typedef uint16_t u16;
typedef uint8_t  u8;
/通用函数声明*/
void CLK_Init(void);    // 时钟初始化函数
void delay(u16 cnt);    // 延迟函数声明#endif

File: mian.c

#include "iostm8s208mb.h"
#include "STM8S208MB_General.h"
#include "STM8S208MB_Flash_Op.h"int main( void )
{CLK_Init(); // 设置时钟为内部16MHz高速时钟delay(200);// 延时系统时钟稳定extern u8 dataBuf[];extern u8 Rec_Buf[];Flash_WriteNByte(FLASH_ADDR, dataBuf);Flash_ReadNByte(FLASH_ADDR, 2, Rec_Buf);while(1){   u8 i;for(i = 0; i < 2; i++){printf("第%d个读到的字节为:0x%.2x\\r\\n", i + 1, Rec_Buf[i]);printf("\\r\\n");printf("\\r\\n");}delay(100);}
}

功能验证

连续在0x27FF1、0x27FF2地址中写入0xFF
STM8S208MB -> 寄存器方式实现对Flash的连续读写操作(IAR)
连续读0x27FF1、0x27FF2两个地址
STM8S208MB -> 寄存器方式实现对Flash的连续读写操作(IAR)

需要注意的一些点捏:)

  • u8*类型的无符号指针变量,在IAR中长度为16个bit,即2个字节;然而在VSCode中测试为32个bit,即4个字节

    这说明数据类型的长度跟平台和编译器是有关联的,不能根据刻板印象来决定数据的类型,不确定数据类型的长度,则用sizeof()打印一下其具体占用多少个字节

  • 如果不用PointerAttr 来修饰u8* 类型指针变量的话,这就意味着,其指向的地址范围为:0x0000 ~ 0xFFFF,即64k的地址大小。开始写的时候没意识到这点,直接就用u8* 类型指针变量来存放了大于64k的地址。例子中读写的地址分别为0x27FF1和0x27FF2,这两个地址明显大于0xFFFF的,将其强行存进16位长度的u8*类型指针变量,显然会发生截断的情况

    如将0x27FF1放进16位长度的u8*类型指针变量,结果为0x7FF1,这显然不是我们需要访问的地址