• AVR Freaks

Hot!PIC16F887 and MC14077BCP

Author
pauline95
New Member
  • Total Posts : 12
  • Reward points : 0
  • Joined: 2019/09/27 00:36:34
  • Location: 0
  • Status: offline
2020/07/12 08:43:23 (permalink)
0

PIC16F887 and MC14077BCP

Hi. I'm connecting the output of the MC14077BCP XNOR gate directly to RB0 of PIC16F887. The output of the XNOR gate is a pulse and I'm trying to measure the low time of the pulse. I was trying to let the output of the XNOR gate to trigger the PORTB change interrupt in PIC16F887. The XNOR was generating a pulse but it doesn't trigger the interrupt. I can confirm that the code is working because the pulse generated using op-amp is triggering the interrupt. So, I would like to know if I can connect the XNOR gate directly to RB0 or I will need to connected some resistor between them? Thanks.
#1

3 Replies Related Threads

    ric
    Super Member
    • Total Posts : 28009
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: PIC16F887 and MC14077BCP 2020/07/12 13:16:42 (permalink)
    +1 (1)
    Is the MC14077 running form the same power supply as the PIC.
    Please show us your code anyway. Interrupt on change can be tricky, and many people misread what the datasheet says about clearing it.
     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #2
    pauline95
    New Member
    • Total Posts : 12
    • Reward points : 0
    • Joined: 2019/09/27 00:36:34
    • Location: 0
    • Status: offline
    Re: PIC16F887 and MC14077BCP 2020/07/13 09:22:20 (permalink)
    0
    Yes. The MC14077 is running form the same power supply as the PIC.
     
    I have modified my code, I try to poll the pulse from the logic gate. At the same time, I need to measure the analog voltage using channel 0 and channel 1 of the ADC. The problem of this new code is that the ADC is not reading the correct value. The voltage is expected to be around 240V and the current should be around 2.20A but the LCD is not showing these value. And, sometimes the pulse is not captured when RB0 is read. Below show my new code. Any help is appreciated.
     

    #pragma config CONFIG1 = 0xE0D4
    #pragma config CONFIG2 = 0xFFFF

    #include <xc.h>
    #include <math.h>

    #define _XTAL_FREQ 8000000

    #define RS PORTCbits.RC0 // LCD RS
    #define EN PORTCbits.RC1 // LCD RW

    void LCD_Init();
    void LCD_Cmd( unsigned char cmd);
    void LCD_Data(unsigned char data);
    void DisplayString(unsigned char *string);;
    unsigned int ADC(char channel);
    void __interrupt() ISR();

    int volt,amp,time1,time2;
    char num[10];
    float Vrms,Irms,PF,time,display;
    char firstNum,secondNum,thirdNum,fourthNum,fifthNum,sixthNum;

    void main()
    {
        
        OSCCON = 0x70; // Set internal oscillator to 8MHz;
        TRISB = 0xFF; // Configure PORTB as input
        WPUB = 0x01; // Enable pull-up for RB0
        IOCB = 0x00; // Disable interrupt-on-change for RB0
        ANSELH = 0x00; // Configure PORTB as digital pin
        TRISC = 0x00; // Configure PORTC as output (for LCD)
        TRISD = 0x00; // Configure PORTD as output (for LCD)
        T1CON = 0x10; // 1:8 prescale value, timer1 off
        INTCON = 0x00; // Disable GIE, PEIE, RBIE (0x90 causes LCD not displaying anything because INT interrupt is enabled and there is no ISR to handle it, causing the program to stop at interrupt)
        PIE1 = 0x00; // Disable TMR1IE
        OPTION_REG = 0x00; // PORTB pull-ups are enabled by individual PORT latch values
        
        LCD_Init(); // Initialize LCD

        while(1){
            if (RB0==0){
                TMR1ON = 1;
                time1=(TMR1H << 8) + TMR1L;
                while(RB0==0){}
                TMR1ON=0;
                time2=(TMR1H << 8) + TMR1L;
                time = (time2-time1)*0.000001;
                PF = cos(50*3.142*2*time);
                time *= 1000000; // 5 d.p. accuracy

                num[0] = (int)time / 1000000;
                num[1] = (int)time / 100000 % 10;
                num[2] = (int)time / 10000 % 10;
                num[3] = (int)time / 1000 % 10;
                num[4] = (int)time / 100 % 10;
                num[5] = (int)time % 10;
                
                LCD_Cmd(0x01);
                LCD_Cmd(0x80); // Go to first line
                DisplayString("Timer1: "); // Print first line
                LCD_Data(num[0]+'0');
                LCD_Data('.');
                LCD_Data(num[1]+'0');
                LCD_Data(num[2]+'0');
                LCD_Data(num[3]+'0');
                LCD_Data(num[4]+'0');
                LCD_Data(num[5]+'0');
                LCD_Data('s');
                
                PF*=100;
                    
                num[0] = (int)PF / 100;
                num[1] = (int)PF / 10;
                num[2] = (int)PF % 10;

                LCD_Cmd(0xC0); // Go to first line
                DisplayString("PF: "); // Print first line
                LCD_Data(num[0]+'0');
                LCD_Data('.');
                LCD_Data(num[1]+'0');
                LCD_Data(num[2]+'0');
                
                __delay_ms(500);
            }
            
            LCD_Cmd(0x01);
            
            volt = ADC(0);
            Vrms = ( (volt * 0.0109) + 0.3 ) * 24.182;

            display = Vrms * 100; // SEPARATE THE DIGITS FOR DISPLAY
            num[0] = (int)display / 10000;
            num[1] = (int)display / 1000 % 10;
            num[2] = (int)display / 100 % 10;
            num[2] = (int)display / 10 % 10;

            LCD_Cmd(0x80);
            DisplayString("Voltage: ");
            
            LCD_Data(num[0]+'0');
            LCD_Data(num[1]+'0');
            LCD_Data(num[2]+'0');
            LCD_Data('.');
            LCD_Data(num[3]+'0');
            LCD_Data('V');
            
            amp = ADC(1);
            Irms = (((amp*0.00365)-2.5)/0.185)*0.7071;
            
            display = Irms * 1000; // SEPARATE THE DIGITS FOR DISPLAY
            num[0] = (int)display / 1000;
            num[1] = (int)display / 100 % 10;
            num[2] = (int)display / 10 % 10;

            LCD_Cmd(0xC0);
            DisplayString("Current: ");
            LCD_Data(num[0]+'0');
            LCD_Data('.');
            LCD_Data(num[1]+'0');
            LCD_Data(num[2]+'0');
            LCD_Data('A');
            
            __delay_ms(500);
        }
        
    }

    unsigned int ADC(char channel){
        
        ADCON0 = 0x81 | (channel << 2); // FOSC/32, enable ADC, select ADC channel
        __delay_ms(1); // Delay for internal capacitor to charge
        GO_nDONE = 1; // Start conversion
        while (GO_nDONE); // Wait for conversion to complete
        ADON = 0; // Turn off ADC
        
        return (ADRESH << 8) + ADRESL;
    }

    /* SEND INSTRUCTION TO LCD */
    void LCD_Cmd( unsigned char cmd){
        PORTD = cmd; // Load value to PORTD
        RS = 0; // Select instruction register
        
        EN = 1; // Send enable pulse
        __delay_ms(1);
        EN = 0;
    }

    /* SEND DATA TO LCD*/
    void LCD_Data(unsigned char data){
        PORTD = data; // Load value to PORTD
        RS = 1; // Select data register
        
        EN = 1; // Send enable pulse
        __delay_ms(1);
        EN = 0;
    }

    /* LCD INITIALIZATION BY INSTRUCTION */
    void LCD_Init(){
        __delay_ms(100);
        LCD_Cmd(0x30);
        __delay_ms(5);
        LCD_Cmd(0x30);
        __delay_us(150);
        LCD_Cmd(0x30);
        __delay_us(150);
        LCD_Cmd(0X38);
        __delay_us(60);
        LCD_Cmd(0x08);
        __delay_us(60);
        LCD_Cmd(0x01);
        __delay_ms(5);
        LCD_Cmd(0x06);
        __delay_us(60);
        LCD_Cmd(0x0C);
        __delay_us(60);
    }

    /* DISPLAY STRING ON LCD */
    void DisplayString(unsigned char *string){
        while(*string)
        {
          LCD_Data(*string++);
        }
    }

     
    #3
    ric
    Super Member
    • Total Posts : 28009
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: PIC16F887 and MC14077BCP 2020/07/13 13:26:25 (permalink)
    +1 (1)

    The problem of this new code is that the ADC is not reading the correct value. The voltage is expected to be around 240V and the current should be around 2.20A but the LCD is not showing these value.

    You didn't think to reveal what it DID display?
    The secret to effiucient debugging is to reduce how many unknowns there are between a problem and what you are able to observe. In this case, don't assume your calculations are perfect. Display the raw value measured by the ADC, and tdo the calculation yourself by hand.
    If that is wrong, you have an ADC setup problem or a hardware problem. If it is right, then there is a problem in the calculation code, and you know where to go looking.
     
    Your timer code is reading the start time while the counter is running, which is a bad idea. Read the TMR value before you start it counting.
     
     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #4
    Jump to:
    © 2020 APG vNext Commercial Version 4.5