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

news2024/12/29 9:05:29

代码

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_Buf
      Addr++; // 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
写操作
连续读0x27FF1、0x27FF2两个地址
读操作

需要注意的一些点捏:)

  • 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,这显然不是我们需要访问的地址

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/424584.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

天猫数据分析:2023年速食品(方便面)市场数据分析

我国的方便面市场是一个比较活跃的市场&#xff0c;其市场规模也比较庞大。近年来&#xff0c;随着中国经济的发展&#xff0c;消费者对方便面的需求量和要求也在不断变化&#xff0c;因此&#xff0c;我国方便面市场的规模和消费者的需求环境也正在不断改变。 根据鲸参谋电商数…

Excel技能之排名,小函数很强大

你还在熬夜加班搞Excel吗&#xff1f; 你还在用手指&#xff0c;指着电脑屏幕&#xff0c;一行一行核对数据吗&#xff1f; 你还在害怕被笑而不敢问同事吗&#xff1f; 赶紧来学Excel&#xff0c;收藏加关注&#xff0c;偷偷地进步&#xff01;日积月累&#xff0c;必成大器&am…

12-python内存地址

1.查看内存地址 a1 print(id(a)) # 24319294835042.数据类型 &#xff08;1&#xff09;不可变数据类型&#xff1a;数值、字符串、布尔值、元组 数据存储在计算机中的某个位置&#xff0c;不管赋值给谁&#xff0c;内存地址都相同 a"jack" b"jack" prin…

常见分布式锁3:Redis setNx

Redis实现分布式锁的核心便在于SETNX命令&#xff0c;它是SET if Not eXists的缩写&#xff0c;如果键不存在&#xff0c;则将键设置为给定值&#xff0c;在这种情况下&#xff0c;它等于SET&#xff1b;当键已存在时&#xff0c;不执行任何操作&#xff1b;成功时返回1&#x…

【python游戏】努力制造阳光,让植物有力量对抗僵尸吧~

前言 大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 晃着脑袋生产阳光的向日葵&#xff0c;突突突吐着子弹的豌豆射手&#xff01;​ 行动迟缓种类丰富的僵尸…… 印象最深的是“僵尸吃掉了你的脑子&#xff01;” 还有疯狂的戴夫&#xff0c;无一不唤醒着我们的童年记忆​ 山…

Hive 拉链表的两种实现方式

目录 1.什么是拉链表 2.拉链表的产生背景 2.1数据同步 2.1.1全量同步 2.1.2增量同步 2.2增量同步和拉链表 3.拉链表的实现方式 3.1数据准备 3.2思路1 3.3思路2 1.什么是拉链表 我们首先要知道&#xff0c;拉链表是一个逻辑上的概念。 拉链表记录的是增量数据&#x…

(链表专题) 328. 奇偶链表 ——【Leetcode每日一题】

328. 奇偶链表 给定单链表的头节点 head &#xff0c;将所有索引为奇数的节点和索引为偶数的节点分别组合在一起&#xff0c;然后返回重新排序的列表。 第一个 节点的索引被认为是 奇数 &#xff0c; 第二个 节点的索引为 偶数 &#xff0c;以此类推。 请注意&#xff0c;偶…

在 RISC-V Linux 内核中添加模块

在 RISC-V Linux 内核中添加模块 flyfish 本例以添加helloworld字符设备为例 一 源码配置 1 源码 源码文件helloworld.c拷贝到 drivers/char 目录中 源码主要是输出Hello world init 2 Kconfig 打开drivers/char 目录下的Kconfig文件 在endmenu之前加上 config HELLO…

统信UOS专业版系统安装教程 - 全盘安装UOS系统

全文导读&#xff1a;本文介绍了UOS系统安装&#xff08;全盘安装&#xff09;的过程&#xff0c;如果没有特殊要求&#xff0c;推荐安装UOS系统都采用全盘安装。 准备环境 制作好统信UOS专业版启动U盘 一台CPU频率≥2GHz、内存≥4GB、硬盘≥64GB的电脑 安装步骤 一、制作…

MySQL复合查询

文章目录一、多表查询二、自连接三、子查询1.单行子查询2.多行子查询3.多列子查询4.在 from 子句中使用子查询5.合并查询一、多表查询 在实际开发中&#xff0c;数据往往来自不同的表&#xff0c;所以需要多表查询。 对多张表做笛卡尔积&#xff0c;实际上就是多张表的所有记…

js 特殊对象 - 数组

1.概述 数组也是对象的一种&#xff0c;数组是一种用于表达有顺序关系的值的集合的语言结构&#xff0c;也就是同类数据元素的有序集合。 数组的存储性能比普通对象要好&#xff0c;在开发中我们经常使用数组来存储一些数据。但是在JavaScript中是支持数组可以是不同的元素&…

使用CH9102F平替ESP32系列下载电路中的CP2102

乐鑫官方ESP32开发板的外围电路主要包含&#xff1a; USB-UART电路自动下载电路RC延迟电路重启按键下载按键电源降压芯片LDO下面简单介绍一下这些电路的功能。 ESP32的USB-UART电路部分&#xff0c;核心芯片CP2102。其作用是将USB接口传入的D、D-信号转换为串口信号RX、TX以及…

如何与 MACOM 建立 EDI 连接?

项目背景 MACOM提供高性能射频&#xff0c;微波和毫米波器件&#xff0c;其产品广泛应用于通信&#xff0c;航空航天&#xff0c;国防和工业市场。近年来MACOM在中国地区的业务一直高速增长。 为了提高其供应链的效率和准确性&#xff0c;MACOM使用EDI&#xff08;电子数据交…

数据挖掘(4.1)--分类和预测

目录 前言 一、分类和预测 分类 预测 二、关于分类和预测的问题 准备分类和预测的数据 评价分类和预测方法 混淆矩阵 评估准确率 参考资料 前言 分类&#xff1a;离散型、分类新数据 预测&#xff1a;连续型、预测未知值 描述属性&#xff1a;连续、离散 类别属性&am…

扬尘天气在家如何防护措施 家里空气中的沙尘怎么处理

扬尘天气在家如何防护措施 家里空气中的沙尘怎么处理 大风起兮尘飞扬 风越强来&#xff0c;天越黄…… 随沙尘而来的还有呼呼呼的大风 刚刚过了一周 “阳光正好&#xff0c;微风不燥”的日子 还没好好感受春花绽放的温柔 沙尘天气就又杀回塔大了 除了吃土 “防护指南…

展心展力 metaapp:基于 DeepRec 的稀疏模型训练实践

作者 metaapp-推荐广告研发部&#xff1a;臧若舟&#xff0c;朱越&#xff0c;司灵通 1 背景 推荐场景大模型在国内的使用很早&#xff0c;早在 10 年前甚至更早&#xff0c;百度已经用上了自研的大规模分布式的 parameter server 系统结合上游自研的 worker 来实现 TB 级别…

【LeetCode】剑指 Offer(27)

目录 题目&#xff1a;剑指 Offer 53 - I. 在排序数组中查找数字 I - 力扣&#xff08;Leetcode&#xff09; 题目的接口&#xff1a; 解题思路&#xff1a; 代码&#xff1a; 过啦&#xff01;&#xff01;&#xff01; 写在最后&#xff1a; 题目&#xff1a;剑指 Offe…

【机器学习 P19】【实战 P1】 MINST 手写数字识别

MINST 手写数字识别引入数据模型训练模型创建程序模型编译程序模型训练程序模型预测程序完整代码引入数据 MINST数据集是一个经典的手写数字识别数据集&#xff0c;由Yann LeCun等人创建。它包含了来自真实手写数字图片的70000个灰度图像&#xff0c;这些图像是由250个不同的人…

三行Python代码,让数据处理速度提高2到6倍

本文可以教你仅使用 3 行代码&#xff0c;大大加快数据预处理的速度。 Python 是机器学习领域内的首选编程语言&#xff0c;它易于使用&#xff0c;也有很多出色的库来帮助你更快处理数据。但当我们面临大量数据时&#xff0c;一些问题就会显现…… 在默认情况下&#xff0c;…

OpenShift 4 - 使用 virtctl 远程访问 OpenShift Virtualization 的虚拟机

《OpenShift / RHEL / DevSecOps 汇总目录》 说明&#xff1a;本文已经在支持 OpenShift 4.12 的 OpenShift 环境中验证 在《OpenShift 4 - 用 OpenShift Virtualization 运行容器化虚拟机 &#xff08;视频&#xff09;》一文中使用了 OpenShift 控制台直接访问运行在 OpenSh…