/******************************************************************************** * File Name: MainTask.c * Function Describe:The main task for the system * Relate Module: * Explain: Hardware version is HS110C * Writer: ShiLiangWen * Date: 2015.1.20 *******************************************************************************/ #include "includes.h" #include "stm32f10x_pwr.h" #include "stm32f10x_iwdg.h" OS_EVENT *PcQ; void *PcMsg[PC_Q_NUM]; char PcMsgBuf[PC_Q_NUM][PC_MSG_BUF_LEN]; int PCMsgBufIndex=0; int g_iMcuVer=MCU_VER; //====================================== #define APP_TASK_MAIN_STK_SIZE 1000 static OS_STK AppMainTaskStk[APP_TASK_MAIN_STK_SIZE]; const char g_apcFirstPowerOnFlag[]={ "HS110C-1" }; unsigned char g_ucRand;//伪随机数,根据MCU ID生成 /*********************************************** 强制复位 ************************************************/ void SystemReset(void) { *((u32 *)0xE000ED0C) = 0x05fa0001; while(1); } /*********************************************** *SetDefNetPara *设置默认网络参数 ************************************************/ void SetDefNetPara(void) { } /*************************************************** *IsFirstPowerOn 判断是否为第一次上电,根据EEPROM标志位来判断 ****************************************************/ int IsFirstPowerOn(void) { // int i; // char flag[8]; // EEPROM_ReadS(EEPROM_FLAG,(unsigned char *)flag,8); // for(i=0;i<8;i++){ // if(flag[i]!=g_apcFirstPowerOnFlag[i])break; // } // if(i!=8){ // EEPROM_WriteS(EEPROM_FLAG,(unsigned char *)g_apcFirstPowerOnFlag,8); // return -1; // } return 0; } /****************************************************************** *SysParaInit ********************************************************************/ void SysParaInit(void) { int i; unsigned char *p=(unsigned char*)&sutNetPara; for(i=0;iIDR; if((k&ONOFF_CK_PIN)==0){ if(sucCt<5)sucCt++; else return 1; }else{ sucCt=0; } return 0; } void GPIO_Config_ALL_AIN(void); /********************************************************************** *系统关机 ***********************************************************************/ void SysShutDown(void) { GPIO_InitTypeDef GPIO_InitStructure; unsigned long k; int len; g_ucNetTaskDisable=0xff; GPS_PWREN_LOW; MODEM_LED1_HIGH; MODEM_LED2_HIGH; ModemSendAT("AT+ZPWROFF\r\n"); SlwTrace(INF,"Set modem OnOff down!\r\n"); OSTimeDlyHMSM(0, 0, 0, 500); ModemSendAT("AT+ZPWROFF\r\n"); //DelayMs(3000); OSTimeDlyHMSM(0, 0, 2, 500); SlwTrace(INF,"Set system power off!\r\n"); SlwTraceWaitCompleted(); MODEM_LED1_LOW; MODEM_LED2_LOW; //------- k=ONOFF_CK_PORT->IDR; if((k&ONOFF_CK_PIN)!=0){ SlwTrace(INF,"Reset system!\r\n"); SlwTraceWaitCompleted(); SystemReset(); }else{ IWDG_ReloadCounter(); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Pin = PWR_EN_PIN; GPIO_Init(PWR_EN_PORT, &GPIO_InitStructure); while(1); } } int g_iVbat=0; unsigned char AscToHex(unsigned char aHex) { if((aHex>=0)&&(aHex<=9)) aHex += 0x30; else if((aHex>=10)&&(aHex<=15))//A-F aHex += 0x37; else aHex = 0xff; return aHex; } void AscStrToHexStr(char *AscStr, char *HexStr) { char *pAscStr=AscStr; unsigned char d,h,l; while(0!=(d=(unsigned char)*pAscStr++)){ l=d&0x0f; h=d>>4; *HexStr++=AscToHex(h); *HexStr++=AscToHex(l); } *HexStr=0; } void PcMsgHandle(char *msg) { char *CmdList[]={ "TM", //Trace Modem "TG", //Trace GPS "DM", //Download Modem "FOTA", //Fota Modem "STP", //Set Test Parameter "SMP", //Set Modem Parameter "SGP", //Set GPS Parameter "RMP", //Read Modem Parameter "PST", //PST Mode for modem "VER", //Read Version "BAT", //Battery voltage "" //必须以空字串为结束 }; unsigned short Port; unsigned long PSN; char buf[150]; char buf1[300]; char strIP[40]; char strAccount[20]; char strPassword[20]; int i,len; char flag; char *pCmd; char *pMsg; int CmdListNum=0; while(*CmdList[CmdListNum++]);//计算命令列表个数 CmdListNum--; //查找与命令列表相同的命令位置 for(i=0;i=40){ SlwTrace(INF,"GT+STP:FAIL[IP Invalid]\r\n"); break; }else strcpy(strIP,buf); len=GetParaFromStr(msg,"Port",buf); if(len==0)Port=0; else if(len>5){ SlwTrace(INF,"GT+STP:FAIL[Port Invalid]\r\n"); break; }else{ Port=atoi(buf); } len=GetParaFromStr(msg,"Account",buf); if(len<1 || len>=20){ SlwTrace(INF,"GT+STP:FAIL[Account Invalid]\r\n"); break; }else strcpy(strAccount,buf); len=GetParaFromStr(msg,"Password",buf); if(len<1 || len>=20){ SlwTrace(INF,"GT+STP:FAIL[Password Invalid]\r\n"); break; }else strcpy(strPassword,buf); //send to modem sprintf(buf,"ip=%s;id=%s;pwd=%s;",strIP,strAccount,strPassword); AscStrToHexStr(buf,buf1); ModemSendAT("AT+POC=120000"); ModemSendAT(buf1); ModemSendAT("\r\n"); //send to pc sprintf(buf,"GT+STP:IP=%s;Port=%u;Account=%s;Password=%s\r\n",strIP,Port,strAccount,strPassword); SlwTrace(INF,buf); break; case 5://"SMP" GT+SMP=IP=地址或域名;Port=端口号;PSN=终端序列号 len=GetParaFromStr(msg,"IP",buf); if(len<1 || len>=40){ SlwTrace(INF,"GT+SMP:FAIL[IP Invalid]\r\n"); break; }else strcpy(strIP,buf); len=GetParaFromStr(msg,"Port",buf); if(len==0)Port=0; else if(len>5){ SlwTrace(INF,"GT+SMP:FAIL[Port Invalid]\r\n"); break; }else{ Port=atoi(buf); } len=GetParaFromStr(msg,"PSN",buf); if(len<1 || len>10){ SlwTrace(INF,"GT+SMP:FAIL[PSN Invalid]\r\n"); break; }else{ PSN=atol(buf); } //PSN sutNetPara.PSN=PSN; strcpy(sutNetPara.PIP,strIP); sutNetPara.PPort=Port; //send to modem if(strlen(sutNetPara.MEID)<14){ SlwTrace(INF,"GT+SMP:FAIL[MEID Invalid]\r\n"); break; } sprintf(buf,"ip=%s;id=%u;pwd=%s;",strIP,sutNetPara.PSN,sutNetPara.MEID); AscStrToHexStr(buf,buf1); ModemSendAT("AT+POC=010000"); ModemSendAT(buf1); ModemSendAT("\r\n"); //save PSN to flash SavePsnToFlash(sutNetPara.PSN); sutNetPara.PSN=ReadPsnFromFlash(); //Save para to flash // SaveParaToFlash(); //send to pc sprintf(buf,"GT+SMP:IP=%s;Port=%u;PSN=%u\r\n",sutNetPara.PIP,sutNetPara.PPort,sutNetPara.PSN); SlwTrace(INF,buf); break; case 6://"SGP" GT+SGP=IP=地址或域名;Port=端口号; len=GetParaFromStr(msg,"IP",buf); if(len<1 || len>=40){ SlwTrace(INF,"GT+SGP:FAIL[IP Invalid]\r\n"); break; }else strcpy(strIP,buf); len=GetParaFromStr(msg,"Port",buf); if(len==0)Port=0; else if(len>5){ SlwTrace(INF,"GT+SGP:FAIL[Port Invalid]\r\n"); break; }else{ Port=atoi(buf); } strcpy(sutNetPara.GIP,strIP); sutNetPara.GPort=Port; //Save para to flash //SaveParaToFlash(); //Send to PC sprintf(buf,"GT+SGP:IP=%s;Port=%u;\r\n",sutNetPara.GIP,sutNetPara.GPort); SlwTrace(INF,buf); break; case 7://"RMP" GT+RMP PSN=终端序列号;MEID=模块MEID号;CNUM=电信号;UIMID=电信UIMID; sutNetPara.PSN=ReadPsnFromFlash(); //Read para from PC //ReadParaFromFlash(); sprintf(buf,"GT+RMP:PSN=%u;MEID=%s;CNUM=%s;UIMID=%s\r\n",sutNetPara.PSN,sutNetPara.MEID,sutNetPara.CNUM,sutNetPara.UIMID); SlwTrace(INF,buf); break; case 8://"PST" g_ucNetTaskDisable=0xff; SlwTrace(INF,"GT+PST:OK\r\n"); SlwTraceWaitCompleted(); OSTimeDlyHMSM(0, 0, 0, 100); ComSelect(COM_SEL_MODEM); SetLedFlash(2,4);//2闪 ModemSetDtrLow(); MODEM_PWRKEY_LOW; MODEM_RESET_HIGH; OSTimeDlyHMSM(0, 0, 0, 500); MODEM_RESET_LOW; while(1){ IWDG_ReloadCounter();//喂狗 if(OnOffCheck()){ PWR_EN_LOW; } } break; case 9://"VER" SlwTrace(INF,"GT+VER:\r\n"); SlwTrace(INF,SOFTWARE_VER); SlwTrace(INF,"\r\n"); break; case 10://BAT sprintf(buf,"GT+BAT: %d V\r\n",g_iVbat); SlwTrace(INF,buf); break; } } void ReportGps(void) { if(!sutGpsInfo.isGpsWork){ //GPS异常 "470050005300025F385E" ModemSendAT("AT+ZTTS=1,\"470050005300025F385E\"\r\n"); return; } if(sutGpsInfo.isServerLogin){ ModemSendAT("AT+ZTTS=1,\"470050005300F25D7B764696"); //GPS已登陆 }else{ ModemSendAT("AT+ZTTS=1,\"4700500053002A677B764696"); //GPS未登陆 } if(sutGpsInfo.isGpsValid){ ModemSendAT("2C00F25D9A5B4D4F\"\r\n"); //,已定位 }else{ ModemSendAT("2C002A679A5B4D4F\"\r\n"); //,未定位 } } /******************************************************************* *MainTask *主任务 ********************************************************************/ static void MainTask(void *pdata) { char *msg; INT8U err; static unsigned char sucCt=0; static unsigned char sucFunReportFlag=0; int Vbat; Uart1Init();//UART1初始化 用于PC通讯,映射到printf(...) Uart2Init();//UART2初始化 用于GPS通讯 Uart3Init();//UART3初始化 用于Modem通讯 SlwTrace(INF,SOFTWARE_VER); SlwTrace(INF," Start...\r\n"); SlwTrace(INF,"Watchdog Init!\r\n"); IWDG_Configuration(); //GetSTM32ID(g_aucSTM32ID); //g_ucRand=GetKey(g_aucSTM32ID); //初始化系统参数 SlwTrace(INF,"SysParaInit!\r\n"); SysParaInit(); //等待PC重新设置参数 //SlwTrace(INF,"Wait for reset para from PC...\r\n"); //SetParaFromPC(); //创建LED指示应用服务 SlwTrace(INF,"Create Led Task!\r\n"); LedTaskCreate(); SetLedFlash(1,7);//设置LED闪烁 //ADC初始化 ADCInit(); SlwTrace(INF,"ModemInit..."); if(ModemInit()){ SlwTrace(INF," Fail\r\n"); SlwTrace(INF,"will be reset the system!\r\n"); OSTimeDlyHMSM(0, 0, 10, 0); SystemReset(); }else{ SlwTrace(INF," OK\r\n"); } KeyInit(); NetTaskCreate();//创建网络应用任务 //创建消息队列,用于与UART1与PC通讯 PcQ=OSQCreate(&PcMsg[0], PC_Q_NUM); OSQFlush(PcQ); //-begin- SlwTrace(INF,"Main task running...\r\n"); while(1) { //喂狗 IWDG_ReloadCounter(); //检查关机键按下 if(OnOffCheck()){ //SlwTrace(INF,"Shutdown now!\r\n"); SysShutDown(); } //消息处理 每次大约等待20ms ,键盘扫描也是20ms msg = (char *)OSQPend(PcQ, 2, &err); if(err==OS_ERR_NONE){//收到PC发过来的消息,处理之 //SlwTrace(DEBUG,"[PC_MSG]\r\n"); PcMsgHandle(msg); continue; } //20ms timeout 处理其他 //键盘扫描 if(GetKey()){ //printf("KeyValue=%02x\r\n",g_ucKeyValue); if(g_ucKeyValue==KEY_FUN){ if(0==sucFunReportFlag){ SlwTrace(INF,"Report Vbat\r\n"); ReportVbat(g_iVbat); sucFunReportFlag=1; }else if(1==sucFunReportFlag){ sucFunReportFlag=2; SlwTrace(INF,"Report CSQ\r\n"); ReportCSQ(g_iCSQ); }else if(2==sucFunReportFlag){ sucFunReportFlag=0; ReportGps(); } }else if(g_ucKeyValue==KEY_FUN_DOWN && g_ucDKC>2){//FOTA升级 g_ucDKC=0; SlwTrace(INF,"Set modem to FOTA!\r\n"); g_ucNetTaskDisable=0xff; OSTimeDlyHMSM(0, 0, 2, 0); ModemSendAT("AT+POC=10000018\r\n"); }else if(g_ucKeyValue==KEY_FUN_UP){//版本播报 if(0==sucFunReportFlag){ sucFunReportFlag=1; ReportModemVer(g_iModemVer); }else if(1==sucFunReportFlag){ sucFunReportFlag=0; ReportMcuVer(g_iMcuVer); } } } //耳机插入监测 if(g_ucEarDetLast!=g_ucEarDet){ g_ucEarDetLast=g_ucEarDet; if(g_ucEarDet){ SlwTrace(INF,"EarIn\r\n"); ModemSendAT("AT+SPEAKER=0\r\n");//切换耳机通路 }else { SlwTrace(INF,"EarOut\r\n"); ModemSendAT("AT+SPEAKER=1\r\n");//切换外放通路 } } //以下控制每秒执行一次 if(++sucCt>99)sucCt=0; else continue; KeyCount();//键盘按下、释放计数控制 //测量电池电压 Vbat=GetVbat(); if(Vbat>0)g_iVbat=Vbat; //判断电池电压是否过低关机 CheckVbat(g_iVbat); } } /********************************************************************* *SKMBCrossTaskCreate **********************************************************************/ void MainTaskCreate(void) { CPU_INT08U os_err; os_err = os_err; /* prevent warning... */ os_err = OSTaskCreate((void (*)(void *)) MainTask, (void * ) 0, (OS_STK * )&AppMainTaskStk[APP_TASK_MAIN_STK_SIZE - 1], (INT8U ) APP_TASK_MAIN_PRIO ); #if OS_TASK_NAME_EN > 0 OSTaskNameSet(APP_TASK_MAIN_PRIO, "MainTask", &os_err); #endif } void ADCInit(void) { ADC_InitTypeDef ADC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AIN; GPIO_Init(GPIOA,&GPIO_InitStructure); //默认速度为两兆 //配置ADC的运行: ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //独立模式 ADC_InitStructure.ADC_ScanConvMode =DISABLE; //连续多通道模式 ADC_InitStructure.ADC_ContinuousConvMode =DISABLE;//ENABLE; //连续转换 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换不受外界决定 ADC_InitStructure.ADC_DataAlign =ADC_DataAlign_Right; //右对齐 ADC_InitStructure.ADC_NbrOfChannel =1; //扫描通道数 ADC_Init(ADC1,&ADC_InitStructure); ADC_RegularChannelConfig(ADC1,ADC_Channel_0, 1,ADC_SampleTime_1Cycles5); //通道X,采样时间为1.5周期,1代表规则通道第1个这个1是啥意思我不太清楚只有是1的时候我的ADC才正常。 ADC_Cmd (ADC1,ENABLE); //使能或者失能指定的ADC ADC_SoftwareStartConvCmd(ADC1,ENABLE);//使能或者失能指定的ADC的软件转换启动功能 SlwTrace(INF,"ADC Init!\r\n"); } void GPIO_Config_ALL_AIN(void) { GPIO_InitTypeDef GPIO_InitStructure; /* Enable GPIOD and GPIOE clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | RCC_APB2Periph_AFIO, ENABLE); /* Disable the Serial Wire Jtag Debug Port SWJ-DP */ GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE); /* PA */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOA, &GPIO_InitStructure); /* PB */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOB, &GPIO_InitStructure); /* PC */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOC, &GPIO_InitStructure); /* PD */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOD, &GPIO_InitStructure); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD , DISABLE); } /*********************************************************************** *获取电池电压 返回值: -1为无效 ; 正数表示电池电压放大100倍,如 382表示3.82V ***********************************************************************/ int GetVbat(void) { char buf[30]; static int Ct=0; static int siVbat[10]={0,0,0,0,0,0,0,0,0,0}; int iVbat[10]; int max[5]; int sum; int i,j,k; int adc; int Vbat; //采集ADC if(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)!=RESET){//检查制定ADC标志位置1与否 ADC_FLAG_EOC 转换结束标志位 if(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)!=RESET){ adc=ADC_GetConversionValue(ADC1); ADC_SoftwareStartConvCmd(ADC1,ENABLE); if(adc<100 && adc>4095)return -1; }else{ return -1; } //循环存储 siVbat[Ct]=adc; if(++Ct>9)Ct=0; //printf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\r\n",siVbat[0],siVbat[1],siVbat[2],siVbat[3],siVbat[4],siVbat[5],siVbat[6],siVbat[7],siVbat[8],siVbat[9]); //滤波处理,排列取3个最大值,3个最大中去掉第一大,其余求平均 //拷贝 for(i=0;i<10;i++){ iVbat[i]=siVbat[i]; } for(i=0;i<4;i++){ max[i]=0; for(j=0;j<10;j++){ if(iVbat[j]>max[i]){ max[i]=iVbat[j]; k=j; } } iVbat[k]=0; } // printf("%d,%d,%d\r\n",max[0],max[1],max[2]); sum=max[1]+max[2]; if(max[2]<200)return -1; Vbat=sum*340/4096; if(g_ucUARTSel==COM_SEL_MCU){ // sprintf(buf,"Vbat=%d\r\n",Vbat); // SlwTrace(DEBUG,buf); //printf("Vbat=%d\r\n",Vbat); } return Vbat; } /******************************************************* *CheckVbat *检查电池电压,控制低压报警, *低压关机已由硬件监测 ******************************************************/ void CheckVbat(int Vbat) { if(Vbat<355){ LedSlecet(LED_SEL_RED); }else{ LedSlecet(LED_SEL_BLUE); } // // if(Vbat>390){ // //电量3级 // // SetLedFlash(3,3); // }else if(Vbat>365){ // //电量2级 // // SetLedFlash(2,3); // }else if(Vbat>355){ // //电量1级 3575CF913100A77E // // SetLedFlash(1,3); // }else if(Vbat>333){ // //电量不足 3575CF910D4EB38D // // ModemSendAT("AT+ZTTS=1,\"3575CF910D4EB38D\"\r\n"); // // SetLedFlash(1,5); // }else { // // } } /************************************************************************** *语音播报电量,用户按键查询电量时播报 信号较强 "E14FF753838F3A5F" 信号适中 "E14FF75302902D4E" 信号偏低 "E14FF7534F504E4F" 信号很弱 "E14FF753885F315F" **************************************************************************/ void ReportVbat(int Vbat) { char buf[20]; if(Vbat<100)return; //sprintf(buf,"Vbat=%d\r\n",Vbat); // SlwTrace(INF,buf); if(Vbat>390){ //电量3级 "3575CF913300A77E" 电量充足 "3575CF914551B38D" ModemSendAT("AT+ZTTS=1,\"3575CF914551B38D\"\r\n"); }else if(Vbat>365){ //电量2级 "3575CF913200A77E" 电量适中 "3575CF9102902D4E" ModemSendAT("AT+ZTTS=1,\"3575CF9102902D4E\"\r\n"); }else if(Vbat>355){ //电量1级 "3575CF913100A77E" 电量偏低 "3575CF914F504E4F" ModemSendAT("AT+ZTTS=1,\"3575CF914F504E4F\"\r\n"); }else{ //电量不足 "3575CF910D4EB38D" ModemSendAT("AT+ZTTS=1,\"3575CF910D4EB38D\"\r\n"); } } /************************************************************************** *语音播报信号强度 信号较强 "E14FF753838F3A5F" 信号适中 "E14FF75302902D4E" 信号偏低 "E14FF7534F504E4F" 信号很弱 "E14FF753885F315F" **************************************************************************/ void ReportCSQ(int CSQ) { char buf[20]; sprintf(buf,"CSQ=%d\r\n",(int)CSQ); SlwTrace(INF,buf); if(CSQ>31 || CSQ<1){ //无网络信号 "E065517FDC7EE14FF753" ModemSendAT("AT+ZTTS=1,\"E065517FDC7EE14FF753\"\r\n"); return; } if(CSQ>25){ //信号较强 "E14FF753838F3A5F" ModemSendAT("AT+ZTTS=1,\"E14FF753838F3A5F\"\r\n"); }else if(CSQ>17){ //信号适中 "E14FF75302902D4E" ModemSendAT("AT+ZTTS=1,\"E14FF75302902D4E\"\r\n"); }else if(CSQ>10){ //信号偏低 "E14FF7534F504E4F" ModemSendAT("AT+ZTTS=1,\"E14FF7534F504E4F\"\r\n"); }else{ //信号很弱 "E14FF753885F315F" ModemSendAT("AT+ZTTS=1,\"E14FF753885F315F\"\r\n"); } } void ReportModemVer(int ver) { char temp[10]; char buf[50]; int i,j,len; //106:310030003100 sprintf(temp,"%d",ver);//0x31 0x30 0x36 len=strlen(temp); j=0; for(i=0;i0x20 && ';'!=*p){ *Value=*p; p++; Value++; ValueLen++; } *Value=0; return ValueLen; } /******************************************************************** *SavePsnToFlash *********************************************************************/ void SavePsnToFlash(unsigned long PSN) { unsigned short psn1,psn2; psn1=(unsigned short)((PSN>>16)&0xffff); psn2=(unsigned short)(PSN&0xffff); FLASH_Unlock(); FLASH_ClearFlag(FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR); FLASH_ErasePage(0x0801FC00); // FLASH_ProgramHalfWord(FLASH_PAGE_ADDR_PARA,psn1); //flash 为一个字节存储,16位数据必须地址加2 FLASH_ProgramHalfWord(FLASH_PAGE_ADDR_PARA+2,psn2); //flash 为一个字节存储,16位数据必须地址加2 FLASH_Lock(); } /******************************************************************** *ReadPsnFromFlash *********************************************************************/ unsigned long ReadPsnFromFlash(void) { unsigned short psn1,psn2; unsigned long PSN; psn1=*(u16*)FLASH_PAGE_ADDR_PARA; psn2=*(u16*)(FLASH_PAGE_ADDR_PARA+2); PSN=(unsigned long)psn1; PSN<<=16; PSN+=(unsigned long)psn2; return PSN; } /******************************************************************** *SaveParaToFlash 将sutNetPara重要参数保存到FLASH *********************************************************************/ void SaveParaToFlash(void) { int i; unsigned short *pData=(unsigned short *)&sutNetPara; unsigned char rand=sutNetPara.Rand; //保存 FLASH_Unlock(); FLASH_ClearFlag(FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR); FLASH_ErasePage(FLASH_PAGE_ADDR_PARA); // for(i=0;i