GD32F103单片机内部FLASH按半字读写驱动

.c部分

#include "gd32_flash.h"
#if GD32_FLASH_WREN	//如果使能了写 
static uint16_t GDFLASH_BUF [ GD_SECTOR_SIZE / 2 ];//最多是2K字节
#endif

/**
  * 函数功能: 读取指定地址的半字(16位数据)
  * 输入参数: faddr:读地址(此地址必须为2的倍数!!)
  * 返 回 值: 返回值:对应数据.
  * 说    明:无
  */
uint16_t GDFLASH_ReadHalfWord (uint32_t faddr)
{
	return *(__IO uint16_t*)faddr; 
}

#if GD32_FLASH_WREN	//如果使能了写   
/**
  * 函数功能: 不检查的写入
  * 输入参数: WriteAddr:起始地址
  *           pBuffer:数据指针
  *           NumToWrite:半字(16位)数
  * 返 回 值: 无
  * 说    明:无
  */
void GDFLASH_Write_NoCheck ( uint32_t WriteAddr, uint16_t * pBuffer, uint16_t NumToWrite )   
{ 			 		 
	uint16_t i;	
	fmc_unlock();//解锁
	for(i=0;i<NumToWrite;i++)
	{
		fmc_halfword_program(WriteAddr,pBuffer[i]);
	  WriteAddr+=2;                                    //地址增加2.
	}  
  fmc_lock();//上锁
} 

/**
  * 函数功能: 从指定地址开始写入指定长度的数据
  * 输入参数: WriteAddr:起始地址(此地址必须为2的倍数!!)
  *           pBuffer:数据指针
  *           NumToWrite:半字(16位)数(就是要写入的16位数据的个数.)
  * 返 回 值: 无
  * 说    明:无
  */
void GDFLASH_Write ( uint32_t WriteAddr, uint16_t * pBuffer, uint16_t NumToWrite )	
{
	uint16_t secoff;	   //扇区内偏移地址(16位字计算)
	uint16_t secremain; //扇区内剩余地址(16位字计算)	   
 	uint16_t i;    
	uint32_t secpos;	   //扇区地址
	uint32_t offaddr;   //去掉0X08000000后的地址
	
	if(WriteAddr<FLASH_BASE||(WriteAddr>=(FLASH_BASE+1024*GD32_FLASH_SIZE)))
    return;//非法地址
	
	fmc_unlock();						//解锁
	
	offaddr   = WriteAddr-FLASH_BASE;		    //实际偏移地址.
	secpos    = offaddr/GD_SECTOR_SIZE;			//扇区地址  0~127 for GD32F103CBT6
	secoff    = (offaddr%GD_SECTOR_SIZE)/2;	//在扇区内的偏移(2个字节为基本单位.)
	secremain = GD_SECTOR_SIZE/2-secoff;		//扇区剩余空间大小   
	if(NumToWrite<=secremain)
    secremain=NumToWrite;//不大于该扇区范围
	
	while(1) 
	{	
    //读取整个扇区数据
    GDFLASH_Read(secpos*GD_SECTOR_SIZE+FLASH_BASE,GDFLASH_BUF,GD_SECTOR_SIZE/2);
		for(i=0;i<secremain;i++)//校验数据
		{
			if(GDFLASH_BUF[secoff+i]!=0XFFFF)
        break;//需要擦除  	  
		}
		if(i<secremain)//需要擦除
		{
      //擦除这个扇区
      fmc_page_erase(secpos);

			for(i=0;i<secremain;i++)//复制
			{
				GDFLASH_BUF[i+secoff]=pBuffer[i];	  
			}
			GDFLASH_Write_NoCheck(secpos*GD_SECTOR_SIZE+FLASH_BASE,GDFLASH_BUF,GD_SECTOR_SIZE/2);//写入整个扇区  
		}
    else
    {
      GDFLASH_Write_NoCheck(WriteAddr,pBuffer,secremain);//写已经擦除了的,直接写入扇区剩余区间. 				   
		}
    if(NumToWrite==secremain)
      break;//写入结束了
		else//写入未结束
		{
			secpos++;				//扇区地址增1
			secoff=0;				//偏移位置为0 	 
		  pBuffer+=secremain;  	//指针偏移
			WriteAddr+=secremain;	//写地址偏移	   
		  NumToWrite-=secremain;	//字节(16位)数递减
			if(NumToWrite>(GD_SECTOR_SIZE/2))
        secremain=GD_SECTOR_SIZE/2;//下一个扇区还是写不完
			else 
        secremain=NumToWrite;//下一个扇区可以写完了
		}	 
	};	
	fmc_lock();//上锁
}
#endif

/**
  * 函数功能: 从指定地址开始读出指定长度的数据
  * 输入参数: ReadAddr:起始地址
  *           pBuffer:数据指针
  *           NumToRead:半字(16位)数
  * 返 回 值: 无
  * 说    明:无
  */
void GDFLASH_Read( uint32_t ReadAddr, uint16_t *pBuffer, uint16_t NumToRead )   	
{
	uint16_t i;
	for(i=0;i<NumToRead;i++)
	{
		pBuffer[i]=GDFLASH_ReadHalfWord(ReadAddr);//读取2个字节.
		ReadAddr+=2;//偏移2个字节.	
	}
}

.h部分

#ifndef _GD32_FLASH_H_
#define _GD32_FLASH_H_

#define GD32_FLASH_SIZE        128  // 所选STM32的FLASH容量大小(单位为K)
#define GD32_FLASH_WREN        1    // stm32芯片内容FLASH 写入使能(0,禁用;1,使能)

#if GD32_FLASH_SIZE < 256
  #define GD_SECTOR_SIZE  1024 //字节
#else 
  #define GD_SECTOR_SIZE	 2048
#endif

uint16_t GDFLASH_ReadHalfWord(uint32_t faddr);		  //读出半字
void GDFLASH_Write_NoCheck ( uint32_t WriteAddr, uint16_t * pBuffer, uint16_t NumToWrite );      //指定地址开始写入指定长度的数据
void GDFLASH_Write( uint32_t WriteAddr, uint16_t * pBuffer, uint16_t NumToWrite );		//从指定地址开始写入指定长度的数据
void GDFLASH_Read( uint32_t ReadAddr, uint16_t * pBuffer, uint16_t NumToRead );   	//从指定地址开始读出指定长度的数据

#endif //_GD32_FLASH_H_
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值