找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机硬件的使用时间限制的程序 这里起抛砖引玉的作用 相当于软件狗 就是指定单片..

[复制链接]
跳转到指定楼层
楼主
ID:13450 发表于 2017-10-30 22:33 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
前两天有客户委托做一个项目。这个项目做好后。我的客户也需要把东西交付给另外的公司。但是这个公司只付了百分之三十的订金。说好交付产品时再付百分之六十。结果交付产品时却没有兑现承诺。
所以客户要求我在程序里面加一个限制使用时间的子程序。如果三十天,或者九十天。客户还没有打款。就不能用了。
想了几天。写了一段小程序。很好用。大家有需要的可以用一下。这里起一个抛砖引玉的作用。
  1. //2017.9.30  带狗测试。运行一段时间后停止运行

  2. #include<reg52.h>
  3. #include<intrins.h>
  4. #include <stc15f102w.h>
  5. typedef unsigned char BYTE;
  6. typedef unsigned int WORD;

  7. //定义端口
  8. //sbit led = P3^4;        //LED指示灯
  9. sbit clk = P3^5;            //IIC时钟
  10. sbit dio = P3^4;                //IIC数据
  11. sbit key_add  = P3^2;        //加按键
  12. sbit key_sub  = P3^3;
  13. sbit JSQ_Sig  = P3^1;                   //计数器脉冲信号
  14. sbit JSQ_Relay= P3^0;                   //计数器继电器返回信号  计数器计数到0后返回信号给电路板

  15. unsigned char  number;
  16. unsigned char qian,bai,shi,ge,count,dog,dog_sec,dog_min,dog_hour,dog_day;
  17. unsigned char code xsbcdbuf[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77};                 //共阳数码管

  18. //测试地址
  19. #define IAP_ADDRESS 0x0200

  20. void Delay(BYTE n);
  21. void IapIdle();
  22. BYTE IapReadByte(WORD addr);
  23. void IapProgramByte(WORD addr, BYTE dat);
  24. void IapEraseSector(WORD addr);


  25. ///=======================================

  26. void Delay_us(unsigned int i) //nus 延时
  27. {
  28.         for(;i>0;i--)
  29.         _nop_();
  30. }
  31. ///======================================

  32. void I2CStart(void) //1637 开始
  33. {
  34.         clk = 1;
  35.         dio = 1;
  36.         Delay_us(2);
  37.         dio = 0;
  38. }
  39. ///=============================================

  40. void I2Cask(void)         //1637 应答
  41. {
  42.         clk = 0;
  43.         Delay_us(5);         //在第八个时钟下降沿之后延时 5us,开始判断 ACK 信号
  44.         while(dio);
  45.         clk = 1;
  46.         Delay_us(2);
  47.         clk=0;
  48. }
  49. ///========================================

  50. void I2CStop(void)         // 1637 停止
  51. {
  52.         clk = 0;
  53.         Delay_us(2);
  54.         dio = 0;
  55.         Delay_us(2);
  56.         clk = 1;
  57.         Delay_us(2);
  58.         dio = 1;
  59. }
  60. ///=========================================

  61. void I2CWrByte(unsigned char oneByte) //写一个字节
  62. {
  63.         unsigned char i;
  64.         for(i=0;i<8;i++)
  65.         {
  66.                 clk = 0;
  67.                 if(oneByte&0x01)        //低位在前
  68.                 {
  69.                         dio = 1;       
  70.                 }
  71.                 else
  72.                 {
  73.                         dio = 0;
  74.                 }
  75.                 Delay_us(3);
  76.                 oneByte=oneByte>>1;
  77.                 clk=1;
  78.                 Delay_us(3);
  79.         }
  80. }
  81. ///================================================

  82. unsigned char ScanKey(void)                 //按键检测程序
  83. {
  84.         if(key_add == 0)                            //按键加
  85.                 {
  86.                         Delay_us(10);
  87.                         if(key_add==0)
  88.                         {
  89.                                 number = number+5;
  90.                                 IapEraseSector(IAP_ADDRESS);
  91.                                 IapProgramByte(IAP_ADDRESS,number);
  92.                                 while(!key_add);    //等待按键松手
  93.                         }
  94.                 }

  95.         if(key_sub == 0)                            //按键减
  96.                 {
  97.                         Delay_us(10);
  98.                         if(key_sub==0)
  99.                         {
  100.                                 number = number-5;
  101.                                 IapEraseSector(IAP_ADDRESS);
  102.                                 IapProgramByte(IAP_ADDRESS,number);
  103.                                 while(!key_sub);    //等待按键松手
  104.                         }
  105.                 }
  106. }

  107. ///================================================
  108. void jisuan()
  109. {
  110.         qian = number/1000;
  111.         bai  = number%1000/100;
  112.         shi         = number%1000%100/10;
  113.         ge         = number%10;
  114. }

  115. void SmgDisplay(void) //写显示寄存器
  116. {
  117.         unsigned char i;
  118.         I2CStart();
  119.         I2CWrByte(0x40); // 40H 地址自动加 1 模式,44H 固定地址模式,本程序采用自加 1 模式
  120.         I2Cask();
  121.         I2CStop();
  122.         I2CStart();
  123.         I2CWrByte(0xc1);//设置首地址,
  124.         I2Cask();
  125.         for(i=0;i<6;i++)//地址自加,不必每次都写地址
  126.         {
  127.                 I2CWrByte(xsbcdbuf[bai]);        //送数据
  128.                 I2Cask();
  129.                 I2CWrByte(xsbcdbuf[shi]);        //送数据
  130.                 I2Cask();
  131.                 I2CWrByte(xsbcdbuf[ge]);        //送数据
  132.                 I2Cask();
  133.                 I2CWrByte(xsbcdbuf[1]);        //送数据
  134.                 I2Cask();
  135.                 I2CWrByte(xsbcdbuf[0]);        //送数据
  136.                 I2Cask();
  137.                 I2CWrByte(xsbcdbuf[qian]);        //送数据
  138.                 I2Cask();
  139.         }

  140.         I2CStop();
  141.         I2CStart();
  142.         I2CWrByte(0x8b); //开显示 ,八级亮度调制 88 89 8a 8b 8c 8d 8e 8f
  143.         I2Cask();
  144.         I2CStop();
  145. }
  146. ///==============================================

  147. void init()                         //定时器中断初始化
  148. {
  149.         TMOD = 0x01;                    //set timer0 as mode1 (16-bit)
  150.     TL0 = (65536-50000)%256;                     //initial timer0 low byte
  151.     TH0 = (65536-50000)/256;               //initial timer0 high byte
  152.     TR0 = 1;                        //timer0 start running
  153.     ET0 = 1;                        //enable timer0 interrupt
  154.     EA = 1;                         //open global interrupt switch
  155.         count = 0;
  156.         number = 200;
  157.         dog_sec = 0;
  158.         dog_min = 0;
  159.         dog_hour = 0;
  160. }
  161. ///==============================================

  162. void dog_test()
  163. {
  164.         dog_sec++;
  165.         if(dog_sec == 60)                          //60s钟让狗加1
  166.         {
  167.                 dog_sec = 0;
  168.                 dog_min++;
  169.                 if(dog_min ==60)
  170.                 {
  171.                         dog_min=0;
  172.                         dog_hour++;
  173.                         if(dog_hour ==24)                   //正常是24小时。测试时用1个小时算1天。
  174.                         {         
  175.                                 dog_hour=0;
  176.                                 dog_day++;
  177.                                 IapEraseSector(0x0000);
  178.                                 IapProgramByte(0x0000,dog_day);
  179.                         }
  180.                 }                       
  181.         }
  182. }

  183. void main(void)
  184. {
  185.         unsigned char keydate;
  186.         init();                         //初始化
  187.         dog_day = IapReadByte(0x0000);
  188.         number  = IapReadByte(IAP_ADDRESS);       
  189.         while(1)
  190.         {
  191.                 jisuan();
  192.                 SmgDisplay();
  193.                 ScanKey();
  194.                 if(count == 20)                         //脉冲信号来一次。计数器减1
  195.                 {
  196.                         count = 0;
  197.                         number--;
  198.                         IapEraseSector(IAP_ADDRESS);
  199.                         IapProgramByte(IAP_ADDRESS,number);
  200.                         dog_test();
  201.                         if(number ==0)
  202.                         {                       
  203.                                 number = 255;
  204.                         }
  205.                 }
  206.                 while(dog_day>=1);                  //2天后停止运行。实际上是2个小时。测试用小时代替天。
  207.         }
  208. }
  209. //===========end==================================

  210. /* Timer0 interrupt routine */
  211. void tm0_isr() interrupt 1 using 1
  212. {
  213.     TL0 = (65536-50000)%256;                   //reload timer0 low byte
  214.     TH0 = (65536-50000)/256;                //reload timer0 high byte
  215.     count++;dog++;
  216. }

  217. /*----------------------------
  218. 软件延时
  219. ----------------------------*/
  220. void Delay(BYTE n)
  221. {
  222.     WORD x;

  223.     while (n--)
  224.     {
  225.         x = 0;
  226.         while (++x);
  227.     }
  228. }

  229. /*----------------------------
  230. 关闭IAP
  231. ----------------------------*/
  232. void IapIdle()
  233. {
  234.     IAP_CONTR = 0;                  //关闭IAP功能
  235.     IAP_CMD = 0;                    //清除命令寄存器
  236.     IAP_TRIG = 0;                   //清除触发寄存器
  237.     IAP_ADDRH = 0x80;               //将地址设置到非IAP区域
  238.     IAP_ADDRL = 0;
  239. }

  240. /*----------------------------
  241. 从ISP/IAP/EEPROM区域读取一字节
  242. ----------------------------*/
  243. BYTE IapReadByte(WORD addr)
  244. {
  245.     BYTE dat;                       //数据缓冲区

  246.     IAP_CONTR = ENABLE_IAP;         //使能IAP
  247.     IAP_CMD = CMD_READ;             //设置IAP命令
  248.     IAP_ADDRL = addr;               //设置IAP低地址
  249.     IAP_ADDRH = addr >> 8;          //设置IAP高地址
  250.     IAP_TRIG = 0x5a;                //写触发命令(0x5a)
  251.     IAP_TRIG = 0xa5;                //写触发命令(0xa5)
  252.     _nop_();                        //等待ISP/IAP/EEPROM操作完成
  253.     dat = IAP_DATA;                 //读ISP/IAP/EEPROM数据
  254.     IapIdle();                      //关闭IAP功能

  255.     return dat;                     //返回
  256. }

  257. /*----------------------------
  258. 写一字节数据到ISP/IAP/EEPROM区域
  259. ----------------------------*/
  260. void IapProgramByte(WORD addr, BYTE dat)
  261. {
  262.     IAP_CONTR = ENABLE_IAP;         //使能IAP
  263.     IAP_CMD = CMD_PROGRAM;          //设置IAP命令
  264.     IAP_ADDRL = addr;               //设置IAP低地址
  265.     IAP_ADDRH = addr >> 8;          //设置IAP高地址
  266.     IAP_DATA = dat;                 //写ISP/IAP/EEPROM数据
  267.     IAP_TRIG = 0x5a;                //写触发命令(0x5a)
  268.     IAP_TRIG = 0xa5;                //写触发命令(0xa5)
  269.     _nop_();                        //等待ISP/IAP/EEPROM操作完成
  270.     IapIdle();
  271. }

  272. /*----------------------------
  273. 扇区擦除
  274. ----------------------------*/
  275. void IapEraseSector(WORD addr)
  276. {
  277.     IAP_CONTR = ENABLE_IAP;         //使能IAP
  278.     IAP_CMD = CMD_ERASE;            //设置IAP命令
  279.     IAP_ADDRL = addr;               //设置IAP低地址
  280.     IAP_ADDRH = addr >> 8;          //设置IAP高地址
  281.     IAP_TRIG = 0x5a;                //写触发命令(0x5a)
  282.     IAP_TRIG = 0xa5;                //写触发命令(0xa5)
  283.     _nop_();                        //等待ISP/IAP/EEPROM操作完成
  284.     IapIdle();
  285. }

复制代码



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

使用道具 举报

沙发
ID:495990 发表于 2020-2-7 10:15 | 只看该作者
这么好的贴咋没人顶一个呢?
回复

使用道具 举报

板凳
ID:620993 发表于 2020-2-7 11:52 | 只看该作者
很好的思路
回复

使用道具 举报

地板
ID:73422 发表于 2020-2-9 20:29 | 只看该作者
这个不好用,别人要是付款了还得去给别人改,很麻烦。
时间到后产生一个随机码,机器锁死,如果客户付款了,让他把随机码发过来,这边用解码算法算出密码,让客户输入设备就可以正常使用了。而且每台设备产生的随机码不相同,密码也就不一样。以前用汇编写过。
回复

使用道具 举报

5#
ID:136189 发表于 2020-2-12 23:09 来自手机 | 只看该作者
很好哦,
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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