打印
[国产单片机]

请教高手:关于stc的中断

[复制链接]
3023|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
lzf7290233|  楼主 | 2011-1-31 09:18 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/*******************************************/
//版本: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,以便进行没有中断的操作。但是实现不了这种功能,请教高手!!!!!

相关帖子

沙发
chunyang| | 2011-1-31 18:30 | 只看该作者
先确定是否进入了中断,没有则说明你的设置不对,进入中断则说明a=1时的处理程序不对,复位a不能在主循环中,必须在a=1的处理程序段内。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

9

帖子

0

粉丝