【问题标题】:Not able to set value 1 to pin as Input in MPLAB无法将值 1 设置为 MPLAB 中的输入引脚
【发布时间】:2018-03-18 01:46:39
【问题描述】:

我正在使用 MPLAB 对 PIC 套件 14f458 执行操作。

现在我想创建一个代码,使用按钮通过微控制器传递不同数量的电压电源 LED。第一次按下按钮时,我应该得到 10% DC 的波形,第二次和第三次分别为 50% 和 95%。

我已经解决了这个问题,但仍然将 RE2 PORT 的值设为 0 而不是 1。而且我也不知道如何在释放按钮时停止计时器。

我的代码如下:

#include<stdio.h>                       //Standard I/O Library
#include<p18cxxx.h>                     //for TRISA,E and PORTA,E declaration
#pragma config WDT = OFF                //watchdog counter
#pragma config OSC = HS, OSCS = OFF
#pragma config PWRT = OFF, BOR = ON, BORV = 45
#pragma config DEBUG = OFF, LVP = OFF, STVR = OFF

void timer_10()
{
    CCP1CON = 0;
    PR2 = 249;
    CCPR1L = 24;
    TRISCbits.TRISC2 = 0;
    T2CON = 0x00;
    CCP1CON = 0x3c;
    TMR2 = 0;
    T2CONbits.TMR2ON = 1;
    while(1)
    {
        PIR1bits.TMR2IF = 0;
        while(PIR1bits.TMR2IF == 0);
    }
}

void timer_50()
{
    CCP1CON = 0;
    PR2 = 249;
    CCPR1L = 124;
    TRISCbits.TRISC2 = 0;
    T2CON = 0x00;
    CCP1CON = 0x2c;
    TMR2 = 0;
    T2CONbits.TMR2ON = 1;
    while(1)
    {
        PIR1bits.TMR2IF = 0;
        while(PIR1bits.TMR2IF == 0);
    }
}

void timer_95()
{
    CCP1CON = 0;
    PR2 = 249;
    CCPR1L = 236;
    TRISCbits.TRISC2 = 0;
    T2CON = 0x00;
    CCP1CON = 0x2c;
    TMR2 = 0;
    T2CONbits.TMR2ON = 1;
    while(1)
    {
        PIR1bits.TMR2IF = 0;
        while(PIR1bits.TMR2IF == 0);
    }
}

void main()
{
    int i = 1;
    ADCON1 = 0x06;                      //Sets RA0 to digital mode
    CMCON = 0x07;
    TRISEbits.TRISE2 = 1;               //set E2 PORTE pins as input
    PORTEbits.RE2 = 1;                  //Here I am not able to SET Value 1

    while(1)
    {
        while(PORTEbits.RE2 == 0)
        {
            switch(i)
            {
                case 1:
                    timer_10();
                    break;
                case 2:
                    timer_50();
                    break;
                case 3:
                    timer_95();
                    break;
            }
            if(i<4)
            {
                i++;
                if(i>=4)
                {
                    i=1;
                }
            }
        }
    }
}

我的编译器卡在函数 timer_10() 中。请帮帮我。

【问题讨论】:

    标签: embedded microcontroller pic mplab interfacing


    【解决方案1】:

    这对于评论来说有点太长了,我认为您可能能够自己找到答案 - 但是,我会给您一些建议。

    在 main() 中

    TRISEbits.TRISE2 = 1;               //set E2 PORTE pins as input
    PORTEbits.RE2 = 1;                  //Here I am not able to SET Value 1
    

    在将 E2 配置为输入后写入端口 E2 时会发生什么行为?它在the PIC18F458 data sheet 中进行了描述,特别是第 9.5 节

    在 timer_10() 中

    void timer_10()
    {
        CCP1CON = 0;
        PR2 = 249;
        CCPR1L = 24;
        TRISCbits.TRISC2 = 0;
        T2CON = 0x00;
        CCP1CON = 0x3c;
        TMR2 = 0;
        T2CONbits.TMR2ON = 1;
        while(1)
        {
            PIR1bits.TMR2IF = 0;
            while(PIR1bits.TMR2IF == 0);
        }
    }
    

    您说您的编译器卡住了,但我假设您的意思是调试器,因为您能够运行 main() 来观察 PORTEbits.RE2 = 1; 没有按照您的预期执行。如果您在调试器中单步执行此操作,它会卡在哪里?你知道为什么吗?

    【讨论】:

    • 是的,你是对的,当我在调试器中运行我的程序时,我在函数 timer_10() 中陷入了 While 循环。当 timer2 完成时,它会一次又一次地启动。因此,当我使用 Stimulus 更改 RE2 的值时,案例 2 应该运行并且应该调用 timer_50() 但它不起作用。我正在使用逻辑分析仪观察 RE2 的值,当我开始运行时,RE2 的值显示为 0 而不是 1。我知道 PORTEbits.RE2 = 1; 设置值 1 但它不起作用,为什么我不知道。
    • 关于timer_10(),您希望while(PIR1bits.TMR2IF == 0 ); 退出后会发生什么,即。当PIR1bits.TMR2IF 更改为1?显然,如果该函数没有退出,您将无法返回main 以检查RE2 继续进行timer_50()
    • 是的,我希望它应该在while(PIR1bits.TMR2IF == 0) 之后退出,但它会重新开始,我想退出函数timer_10,请帮助我了解如何退出。在main() 中,我设置了PORTEbits.RE2 = 1,但在逻辑分析仪中,当我开始运行我的代码时,它从0 开始。如果我设置了PORTEbits.RE2 = 1 为什么它以PORTEbits.RE2 = 0 开头。
    • while(PIR1bits.TMR2IF == 0);退出时,程序在while(1)循环体的末尾,所以它检查while(1)的循环条件。 1 始终为真,因此while(1) 是一个无限循环。要使其退出函数,请移除外部循环,保留其循环体 PIR1bits.TMR2IF = 0; while (PIR1bits.TMR2IF == 0);
    • 是的,我知道了,但是每当我调试我的程序时,它都会以 RE2 = 0 开头,为什么它会在我设置它 PORTEbits.RE2 = 1 时发生。我可以在函数timer_10() 中使用while(PORTEbits.RE2 == 0) 条件而不在函数中定义 PORTE 吗?在我释放按钮时退出循环。
    【解决方案2】:

    好的,让我们稍微简化一下。如果您希望占空比在按钮的下降沿改变,并且您不想使用中断,那么您需要重组您所拥有的。首先,timer_x 例程有几个问题: 1) 你不需要 while 循环,这就是你被卡住的原因。 2)如果您删除该循环,您将不断调用一个计时器例程,该例程将重置寄存器值,您将不会得到您期望的结果。此外,由于您没有使用中断,谁在乎是否设置了溢出标志,只需保持设置即可。 要解决此问题,首先,删除所有 timer_x 例程。接下来,您需要一个定时器程序来读取开关输入。请记住,所有开关都有开关弹跳,因此读取一个值是不可靠的。您要么需要以大于开关弹跳(约 50 毫秒)的速度缓慢读取开关,并且仅在连续两个读数相同时才运行例程,或者您可以更快地读取它,但您需要更多相同的读数知道你有一个稳定的值。 从那里,您只能在第一个下降沿增加“i”,而不是一直按住开关(除非您想要那样)。你的主程序应该看起来像(原谅定时器寄存器的快捷方式):

    Main()
    if (tmr2.overflow)     // 50ms switch read timer
    {
      switchCurrent = PORTE2;
    }
    if (   (switchCurrent == swtichLast)    // Two readings of the same value
        && (!switchCurrent)                 // and switch is pressed
        && (!switchUpdated)  )              // and haven't updated the pwm yet
    {
          switchUpdated = TRUE;             // Only allow one update per switch 
          i++;
          if (i > 4)
          {
              i = 0;
          }
          switch (i)
          {
             case 0:
                 CCPR1L = 24;
                 break;
             case 1:
                 CCPR1L = 124;
                 break;
            ... and so on.  Note, the only difference in each case is CCPR1L, so just rewrite that register instead of resetting everything.
    }
    switchLast = swtichCurrent;
    if (swtichCurrent)
        switchUpdated = 0
    

    这应该为您提供一个起点,希望对您有所帮助

    【讨论】:

      猜你喜欢
      • 2021-08-31
      • 2020-05-27
      • 1970-01-01
      • 2017-10-07
      • 1970-01-01
      • 1970-01-01
      • 2012-03-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多