/*************************** (C) COPYRIGHT 2017 CXHY **************************** * 文件名 :stmflash.c * 描 述 :STM32-FLASH操作函数 * 版 本 :V1.0 * 作 者 :XuZhongPing * 日 期 :2017/07/23 *********************************************************************************/ #include "stmflash.h" #include "stdio.h" #include "delay.h" #include "timer.h" #include "gsm_gprs.h" #include "data_typedef.h" #if STM32_FLASH_SIZE < 256 //中容量和小容量的MCU一页的大小都为1K字节 #define STM_SECTOR_SIZE 1024 //一页字节数 #else #define STM_SECTOR_SIZE 2048 #endif uint16_t STMFLASH_BUF[STM_SECTOR_SIZE/2]; //用于保存一个扇区的数据缓存,擦除扇区时需先读取原来保存的数据,然后再重新写入 /* *********************************************************************** * 函 数 名: STMFLASH_ReadHalfWord * 功能说明: 读取指定地址的半字(16位数据) * 形 参:faddr:读地址(此地址必须为2的倍数!!) * 返 回 值: 对应地址保存的数据 *********************************************************************** */ uint16_t STMFLASH_ReadHalfWord(uint32_t faddr) { return *(vu16*)faddr; } /* *********************************************************************** * 函 数 名: STMFLASH_Write_NoCheck * 功能说明: 不检查的向指定地址写入数据 * 形 参:WriteAddr:起始地址 * pBuffer:数据指针 * NumToWrite:半字(16位)数 * 返 回 值: 无 *********************************************************************** */ void STMFLASH_Write_NoCheck(uint32_t WriteAddr, uint16_t *pBuffer, uint16_t NumToWrite) { uint16_t i; for(i = 0; i < NumToWrite; i++) { FLASH_ProgramHalfWord(WriteAddr, pBuffer[i]); WriteAddr += 2; //地址增加2. } } /* *********************************************************************** * 函 数 名: STMFLASH_Write * 功能说明: 从指定地址开始写入指定长度的数据 * 形 参:WriteAddr:起始地址(此地址必须为2的倍数!!) * pBuffer:数据指针 * NumToWrite:半字(16位)数(就是要写入的16位数据的个数.) * 返 回 值: 无 *********************************************************************** */ void STMFLASH_Write(uint32_t WriteAddr, uint16_t *pBuffer, uint16_t NumToWrite) { uint32_t secpos; //扇区地址 uint16_t secoff; //扇区内偏移地址(16位字计算) uint16_t secremain; //扇区内剩余地址(16位字计算) uint32_t offaddr; //去掉0X08000000后的地址 uint16_t i; if((WriteAddr < STM32_FLASH_BASE) || (WriteAddr >= (STM32_FLASH_BASE + 1024*STM32_FLASH_SIZE)))return; //非法地址 FLASH_Unlock(); //解锁 offaddr = WriteAddr-STM32_FLASH_BASE; //实际偏移地址. secpos = offaddr/STM_SECTOR_SIZE; //扇区地址 0~127 for STM32F103RBT6 secoff = (offaddr%STM_SECTOR_SIZE)/2; //在扇区内的偏移(2个字节为基本单位.) secremain = STM_SECTOR_SIZE/2 - secoff; //扇区剩余空间大小 if(NumToWrite <= secremain) //不大于该扇区范围 { secremain = NumToWrite; } 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 (STM_SECTOR_SIZE/2)) //下一个扇区还是写不完 { secremain = STM_SECTOR_SIZE/2; }else{ //下一个扇区可以写完了 secremain = NumToWrite; } } } FLASH_Lock(); //上锁 } /* *********************************************************************** * 函 数 名: STMFLASH_Read * 功能说明: 从指定地址开始读出指定长度的数据 * 形 参:ReadAddr:起始地址 * pBuffer:数据指针 * NumToRead:半字(16位)数 * 返 回 值: 无 *********************************************************************** */ void STMFLASH_Read(uint32_t ReadAddr, uint16_t *pBuffer, uint16_t NumToRead) { uint16_t i; for(i = 0; i < NumToRead; i++) { pBuffer[i] = STMFLASH_ReadHalfWord(ReadAddr); //读取2个字节. ReadAddr += 2; //偏移2个字节. } } /* *********************************************************************** * 函 数 名: STMFLASH_WriteHalfWord * 功能说明: 向指定FLASH地址写入一个16位数据 * 形 参:WriteAddr:起始地址 * WriteData:要写入的数据 * 返 回 值: 无 *********************************************************************** */ void STMFLASH_WriteHalfWord(uint32_t WriteAddr, uint16_t WriteData) { // STMFLASH_Write(WriteAddr, &WriteData, 1); //写入一个字(16位) FLASH_ProgramHalfWord(WriteAddr, WriteData); } /* *********************************************************************** * 函 数 名: DeviceConfigErase * 功能说明: 擦除参数保存区的flash * 形 参:无 * 返 回 值: 无 *********************************************************************** */ void DeviceConfigErase(uint32_t WriteAddr) { uint32_t secpos; //扇区地址 uint16_t secoff; //扇区内偏移地址(16位字计算) uint32_t offaddr; //去掉0X08000000后的地址 if((WriteAddr < STM32_FLASH_BASE) || (WriteAddr >= (STM32_FLASH_BASE + 1024*STM32_FLASH_SIZE)))return; //非法地址 offaddr = WriteAddr-STM32_FLASH_BASE; //实际偏移地址. secpos = offaddr/STM_SECTOR_SIZE; //扇区地址 0~127 for STM32F103RBT6 FLASH_ErasePage(secpos * STM_SECTOR_SIZE + STM32_FLASH_BASE); //擦除这个扇区 } /* *********************************************************************** * 函 数 名: SaveDeviceConfig * 功能说明: 保存设备配置的参数 * 形 参:无 * 返 回 值: 无 *********************************************************************** */ void SaveDeviceConfig(void) { uint8_t i = 0; uint16_t uTempData = 0; uint32_t flashSaveAddr = 0; flashSaveAddr = FLASH_SAVE_ADDR; printf("\r\nTime1 = %d\r\n", time_value); FLASH_Unlock(); //解锁 DeviceConfigErase(FLASH_SAVE_ADDR); //数据保存成功标志位 uTempData = 0xFFFF; STMFLASH_WriteHalfWord(flashSaveAddr, uTempData); flashSaveAddr += 2; //设备操作密码 uTempData = (uint16_t)(setPassword >> 16); STMFLASH_WriteHalfWord(flashSaveAddr, uTempData); flashSaveAddr += 2; uTempData = (uint16_t)setPassword; STMFLASH_WriteHalfWord(flashSaveAddr, uTempData); flashSaveAddr += 2; //设备客户号 uTempData = (uint16_t)(setCustomerID >> 16); STMFLASH_WriteHalfWord(flashSaveAddr, uTempData); flashSaveAddr += 2; uTempData = (uint16_t)setCustomerID; STMFLASH_WriteHalfWord(flashSaveAddr, uTempData); flashSaveAddr += 2; //设备类型及通道数量 uTempData = (uint16_t)(setDeviceType << 8) | setDevChannelNumbers; STMFLASH_WriteHalfWord(flashSaveAddr, uTempData); flashSaveAddr += 2; //第1路投口相关参数 uTempData = (uint16_t)(setDevChannel1Type << 8) | setDevChannel1DisDepthVal; STMFLASH_WriteHalfWord(flashSaveAddr, uTempData); flashSaveAddr += 2; uTempData = (uint16_t)(setDevChannel1DisMaxVal << 8) | setDevChannel1DisAlarmPercent; STMFLASH_WriteHalfWord(flashSaveAddr, uTempData); flashSaveAddr += 2; //第2路投口相关参数 uTempData = (uint16_t)(setDevChannel2Type << 8) | setDevChannel2DisDepthVal; STMFLASH_WriteHalfWord(flashSaveAddr, uTempData); flashSaveAddr += 2; uTempData = (uint16_t)(setDevChannel2DisMaxVal << 8) | setDevChannel2DisAlarmPercent; STMFLASH_WriteHalfWord(flashSaveAddr, uTempData); flashSaveAddr += 2; //第3路投口相关参数 uTempData = (uint16_t)(setDevChannel3Type << 8) | setDevChannel3DisDepthVal; STMFLASH_WriteHalfWord(flashSaveAddr, uTempData); flashSaveAddr += 2; uTempData = (uint16_t)(setDevChannel3DisMaxVal << 8) | setDevChannel3DisAlarmPercent; STMFLASH_WriteHalfWord(flashSaveAddr, uTempData); flashSaveAddr += 2; //第4路投口相关参数 uTempData = (uint16_t)(setDevChannel4Type << 8) | setDevChannel4DisDepthVal; STMFLASH_WriteHalfWord(flashSaveAddr, uTempData); flashSaveAddr += 2; uTempData = (uint16_t)(setDevChannel4DisMaxVal << 8) | setDevChannel4DisAlarmPercent; STMFLASH_WriteHalfWord(flashSaveAddr, uTempData); flashSaveAddr += 2; flashSaveAddr += 24; //预留32个字节用于保存投口通道参数 //禁用IC卡用户功能和启用收运IC卡二维码功能标志位 uTempData = (uint16_t)(setDisableICCardFunStatus << 8) | setEnableCleanQRCodeStatus; STMFLASH_WriteHalfWord(flashSaveAddr, uTempData); flashSaveAddr += 2; //设备编号长度 STMFLASH_WriteHalfWord(flashSaveAddr, setDeviceIdLength); flashSaveAddr += 2; printf("\r\nTime2 = %d\r\n", time_value); //设备编号 for(i = 0; i < 32; i+=2) { uTempData = (uint16_t)(setDeviceIdBuf[i] << 8) | setDeviceIdBuf[i+1]; STMFLASH_WriteHalfWord(flashSaveAddr, uTempData); flashSaveAddr += 2; } printf("\r\nTime3 = %d\r\n", time_value); //服务器IP地址及端口号 uTempData = (uint16_t)(setIpAddr0 << 8) | setIpAddr1; STMFLASH_WriteHalfWord(flashSaveAddr, uTempData); flashSaveAddr += 2; uTempData = (uint16_t)(setIpAddr2 << 8) | setIpAddr3; STMFLASH_WriteHalfWord(flashSaveAddr, uTempData); flashSaveAddr += 2; STMFLASH_WriteHalfWord(flashSaveAddr, setIpPort); flashSaveAddr += 2; //标志参数保存完成 uTempData = 0x0A0B; STMFLASH_WriteHalfWord(FLASH_SAVE_ADDR, uTempData); FLASH_Lock(); //上锁 printf("\r\nTime4 = %d\r\n", time_value); printf("\r\n参数保存成功!\r\n"); } /* *********************************************************************** * 函 数 名: GetDeviceConfig * 功能说明: 取得设备配置参数 * 形 参:无 * 返 回 值: 无 *********************************************************************** */ uint8_t GetDeviceConfig(void) { uint8_t i = 0; uint16_t uTempData = 0; uint32_t flashSaveAddr = 0; flashSaveAddr = FLASH_SAVE_ADDR; uTempData = STMFLASH_ReadHalfWord(flashSaveAddr); flashSaveAddr += 2; if(uTempData == 0x0A0B) { //设备操作密码 uTempData = STMFLASH_ReadHalfWord(flashSaveAddr); flashSaveAddr += 2; setPassword = uTempData; uTempData = STMFLASH_ReadHalfWord(flashSaveAddr); flashSaveAddr += 2; setPassword = (setPassword << 16) | uTempData; //设备客户号 uTempData = STMFLASH_ReadHalfWord(flashSaveAddr); flashSaveAddr += 2; setCustomerID = uTempData; uTempData = STMFLASH_ReadHalfWord(flashSaveAddr); flashSaveAddr += 2; setCustomerID = (setCustomerID << 16) | uTempData; //设备类型 uTempData = STMFLASH_ReadHalfWord(flashSaveAddr); flashSaveAddr += 2; setDeviceType = uTempData >> 8; setDevChannelNumbers = (uint8_t)uTempData; //第1路投口相关参数 uTempData = STMFLASH_ReadHalfWord(flashSaveAddr); flashSaveAddr += 2; setDevChannel1Type = uTempData >> 8; setDevChannel1DisDepthVal = (uint8_t)uTempData; uTempData = STMFLASH_ReadHalfWord(flashSaveAddr); flashSaveAddr += 2; setDevChannel1DisMaxVal = uTempData >> 8; setDevChannel1DisAlarmPercent = (uint8_t)uTempData; //第2路投口相关参数 uTempData = STMFLASH_ReadHalfWord(flashSaveAddr); flashSaveAddr += 2; setDevChannel2Type = uTempData >> 8; setDevChannel2DisDepthVal = (uint8_t)uTempData; uTempData = STMFLASH_ReadHalfWord(flashSaveAddr); flashSaveAddr += 2; setDevChannel2DisMaxVal = uTempData >> 8; setDevChannel2DisAlarmPercent = (uint8_t)uTempData; //第3路投口相关参数 uTempData = STMFLASH_ReadHalfWord(flashSaveAddr); flashSaveAddr += 2; setDevChannel3Type = uTempData >> 8; setDevChannel3DisDepthVal = (uint8_t)uTempData; uTempData = STMFLASH_ReadHalfWord(flashSaveAddr); flashSaveAddr += 2; setDevChannel3DisMaxVal = uTempData >> 8; setDevChannel3DisAlarmPercent = (uint8_t)uTempData; //第4路投口相关参数 uTempData = STMFLASH_ReadHalfWord(flashSaveAddr); flashSaveAddr += 2; setDevChannel4Type = uTempData >> 8; setDevChannel4DisDepthVal = (uint8_t)uTempData; uTempData = STMFLASH_ReadHalfWord(flashSaveAddr); flashSaveAddr += 2; setDevChannel4DisMaxVal = uTempData >> 8; setDevChannel4DisAlarmPercent = (uint8_t)uTempData; flashSaveAddr += 24; //禁用IC卡用户功能和启用收运IC卡二维码功能标志位 uTempData = STMFLASH_ReadHalfWord(flashSaveAddr); flashSaveAddr += 2; setDisableICCardFunStatus = uTempData >> 8; setEnableCleanQRCodeStatus = (uint8_t)uTempData; //设备编号长度 uTempData = STMFLASH_ReadHalfWord(flashSaveAddr); flashSaveAddr += 2; setDeviceIdLength = uTempData; //设备编号 for(i = 0; i < 32; i+=2) { uTempData = STMFLASH_ReadHalfWord(flashSaveAddr); flashSaveAddr += 2; setDeviceIdBuf[i] = uTempData >> 8; setDeviceIdBuf[i+1] = (uint8_t)uTempData; } //服务器IP地址及端口号 uTempData = STMFLASH_ReadHalfWord(flashSaveAddr); flashSaveAddr += 2; setIpAddr0 = uTempData >> 8; setIpAddr1 = (uint8_t)uTempData; uTempData = STMFLASH_ReadHalfWord(flashSaveAddr); flashSaveAddr += 2; setIpAddr2 = uTempData >> 8; setIpAddr3 = (uint8_t)uTempData; uTempData = STMFLASH_ReadHalfWord(flashSaveAddr); flashSaveAddr += 2; setIpPort = uTempData; printf("\r\n参数读取成功!\r\n"); printf("\r\nSet P=%d; ID=%d; Type=%d; Cnt=%d; T1=%d, h1=%d, H1=%d, A1=%d; T2=%d, h2=%d, H2=%d, A2=%d, ICE=%d; ICQR=%d; "\ "devLen=%d; devID=%s; IP=%d.%d.%d.%d:%d\r\n", setPassword, setCustomerID, setDeviceType, setDevChannelNumbers, setDevChannel1Type, setDevChannel1DisDepthVal, setDevChannel1DisMaxVal, setDevChannel1DisAlarmPercent, setDevChannel2Type, setDevChannel2DisDepthVal, setDevChannel2DisMaxVal, setDevChannel2DisAlarmPercent, setDisableICCardFunStatus, setEnableCleanQRCodeStatus, setDeviceIdLength, setDeviceIdBuf, setIpAddr0,setIpAddr1,setIpAddr2,setIpAddr3,setIpPort ); return 0; }else{ printf("\r\n还没有保存过设备参数!\r\n"); return 1; } } /* *********************************************************************** * 函 数 名: ResetDeviceConfig * 功能说明: 恢复设备配置参数到出厂设置 * 形 参:无 * 返 回 值: 无 *********************************************************************** */ void ResetDeviceConfig(void) { FLASH_Unlock(); //解锁 DeviceConfigErase(FLASH_SAVE_ADDR); FLASH_Lock(); //上锁 printf("\r\n设备配置参数已恢复成出厂设置!\r\n"); } /******************** (C) COPYRIGHT 2017 CXHY *****END OF FILE*******************/