nRF52 Flash读写数据(有无协议栈的不同方式)

前言

最近开发nrf52833,需要往Flash中读写数据,发现开启蓝牙协议栈后,原有的操作寄存器方式会导致程序报错,网上看了一下,开启协议栈后,读写Flash需要用协议栈提供的特定函数,这里记录一下有无协议栈时不同的读写方式。
另外在我的开发中开启了蓝牙嗅探,读写即使用了协议栈提供的读写函数也操作失败,最后发现要先关闭嗅探才能正常写入,猜测不止是嗅探,估计广播时,读写Flash也要先关闭广播。

一、无协议栈时的读写

1、数据写入

//按字节,连续写FLASH
//注意Addr得是每一页的起始地址
void NRF_Flash_Write(uint32_t Addr,uint8_t* Data,uint32_t Lenth)
{
    
    
	//擦除页
	nrf_nvmc_page_erase(Addr);
	nrf_delay_ms(100);
	//写数据
	nrf_nvmc_write_bytes(Addr,Data,Lenth);
}

2、数据读出

//按字节,连续读取FLASH
//每次读取一个字,然后转成字节
void NRF_Flash_Read(uint32_t Addr,uint8_t* Data,uint32_t Lenth)
{
    
    
	uint32_t *pData,i,j,idx=0;
	
	//要读的字个数
	j=Lenth/4;
	j=((Lenth%4)!=0)?j+1:j;

	for(i=0;i<j;i++)
	{
    
    
		pData=(uint32_t*)Addr;
		Data[idx++] = *pData;
		Data[idx++] = (*pData)>>8;
		Data[idx++] = (*pData)>>16;
		Data[idx++] = (*pData)>>24;
		Addr += 4;
	}
}

二、有协议栈时的数据读写

使用fstorage方式,这里封装的函数,和无协议栈时的读写方式,读写的结果都是一样的,比如写入{0x01,0x02,0x03,0x04},读写结果都会是{0x01,0x02,0x03,0x04},因为考虑到了大小端问题

1、初始化

//头文件,对应的C文件也要添工程中
#include "nrf_fstorage.h"
#include "nrf_fstorage_sd.h"
//Flash读写回调
void fstorage_evt_handler(nrf_fstorage_evt_t * p_evt);
static void fstorage_evt_handler(nrf_fstorage_evt_t * p_evt)
{
    
    
	if(p_evt->result != NRF_SUCCESS)
	{
    
    
		//printf("--> Event received: ERROR while executing an fstorage operation.");
		return;
	}

	switch (p_evt->id)
	{
    
    
		case NRF_FSTORAGE_EVT_WRITE_RESULT:
		{
    
    
			//printf("--> Event received: wrote %d bytes at address 0x%x.",p_evt->len, p_evt->addr);
		} break;

		case NRF_FSTORAGE_EVT_ERASE_RESULT:
		{
    
    
			// printf("--> Event received: erased %d page from address 0x%x.",p_evt->len, p_evt->addr);
		} break;

		default:break;
	}
}

//定义可操作的Flash空间
NRF_FSTORAGE_DEF(nrf_fstorage_t fstorage) =
{
    
    
    .evt_handler = fstorage_evt_handler,	//回调
    .start_addr  = Sys_Info_Addr,			//操作的起始地址
    .end_addr    = Sys_Info_Addr+0xFFF, 	//操作的结束地址
};

//协议栈下读写Flash初始化
void ble_fstorage_init()
{
    
    
	ret_code_t err;
	nrf_fstorage_api_t * p_fs_api;
	p_fs_api = &nrf_fstorage_sd;	//处理操作类型设置
	
	err = nrf_fstorage_init(&fstorage, p_fs_api, NULL);//flash处理的开始地址和结束地址初始化
	APP_ERROR_CHECK(err);	
}

//协议栈下读写Flash反初始化
void ble_fstorage_deinit()
{
    
    
	nrf_fstorage_uninit(&fstorage,NULL);
}

2、数据写入

注意先把蓝牙嗅探、广播关闭

//协议栈下,Flash写入,Addr需要是页地址的开头
void ble_fstorage_write(uint32_t Addr,uint8_t* Data,uint32_t Lenth)
{
    
    
	uint32_t err;

	//先擦除页
	err=nrf_fstorage_erase(&fstorage,Addr,1,NULL);
	APP_ERROR_CHECK(err);
	nrf_delay_ms(10);
	
	//写入数据,按字节
	err = nrf_fstorage_write(&fstorage,Addr,Data,Lenth,NULL);
	APP_ERROR_CHECK(err);
	nrf_delay_ms(10);
}

3、数据读出

//协议栈下数据读出
void ble_fstorage_read(uint32_t Addr,uint8_t* Data,uint32_t Lenth)
{
    
    
	uint32_t err;
	
	err = nrf_fstorage_read(&fstorage,Addr,Data,Lenth);
	APP_ERROR_CHECK(err);
}

4、实际使用

//协议栈初始化
void ble_init()
{
    
    
	/* code begin*/

	ble_fstorage_init();

	/* code end*/
}

	//调用协议栈提供的Flash读写函数前,要先停止广播或嗅探
	ble_scan_stop();
	
	//开启蓝牙协议栈后,要用协议栈提供的Flash读写函数
	ble_fstorage_write(Sys_Info_Addr,(uint8_t *)&Sys_Info,sizeof(Sys_Info));
	
	//读数据
	ble_fstorage_read(Sys_Info_Addr,(uint8_t *)&Sys_Info,sizeof(Sys_Info));

	//恢复嗅探
	ble_scan_start();

三、总结

1、开启协议栈后,要用协议栈的专用读写函数
2、读写前,关闭嗅探,或广播

猜你喜欢

转载自blog.csdn.net/qq_36365231/article/details/127276702