前两天有客户委托做一个项目。这个项目做好后。我的客户也需要把东西交付给另外的公司。但是这个公司只付了百分之三十的订金。说好交付产品时再付百分之六十。结果交付产品时却没有兑现承诺。
所以客户要求我在程序里面加一个限制使用时间的子程序。如果三十天,或者九十天。客户还没有打款。就不能用了。
想了几天。写了一段小程序。很好用。大家有需要的可以用一下。这里起一个抛砖引玉的作用。
- //2017.9.30 带狗测试。运行一段时间后停止运行
- #include<reg52.h>
- #include<intrins.h>
- #include <stc15f102w.h>
- typedef unsigned char BYTE;
- typedef unsigned int WORD;
- //定义端口
- //sbit led = P3^4; //LED指示灯
- sbit clk = P3^5; //IIC时钟
- sbit dio = P3^4; //IIC数据
- sbit key_add = P3^2; //加按键
- sbit key_sub = P3^3;
- sbit JSQ_Sig = P3^1; //计数器脉冲信号
- sbit JSQ_Relay= P3^0; //计数器继电器返回信号 计数器计数到0后返回信号给电路板
- unsigned char number;
- unsigned char qian,bai,shi,ge,count,dog,dog_sec,dog_min,dog_hour,dog_day;
- unsigned char code xsbcdbuf[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77}; //共阳数码管
- //测试地址
- #define IAP_ADDRESS 0x0200
- void Delay(BYTE n);
- void IapIdle();
- BYTE IapReadByte(WORD addr);
- void IapProgramByte(WORD addr, BYTE dat);
- void IapEraseSector(WORD addr);
- ///=======================================
- void Delay_us(unsigned int i) //nus 延时
- {
- for(;i>0;i--)
- _nop_();
- }
- ///======================================
- void I2CStart(void) //1637 开始
- {
- clk = 1;
- dio = 1;
- Delay_us(2);
- dio = 0;
- }
- ///=============================================
- void I2Cask(void) //1637 应答
- {
- clk = 0;
- Delay_us(5); //在第八个时钟下降沿之后延时 5us,开始判断 ACK 信号
- while(dio);
- clk = 1;
- Delay_us(2);
- clk=0;
- }
- ///========================================
- void I2CStop(void) // 1637 停止
- {
- clk = 0;
- Delay_us(2);
- dio = 0;
- Delay_us(2);
- clk = 1;
- Delay_us(2);
- dio = 1;
- }
- ///=========================================
- void I2CWrByte(unsigned char oneByte) //写一个字节
- {
- unsigned char i;
- for(i=0;i<8;i++)
- {
- clk = 0;
- if(oneByte&0x01) //低位在前
- {
- dio = 1;
- }
- else
- {
- dio = 0;
- }
- Delay_us(3);
- oneByte=oneByte>>1;
- clk=1;
- Delay_us(3);
- }
- }
- ///================================================
- unsigned char ScanKey(void) //按键检测程序
- {
- if(key_add == 0) //按键加
- {
- Delay_us(10);
- if(key_add==0)
- {
- number = number+5;
- IapEraseSector(IAP_ADDRESS);
- IapProgramByte(IAP_ADDRESS,number);
- while(!key_add); //等待按键松手
- }
- }
- if(key_sub == 0) //按键减
- {
- Delay_us(10);
- if(key_sub==0)
- {
- number = number-5;
- IapEraseSector(IAP_ADDRESS);
- IapProgramByte(IAP_ADDRESS,number);
- while(!key_sub); //等待按键松手
- }
- }
- }
- ///================================================
- void jisuan()
- {
- qian = number/1000;
- bai = number%1000/100;
- shi = number%1000%100/10;
- ge = number%10;
- }
- void SmgDisplay(void) //写显示寄存器
- {
- unsigned char i;
- I2CStart();
- I2CWrByte(0x40); // 40H 地址自动加 1 模式,44H 固定地址模式,本程序采用自加 1 模式
- I2Cask();
- I2CStop();
- I2CStart();
- I2CWrByte(0xc1);//设置首地址,
- I2Cask();
- for(i=0;i<6;i++)//地址自加,不必每次都写地址
- {
- I2CWrByte(xsbcdbuf[bai]); //送数据
- I2Cask();
- I2CWrByte(xsbcdbuf[shi]); //送数据
- I2Cask();
- I2CWrByte(xsbcdbuf[ge]); //送数据
- I2Cask();
- I2CWrByte(xsbcdbuf[1]); //送数据
- I2Cask();
- I2CWrByte(xsbcdbuf[0]); //送数据
- I2Cask();
- I2CWrByte(xsbcdbuf[qian]); //送数据
- I2Cask();
- }
- I2CStop();
- I2CStart();
- I2CWrByte(0x8b); //开显示 ,八级亮度调制 88 89 8a 8b 8c 8d 8e 8f
- I2Cask();
- I2CStop();
- }
- ///==============================================
- void init() //定时器中断初始化
- {
- TMOD = 0x01; //set timer0 as mode1 (16-bit)
- TL0 = (65536-50000)%256; //initial timer0 low byte
- TH0 = (65536-50000)/256; //initial timer0 high byte
- TR0 = 1; //timer0 start running
- ET0 = 1; //enable timer0 interrupt
- EA = 1; //open global interrupt switch
- count = 0;
- number = 200;
- dog_sec = 0;
- dog_min = 0;
- dog_hour = 0;
- }
- ///==============================================
- void dog_test()
- {
- dog_sec++;
- if(dog_sec == 60) //60s钟让狗加1
- {
- dog_sec = 0;
- dog_min++;
- if(dog_min ==60)
- {
- dog_min=0;
- dog_hour++;
- if(dog_hour ==24) //正常是24小时。测试时用1个小时算1天。
- {
- dog_hour=0;
- dog_day++;
- IapEraseSector(0x0000);
- IapProgramByte(0x0000,dog_day);
- }
- }
- }
- }
- void main(void)
- {
- unsigned char keydate;
- init(); //初始化
- dog_day = IapReadByte(0x0000);
- number = IapReadByte(IAP_ADDRESS);
- while(1)
- {
- jisuan();
- SmgDisplay();
- ScanKey();
- if(count == 20) //脉冲信号来一次。计数器减1
- {
- count = 0;
- number--;
- IapEraseSector(IAP_ADDRESS);
- IapProgramByte(IAP_ADDRESS,number);
- dog_test();
- if(number ==0)
- {
- number = 255;
- }
- }
- while(dog_day>=1); //2天后停止运行。实际上是2个小时。测试用小时代替天。
- }
- }
- //===========end==================================
- /* Timer0 interrupt routine */
- void tm0_isr() interrupt 1 using 1
- {
- TL0 = (65536-50000)%256; //reload timer0 low byte
- TH0 = (65536-50000)/256; //reload timer0 high byte
- count++;dog++;
- }
- /*----------------------------
- 软件延时
- ----------------------------*/
- void Delay(BYTE n)
- {
- WORD x;
- while (n--)
- {
- x = 0;
- while (++x);
- }
- }
- /*----------------------------
- 关闭IAP
- ----------------------------*/
- void IapIdle()
- {
- IAP_CONTR = 0; //关闭IAP功能
- IAP_CMD = 0; //清除命令寄存器
- IAP_TRIG = 0; //清除触发寄存器
- IAP_ADDRH = 0x80; //将地址设置到非IAP区域
- IAP_ADDRL = 0;
- }
- /*----------------------------
- 从ISP/IAP/EEPROM区域读取一字节
- ----------------------------*/
- BYTE IapReadByte(WORD addr)
- {
- BYTE dat; //数据缓冲区
- IAP_CONTR = ENABLE_IAP; //使能IAP
- IAP_CMD = CMD_READ; //设置IAP命令
- IAP_ADDRL = addr; //设置IAP低地址
- IAP_ADDRH = addr >> 8; //设置IAP高地址
- IAP_TRIG = 0x5a; //写触发命令(0x5a)
- IAP_TRIG = 0xa5; //写触发命令(0xa5)
- _nop_(); //等待ISP/IAP/EEPROM操作完成
- dat = IAP_DATA; //读ISP/IAP/EEPROM数据
- IapIdle(); //关闭IAP功能
- return dat; //返回
- }
- /*----------------------------
- 写一字节数据到ISP/IAP/EEPROM区域
- ----------------------------*/
- void IapProgramByte(WORD addr, BYTE dat)
- {
- IAP_CONTR = ENABLE_IAP; //使能IAP
- IAP_CMD = CMD_PROGRAM; //设置IAP命令
- IAP_ADDRL = addr; //设置IAP低地址
- IAP_ADDRH = addr >> 8; //设置IAP高地址
- IAP_DATA = dat; //写ISP/IAP/EEPROM数据
- IAP_TRIG = 0x5a; //写触发命令(0x5a)
- IAP_TRIG = 0xa5; //写触发命令(0xa5)
- _nop_(); //等待ISP/IAP/EEPROM操作完成
- IapIdle();
- }
- /*----------------------------
- 扇区擦除
- ----------------------------*/
- void IapEraseSector(WORD addr)
- {
- IAP_CONTR = ENABLE_IAP; //使能IAP
- IAP_CMD = CMD_ERASE; //设置IAP命令
- IAP_ADDRL = addr; //设置IAP低地址
- IAP_ADDRH = addr >> 8; //设置IAP高地址
- IAP_TRIG = 0x5a; //写触发命令(0x5a)
- IAP_TRIG = 0xa5; //写触发命令(0xa5)
- _nop_(); //等待ISP/IAP/EEPROM操作完成
- IapIdle();
- }
复制代码
|