main.c
#include "stm32f10x.h"
#include "RS232_module.h"
#include "RS485_module.h"
#include "Display_module.h"
#include "Flash_module.h"
#include "Progess_module.h"
#include "System_module.h"
#include "Iwdg_hard_dri.h"
#include <string.h>
#include <stdio.h>
int main(void)
{
//系统初始化
STM32APP_Init();
//初始化看门狗4s
IWDG_Init(6,625);
//模块初始化
Ds_NetInit();
Ds_TimInit();
Ds_DisplayInit();
//获取复位状态
Ds_GetRest();
//获取序列号
Ds_GetXULIEversions();
if(memcmp((u32*)ARMAPP_upstatus,"SUCCESS_UPDATA_M3APP",20) == 0)
{
//升级成功
g_bSendARMUpdateStatusFlag = TRUE;
g_bARMUpdateStatus = 0xAA;
printf("updata m3 app is sucess \r\n");
}
STMFLASH_ERASEBANK(ARMAPP_upstatus);
while(1)
{
if(UPMCU_FLAG == TRUE)
{
RS485_TX_ENABLE; //关掉串口接收485数据
Ds_UPDATAMCU(); //升级mcu
Rs485_Init_Flag = TRUE; //清除485缓冲区
RS485_RX_ENABLE; //使能串口接收485
UPMCU_FLAG = FALSE;
}
else
{
//300ms
if(Tim_to_Dispalystate == TRUE)
{
Ds_M3Display();
Tim_to_Dispalystate = FALSE;
}
//100ms
if(Tim_to_gate485state == TRUE)
{
Get_Rs485_State();
Tim_to_gate485state = FALSE;
}
//20ms
if(Tim_to_gate232state == TRUE)
{
Get_Rs232_State();
Tim_to_gate232state = FALSE;
}
}
//喂狗
IWDG_Feed();
}
}
Progess_module.c
#include "stm32f10x.h"
#include "RS232_module.h"
#include "RS232_commun.h"
#include "RS485_module.h"
#include "Tim_module.h"
#include "Display_module.h"
#include "Printf_Select.h"
#include "Flash_module.h"
#include "System_module.h"
#include "Time_hard_dri.h"
#include "Iwdg_hard_dri.h"
#include "Display_module.h"
#include "ProductTypedef.h"
#include <string.h>
#include <stdio.h>
u8 const work[]={
0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,
0xc6,0xa1,0x86,0x8e
};
u8 const pro1[][2]={
{0x8c,0xc0},{0x8c,0xf9},
{0x8c,0xa4},{0x8c,0xb0},
{0x8c,0x99},{0x8c,0x92},
{0x8c,0x82},{0x8c,0xf8},
{0x8c,0x80},{0x8c,0x90},
};
u8 const error1[][2]={
{0x86,0xc0},{0x86,0xf9},
{0x86,0xa4},{0x86,0xb0},
{0x86,0x99},{0x86,0x92},
{0x86,0x82},{0x86,0xf8},
{0x86,0x80},{0x86,0x90},
};
u8 const error2[][3]={
{0x86,0xf9,0xc0},
{0x86,0xf9,0xf9},
};
u8 error_pos;
u8 pro_pos;
u8 Dispos_tim;
u8 ba_pos;
void Ds_NetInit(void)
{
RS232_Init(UART_Fir); //初始化232 UART1
Rs485_Init_Flag = TRUE;//先清除485缓冲
RS485_RX_ENABLE; //使能485 接收
RS485_Init(UART_Sec); //初始化485 UART2
Printf_Debug_Init(UART_Thou); //初始化调试口 UART4
}
void Ds_TimInit(void)
{
Tim_select_Init(Tim_Thr); //3//1.8s RS232心跳
Tim_select_Init(Tim_tw); // 20ms获取一次状态 232
Tim_select_Init(Tim_Fou); //100ms获取一次状态485
Tim_select_Init(Tim_Five); //300ms 更新 显示 18s RS232 通讯故障 9s云灯故障 升级mcu 3s超时
}
void Ds_DisplayInit(void)
{
CD4094_Init();//显示初始化
LED_Init(); //灯初始化
LED_STATE_OFF; //状态灯亮
LED_ERROR_OFF;//故障灯亮
LED_CLOUD_OFF; //云灯亮
LED_UPdata_ON; //电源指示灯亮
g_uCurrentKeyRelatedLevel = 0; //档位初始为0
Cd4094DataOutPut(work[g_uCurrentKeyRelatedLevel ]); //显示0档待机
}
//NRST引脚上的低电平复位
int Ds_ResetSelect(void)
{
if(RCC_GetFlagStatus(RCC_FLAG_IWDGRST) == SET) //看门狗复位
return 11 ;
if(RCC_GetFlagStatus(RCC_FLAG_PINRST) == SET) //引脚复位
return 1;
if(RCC_GetFlagStatus(RCC_FLAG_LPWRRST) == SET) //低电平复位
return 12;
if(RCC_GetFlagStatus(RCC_FLAG_PORRST) == SET) //POR/PDR复位
return 3;
return 4;
}
void Ds_GetRest(void)
{
M3Risk.ucChildRisk = Ds_ResetSelect();
// printf("reset is %d\r\n",M3Risk.Risk_nu);
if(M3Risk.ucChildRisk !=1)
M3Risk.Risk_nu = 1;
else
M3Risk.Risk_nu = 0;
}
void Ds_GetXULIEversions(void)
{
STMFLASH_ReadByte_buf(BACK_M3DAT_ADDR_START ,M3_XULIEversions,5);
g_uHardwareType = M3_XULIEversions[0];
memcpy(&g_uiProductSn,&M3_XULIEversions[1],4);
printf("g_uHardwareType is %d\r\n",g_uHardwareType);
printf("g_uiProductSn is %d\r\n",g_uiProductSn);
if((M3_XULIEversions[0] == 255) && (M3_XULIEversions[1] == 255) && (M3_XULIEversions[2] == 255)
&&(M3_XULIEversions[3] == 255)&&(M3_XULIEversions[4] == 255))
{
g_uHardwareType = HardwareType;
g_uiProductSn = ProductSn;
printf("g_uHardwareType is %d\r\n",g_uHardwareType);
printf("g_uiProductSn is %d\r\n",g_uiProductSn);
}
}
void Ds_UPDATAMCU(void)
{
IWDG_Feed();//喂狗
LED_UPdata_ON;
LED_ERROR_ON;//
LED_CLOUD_ON; //
LED_STATE_ON;
TIM2_Stop(); //关掉获取232状态
TIM4_Stop(); //关掉获取485状态
TIM3_Stop(); //停止心跳
printf("main is into upmcu_app\r\n");
if(UPMCUCFI_FLAG == TRUE)
{
UPDATA_MCUAPP(BACK_MCUDAT_ADDR_START); //升级机芯配置
UPMCUCFI_FLAG = FALSE;
}
else
{
UPDATA_MCUAPP(BACK_MCUAPP_ADDR_START); //升级机芯程序
}
IWDG_Feed();//喂狗
Tim_select_Init(Tim_Thr); //3//1.8s心跳
Tim_select_Init(Tim_tw); // 20ms获取一次状态 232
Tim_select_Init(Tim_Fou); //100ms获取一次状态485
LED_STATE_OFF; //状态灯亮
LED_ERROR_OFF;//故障灯灭
LED_CLOUD_OFF; //云灯灭
LED_UPdata_ON; //电源指示指示灯
g_uCurrentKeyRelatedLevel = 0; //档位初始为0
Cd4094DataOutPut(work[g_uCurrentKeyRelatedLevel]); //显示0档待机
printf("leve updata_mcu\r\n");
}
void Dis_FEpos(void)
{
Dispos_tim ++;
if(Dispos_tim >= 2)
{
Dispos_tim = 0;
error_pos ++;
if(error_pos >= ba_pos)
error_pos = 0;
}
}
void Dis_FPpos(void)
{
Dispos_tim ++;
if(Dispos_tim >= 2)
{
Dispos_tim = 0;
pro_pos ++;
if(pro_pos >= ba_pos)
pro_pos = 0;
}
}
void Dis_ErrorInit(void)
{
Dis_c = 0;
Dis_e = 0;
Dispos_tim = 0;
error_pos = 0;
if(Error_value <= 9)
{
ba_pos = 2;
CD4094_Changeshow(error1[Error_value ][error_pos]);
Error_or_pro_lcd();
}
else
{
ba_pos = 3;
CD4094_Changeshow(error2[Error_value - 10 ][error_pos]);
Error_or_pro_lcd();
}
Dis_FEpos();
}
void Dis_PorInit(void)
{
Dis_c = 0;
Dis_e = 0;
Dispos_tim = 0;
pro_pos = 0;
ba_pos = 2;
CD4094_Changeshow(pro1[Pro_value ][pro_pos]);
Error_or_pro_lcd();
Dis_FPpos();
}
void Dis_ProProgess(void)
{
CD4094_Changeshow(pro1[Pro_value][pro_pos]);
Error_or_pro_lcd();
Dis_FPpos();
}
void Dis_ErrorProgess(void)
{
switch(ba_pos)
{
case 2:
CD4094_Changeshow(error1[Error_value ][error_pos]);
Error_or_pro_lcd();
break;
case 3:
CD4094_Changeshow(error2[Error_value - 10][error_pos]);
Error_or_pro_lcd();
break;
}
Dis_FEpos();
}
void Ds_M3Display(void)
{
static SysState_S prestate;
static u8 pretKeyRelatedLevel = 0;
switch(Rs232Sate.eMainState)
{
case IDLE_STATE:
switch(prestate.eMainState)
{
case IDLE_STATE:
break;
default:
LED_STATE_OFF;
LED_ERROR_OFF;
Cd4094DataOutPut(work[0]); //显示0档待机
break;
}
break;
case WORKING_STATE:
switch(prestate.eMainState)
{
case WORKING_STATE:
if(pretKeyRelatedLevel != g_uCurrentKeyRelatedLevel )
{
Cd4094DataOutPut(work[g_uCurrentKeyRelatedLevel]);
pretKeyRelatedLevel = g_uCurrentKeyRelatedLevel;
}
break;
default:
LED_STATE_ON;
LED_ERROR_OFF;
Cd4094DataOutPut(work[g_uCurrentKeyRelatedLevel]);
pretKeyRelatedLevel = g_uCurrentKeyRelatedLevel;
break;
}
break;
case PRO_STATE:
#if (STM32_15KWCOOK ||STM32_15KWSOUP)
switch(Rs232Sate.ucChildState)
{
case NO_PAN_PRO:
switch(prestate.eMainState)
{
case PRO_STATE:
CD4094_Changeshow(work[g_uCurrentKeyRelatedLevel]);
Nopan_Pro_lcd();
break;
default:
Dis_c = 0;
Dis_p = 0;
break;
}
break;
default:
switch(prestate.eMainState)
{
case PRO_STATE:
Dis_ProProgess();
break;
default:
Dis_PorInit();
break;
}
break;
}
#elif STM32_20KWCOOK
switch(prestate.eMainState)
{
case PRO_STATE:
Dis_ProProgess();
break;
default:
Dis_PorInit();
break;
}
#endif
break;
case ERROR_STATE:
switch(prestate.eMainState)
{
case ERROR_STATE:
Dis_ErrorProgess();
break;
default:
Dis_ErrorInit();
break;
}
break;
default :
break;
}
prestate = Rs232Sate;
}
#include "stm32f10x.h"
#include "System_module.h"
#include "Flash_module.h"
void MYRCC_DeInit(void)
{
RCC->APB1RSTR = 0x00000000;//复位结束
RCC->APB2RSTR = 0x00000000;
RCC->AHBENR = 0x00000014; //睡眠模式闪存和SRAM时钟使能.其他关闭.
RCC->APB2ENR = 0x00000000; //外设时钟关闭.
RCC->APB1ENR = 0x00000000;
RCC->CR |= 0x00000001; //使能内部高速时钟HSION
RCC->CFGR &= 0xF8FF0000; //复位SW[1:0],HPRE[3:0],PPRE1[2:0],PPRE2[2:0],ADCPRE[1:0],MCO[2:0]
RCC->CR &= 0xFEF6FFFF; //复位HSEON,CSSON,PLLON
RCC->CR &= 0xFFFBFFFF; //复位HSEBYP
RCC->CFGR &= 0xFF80FFFF; //复位PLLSRC, PLLXTPRE, PLLMUL[3:0] and USBPRE
RCC->CIR = 0x00000000; //关闭所有中断
//配置向量表
}
void Stm32_Clock_Init(u8 PLL)
{
unsigned char temp=0;
// MYRCC_DeInit(); //复位并配置向量表
RCC->CR|=0x00010000; //外部高速时钟使能HSEON
while(!(RCC->CR>>17));//等待外部时钟就绪
RCC->CFGR=0X00000400; //APB1=DIV2;APB2=DIV1;AHB=DIV1;
PLL-=2;//抵消2个单位
RCC->CFGR|=PLL<<18; //设置PLL值 2~16
RCC->CFGR|=1<<16; //PLLSRC ON
FLASH->ACR|=0x32; //FLASH 2个延时周期
RCC->CR|=0x01000000; //PLLON
while(!(RCC->CR>>25));//等待PLL锁定
RCC->CFGR|=0x00000002;//PLL作为系统时钟
while(temp!=0x02) //等待PLL作为系统时钟设置成功
{
temp=RCC->CFGR>>2;
temp&=0x03;
}
}
#define IAP_ADDR 0X08000000
void IapProgramRun(void)
{
u32 IapSpInitVal; //IAP程序的SP初值.
u32 IapJumpAddr; //IAP程序的跳转地址.即,IAP程序的入口.
void (*pIapFun)(void); //定义一个函数指针.用于指向APP程序入口.
MYRCC_DeInit(); //恢复NVIC为复位状态.使中断不再发生.
IapSpInitVal = *(u32 *)IAP_ADDR; //取APP的SP初值.
IapJumpAddr = *(u32 *)(IAP_ADDR + 4); //取程序入口.
__set_MSP (IapSpInitVal); //设置SP.
pIapFun = (void (*)(void))IapJumpAddr; //生成跳转函数.
(*pIapFun) (); //跳转.不再返回.
}
void STM32APP_Init(void)
{
MYRCC_DeInit();
NVIC_SetVectorTable (NVIC_VectTab_FLASH, RUN_M3APP_VECTABLE); //设置APP的向量表
Stm32_Clock_Init(Clock_72MHZ); //72mhz
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
}
#include "stm32f10x.h"
#include "Flash_module.h"
void STMFLASH_WriteByte_buf(u32 addr , u8 *p , u16 Byte_Num)
{
u16 HalfWord;
u16 byte_nu;
byte_nu = Byte_Num%2;
Byte_Num = Byte_Num/2;
FLASH_Unlock();
FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
FLASH_ErasePage(addr);
while(Byte_Num --)
{
HalfWord=*(p);
HalfWord|=*(p+1)<<8;
FLASH_ProgramHalfWord(addr, HalfWord);
addr += 2;
p+=2;
}
if( byte_nu>0)
{
HalfWord = *p;
FLASH_ProgramHalfWord(addr, HalfWord);
}
FLASH_Lock();
}
void STMFLASH_WriteHalfWord_buf(u32 addr , u16 *p , u16 Byte_Num)
{
u16 HalfWord;
FLASH_Unlock();
FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
FLASH_ErasePage(addr);
while(Byte_Num --)
{
HalfWord=*(p++);
FLASH_ProgramHalfWord(addr, HalfWord);
addr += 2;
}
FLASH_Lock();
}
void STMFLASH_ReadByte_buf(u32 ReadAddr, u8 *pBuffer,u16 NumToWrite)
{
u16 i;
for(i =0 ;i<NumToWrite;i++)
{
pBuffer[i] = (u8)(*(u32*)ReadAddr);
ReadAddr +=1;
}
}
void STMFLASH_ReadHalfWord_buf(u32 ReadAddr, u16 *pBuffer,u16 NumToWrite)
{
u16 i;
for(i =0 ;i<NumToWrite;i++)
{
pBuffer[i] = (u16)(*(u32*)ReadAddr);
ReadAddr +=2;
}
}
void STMFLASH_ERASEBANK(u32 bankaddr)
{
u16 i = 100;
FLASH_Unlock();
FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
FLASH_ErasePage(bankaddr);
while(i--);
FLASH_Lock();
}
#ifndef __FASH_MODULE__
#define __FASH_MODULE__
#include "stm32f10x.h"
#define STM32_FLASH_BASE 0x08000000
#define STM32_FLASH_SIZE 512 // 单位k
#define OneKbit 1024
#define PAGE_SIZE 2048
#define PAGE_NU 255
#define BOOTLOADER_ADDR_START 0x08000000
#define RUN_M3APP_VECTABLE 0x00010000
#define BOOTLOADER_VECTABLE 0x0
#define RUN_M3APP_ADDR_START 0x08010000 // 0x08010 000 --- 0x0802 8FFF
#define RUN_M3APP_PAGE_SIZE ( PAGE_SIZE * 50 )
#define RUN_M3DAT_ADDR_START 0x08029000 //0x0802 9000---- 0X0802 B7FF
#define RUN_M3DAT_PAGE_SIZE ( PAGE_SIZE * 5 )
#define BACK_M3APP_ADDR_START 0x0802b800
#define BACK_M3APP_PAGE_SIZE ( PAGE_SIZE * 50 )
#define BACK_M3DAT_ADDR_START 0x08044800
#define BACK_M3DAT_PAGE_SIZE ( PAGE_SIZE * 5 )
#define BACK_MCUAPP_ADDR_START 0x08047000
#define BACK_MCUAPP_PAGE_SIZE ( PAGE_SIZE * 50 )
#define BACK_MCUDAT_ADDR_START 0x08060000
#define BACK_MCUDAT_PAGE_SIZE ( PAGE_SIZE * 5 )
#define ARMAPP_upstatus 0x08062800
#define ARMAPP_upstatus_PAGE_SIZE ( PAGE_SIZE *1)
#define ARMCFG_upstatus 0x08063000
#define ARMCFG_upstatus_PAGE_SIZE ( PAGE_SIZE *1)
#define PRODUCT_ID_MAX_SIZE 5 //max size of all product device
#define RS485_RECE_MAX ( PAGE_SIZE *20)
void STMFLASH_WriteByte_buf(u32 , u8 * , u16 );
void STMFLASH_WriteHalfWord_buf(u32 , u16 * , u16 );
void STMFLASH_ReadByte_buf(u32 , u8 *,u16 );
void STMFLASH_ReadHalfWord_buf(u32 , u16 *,u16 );
void STMFLASH_ERASEBANK(u32 );
typedef enum RS485_UPdatetype
{
ARMAPP,
}RS485_UPdatetype_E;
typedef struct UpdateFilePacket_Stru
{
u8 ucDevType; //cmd type define in UplinkCmdType_E
u32 uiTotalLen; //total len of update file
u32 uiLenOffset; //total len of update file
int uinDataPackNum;
u8 bufProductID[PRODUCT_ID_MAX_SIZE];//product NO. + SN
u32 uiFileNameLen; //len of update file name
u8 pFileName[60]; //update file name
u8 pDataBuf[RS485_RECE_MAX]; //data of file
}UpdateFilePacket_S;
typedef struct FlashW_buf
{
u8 UPdateW_buf[ PAGE_SIZE];
u16 UPdateW_Pagenu;
u16 UPdateW_Bytenu;
}upFlashW_buf;
#endif
#include "stm32f10x.h"
#include "CRC16.h"
u16 GetCRC16Code( u8 *pCalcBuf,u32 nSize)
{
u32 i = 0;
u32 j = 0;
u16 usReturnValue = 0xFFFF;
u16 usNew = 0xA001;
for (i=0; i<nSize; ++i)
{
usReturnValue ^= pCalcBuf[i];
for(j=0; j<8; ++j)
{
if(usReturnValue & 0x0001)
{
usReturnValue >>= 1;
usReturnValue ^= usNew;
}
else
{
usReturnValue >>= 1;
}
}
}
return usReturnValue;
}
void Write_Data_toFlash(u8 *File_RECEBUF ,u32 recelen ,u32 FlashAddr)
{
u8 i;
u16 pagenu;
u16 Bytenu;
u16 upadte_statue[2];
u16 buf[2];
pagenu = recelen /PAGE_SIZE ;
Bytenu = recelen % PAGE_SIZE;
upadte_statue[0] = pagenu;
upadte_statue[1] = Bytenu;
printf("pagenu is %d\r\n" ,pagenu);
printf("Bytenu is %d\r\n" , Bytenu);
//喂狗
IWDG_Feed();
WFlash_buf.UPdateW_Pagenu = pagenu;
WFlash_buf.UPdateW_Bytenu = Bytenu;
STMFLASH_WriteHalfWord_buf(FlashAddr -4 , upadte_statue , 2 );
STMFLASH_ReadHalfWord_buf(FlashAddr -4 , buf, 2);
printf(" read buf[0] is %d\r\n",buf[0]);
printf(" read buf[1] is %d\r\n",buf[1]);
#if 1
if(pagenu > 0)
{
for(i = 0;i<pagenu;i++)
{
memcpy(WFlash_buf.UPdateW_buf,File_RECEBUF, PAGE_SIZE);
STMFLASH_WriteByte_buf(FlashAddr , WFlash_buf.UPdateW_buf , PAGE_SIZE);
File_RECEBUF +=PAGE_SIZE;
FlashAddr +=PAGE_SIZE;
printf("write paegnu is %d\r\n",i);
}
}
memset(WFlash_buf.UPdateW_buf,0x00,PAGE_SIZE);
memcpy(WFlash_buf.UPdateW_buf,File_RECEBUF, Bytenu);
STMFLASH_WriteByte_buf(FlashAddr , WFlash_buf.UPdateW_buf , Bytenu);
#endif
}
Write_Data_toFlash(g_sUpdateInfo.pDataBuf ,g_sUpdateInfo.uiTotalLen ,BACK_MCUAPP_ADDR_START);
//写上升级标志
STMFLASH_WriteByte_buf(ARMAPP_upstatus ,updataM3status , strlen(updataM3status));
STMFLASH_ReadByte_buf(ARMAPP_upstatus , debugupdata,strlen(updataM3status));
debugupdata[strlen(updataM3status)] = '\0' ;
printf("debugupdata is %s\r\n",debugupdata);
RS485_delay();
NVIC_SetVectorTable (NVIC_VectTab_FLASH, 0x0);
IapProgramRun(); //跳转向Bootloader
#include "stm32f10x.h"
#include "Iwdg_hard_dri.h"
//初始化独立看门狗
//prer:分频数:0~7(只有低 3 位有效!)
//分频因子=4*2^prer.但最大值只能是 256!
//rlr:重装载寄存器值:低 11 位有效.
//时间计算(大概):Tout=((4*2^prer)*rlr)/40 (ms).
//prer 4 rlr 625 时间是1s
void IWDG_Init(u8 prer,u16 rlr)
{
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //①使能对寄存器 I 写操作
IWDG_SetPrescaler(prer); //②设置 IWDG 预分频值:设置 IWDG 预分频值
IWDG_SetReload(rlr); //②设置 IWDG 重装载值
IWDG_ReloadCounter(); //③按照 IWDG 重装载寄存器的值重装载 IWDG 计数器
IWDG_Enable(); //④使能 IWDG
}
//喂独立看门狗
void IWDG_Feed(void)
{
IWDG_ReloadCounter();//reload
}