找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2240|回复: 12
打印 上一主题 下一主题
收起左侧

单片机定时工作4000个小时自动损坏的程序

  [复制链接]
跳转到指定楼层
楼主
ID:280979 发表于 2019-10-7 23:42 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
//实现功能:定时自毁应用程序
//使用芯片:STC15F104E
//晶振:12MHZ
//编译环境:Keil
#include "reg52.h"
#include <intrins.H>
#define uchar unsigned char //宏定义字符型变量
#define uint  unsigned int        //宏定义整型变量
/********************************************************************
                            寄存器设置
*********************************************************************/
sfr IAP_DATA  =0xc2;            //数据寄存器
sfr IAP_ADDRH =0xc3;            //地址寄存器
sfr IAP_ADDRL =0xc4;            //地址寄存器
sfr IAP_CMD   =0xc5;        //命令寄存器
sfr IAP_TRIG  =0xc6;             //触发寄存器
sfr IAP_CONTR =0xc7;        //擦除寄存器

/********************************************************************
                            命令定义
*********************************************************************/
#define CMD_IDLE     0            //EEPROM无操作
#define CMD_READ     1            //读取字节
#define CMD_PROGRAM  2            //写入字节
#define CMD_ERASE    3            //擦除字节
/********************************************************************
                       编程周期由晶振决定
*********************************************************************/
//#define ENABLE_IAP 0X80         //编程周期由晶振决定(如果<30MHZ选用此项)
//#define ENABLE_IAP 0X81         //编程周期由晶振决定(如果<24MHZ选用此项)
//#define ENABLE_IAP 0X82         //编程周期由晶振决定(如果<20MHZ选用此项)
  #define ENABLE_IAP 0X83         //编程周期由晶振决定(如果<12MHZ选用此项)
//#define ENABLE_IAP 0X84         //编程周期由晶振决定(如果<6MHZ选用此项)
//#define ENABLE_IAP 0X85         //编程周期由晶振决定(如果<3MHZ选用此项)
//#define ENABLE_IAP 0X86         //编程周期由晶振决定(如果<2MHZ选用此项)
//#define ENABLE_IAP 0X87         //编程周期由晶振决定(如果<1MHZ选用此项)

#define IAP_ADDRESS1 0X0000         //内部EEPROM地址
#define IAP_ADDRESS2 0X0200
/********************************************************************
                         最长时间定义
*********************************************************************/

#define T  4000         //定时时间(小时)
/********************************************************************
                            初始定义
*********************************************************************/
uint fen,days;
uchar Count;
uchar Count1;
uint cnt;
bit write;
sbit OUT1=P3^3;
sbit IN0=P3^5;

//============================================================
//延时程序
void delayms(unsigned int x)
{
    int i,j;                                                                                
    for(i=0;i<x;i++)                                                                    
       {
             for(j=0;j<260;j++);
       }                                                                                    
}

/********************************************************************
                            操作函数
*********************************************************************/
void IapIdle()
{
        IAP_CONTR=0;
        IAP_CMD=0;
        IAP_TRIG=0;
        IAP_ADDRH=0X80;
        IAP_ADDRL=0;
}
/********************************************************************
                            读取一个字节函数
*********************************************************************/
uchar IapReadByte(uint addr)
{
        uchar dat;  
        IAP_CONTR=ENABLE_IAP;
        IAP_CMD=CMD_READ;
        IAP_ADDRL=addr;
        IAP_ADDRH=addr>>8;
        IAP_TRIG=0X5A;
        IAP_TRIG=0XA5;
        _nop_();
        _nop_();
        _nop_();
        dat=IAP_DATA;
        IapIdle();
        return dat;
}

/********************************************************************
                            写入一个字节函数
*********************************************************************/
void IapProgramByte(uint addr,uchar dat)
{

        IAP_CONTR=ENABLE_IAP;
        IAP_CMD=CMD_PROGRAM;
        IAP_ADDRL=addr;
        IAP_ADDRH=addr>>8;
        IAP_DATA=dat;
        IAP_TRIG=0X5A;
        IAP_TRIG=0XA5;
        _nop_();
        _nop_();
        _nop_();
        IapIdle();
}
/********************************************************************
                            擦除一个字节函数
*********************************************************************/
void IapEraseSector(uint addr)
{
        IAP_CONTR=ENABLE_IAP;
        IAP_CMD=CMD_ERASE;
        IAP_ADDRL=addr;
        IAP_ADDRH=addr>>8;
        IAP_TRIG=0X5A;
        IAP_TRIG=0XA5;
        _nop_();
        _nop_();
        _nop_();
        IapIdle();
}
/********************************************************************
                            定时中断服务函数
*********************************************************************/
void t0(void) interrupt 1 using 1 //定时中断服务函数
{   
    TH0=(65536-50000)/256; //对TH0 TL0 赋值
        TL0=(65536-50000)%256;

        cnt++;         //每过50ms tcnt 加一
        if(cnt==1200) //计满1200次1分钟
        {   cnt=0;          //重新再计
                fen++;   
                if(fen==60) //定时60分钟,在从零开始计时
                {
                        fen=0;
                        days++;
                        write=1;
                }
        }
}
/********************************************************************
                            主函数
*********************************************************************/
void main()
{                                                                                          
         TMOD=0x01; //定时器工作在方式1
        TH0=(65536-50000)/256; //对TH0 TL0 赋值
        TL0=(65536-50000)%256;
        ET0=1;
        EA=1;
    TR0=1;                              //定时器函数初始化
        delayms(10);                                                          //开机延时
    Count=IapReadByte(IAP_ADDRESS1);                  //读取EEPROM数据
        Count1=IapReadByte(IAP_ADDRESS1+1);                  //读取EEPROM数据
        days=(Count*100)+Count1;                                  //从读取数据中计算时间值
        
                while(1)
        {

         if(days>=T)                                                  //判断如果延时时间大于等于设置时间,继电器断开,模块停止工作。否则继电器吸合
         {
           OUT1=0;
           TR0=0;
          }
        else
         {
           OUT1=1;
           TR0=1;
          }

    if(write==1) // 记满一个小时,数据存储一次
        {
        write=0;
         Count=days/100;
         Count1=days%100;;
          IapEraseSector(IAP_ADDRESS1);   //擦除0扇区        //34us
          IapEraseSector(IAP_ADDRESS1+1);   //擦除0扇区        //34us
      IapProgramByte(IAP_ADDRESS1,Count);            //写入数据//38us
      IapProgramByte(IAP_ADDRESS1+1,Count1);            //写入数据//38us
        
        }

         if(IN0==0)
         {
          delayms(10);
          if(IN0==0)
          {
           while(!IN0);
           days=0;
           Count=0;
           Count1=0;
          IapEraseSector(IAP_ADDRESS1);   //擦除0扇区        //34us
          IapEraseSector(IAP_ADDRESS1+1);   //擦除0扇区        //34us
      IapProgramByte(IAP_ADDRESS1,Count);            //写入数据//38us
      IapProgramByte(IAP_ADDRESS1+1,Count1);            //写入数据//38us
          }
        }
}
}


/********************************************************************
                            结束
*********************************************************************/

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏8 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:969272 发表于 2023-7-15 11:20 | 只看该作者
有没有计算开机次数损坏的?
回复

使用道具 举报

板凳
ID:1083996 发表于 2023-7-15 11:32 | 只看该作者
sh1900 发表于 2023-7-15 11:20
有没有计算开机次数损坏的?

应该也能设置吧,开机多少次或复位多少次就损坏;
也可以设置成,逐渐的让运行速度降低(intel是不是这样操作的?)变卡,逼着用户升级
回复

使用道具 举报

地板
ID:1083996 发表于 2023-7-15 11:35 | 只看该作者
记得以前日本的S尼就弄过这种操作,DVD机质保1年,从第5次通电开始计算时间,到12个月时候加大激光头输出功率,然后15个月左右全部歇菜,后来维修换上后,激光头只能用3个月,然后被人发现后弄出来一场风暴,从此S尼在国内逐渐势微
回复

使用道具 举报

5#
ID:992936 发表于 2023-7-17 22:41 | 只看该作者
某米,某想,是不是你设计的?老实交待
回复

使用道具 举报

6#
ID:854496 发表于 2023-7-17 23:06 | 只看该作者
计划性报废,美其名曰:新技术,新环保,新理念
回复

使用道具 举报

7#
ID:641483 发表于 2023-7-19 09:57 | 只看该作者
不应该自毁,应该限制功能,对于工程完成没付 的可以用
回复

使用道具 举报

8#
ID:213173 发表于 2023-7-19 16:57 | 只看该作者
sh1900 发表于 2023-7-15 11:20
有没有计算开机次数损坏的?

不论用开机次数或开机累计时间自毁都很容易实现。
回复

使用道具 举报

9#
ID:332444 发表于 2023-7-20 08:09 | 只看该作者
生产垃圾?!可耻的浪费和。
回复

使用道具 举报

10#
ID:135715 发表于 2023-7-21 10:39 | 只看该作者
量子工业 发表于 2023-7-15 11:32
应该也能设置吧,开机多少次或复位多少次就损坏;
也可以设置成,逐渐的让运行速度降低(intel是不是这 ...

这个可以 开机一次循环中delay增加一点点 直到最后卡的不要不要的
回复

使用道具 举报

11#
ID:427868 发表于 2023-7-21 11:07 | 只看该作者
       看都楼主的方法我也在想采用类似的方法,就是开机计时,到一个小时写入EEPROM,在程序中执行一个不到总时间的条件判断,使程序正常运行,总时间到了不执行某个动作以达到保护的目的。但考虑会有一个问题,就是在程序正常运行中随时写入EEPROM,整个写的过程会有几十ms,这几十ms过程中要关总中断,这几十秒很有可能会影响程序的正常运行。我考虑的解决方式是在写EEPROM时再加一个判断条件,这个条件成立时容许几十毫秒的延时,不影响程序正常运行,比如在计数时,正常计数状态下即使该写入了也不写入,只有当计数清零后再写入。不知朋友是否有更好的方法。
回复

使用道具 举报

12#
ID:709761 发表于 2023-7-21 16:07 | 只看该作者
如果硬改电路呢
回复

使用道具 举报

13#
ID:584814 发表于 2023-7-21 17:22 | 只看该作者
当年电视台用的肩扛的录相机中就有个硬件,按时长自动报废,有可视进度条。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表