微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > stc单片机累计浮点数自动清零的问题

stc单片机累计浮点数自动清零的问题

时间:10-02 整理:3721RD 点击:

写了个电表程序,把累计的电量值放在定义的一个浮点数中(float),一段时间后会自动清零,哪位大神知道是什么原因吗?程序在附件中,加了掉电存储和定时存入24C08,重启后读取,数值清零发生在芯片重启(可能是看门狗溢出)后,手动离线或断电,或者使看门狗启动都不会掉数据,但正常运行一段时间就会发生(E_Power)这个变量!
下面是主程序,后面是CS5460的程序


*************************************************************************/
#include <stdio.h>
#include <intrins.h>
#include <stc12c5a60s2.h>
#include "mytypes.h"
#include "i2c.h"
#include "spi.h"
#include "2send1re.H"
#include "net_com.h"
#include "DS1302.H"
#include "EEPROM.H"


//sbit RS485EE=P4^3;      //串口2定义485的使能脚A板
sbit RS485EE=P3^4;      //串口2定义485的使能脚B板
sbit RELAY=P4^1;      //RELAY3.5-4.1
sbit LED1=P3^6;      //led1  D14
sbit LED2=P3^5;      //led2 D15
sbit CP=P1^0;      //CP
unsigned char RELAY_val=0xff;     //继电器保存的值
unsigned char  SendFlag=0;
uchar g_eeprom_sector_cnt=0;
#define OFFLINE_TIME   130      //掉线检测周期130s
#define EEPROM_SECTOR_CNT 15  //16个扇区  
#define EEPROM_FLAG  0X66  //eeprom erase
#define S2RI 0x01
#define S2TI 0x02
bit RI2;
bit TI2;
//定时,延时用
unsigned int count=0;
unsigned int timer_count=0;
unsigned int gtimer_count2=0;
unsigned int gLoopQueryCount=0;
unsigned int g_comStat=0;
unsigned char g_ComCnt=0; //统计通信次数,离线判断用
volatile unsigned int His_data_len=0;
unsigned int E_Con=0;
unsigned int re_con=0;
//操作eeprom记录用
EEPROM_STAT g_eeprom_stat;
unsigned char xdata g_Address[56]={0};   //28K56个扇区
//数据集中器通信用变量
volatile uchar g_totalRvcCnt=0;
volatile uchar g_RvcCnt=0;
volatile bit g_NetStat;
uchar g_swStat,g_slaveId;
//延时用
volatile uint g_timeCnt;
unsigned char xdata E_Frame[20]={0};
unsigned char xdata EEPROM_Frame[25]={0}; //从EEPROM中读取的数据帧
float E_Power;
volatile unsigned char xdata Elect[6]={0};      //定义电量累计数据
unsigned char xdata UIData[6]={0};  //读取的电流和电压
unsigned char xdata N_Frame[20]={0};  //数据集中器对下发送的查询指令
typedef union
             {
      unsigned char var[4];
         float floatvar;
     }float_var;
float_var elevar;
/**************************************
           延时程序
**************************************/
void delay(uint i)
{
unsigned char j;
for(i; i > 0; i--)
  for(j = 200; j > 0; j--);
}
//*****************************************************************************
//函数名:     void save_parameter_toflash(void)
//函数功能描述: 保存参数到eerom
//函数参数:   无
//函数返回值:    无
//作者:    szl
//修改人:
//修改原因:
//*****************************************************************************
void save_parameter_toflash(void)
{
uint addr=0;
uchar xdata tmp[70];
addr=0x1fa4;
// addr=100;
// elevar.floatvar=E_Power;

tmp[0]=(uchar)g_eeprom_stat.last_write_addr;     //eeprom操作当前地址
tmp[1]=(uchar)g_eeprom_stat.last_write_addr>>8;     //eeprom操作当前地址
tmp[2]=g_eeprom_stat.record_cnt;     //记录数
tmp[3]=g_eeprom_stat.current_send_sector_num;     //已发送数据的当前扇区编号
tmp[4]=g_eeprom_stat.sector_send_up;     //上半部分记录已发送
tmp[5]=g_eeprom_stat.last_write_sector_num;     //最后一个扇区编号

tmp[6]=g_eeprom_stat.overflow_flag;     //溢出标志
tmp[7]=g_eeprom_stat.sector_cnt;     //扇区编号
tmp[8]=EEPROM_FLAG;     //parameter save flag,means save ok
       //
// tmp[9]=elevar.var[0];
// tmp[10]=elevar.var[1];
// tmp[11]=elevar.var[2];
// tmp[12]=elevar.var[3];    //保存累计电量
tmp[13]=RELAY_val;      //保存继电器状态
MyMemCpy(tmp+14,g_Address,56); //加入数据段
eeprom_data_write(tmp,addr,70);  //将数据存入eeprom
// write_i2c_data(addr,tmp,70);
}
//*****************************************************************************
//函数名:     void read_parameter_fromflash(void)
//函数功能描述: 从eerom读取参数
//函数参数:   无
//函数返回值:    无
//作者:    szl
//修改人:
//修改原因:
//*****************************************************************************
void read_parameter_fromflash(void)
{
uint addr=0;
uchar xdata tmp[70]={0};
addr=0x1fa4;
// addr=100;
eeprom_data_read(tmp,addr,70);
    eeprom_byte_erase(0x1e00);
// Uart2Send(tmp,70);
if(tmp[8]==EEPROM_FLAG)                    //保存过参数
{
  g_eeprom_stat.last_write_addr=tmp[0];     //eeprom操作当前地址
  g_eeprom_stat.last_write_addr=tmp[1]*256;     //eeprom操作当前地址 左移8位
  
  g_eeprom_stat.record_cnt=tmp[2];     //记录数
  g_eeprom_stat.current_send_sector_num=tmp[3];     //已发送数据的当前扇区编号
  g_eeprom_stat.sector_send_up=tmp[4];     //上半部分记录已发送
  g_eeprom_stat.last_write_sector_num=tmp[5];     //最后一个扇区编号
  
  g_eeprom_stat.overflow_flag=tmp[6];     //溢出标志
  g_eeprom_stat.sector_cnt=tmp[7];     //扇区编号
//  elevar.var[0]=tmp[9];
//  elevar.var[1]=tmp[10];
//  elevar.var[2]=tmp[11];
//  elevar.var[3]=tmp[12];
  RELAY_val=tmp[13];
//  E_Power=elevar.floatvar;
  MyMemCpy(g_Address,tmp+14,56); //加入数据段
   if(g_eeprom_stat.sector_cnt==0&&g_Address[0]==1)    //无离线保存的记录
  {
    His_data_len=1;
  }
  if(g_eeprom_stat.sector_cnt>0)    //有离线保存的记录
   {
    His_data_len=(g_eeprom_stat.sector_cnt-1)*30;
    His_data_len+=g_Address[g_eeprom_stat.last_write_sector_num];
    if(g_eeprom_stat.overflow_flag==1)
    {
     His_data_len=EEPROM_SECTOR_CNT*30;
     His_data_len+=g_Address[g_eeprom_stat.last_write_sector_num];
    }
   }
}else     //第一次使用
{
     EEPROM_Erase();
  delay(400);
  delay(400);
}
}
//*****************************************************************************
//函数名:     void poweroff_init(void)
//函数功能描述: 使能掉电检测中断
//函数参数:   无
//函数返回值:    无
//作者:    szl
//修改人:
//修改原因:
//*****************************************************************************
void poweroff_check_init(void)
{
P4SW&=0XBF;   //set p4.6 as lvd pin
WAKE_CLKO=0X08; //enable lvd signal wakeup mcu
ELVD=1;             //enable lvd interrupt
PCON&=0XDF;
}
//*****************************************************************************
//函数名:     void lvdint()
//函数功能描述: 掉电检测中断
//函数参数:   无
//函数返回值:    无
//作者:   szl
//修改人:
//修改原因:
//*****************************************************************************
void lvdint() interrupt 6
{
  uchar tmp;
PCON&=0XDF;  //clear LVD flag
tmp=(PCON&0X20);
if(tmp>0)  //还是1则是掉电了,否则是电源波动
{
   elevar.floatvar=E_Power;
   write_i2c_data(0,elevar.var,4);                      //掉电时保存电量数据
   save_parameter_toflash();    //保存数据
   PCON&=0XDF;  //clear LVD flag
   ELVD=0;             //disenable lvd interrupt
   PCON&=0Xfd;
}
}
//*****************************************************************************
//函数名:     void exint0()
//函数功能描述: 外部0中断处理 ,读取电表累计电量
//函数参数:   无
//函数返回值:    无
//作者:       szl
//修改人:
//修改原因:
//*****************************************************************************
void exint1() interrupt 2
  {
//   EA=0;
   SCAN_CS5460();
   SendFlag++;
//   EA=1;
  }
/**************************************
       取电表返回数据E_Frame中数据域处理并加入时钟nowTime组成新数组EEPROM_Frame
**************************************/
void NewFrame(void)
{
unsigned long elect ;
uchar xdata nowTime[7];
EX1=0;  //关闭外部中断
elect=E_Power;
Elect[2]=elect;
Elect[1]=elect>>8;
Elect[0]=elect>>16;
elect=E_Power;
Elect[3]=(E_Power-elect)*100;
//// if(Elect[3]==0xff)
//// {
////   unsigned char i;
////  for(i=0;i<6;i++)
////     {
////   Elect=0;
////   }
//// }
Elect[4]=0x01;       //表示后面没有其它电量数据
Elect[5]=0x04;       //电量值为四个字节
    EX1=1;    //打开外部中断
dsReadTime(nowTime);
Reverse(nowTime,7);
MyMemCpy(EEPROM_Frame,nowTime,7);  
MyMemCpy((EEPROM_Frame+7),UIData,6); ///----------------- 电流电压放入
MyMemCpy((EEPROM_Frame+13),Elect,6); //电量放入
MyMemCpy((EEPROM_Frame+19),Elect,4); //电量放入
// Uart2Send(EEPROM_Frame,17);
}

/*******************************************************
*******************************************************
                     主程序
*******************************************************
*******************************************************/
void main (void)
{

uint sysStat=0;
EA = 0;        // 关总中断
// LED1=1;
// LED2=0;
P0=0XFF;
PortsInit();  //set port0 input
GetSlaveId();
Uart2Init();  //1200   
// UartInit();  //4800
DS1302_init(); //DS1302 io初始化
// RtcInit();   //第一次使用时初始化DS1302时间
Timer0Init();
eeprom_op_init();
delay(1000);
    WDT_CONTR=0x3F;    //清狗指令
poweroff_check_init();  //使能掉电检测
read_parameter_fromflash();
//// P1DIR |= 0x60;  //P15、P16定义为输出
Init_5460(); //初始化SPI
// Sync_5460(); //5460校准
TR0=1;
g_comStat=0;      //默认不在线
//  
// RS485E=0; //串口2 485置接收
RS485EE=0; //串口1 485置接收
LED2=1;
read_i2c_data(0,elevar.var,4);
E_Power=elevar.floatvar;               //上电读取以前的累计电量
RELAY=RELAY_val;
IT1=0;        //外部1中断模式1 下降沿触发0低电平触发
EX1=1;        //外部1中断允许1允许中断 0禁止中断
EA =1;               // 开总中断
E_Con=0;
if(E_Power==0)                         //没读到数据再读一次
   {
     delay(100000);
     read_i2c_data(0,elevar.var,4);
     E_Power=elevar.floatvar;
       }
while(1)
   {
  sysStat++;
     WDT_CONTR=0x3F;    //清狗指令
  
  if(sysStat==120)   //灯闪一次
  {
   E_Con++;
   re_con++;
      if((g_comStat==0)&&(re_con>300))    //采集器离线
         {
       EA=0;
    elevar.floatvar=E_Power;
    write_i2c_data(0,elevar.var,4);
       ((void (code *) (void)) 0x0000) ();
      }
   sysStat=0;
      LED1=~LED1;   
   }
    //*******************************************************
//处理与主控制器的通信
//*******************************************************
  DealCmd();   //处理从控制器发来的命令
  LoopQueryStat();       //判断是否掉线
delay(20);
if(g_eeprom_stat.overflow_flag==1)
{
     g_eeprom_stat.read_start_sector=(g_eeprom_stat.last_write_sector_num+1);
}else
{
  g_eeprom_stat.read_start_sector=0;
}
//*******************************************************
//处理电表数据
//*******************************************************   
          if(g_comStat)  //如果控制器在线
   {
     if(g_Address[0]>1||g_eeprom_stat.sector_cnt>0)    //有离线保存的记录send and insert record
     {
         LostConnection_Process();  //处理从电表发来的数据(掉电存储)
     }
     else //没有离线保存的记录read and update data
     {
      
      if (SendFlag>=10)   //CS5460 转换就绪
      {
      //存储当前检测的数据
      SendFlag=0;      
      NewFrame();     //打包准备数据
      
      eeprom_byte_erase(0x0000);
      delay(100);
      eeprom_data_write(EEPROM_Frame,0x0000,23);   //将数据存入eeprom
      g_Address[0]=0x01;
      g_eeprom_stat.last_write_addr=0x00;       //存储记录
      g_eeprom_stat.last_write_sector_num=0;
      g_eeprom_stat.current_send_sector_num=0;
      His_data_len=1;
      if(E_Con==800)
      {
      E_Con=0;
      EA = 0;        // 关总中断
      while(1)
      {
      elevar.floatvar=E_Power;                   //定时保存电量数据至24C08
      write_i2c_data(0,elevar.var,4);
         read_i2c_data(0,elevar.var,4);
      if(elevar.floatvar==E_Power)
      break;
             WDT_CONTR=0x3F;    //清狗指令
      delay(100000);
      }
//      x24c08_write(5,RELAY_val);      
      EA = 1;
      }
      }
      }
   }
   else   //控制器离线
   {
               LostConnection_Process();  //处理从电表发来的数据(掉电存储)
   }
}
}

cs5460程序,只有最后涉及E_Power这个变量

void SCAN_CS5460(void)
   {

   VoltRMS = CS5460_GetRMS(12)*432.5;
   VoltRMS += 0.005;      //保留小数点后两位
   CurrentRMS = CS5460_GetRMS(11)*10.58;
   CurrentRMS += 0.005;    //保留小数点后两位
  
UIData[0]=CurrentRMS/256;
UIData[1]=CurrentRMS;
UIData[2]=(CurrentRMS-UIData[1])*100;
UIData[3]=VoltRMS/256;
UIData[4]=VoltRMS;
UIData[5]=(VoltRMS-UIData[4])*100;
if(UIData[2]>0)
  {
      ElectRMS=CS5460_GetElectRMS(10)*2.048*432.5*10.58;  //读取电量
   ElectRMS=ElectRMS/3600.0/1000.0 ;
   CurrentRMS=CurrentRMS/10000.0;
   if(ElectRMS<CurrentRMS)                          //过滤数据
   {
     float power;
  power=E_Power;
  power+=ElectRMS;
  if((power>0)&(ElectRMS<1))
     E_Power=power;
   }
   }
  Clear_DRDY();
}

a

b

ssssssssssssssssssssssssssssssssssssssssssssssss

上面是CS5460程序,下面是主程序,主要是E_POWER这个变量

/*************************************************************************
* Copyright (c) 2012, 元澄智能科技有限公司
* All rights reserved.
* STC12C5A16S2
* 文件名称:2send1re.c
* 文件标识:2send1re.c
* 摘要:采集电表数据,存储,然后发送给网络控制器,如果控制器在线直接发送,不在线显存储,上线后发送
* 资源配置:UART1和网络控制器通信,UART2和电表通信
* 电表波特率:1200   和网络控制器通信波特率:4800
* eeprom分配最后一个扇区存放参数,其他的存放电量数据
*
* 当前版本:1.0.03
* 作者:wenzer
* 完成日期:2013-02-26
* 修改内容:
*
* 当前版本:1.0.04
* 修改者: 张振亮
* 完成日期:2012年11月10日
*
* 当前版本:1.0.05
* 修改者:         张振亮
*修改内容:命令接收函数,发送函数
* 完成日期:2013年03月18日
* 当前版本:1.0.07
* 修改者:         张振亮
*修改内容:命令接收函数,发送函数
* 完成日期:2013年03月25日
*************************************************************************/
#include <stdio.h>
#include <intrins.h>
#include <stc12c5a60s2.h>
#include "mytypes.h"
#include "i2c.h"
#include "spi.h"
#include "2send1re.H"
#include "net_com.h"
#include "DS1302.H"
#include "EEPROM.H"

//sbit RS485EE=P4^3;                           //串口2定义485的使能脚A板
sbit RS485EE=P3^4;                           //串口2定义485的使能脚B板
sbit RELAY=P4^1;                           //RELAY3.5-4.1

sbit LED1=P3^6;                           //led1  D14
sbit LED2=P3^5;                           //led2        D15
sbit CP=P1^0;                           //CP
unsigned char RELAY_val=0xff;                                 //继电器保存的值
unsigned char  SendFlag=0;
uchar g_eeprom_sector_cnt=0;
#define OFFLINE_TIME   130             //掉线检测周期130s
#define EEPROM_SECTOR_CNT 15                //16个扇区         
#define EEPROM_FLAG  0X66                //eeprom erase
#define S2RI 0x01
#define S2TI 0x02
bit RI2;
bit TI2;
//定时,延时用
unsigned int count=0;
unsigned int timer_count=0;
unsigned int gtimer_count2=0;
unsigned int gLoopQueryCount=0;
unsigned int g_comStat=0;
unsigned char g_ComCnt=0; //统计通信次数,离线判断用
volatile unsigned int His_data_len=0;
unsigned int E_Con=0;
unsigned int re_con=0;
//操作eeprom记录用
EEPROM_STAT g_eeprom_stat;
unsigned char xdata g_Address[56]={0};          //28K56个扇区



//数据集中器通信用变量
volatile uchar g_totalRvcCnt=0;
volatile uchar g_RvcCnt=0;
volatile bit g_NetStat;
uchar g_swStat,g_slaveId;
//延时用
volatile uint g_timeCnt;

unsigned char xdata E_Frame[20]={0};
unsigned char xdata EEPROM_Frame[25]={0};        //从EEPROM中读取的数据帧
float E_Power;
volatile unsigned char xdata Elect[6]={0};                    //定义电量累计数据
unsigned char xdata UIData[6]={0};                //读取的电流和电压
unsigned char xdata N_Frame[20]={0};                //数据集中器对下发送的查询指令
typedef union
             {
                           unsigned char var[4];
                       float floatvar;
                          }float_var;
float_var elevar;
//*****************************************************************************
//函数名:                  将一个数组所有元素清0
//函数功能描述:         
//函数参数:                 数组名,长度
//函数返回值:                  无
//作者:                  wenzer
//修改人:
//修改原因:
//*****************************************************************************
void my_bzero(unsigned char *arr,unsigned int len)
{
unsigned int i;
for(i=0;i<len;i++)
        {
          arr[i]=0;
        }
}
/**************************************
                  延时程序
**************************************/
void delay(uint i)
{
        unsigned char j;
        for(i; i > 0; i--)
                for(j = 200; j > 0; j--);
}
//*****************************************************************************
//函数名:                          void save_parameter_toflash(void)
//函数功能描述:        保存参数到24c08
//函数参数:                 无
//函数返回值:                  无
//作者:                  wenzer
//修改人:
//修改原因:
//*****************************************************************************
void save_parameter_toflash(void)
{
        uint addr=0;
        uchar xdata tmp[70];
        addr=0x1fa4;
//        addr=100;
//        elevar.floatvar=E_Power;
       
        tmp[0]=(uchar)g_eeprom_stat.last_write_addr;     //eeprom操作当前地址
        tmp[1]=(uchar)g_eeprom_stat.last_write_addr>>8;     //eeprom操作当前地址
        tmp[2]=g_eeprom_stat.record_cnt;     //记录数
        tmp[3]=g_eeprom_stat.current_send_sector_num;     //已发送数据的当前扇区编号
        tmp[4]=g_eeprom_stat.sector_send_up;     //上半部分记录已发送
        tmp[5]=g_eeprom_stat.last_write_sector_num;     //最后一个扇区编号
       
        tmp[6]=g_eeprom_stat.overflow_flag;     //溢出标志
        tmp[7]=g_eeprom_stat.sector_cnt;     //扇区编号
        tmp[8]=EEPROM_FLAG;     //parameter save flag,means save ok
                                                        //
//        tmp[9]=elevar.var[0];
//        tmp[10]=elevar.var[1];
//        tmp[11]=elevar.var[2];
//        tmp[12]=elevar.var[3];                  //保存累计电量
        tmp[13]=RELAY_val;                           //保存继电器状态
        MyMemCpy(tmp+14,g_Address,56);        //加入数据段
        eeprom_data_write(tmp,addr,70);  //将数据存入eeprom
//        write_i2c_data(addr,tmp,70);
}
//*****************************************************************************
//函数名:                          void read_parameter_fromflash(void)
//函数功能描述:        从24c08读取参数
//函数参数:                 无
//函数返回值:                  无
//作者:                  wenzer
//修改人:
//修改原因:
//*****************************************************************************
void read_parameter_fromflash(void)
{
        uint addr=0;
        uchar xdata tmp[70]={0};
        addr=0x1fa4;
//        addr=100;
        eeprom_data_read(tmp,addr,70);
    eeprom_byte_erase(0x1e00);
//        Uart2Send(tmp,70);
        if(tmp[8]==EEPROM_FLAG)                           //保存过参数
        {
                g_eeprom_stat.last_write_addr=tmp[0];     //eeprom操作当前地址
                g_eeprom_stat.last_write_addr=tmp[1]*256;     //eeprom操作当前地址 左移8位
               
                g_eeprom_stat.record_cnt=tmp[2];     //记录数
                g_eeprom_stat.current_send_sector_num=tmp[3];     //已发送数据的当前扇区编号
                g_eeprom_stat.sector_send_up=tmp[4];     //上半部分记录已发送
                g_eeprom_stat.last_write_sector_num=tmp[5];     //最后一个扇区编号
               
                g_eeprom_stat.overflow_flag=tmp[6];     //溢出标志
                g_eeprom_stat.sector_cnt=tmp[7];     //扇区编号
//                elevar.var[0]=tmp[9];
//                elevar.var[1]=tmp[10];
//                elevar.var[2]=tmp[11];
//                elevar.var[3]=tmp[12];
                RELAY_val=tmp[13];       
//                E_Power=elevar.floatvar;
                MyMemCpy(g_Address,tmp+14,56);        //加入数据段
                 if(g_eeprom_stat.sector_cnt==0&&g_Address[0]==1)                  //无离线保存的记录
                {
                  His_data_len=1;
                }
                if(g_eeprom_stat.sector_cnt>0)                  //有离线保存的记录
                        {
                                His_data_len=(g_eeprom_stat.sector_cnt-1)*30;
                                His_data_len+=g_Address[g_eeprom_stat.last_write_sector_num];
                                if(g_eeprom_stat.overflow_flag==1)
                                {
                                        His_data_len=EEPROM_SECTOR_CNT*30;
                                        His_data_len+=g_Address[g_eeprom_stat.last_write_sector_num];
                                }       
                        }
        }else                   //第一次使用
        {
            EEPROM_Erase();
                delay(400);
                delay(400);
        }
}
//*****************************************************************************
//函数名:                          void poweroff_init(void)
//函数功能描述:        使能掉电检测中断
//函数参数:                 无
//函数返回值:                  无
//作者:                  wenzer
//修改人:
//修改原因:
//*****************************************************************************
void poweroff_check_init(void)
{
        P4SW&=0XBF;   //set p4.6 as lvd pin
        WAKE_CLKO=0X08; //enable lvd signal wakeup mcu
        ELVD=1;             //enable lvd interrupt
        PCON&=0XDF;
}
//*****************************************************************************
//函数名:                          void lvdint()
//函数功能描述:        掉电检测中断
//函数参数:                 无
//函数返回值:                  无
//作者:                  wenzer
//修改人:
//修改原因:
//*****************************************************************************
void lvdint() interrupt 6
{
  uchar tmp;
        PCON&=0XDF;  //clear LVD flag
        tmp=(PCON&0X20);
        if(tmp>0)  //还是1则是掉电了,否则是电源波动
        {
          elevar.floatvar=E_Power;
          write_i2c_data(0,elevar.var,4);
          save_parameter_toflash();                                //保存数据
          PCON&=0XDF;  //clear LVD flag
          ELVD=0;             //disenable lvd interrupt
          PCON&=0Xfd;
        }
}
//*****************************************************************************
//函数名:                          void exint0()
//函数功能描述:        外部0中断处理 ,读取电表累计电量
//函数参数:                 无
//函数返回值:                  无
//作者:                     szl
//修改人:
//修改原因:
//*****************************************************************************
void exint1() interrupt 2
  {
//   EA=0;
   SCAN_CS5460();
   SendFlag++;
//   EA=1;
  }
//*****************************************************************************
//函数名:                          Timer0Init(void)
//函数功能描述:        定时器0初始化,初值设定1毫秒@11.0592MHz
//函数参数:         
//函数返回值:          
//作者:                  wenzer
//修改人:
//修改原因:
//*****************************************************************************
void Timer0Init(void)                //1毫秒@11.0592MHz
{
        AUXR |= 0x80;                //定时器时钟1T模式
        TMOD &= 0xF0;                //设置定时器模式
        TMOD |= 0x01;                //设置定时器模式
        TL0 = 0xCD;                //设置定时初值
        TH0 = 0xD4;                //设置定时初值
        TF0 = 0;                //清除TF0标志
        TR0 = 1;                //定时器0开始计时
        ET0 = 1;
        count = 1;
}
//*****************************************************************************
//函数名:                         tm0_isr() interrupt 1 using 1
//函数功能描述:        定时器1中断服务函数(1s)
//函数参数:         
//函数返回值:          
//作者:                  wenzer
//修改人:
//修改原因:
//*****************************************************************************
void tm0_isr() interrupt 1 using 1                  //定时器1中断,方式1(1s)
{
        TR0=0;
        TF0=0;
        TL0 = 0xCD;                //设置定时初值
        TH0 = 0xD4;                //设置定时初值
        if (count--==0)
        {               
        count =1000;
                timer_count++;
                gLoopQueryCount++;
                gtimer_count2++;
               
        }
        TR0=1;
}
/**************************************
       数组反转倒序输出
**************************************/
void Reverse(uchar * array, uchar len)
{
        uchar i;
        for ( i = 0; i < len / 2; ++ i)
        {
                uchar temp = array[i];
                array[i] = array[len - 1 - i];
                array[len - 1 - i] = temp;
        }
}
//*****************************************************************************
//函数名:                  
//函数功能描述:
//函数参数:          
//函数返回值:          
//作者:                  wenzer
//修改人:
//修改原因:
//*****************************************************************************
/*
uchar RolData(uchar x)
{
         x = ((x<<4) & 0xf0) | ((x>>4) & 0x0f);
         x = ((x<<2) & 0xcc) | ((x>>2) & 0x33);
         x = ((x<<1) & 0xaa) | ((x>>1) & 0x55);
         return x;
}
*/
//*****************************************************************************
//函数名:                  
//函数功能描述:
//函数参数:引脚序号,0输出1输入         
//函数返回值:          
//作者:                  wenzer
//修改人:
//修改原因:
//*****************************************************************************
void Port0Set(uchar pnum,uchar stat)
{
        if(stat)
        {
                P0M1|=pnum;
                P0M0&=(~pnum);
        }
        else
        {
                P0M0|=pnum;
                P0M1&=(~pnum);
        }
}
//*****************************************************************************
//函数名:                  
//函数功能描述:
//函数参数:          
//函数返回值:          
//作者:                  wenzer
//修改人:
//修改原因:
//*****************************************************************************
void PortsInit(void)
{
        Port0Set(0xff,1);
}
//*****************************************************************************
//函数名:                  
//函数功能描述:
//函数参数:          
//函数返回值:          
//作者:                  wenzer
//修改人:
//修改原因:
//*****************************************************************************
void GetSlaveId(void)
{
        volatile uchar st;
        CP=0;
        delay(50);
        CP=1;
        delay(50);
        st=P0;  
        g_swStat=~st;
        g_slaveId=(g_swStat&0x1f);
       
}
/**************************************
            串口2波特率设置
**************************************/
unsigned char SetBaudRate(void)
{
        unsigned char Baud,BaudRate;
        Baud=(g_swStat>>5);                                //PO口前三个引脚设置波特率4800/9600/14400/19200/38400
        Baud=(Baud&0x07);
        switch(Baud)
        {
        case 1:
                        BaudRate=0xF4;                        //2400
                        break;
        case 2:
                        BaudRate=0xFA;                        //4800
                        break;
        case 3:
                        BaudRate=0xFD;                        //9600
                        break;
        case 4:
                        BaudRate=0xFE;                        //19200
                        break;
        case 5:
                        BaudRate=0xFF;                        //38400
                        break;
        case 6:
                        BaudRate=0xFF;                        //38400
                        break;          
        default:
                        break;
        }
        return BaudRate;
}
//*****************************************************************************
//函数名:                  
//函数功能描述:
//函数参数:          
//函数返回值:          
//作者:                  wenzer
//修改人:
//修改原因:
//*****************************************************************************
void UartInit(void)                //14400bps@11.0592MHz
{
//        PCON &= 0x7F;                //波特率不倍速
//        SCON = 0x50;                //8位数据,可变波特率
//        AUXR |= 0x40;                //定时器1时钟为Fosc,即1T
//        AUXR &= 0xFE;                //串口1选择定时器1为波特率发生器
//        TMOD &= 0x0F;                //清除定时器1模式位
//        TMOD |= 0x20;                //设定定时器1为8位自动重装方式
//        TL1 = 0XE8        ;
//        TH1 = 0xE8  ;
//        ET1 = 0;                //禁止定时器1中断
//        TR1 = 1;                //启动定时器1
//        ES = 1;
        PCON &= 0x7F;                //波特率不倍速
        SCON = 0x50;                //8位数据,可变波特率
        AUXR &= 0xBF;                //定时器1时钟为Fosc/12,即12T
        AUXR &= 0xFE;                //串口1选择定时器1为波特率发生器
        TMOD &= 0x0F;                //清除定时器1模式位
        TMOD |= 0x20;                //设定定时器1为8位自动重装方式
        TL1 = 0xE8;                //设定定时初值
        TH1 = 0xE8;                //设定定时器重装值
        ET1 = 0;                //禁止定时器1中断
        TR1 = 1;                //启动定时器1
        ES = 1;
}
//*****************************************************************************
//函数名:                  
//函数功能描述:
//函数参数:          
//函数返回值:          
//作者:                  wenzer
//修改人:
//修改原因:
//*****************************************************************************
void Uart2Init(void)                //1200bps@11.0592MHz
{
/*        AUXR &= 0xF7;                //波特率不倍速
        S2CON = 0xD0;                //9位数据,可变波特率
        AUXR &= 0xFB;                //独立波特率发生器时钟为Fosc/12,即12T
        BRT = 0xE8;                //设定独立波特率发生器重装值
        AUXR |= 0x10;                //启动独立波特率发生器
*/
//        S2CON = 0xD0;                      //REN=1允许串行接受状态,串口工作模式3,数据位8、停止位1。偶校验 (11.0592)
//        PCON|= 0x00;                                //不加倍
//        AUXR = 0x11;                                //BRTx12=0,独立波特率发生器每12个时钟技计数一次
//        BRT = 0xfa;                          //波特率4800
        AUXR &= 0xF7;                //波特率不倍速
        S2CON = 0x50;                //8位数据,可变波特率
        AUXR &= 0xFB;                //独立波特率发生器时钟为Fosc/12,即12T
        BRT = SetBaudRate();                    //设定独立波特率发生器重装值
        AUXR |= 0x10;                //启动独立波特率发生器
        IE2 = 0x01;         //开串口2中断  
       
}
/**************************************
            串口2发送一字节(加偶校验)
**************************************/
void SendByte2(unsigned char dat)
{
//        unsigned char S2TB8;
////        ACC=dat;
//        S2TB8=P;                                                //偶校验位(P判断ACC的奇偶特性)
//
//
//        if (S2TB8)                                                //S2TB8发送校验位判断
//        {
//                S2CON|=0x08;                       
//        }
//        else
//        {
//                S2CON&=~0x08;
//        }
        S2BUF=dat;                                        //发送一个字节
        while(!(S2CON&0x02));        //等待发送标志位
        S2CON &=~S2TI;                                //清空发送标志位
}
/**************************************
            串口2发送一字符串meter
**************************************/
void Uart2Send(uchar *dat,uchar len)
{
        uchar tmp;
        RS485EE=1;                                            //485置1发送
        _nop_();                                                //485置1等待时间
        _nop_();
        _nop_();
        _nop_();
           _nop_();
        _nop_();
        for(tmp=0;tmp<len;tmp++)
        {
                SendByte2(*dat);
                dat++;
        }
        _nop_();
        _nop_();
        _nop_();                                                //485置0等待时间
        _nop_();
        _nop_();
        RS485EE=0;                                        //485置0接收
        _nop_();
        _nop_();
        _nop_();
       
}
/**************************************
            串口1发送一字节
//**************************************/
void SendByte1(unsigned char dat1)
{
        SBUF=dat1;
        while (!TI);                                //等待发送完成
        TI=0;                                                        //清空发送标志位
}
/**************************************
            串口1发送一字符串net
**************************************/
void Uart1Send(uchar *dat,uchar len)
{
        uchar tmp;
//        RS485EE=1;                                            //485置1发送
        _nop_();                                                //485置1等待时间
        _nop_();
        _nop_();
        _nop_();

        for(tmp=0;tmp<len;tmp++)
        {
                SendByte1(*dat);
                dat++;
        }
       
        _nop_();                                                //485置0等待时间
        _nop_();
        _nop_();
//        RS485EE=0;                                        //485置0接收
        _nop_();
        _nop_();
        _nop_();
       
}
/**************************************
               清空接收缓存区
**************************************/
void ClearComDat(void)
{
        g_RvcCnt=0;
        g_totalRvcCnt=0;

}
/****************************************************
               串口2中断程序(NET)
                           与网络控制器通信
******************************************************/
void UART2_int (void) interrupt 8 using 1
{

//        TI2=S2CON & S2TI;
        RI2=S2CON & S2RI;
//        if(TI2)         {S2CON=S2CON&0xfd;}                //TI标志清除
        if(RI2)                                        //RI接受中断标志
        {
                S2CON = S2CON&=~S2RI;
                N_Frame[g_RvcCnt]= S2BUF;                  //SUBF接受/发送缓冲器
                if(g_RvcCnt<5)
                {
       
                        switch(g_RvcCnt)
                        {
                        case 0:
                                if(N_Frame[0]==0x0a)
                                g_RvcCnt++;
                                break;
                        case 1:
                                if(N_Frame[1]==0x0c)
                                  {       
                                  g_RvcCnt++;
                                  }
                                else if(N_Frame[1]==0x0a)
                                        {
                                                 N_Frame[0]=N_Frame[1];
                                                }
                                else
                                        {
                                                 g_RvcCnt=0;
                                                }
                                break;
                        case 2:
                                if(N_Frame[2]==0x0e)
                                 {
                                 g_RvcCnt++;
                                 }
                          &nb

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top