OTA升级-1-通过链表对单片机FLASH进行读写操作
一、flash读取到链表操作过程:
1、FLASH 读取方法
*(uint32_t *)0x8000000;//读一个字
*(uint8_t *)0x8000000;//读一个字节;
*(uint16_t *)0x8000000;//读半字;
举例:
uint8_t data;
data = *(uint8_t *)0x8000000;//就是读取FLASH中地址0x8000000处的数据
2、读出来完整的一个字:
uint32_t READ_Flash(uint32_t faddr)
{return *(uint32_t*)faddr;
}printf( " %02X ", READ_Flash ( 0x08000000 ) ); //按照16进制的形式显示
3、把flash里面的数据读取到数组当中:
uint32_t group_an[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};/** 把20个字的数据从FLASH里面的数据读取到数组当中*/
void READ_Flash_group(uint32_t *group)
{unsigned int i = 0;for ( i=0; i<20; i++){group[i] = READ_Flash ( 0x08000000 + 4 * i );}
}//每次读取20个字的Flash并存放到数组当中:
//把数组里面的数据读取出来:
for( i=0; i<20; i++)
{printf( "%d \r\n ", group_an[i]);
}READ_Flash_group(group_an);for( i=0; i<20; i++)
{printf( "%d ", i);printf( "%02X \r\n", group_an[i] ); //以16进制的方式显示数据
}
成片的读取FLASH可以使用链表的方法,制作一个链表,每个节点可以保存有20个字的数据。节点里保存数据的结构是数组,FLASH_Data[20]。
4、建立一个简单的链表的节点结构体:
//定义一个结构体
struct List
{int data;struct List *node; //定义结构体指针,用来指向下一个节点
};struct List Head; //定义链表的头,用来引出链表
5、首先测试,建立只有三个节点的简单的单向链表:
Head.node = NULL; //对链表头内的指针定义,定义指向空Head.data = 1; //对头节点内的数据赋值printf("nomber 1: %d \r\n", Head.data); //检测struct List *a_node_1 = (struct List*)malloc(sizeof(Head)); //申请一块内存,新建立一个节点,并把这个节点指向这块新开辟的内存Head.node = a_node_1; //把头节点和下一个节点连接a_node_1->data = 2; //对下一个节点进行赋值printf("nomber 2: %d \r\n", a_node_1->data); //检测struct List *a_node_2 = (struct List*)malloc(sizeof(Head)); //申请一块内存,新建立一个节点,并把这个节点指向这块新开辟的内存a_node_1->node = a_node_2; //把上一个节点和这个新建立的节点连接a_node_2->data = 3; //为新节点赋值a_node_2-> node = NULL; //为新节点的指针复制printf("nomber 3: %d \r\n", a_node_2->data); //检测test = &Head; //建立一个用来循环的测试节点for(i = 0; i<10; i++) //通过循环,遍历链表{printf("%d\r\n", test->data); //显示节点内的数据test = test->node; //更新测试节点指向的节点,指向下一个节点if(test->node == NULL) //检查下一个节点是不是一个空的末尾的节点{printf("%d\r\n", test->data); //显示这个节点内的数据break; //链表结尾推出}}
经过上面简单的测试以后可以直接使用函数来对链表的操作进行封装。
6、通过输入头指针和循环函数来建立一条简单的链表:
/**建立新的链表节点,并对新的节点赋值。* 输入变量是链表的头指针,和要存放的目标变量值* 需要通过循环增加链表的节点以及赋值* */
unsigned char Linked_list_node_flag = 1; //为了方便操作指针的头,对循环的第一次操作进行限制void Establish_linked_list_node(struct List *Old_node ,int value)
{static struct List *_node; //建立一个用来遍历链表的节点if(Linked_list_node_flag == 1) //一开始建立链表的头{Old_node->data = value; //对链表的头进行赋值Old_node->node = NULL; //对链表的指针进行赋值清空_node = Old_node; //储存链表的头地址Linked_list_node_flag = 0; //改变循环标志}else //第二次循环在此处开始执行{struct List *New_node = (struct List*)malloc(sizeof(Head)); //开辟一块新的内存New_node->node = NULL; //新的链表的地址赋值New_node->data = value; //新的链表的节点赋值_node->node = New_node; //循环至下一个节点_node = New_node; //移动链表操作的节点}
}
测试上面的函数:
//定义一个结构体
struct List
{int data;struct List *node; //定义结构体指针,用来指向下一个节点
};struct List Head; //定义链表的头,用来引出链表struct List *test;Head.node = NULL;for(i=0; i<10; i++)
{Establish_linked_list_node( &Head, i);
}test = &Head; //建立一个用来循环的测试节点for(i = 0; i<1000; i++) //通过循环,遍历链表
{printf("%d\r\n", test->data); //显示节点内的数据test = test->node; //更新测试节点指向的节点,指向下一个节点if(test->node == NULL) //检查下一个节点是不是一个空的末尾的节点{printf("%d\r\n", test->data); //显示这个节点内的数据break; //链表结尾推出}
}Linked_list_node_flag = 1;
7、对前面的函数进行总结整合,成为一套完整的可以把Flash里面的数据读取到链表内的函数
建立结构体和相关定义
//定义一个结构体
struct List
{int Serial_number;uint32_t Flash_data[20];struct List *node; //定义结构体指针,用来指向下一个节点
};struct List Head; //定义链表的头,用来引出链表uint32_t group_an[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};struct List *test;
存放Flash数据的数组操作函数:
/** 把20个字的数据从FLASH里面的数据读取到数组当中*/
uint32_t READ_Flash_group(uint32_t *group, uint32_t Flash_address)
{unsigned int i = 0;uint32_t Next_Flash_address = 0;for ( i=0; i<20; i++){Next_Flash_address = Flash_address + 4 * i ; //计算得到下一个地址group[i] = READ_Flash ( Next_Flash_address ); //读取地址上面的数据保存在数组内}return Next_Flash_address + 4; //返回值为下一个地址
}
通过函数读取Flash成为一条链表:
/**建立新的链表节点,并对新的节点赋值。* 输入变量是链表的头指针,和要存放的目标变量值* 需要通过循环增加链表的节点以及赋值* */
unsigned char Linked_list_node_flag = 1; //为了方便操作指针的头,对循环的第一次操作进行限制long int Linked_list_node_Flash_address;void Establish_linked_list_node(struct List *Old_node ,int value, uint8_t Flash_address)
{static struct List *_node; //建立一个用来遍历链表的节点if(Linked_list_node_flag == 1) //一开始建立链表的头{Linked_list_node_Flash_address = READ_Flash_group(Old_node->Flash_data, Flash_address); //读取FLASH内的数据Old_node->Serial_number = value; //对链表的头进行赋值Old_node->node = NULL; //对链表的指针进行赋值清空_node = Old_node; //储存链表的头地址Linked_list_node_flag = 0; //改变循环标志}else //第二次循环在此处开始执行{struct List *New_node = (struct List*)malloc(sizeof(Head)); //开辟一块新的内存Linked_list_node_Flash_address = READ_Flash_group(New_node->Flash_data, Linked_list_node_Flash_address); //读取FLASH内的数据New_node->node = NULL; //新的链表的地址赋值New_node->Serial_number = value; //新的链表的节点赋值_node->node = New_node; //循环至下一个节点_node = New_node; //移动链表操作的节点}
}
引用上面的函数的具体操作过程:
Head.node = NULL;for(i=0; i<10; i++){Establish_linked_list_node( &Head, i, 0x08000000);}test = &Head; //建立一个用来循环的测试节点for(j = 0; j<1000; j++) //通过循环,遍历链表{printf("\r\n %d\r\n\r\n", test->Serial_number); //显示节点内的数据for( i=0; i<20; i++){printf( "%02X ", test->Flash_data[i]);if(i == 3 || i == 7 || i == 11 || i ==15 || i == 19){printf("\r\n");}}test = test->node; //更新测试节点指向的节点,指向下一个节点if(test->node == NULL) //检查下一个节点是不是一个空的末尾的节点{printf("\r\n %d\r\n\r\n", test->Serial_number); //显示这个节点内的数据for( i=0; i<20; i++){printf( "%02X ", test->Flash_data[i]);if(i == 3 || i == 7 || i == 11 || i ==15 || i == 19){printf("\r\n");}}break; //链表结尾推出}}Linked_list_node_flag = 1;Linked_list_node_Flash_address = 0;
最后的结果:
二、Flash链表写入过程:
1、基础的Flash写入一个数据:
基本的,先把一个数据写到Flash上面:
printf( "%02X \r\n\r\n", READ_Flash ( 0x08004000 ) );HAL_FLASH_Unlock(); //对flash解锁HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x08004000, 1); //在地址为08004000的地址上写入1;HAL_FLASH_Lock(); //锁住flashprintf( "%d \r\n\r\n", READ_Flash ( 0x08004000 ) );
2、使用数组向flash内写入数据
编辑了如下的函数,使用的是HAL库的Flash操作函数
/** 把20个字的数据写入到Flash当中* */
uint32_t WRITE_Flash_group(uint32_t *group, uint32_t Flash_address)
{unsigned int i = 0;uint32_t Next_Flash_address = 0;HAL_FLASH_Unlock(); //对flash解锁for ( i=0; i<20; i++){Next_Flash_address = Flash_address + 4 * i ; //计算得到下一个地址HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, Next_Flash_address, group[i]); //在目标地址上面写入数据;}HAL_FLASH_Lock(); //锁住flashreturn Next_Flash_address + 4; //返回值为下一个地址
}
调用函数的具体操作:
WRITE_Flash_group(group_an, 0x08004000);READ_Flash_group(group_bn, 0x08004000);for( i=0; i<20; i++){printf( "%d \r\n ", group_bn[i]);}
3、按照链表写入
最终可以实现出通过链表读取FLASH内的内容,再把读取出来的内容重新以链表的形式写入到指定的位置。
/********测把FLASH内的数据写入到链表中**********/Head.node = NULL;for(i=0; i<10; i++) //建立了一条十个节点的链表,读取从指定地址开始的20*10个字的数据{Establish_linked_list_node( &Head, i, 0x08000000);}Linked_list_node_flag = 1;Linked_list_node_Flash_address = 0;test = &Head; //建立一个用来循环的测试节点for(j = 0; j<1000; j++) //通过循环,遍历链表{printf("\r\n %d\r\n\r\n", test->Serial_number); //显示节点内的数据for( i=0; i<20; i++){printf( "%02X ", test->Flash_data[i]);if(i == 3 || i == 7 || i == 11 || i ==15 || i == 19){printf("\r\n");}}test = test->node; //更新测试节点指向的节点,指向下一个节点if(test->node == NULL) //检查下一个节点是不是一个空的末尾的节点{printf("\r\n %d\r\n\r\n", test->Serial_number); //显示这个节点内的数据for( i=0; i<20; i++){printf( "%02X ", test->Flash_data[i]);if(i == 3 || i == 7 || i == 11 || i ==15 || i == 19){printf("\r\n");}}break; //链表结尾推出}}/********测试把链表里面的数据按照顺序写入到FLASH中**********/test = &Head; //建立一个用来循环的测试节点next_address = 0x08005000; //开始写入的地址while(1){next_address = WRITE_Flash_group(test->Flash_data, next_address); //把数据写入到此地址上及此地址之后的共20个连续地址test = test->node; //更新测试节点指向的节点,指向下一个节点if(test->node == NULL) //检查下一个节点是不是一个空的末尾的节点{next_address = WRITE_Flash_group(test->Flash_data, next_address); //把数据写入到此地址上及此地址之后的共20个连续地址break; //链表结尾推出}}printf("\r\n");printf("\r\n");printf("\r\n");printf("\r\n");printf("\r\n");printf("\r\n");printf("\r\n");/*********把从链表写入到FLASH内的数据读取出来*********/test = &Head; //建立一个用来循环的测试节点for(i=0; i<10; i++) //建立了一条十个节点的链表,读取从指定地址开始的20*10个字的数据{Establish_linked_list_node( &Head, i, 0x08005000);}Linked_list_node_flag = 1;Linked_list_node_Flash_address = 0;for(j = 0; j<1000; j++) //通过循环,遍历链表{printf("\r\n %d\r\n\r\n", test->Serial_number); //显示节点内的数据for( i=0; i<20; i++){printf( "%02X ", test->Flash_data[i]);if(i == 3 || i == 7 || i == 11 || i ==15 || i == 19){printf("\r\n");}}test = test->node; //更新测试节点指向的节点,指向下一个节点if(test->node == NULL) //检查下一个节点是不是一个空的末尾的节点{printf("\r\n %d\r\n\r\n", test->Serial_number); //显示这个节点内的数据for( i=0; i<20; i++){printf( "%02X ", test->Flash_data[i]);if(i == 3 || i == 7 || i == 11 || i ==15 || i == 19){printf("\r\n");}}break; //链表结尾推出}}printf("be in while(1)\r\n");
OTA升级-1-通过链表对单片机FLASH进行读写操作相关推荐
- 华大单片机HC32L136X单片机flash数据读写操作使用
此款单片机是由有64K的字节flash,一共有128页,一页有512字节,以下是容量划分: 这里使用的是字节位宽的数据读写操作进行演示,其他2种方式大同小异,需要用到自己去研究,首先需要添加对应的fl ...
- 单片机flash通用读写库:TZFlash
单片机flash通用读写库:TZFlash 本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明. 说明 本文发布单片机flash通用读写库TZFlash,有两 ...
- NAND FLASH的读写操作(硬件原理图分析)
转载:NAND FLASH的读操作及原理 硬件原理 上面是我使用的NAND FLASH的硬件原理图,面对这些引脚,很难明白他们是什么含义,下面直接引用韦东山老师的课程中的提问: NAND FLASH是 ...
- QCC300x笔记(5) -- 外部Flash的读写操作
哈喽大家好,这是该系列博文的第五篇~ 篇~ <<[系列博文索引]快速通道 > 1. QCC300X 外部Flash的读写 QCC300x是使用外部Flash片子 ...
- STM32 进阶教程 13 – FLASH的读写操作
前言 在嵌入式应用开发中,经常会遇到掉电后还要保存的信息,这些信息通常只能保存在外部的一些存储芯片中,如外部flash,外部EEPROM, 其实这些信息同样可以保存在STM32自带的内部flash中, ...
- STM32 FLASH 简单读写操作【有代码】
[举报再看养成习惯,噢 不对,点赞再看 养成习惯.感谢支持] STM32的Flash操作分为读写:读写. 一.读操作 读取比较简单,直接指针解引用地址就可以读取.注意一下读取的单位即可 /****** ...
- 安信可 BL602 平台模组 OTA 升级教程
概述 本文以安信可 Ai-WB2-12F 为例介绍安信可模组从生成 OTA 固件到通过 WiFi 升级固件的全过程. 固件增加 OTA 功能 要开启 OTA,固件必须要包含以下功能: 蓝牙或命令行配网 ...
- STM32F10X SPI操作flash MX25L64读写数据
STM32F10X SPI操作flash MX25L64读写数据 前一段时间在弄SPI,之前没接触过嵌入式外围应用,就是单片机也只接触过串口通信,且也是在学校的时候了.从离开手机硬件测试岗位后,自己一 ...
- STM32F10X SPI操作flash MX25L64读写数据(转)
源:STM32F10X SPI操作flash MX25L64读写数据 前一段时间在弄SPI,之前没接触过嵌入式外围应用,就是单片机也只接触过串口通信,且也是在学校的时候了.从离开手机硬件测试岗位后,自 ...
最新文章
- profiling mysql_MySQL如何利用profiling分析SQL查询语句
- CRLF line terminators导致shell脚本报错:command not found
- python0.1+0.2不等于0.3_为什么0.1 + 0.2不等于0.3?
- 软件测试——JUnit中的参数化测试
- 从书上截取一段TCP三次握手和四次挥手
- “相对论“ 2019-07-10
- [sharepoint]rest api文档库文件上传,下载,拷贝,剪切,删除文件,创建文件夹,修改文件夹属性,删除文件夹,获取文档列表...
- 计算机基础与应用教程计算机硬件,计算机基础系列一:计算机硬件
- 类中构造函数、析构函数与赋值函数的重写
- OpenCV Mat主要用法(1)
- The Nighth Assignment
- 闪烁指示灯监控方案_机房温湿度监控检测方案【斯必得智慧机房】
- 冯诺依曼体系结构与计算机基本组成
- 基于 Flink、ClickHouse 的舆情分析系统:需求规格说明书与需求界面
- fastposter v2.7.1 紧急发布 电商海报编辑器
- 德普测试仪EOL软件,电池充放电测试系统 EOL
- 数据库 关系模式和关系的区别
- Ebay API item_get - 获得EBAY商品详情
- 贪吃蛇(C语言版)链表实现
- 顺丰亮出无人机杀手锏:可以载重1.2吨