/*******************************************/
//版本:NO.3
//日期:2010.12.10
//功能:通过先调节亮度,再接外面的脉冲,夜间时,正常情况下,是半亮状态(也就是说,是正常电流的1/3)
// 当有外部脉冲来的时候,又恢复到了全亮状态
//eeprom程序引用STC
//设计者:zfliu
/*******************************************/
#include <STC11.h>
#include <intrins.h>
#define CIRCLE 10
#define CIRCLE1 30
typedef unsigned char INT8U; //定义8位字符
typedef unsigned int INT16U; //定义16位整型
INT8U count,last,last1;
INT16U count1,count2;
//sfr IAP_DATA = 0xC2;
//sfr IAP_ADDRH = 0xC3;
//sfr IAP_ADDRL = 0xC4;
//sfr IAP_CMD = 0xC5;
//sfr IAP_TRIG = 0xC6;
//#define ENABLE_ISP 0x87 //系统工作时钟<1MHz 时,对IAP_CONTR 寄存器设置此值
//定义Flash 操作等待时间及允许IAP/ISP/EEPROM 操作的常数
//#define ENABLE_ISP 0x80 //系统工作时钟<30MHz 时,对IAP_CONTR 寄存器设置此值
//#define ENABLE_ISP 0x81 //系统工作时钟<24MHz 时,对IAP_CONTR 寄存器设置此值
//#define ENABLE_ISP 0x82 //系统工作时钟<20MHz 时,对IAP_CONTR 寄存器设置此值
#define ENABLE_ISP 0x83 //系统工作时钟<12MHz 时,对IAP_CONTR 寄存器设置此值
//#define ENABLE_ISP 0x84 //系统工作时钟<6MHz 时,对IAP_CONTR 寄存器设置此值
//#define ENABLE_ISP 0x85 //系统工作时钟<3MHz 时,对IAP_CONTR 寄存器设置此值
//#define ENABLE_ISP 0x86 //系统工作时钟<2MHz 时,对IAP_CONTR 寄存器设置此值
//#define ENABLE_ISP 0x87 //系统工作时钟<1MHz 时,对IAP_CONTR 寄存器设置此值
union union_temp16 // 存放最大数据是16位的数据
{
INT16U un_temp16;
INT8U un_temp8[2];
}my_unTemp16;
INT8U Byte_Read(INT16U add); //读一字节,调用前需打开IAP 功能
void Byte_Program(INT16U add, INT8U ch); //字节编程,调用前需打开IAP 功能
void Sector_Erase(INT16U add); //擦除扇区
void IAP_Disable(); //关闭IAP 功能
void Delay();
bit LED_PWM; //占空比为10/30的脉冲输出
bit LED_INIT; //中断80MS出来的脉冲
bit LED_PWM1; //占空比为30/30的脉冲输出
bit a; //判断中断是否到来
//bit LED_VAR;
sbit key1=P1^0;
sbit key2 = P1^1;
sbit key3 = P1^2;
sbit Day_Night_led = P1^7; //白天黑夜控制变量
sbit tempt_var = P1^6; //温度控制变量
sbit Flash_led = P1^5; //闪光灯输出管脚
sbit INIT = P3^3; //中断时,输出信号脚
sbit Button = P3^7; // 按键,用来调节亮度
//函数初始化
void Delay(); //延时函数
void INT_T0(void); // 定时器0的初始化函数
void Delay_ms (INT8U t); //延时函数
void INT_T1 (void); //定时器1的初始化函数
void INT_INT1(void); //中断1的初始化函数
/******************************************/
//主函数
/******************************************/
void main(void)
{
TMOD = 0x21; //定时器的方式控制
TH0 = 0X00; //定时器清零
TL0 = 0X00;
TH1 = 0X00;
TL1 = 0X00;
PX1 = 1; //中断1最高优先级
INT_T1 (); //定时器1初始化函数
INT_INT1(); //外部中断1初始函数
INT_T0(); //定时器0初始化函数
count=1; //脉宽占空比的变量
count1 = 0; //按键定时5S
count2 = 0; //80ms脉冲定时时的变量
// last = 5;
TR0 = 0; //定时器0开始工作标志位
TR1= 0 ; //定时器1开始工作标志位
a = 0;
//LED_PWM1 = 1; // 开始的时候,中断脉冲赋给LED灯口
while(1)
{
// if(key1 == 1)
// {
if(tempt_var == 0) //温度监控,为低电平时,表示温度正常
{
if(Day_Night_led == 1) //白天黑夜控制位,为高电平时,表示白天
{
TR1 = 1; //开定时器1
last1 = Byte_Read(0x200); // 读取
Flash_led = LED_INIT&LED_PWM1;
}
else //低电平,表示黑夜
{
TR1 = 1; //开定时器1
last = Byte_Read(0x00);
// LED_VAR = 1;
if (a == 1)
{
Flash_led = LED_INIT&LED_PWM1;
a = 0;
}
else
{
Flash_led = LED_PWM; //直接把调节亮度给LED灯的口
}
}
//通过80MS的中断,和LED_PWM1相与
}
else //为低时,表示温度过高
{
Flash_led = 0;
}
// }
// else
// {
if( Button == 0) //按钮控制
{
Delay_ms(10); //防抖动
if(Button == 0)
{
Flash_led = 1; //按键按一下,闪光灯闪一下,表示开始调节亮度
Delay_ms(40); //延时40MS
Flash_led = 0; //LED熄灭
TR0 = 1; //打开定时器0
while (1)
{
if(Button == 1) //判断按键的状态
{
count1 = 0; //按键5MS放下来后,记数变清零
break; //按键状态为1时,跳出这个循环
}
}
}
}
// Flash_led = LED_PWM;
// }
}
}
/******************************************/
//定时器0函数
/******************************************/
void INT_T0_INT(void) interrupt 1 using 1
{
count2++; //脉冲80MS的记数
if(count2 ==40) //STC的时钟比普通的单片机时钟快一倍的速度
{
LED_INIT =0 ; //记到80MS就变为低电平
count2 = 0; //重新记数
}
if(Button == 0) //按键
{
Delay_ms(10); //防抖动
if(Button == 0)
{
count1++; //开始记数
}
if(count1 == 800) //记够5秒
{
TR1 = 1; // 开定时器1
last ++; //按键按一下,last加一
last1 = last1; //按键按一下时,先把last1赋给last1,然后再加3
last1 = last1 + 3; //按键按一下,last加三
count1 = 0; //重新开始按键计数
Sector_Erase(0x00); //擦除EEPROM里面第一个扇区的东西
Byte_Program(0x00, last) ; //把last的数值放到00的地址里面
Sector_Erase(0x200); //探除EEPROM里面第二个扇区的内容
Byte_Program(0x200,last1); //把last1的数值放到200的地址里面
Flash_led = 1; //调节完亮度后,闪光灯闪一下,表示亮度已调节完成
Delay_ms(40);
Flash_led = 0;
}
if(last>CIRCLE) //记到10时重新从5开始计数
last=5;
if(last1>CIRCLE1) //记到30时重新从15开始计数
last1 = 15;
}
// else
// {
// TR0 = 0;
// } */
TH0 = (65536 - 1000)/256;
TL0 = (65536 - 1000)%256;
}
/*****************************************/
//定时器1函数
/*****************************************/
void INT_T1_INT(void) interrupt 3 using 1
{
count++; //开始记数
if(count>CIRCLE1) // 记到30时重新从1开始计数
{
count=1;
}
if(count<=last) //调节占空比,
{
LED_PWM = 1; //高电平占的比例
}
else
{
LED_PWM = 0; //低电平占的比例
}
if(count <= last1) //调节占空比
{
LED_PWM1 = 1; //高电平占的比例
}
else
{
LED_PWM1 = 0; //低电平占的比例
}
}
/*****************************************/
//外部中断1函数
/*****************************************/
void INT_INT1_INT (void) interrupt 2 using 1
{
a = 1;
// LED_VAR = 0;
LED_INIT = 1; //80MS出来的高电平
TR0 = 1; //开定时器0
count2 = 0; //80MS重新计数
//LED_PWM = 0;
}
/******************************************/
//定时器1初始化
/******************************************/
void INT_T1 (void)
{
EA=1; //开总中断
ET1=1; //定时器1开始计数
TH1=0XFC; //填充252个数,实际计3个数
TL1=0XFC;
// TR1=1;
}
/******************************************/
//定时器0初始化
/******************************************/
void INT_T0 (void)
{
EA=1; //开总中断
ET0=1; //开定时器0
TH0=(65536-1000)/256;
TL0=(65536-1000)%256;
// TR0=1;
}
/******************************************/
//外部中断1初始化
/******************************************/
void INT_INT1(void)
{
EA = 1;
EX1 = 1;
IT1 = 1;
}
/*******************************************/
//延时函数 延时时间是MS级的
/*******************************************/
void Delay_ms ( INT8U t)
{
int i,j;
for(i=t;i>0;i--)
for(j=125;j>0;j--);
}
//读一字节,调用前需打开IAP 功能,入口:DPTR = 字节地址,返回:A = 读出字节
INT8U Byte_Read(INT16U add)
{
IAP_DATA = 0x00;
IAP_CONTR = ENABLE_ISP; //打开IAP 功能, 设置Flash 操作等待时间
IAP_CMD = 0x01; //IAP/ISP/EEPROM 字节读命令
my_unTemp16.un_temp16 = add;
IAP_ADDRH = my_unTemp16.un_temp8[0]; //设置目标单元地址的高8 位地址
IAP_ADDRL = my_unTemp16.un_temp8[1]; //设置目标单元地址的低8 位地址
//EA = 0;
IAP_TRIG = 0x5A; //先送 5Ah,再送A5h 到ISP/IAP 触发寄存器,每次都需如此
IAP_TRIG = 0xA5; //送完A5h 后,ISP/IAP 命令立即被触发起动
_nop_();
//EA = 1;
IAP_Disable(); //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,
//一次连续的IAP 操作完成之后建议关闭IAP 功能,不需要每次都关
return (IAP_DATA);
}
//字节编程,调用前需打开IAP 功能,入口:DPTR = 字节地址, A= 须编程字节的数据
void Byte_Program(INT16U add, INT8U ch)
{
IAP_CONTR = ENABLE_ISP; //打开 IAP 功能, 设置Flash 操作等待时间
IAP_CMD = 0x02; //IAP/ISP/EEPROM 字节编程命令
my_unTemp16.un_temp16 = add;
IAP_ADDRH = my_unTemp16.un_temp8[0]; //设置目标单元地址的高8 位地址
IAP_ADDRL = my_unTemp16.un_temp8[1]; //设置目标单元地址的低8 位地址
IAP_DATA = ch; //要编程的数据先送进IAP_DATA 寄存器
//EA = 0;
IAP_TRIG = 0x5A; //先送 5Ah,再送A5h 到ISP/IAP 触发寄存器,每次都需如此
IAP_TRIG = 0xA5; //送完A5h 后,ISP/IAP 命令立即被触发起动
_nop_();
//EA = 1;
IAP_Disable(); //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,
//一次连续的IAP 操作完成之后建议关闭IAP 功能,不需要每次都关
}
//擦除扇区, 入口:DPTR = 扇区地址
void Sector_Erase(INT16U add)
{
IAP_CONTR = ENABLE_ISP; //打开IAP 功能, 设置Flash 操作等待时间
IAP_CMD = 0x03; //IAP/ISP/EEPROM 扇区擦除命令
my_unTemp16.un_temp16 = add;
IAP_ADDRH = my_unTemp16.un_temp8[0]; //设置目标单元地址的高8 位地址
IAP_ADDRL = my_unTemp16.un_temp8[1]; //设置目标单元地址的低8 位地址
//EA = 0;
IAP_TRIG = 0x5A; //先送 5Ah,再送A5h 到ISP/IAP 触发寄存器,每次都需如此
IAP_TRIG = 0xA5; //送完A5h 后,ISP/IAP 命令立即被触发起动
_nop_();
//EA = 1;
IAP_Disable(); //关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,
//一次连续的IAP 操作完成之后建议关闭IAP 功能,不需要每次都关
}
void IAP_Disable()
{
//关闭IAP 功能, 清相关的特殊功能寄存器,使CPU 处于安全状态,
//一次连续的IAP 操作完成之后建议关闭IAP 功能,不需要每次都关
IAP_CONTR = 0; //关闭IAP 功能
IAP_CMD = 0; //清命令寄存器,使命令寄存器无命令,此句可不用
IAP_TRIG = 0; //清命令触发寄存器,使命令触发寄存器无触发,此句可不用
IAP_ADDRH = 0;
IAP_ADDRL = 0;
}
/*void Delay()
{
INT8U i;
INT16U d=5000;
while (d--)
{
i=255;
while (i--);
}
} */我用的是STC1104E的单片机,想用一个管脚来显示两种不同的脉宽。还要根据外部的中断来显示,有中断就显示一种脉宽,没有中断就显示另外一种。我就想用一个变量a来测量外部中断的到来,程序里面下画线就是中断的程序。我是把变量a放到中断里面,当中断来临时,就让a为1,接着在主程序里面让a为0,以便进行没有中断的操作。但是实现不了这种功能,请教高手!!!!! |
|