打印
[PIC®/AVR®/dsPIC®产品]

PIC16f1937电平变化中断问题

[复制链接]
1712|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
sihhepl|  楼主 | 2016-6-30 17:20 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我使用了RB0,RB1, RB2, RB3作为电平变化中断管脚,当RB0按下时,使得继电器1闭合(由RD0控制,继电器1控制交流220v电路的通断),当RB2按下时,使得继电器1断开,当RB2按下时,使得继电器2闭合(由RD1控制,继电器2控制交流220v电路的通断),当RB3按下时,使得继电器2断开.
现在的问题是:当RB0和RB2按下时,大约50%的概率不能使得继电器1、2闭合,程序是否有需要改进的地方

谢谢大家!

我的程序如下:

//*******************************************************************//
//                          系统初始化
//*******************************************************************//
void System_Init(void)
{
    OSCCON = 0b01101000;            //内部4MHz,不使能4xPLL
    OSCTUNE= 0b00000000;            //出厂校准
    //  PORTA用于读取端口的电平
    TRISA  = 0b00111111;            //RA0-RA5输入、RA6-RA7输出
    ANSELA = 0b00000000;            //RA0-RA7均为数字I/O
      LATA   = 0x00;                    //用于向端口写数据


    TRISB  = 0b00011111;            //RB0-RB4输入,RB5-RB7输出
    ANSELB = 0b00000000;            //RB0-RB7均为数字I/O
      LATB   = 0x00;                    //用于向端口写数据
    WPUB   = 0b00000000;            //无上拉
    IOCBN  = 0b00001111;            //检测RB0-RB3下降沿,会产生中断
   

    TRISC  = 0b00000000;            //RC0-RC7输出
    LATC   = 0x00;                    //用于向端口写数据


    TRISD  = 0b00111100;            //RD0-RD1输出,RD2-RD5输入,RD6-RD7输出
    ANSELD = 0b00000000;            //RD0-RD7均为数字I/O
    LATD   = 0x00;                    //用于向端口写数据

   
    TRISE  = 0b00000000;            //RE0-RE2输出
    ANSELE = 0b00000000;            //RE0-RE2均为数字I/O
    WPUE   = 0b00000000;            //无上拉
    LATE   = 0x00;                    //用于向端口写数据
}
   

//*******************************************************************//
//                             中断程序部分
//*******************************************************************//
void interrupt portb_int(void)
{
    if(IOCIE && IOCIF && IOCBF0)
    {
        RB0;
        IOCBF0 = 0;            //清中断标志位
        RD0 = 0;            //继电器1断电
        RD1 = 0;            //继电器2断电
        IOCBF0_FLAG = 1;    //设置标志
    }
    else if(IOCIE && IOCIF && IOCBF1)
    {
        RB1;
        IOCBF1 = 0;            //清中断标志位
        RD1 = 0;            //继电器2断电
        RD0 = 1;            //继电器1上电
        IOCBF1_FLAG = 1;    //设置标志
    }
    else if(IOCIE && IOCIF && IOCBF2)
    {
        RB2;
        IOCBF2 = 0;            //清中断标志位
        RD1 = 0;            //继电器2断电
        RD0 = 0;            //继电器1断电
        IOCBF2_FLAG = 1;    //设置标志
    }
    else if(IOCIE && IOCIF && IOCBF3)
    {
        RB3;
        IOCBF3 = 0;            //清中断标志位
        RD0 = 0;            //继电器1断电
        RD1 = 1;            //继电器2上电
        IOCBF3_FLAG = 1;    //设置标志
    }
}



//*******************************************************************//
//                             主程序部分
//*******************************************************************//

void main(void)
{
    __delay_ms(100);
    System_Init();          //系统初始化
    IOCIE = 1;                //电平变化中断使能
    GIE = 1;                //总中断允许

    IOCBF0 = 0;
    IOCBF1 = 0;
    IOCBF2 = 0;
    IOCBF3 = 0;
    IOCBF4 = 0;

    while(1)
    {        
        if(RA1 == 0)//手动模式
        {

            if(IOCBF0_FLAG == 1)
            {
                RD0 = 0;//继电器1断电
                RD1 = 0;//继电器2断电
                IOCBF0_FLAG = 0;
            
            }   
            else if(IOCBF1_FLAG == 1)
            {
                RD1 = 0;//继电器2断电
                RD0 = 1;//继电器1上电
                IOCBF1_FLAG = 0;
            
            }
            else if(IOCBF2_FLAG == 1)
            {
                RD1 = 0;//继电器2断电
                RD0 = 0;//继电器1断电
                IOCBF2_FLAG = 0;
               
            }
            else if(IOCBF3_FLAG == 1)
            {
                RD0 = 0;//继电器1断电
                RD1 = 1;//继电器2上电
                IOCBF3_FLAG = 0;
            
            }
        }
    }
}
沙发
JY-DX-JY| | 2016-6-30 17:39 | 只看该作者
会不会是硬件问题?有干扰

使用特权

评论回复
板凳
tdh03z| | 2016-6-30 22:01 | 只看该作者
不要连续操作端口,中间用几个NOP指令

使用特权

评论回复
地板
sihhepl|  楼主 | 2016-7-1 08:39 | 只看该作者
JY-DX-JY 发表于 2016-6-30 17:39
会不会是硬件问题?有干扰

我觉得这个是有可能的,不过不知道怎么处理干扰

使用特权

评论回复
5
sihhepl|  楼主 | 2016-7-1 08:41 | 只看该作者
tdh03z 发表于 2016-6-30 22:01
不要连续操作端口,中间用几个NOP指令

这个怎么添加啊?在while(1)内?

使用特权

评论回复
6
tdh03z| | 2016-7-5 21:32 | 只看该作者
本帖最后由 tdh03z 于 2016-7-5 21:36 编辑
sihhepl 发表于 2016-7-1 08:41
这个怎么添加啊?在while(1)内?

RD0 = 0;//继电器1断电
NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();
RD1 = 1;//继电器2上电
NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();

另外,端口输出要用LAT寄存器,忘记了RD0是不是操作LAT寄存器了,用下面的就可以操作端口输出
LATDbits.LATD0 = 0;
NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();
LATDbits.LATD1 = 1;
NOP();NOP();NOP();NOP();NOP();NOP();NOP();NOP();

使用特权

评论回复
7
ZG11211| | 2016-7-5 21:42 | 只看该作者
为何要用电平变化中断?
你的中断是用来唤醒?
非得在中断里执行?

使用特权

评论回复
8
tobyran| | 2016-9-20 14:28 | 只看该作者

1,继电器通电要有个延时,看规格继电器规格书,(不少于180MS)
2,你的继电器要有中断马上就要响应吗,中断后给一个标志位,用标志位在中断外处理继电器
3,软件没有按键防抖,

使用特权

评论回复
9
dogglove| | 2016-10-31 13:13 | 只看该作者
用状态机试试

使用特权

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

本版积分规则

2

主题

4

帖子

0

粉丝