stm32做PVD掉电检测保存数据到flash

2019-12-12 18:17发布

我用STM32做掉电检测,在检测到掉电后保存数据到flash,我已经检测到掉电了,而且已经进入PVD中断了,保存数据的函数也是执行完了的,但为什么就是数据没有保存成功呢?求大神指点!
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
73条回答
raydsp
2019-12-21 16:43
经过几天调试,写出可以使用的STM32  PVD掉电存储数据,目前只能一个扇区内存储数据,不过应该够用。希望可以帮助有需要的人。代码可能不是很严谨,需自己改进。
写入数据修改(摖除与写入分开):
void STMFLASH_Write(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite)        //摖除
{
       
       
         
        u16 i;   
        u32 offaddr;   //去掉0X08000000后的地址
        if(WriteAddr<STM32_FLASH_BASE||(WriteAddr>=(STM32_FLASH_BASE+1024*STM32_FLASH_SIZE)))return;//非法地址
        FLASH_Unlock();                                                //解锁
        offaddr=WriteAddr-STM32_FLASH_BASE;                //实际偏移地址.0X08034000-0X08000000=0X00034000
        secpos=offaddr/STM_SECTOR_SIZE;                        //扇区地址  0~127 for STM32F103RBT6   16
        secoff=(offaddr%STM_SECTOR_SIZE)/2;                //在扇区内的偏移(2个字节为基本单位.)616
        secremain=STM_SECTOR_SIZE/2-secoff;                //扇区剩余空间大小   408
        if(NumToWrite<=secremain)secremain=NumToWrite;//不大于该扇区范围 4
        while(1)
        {       
                STMFLASH_Read(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);//读出整个扇区的内容
                for(i=0;i<secremain;i++)//校验数据
                {
                        if(STMFLASH_BUF[secoff+i]!=0XFFFF)break;//需要擦除            
                }
                if(i<secremain)//需要擦除
                {
                        FLASH_ErasePage(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE);//擦除这个扇区
                        for(i=0;i<secremain;i++)//复制
                        {
                                STMFLASH_BUF[i+secoff]=pBuffer[i];          
                        }
               
                }       
if(NumToWrite==secremain)break;//摖除跳出
        }       
                                 
}
void STMFLASH_Writego(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite)        //中断写入
{
       
                         STMFLASH_Write_NoCheck(WriteAddr,pBuffer,NumToWrite);//写已经擦除了的,直接写入扇区剩余区间.
       FLASH_Lock();//上锁                         
}


PVD初始化与中断函数:
void NVIC_pvdConfiguration(void)
{ static u16 TEXT_Buffer[4];
  NVIC_InitTypeDef NVIC_InitStructure;

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
//PVD
  NVIC_InitStructure.NVIC_IRQChannel = PVD_IRQn;//PVD_IRQChannel;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
  NVIC_Init(&NVIC_InitStructure);  


                    last_data[0]=lastNM;last_data[1]=lastNM2;//摖除之前需要将掉电存储到的数据转移到其他地方
                                                         STMFLASH_Write(FLASH_SAVE_LAST,(u16*)TEXT_Buffer,4);        
}
void ExterLineInterrupt(void)
{
    EXTI_InitTypeDef EXTI_InitStructure;
    EXTI_DeInit();
    EXTI_StructInit(&EXTI_InitStructure);
     PWR_PVDLevelConfig(PWR_PVDLevel_2V9); // ???????
    PWR_PVDCmd(ENABLE); // ??PVD
    EXTI_InitStructure.EXTI_Line = EXTI_Line16;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);
}
void PVD_IRQHandler(void)
{
        static u16 TEXT_Buffer[4];
       

        LCD_LED=0;
                EXTI_ClearITPendingBit(EXTI_Line16);//clear bit;
          
                                                 STMFLASH_Writego(FLASH_SAVE_LAST,(u16*)TEXT_Buffer,4); //写入需要保存的数据

   if (PWR_GetFlagStatus(PWR_FLAG_PVDO)== SET) {
                 PWR_ClearFlag(PWR_FLAG_PVDO);
   
    }
  
}

一周热门 更多>