PIC16F676 PORTA doesn't work as intended.

Thread Starter

anshumaan

Joined Feb 25, 2020
6
There is a simple project I want to build which consists of five buttons and five leds, two of the buttons that I want to stick to PORTA, require pullups to work as they share a common ground while the rest of the three buttons on PORTC doesn't need pullups. The problem that I am facing is that PORTC works very well. I can control the inputs as well as outputs how I want. But its the PORTA that is not working at all especially the pins RA0 , RA1 & RA2. If I set them to output , the output start flickering but when I set them to input they doesn't read the input. Also the pullups doesn't work as well. But I also think that my pins definitions and pin access is not correct. Please correct me where necessary and tell me what I should do.
Here is the circuit along with the code.(its in proteus actually and not on actual hardware which will be ready after I had tested the code).
I have no problem in programming the logic so I am just including the pin declarations:-

C:
#define sensor_1 RA1
#define relay RA2
#define sensor_2 RA3
#define led_1 RA4

#define on_button RC0
#define auto_button RC1
#define off_button RC2
#define relay_led RC3
#define power_led RC4
#define led_2 RC5

// Initialize function to configure I/O pins
void initialize(void) {
    ANSEL = 0x00;
    
    TRISA = 0x00;
    PORTA = 0x00;
//    TRISA = 0b001011;
//    PORTA = 0x00;
//    TRISC = 0b000111;
//    PORTC = 0x00;
   // PORTAbits.RA0 = 1;
   // PORTAbits.RA1 = 1;
   // OPTION_REGbits.nRAPU = 0;
   // WPUAbits.WPUA0 = 1;
   // WPUAbits.WPUA1 = 1;
}
 

Attachments

Thread Starter

anshumaan

Joined Feb 25, 2020
6
Oh thanks for replying quickly. I will be sure to read the articles you have provided and come back with the results.
 

Thread Starter

anshumaan

Joined Feb 25, 2020
6
@MrChips[/USER] Yeah that is correct, but I had also stated that I can handle the programming but I don't know how to initialize the ports I glanced the datasheet earlier and understood only that
1. ANSEL register should be set to 0 to enable adc pins to go into digital mode
2. TRISA register to 0 sets the whole port A into output mode and vice versa( said this because its actually opposite to what AVR devices are set, when using AVR devices you should DDR register to 1 to set the port as output)
3. PORT register to turn ON or OFF the entire port.
4. To access the individual pins you have to use the RA0 for pin 0 and so on.
This is what I knew at this point.
Note however that by doing this I am able to set the PORTC however I want but its the PORTA especially the pins RA0 to RA2 which are not working properly meaning RA0 , RA1 and RA2 will flicker if set to 1 in output mode and will not read digital input if set in Input mode, so I am thinking that I am missing something. Here is the entire code if anyone wants to check :-

C:
// PIC16F676 Configuration Bit Settings

// 'C' source line config statements

// CONFIG
#pragma config FOSC = INTRCIO   // Oscillator Selection bits (INTOSC oscillator: I/O function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON       // RA3/MCLR pin function select (RA3/MCLR pin function is MCLR)
#pragma config BOREN = OFF      // Brown-out Detect Enable bit (BOD disabled)
#pragma config CP = OFF         // Code Protection bit (Program Memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <xc.h>

#define _XTAL_FREQ   4000000

#define sensor_1 RA1
#define relay RA2
#define sensor_2 RA3
#define led_1 RA4


#define on_button RC0
#define auto_button RC1
#define off_button RC2
#define relay_led RC3
#define power_led RC4
#define led_2 RC5

#define ON 1

#define PRESSED 1

//Function variables
unsigned char relay_flag = 0;
int auto_flag = 0;
int error_flag = 0;
int low_flag = 0;
unsigned long int ticks = 0;

// Function prototypes
void initialize(void);
void lamp_test(void);

void button_operation(void);
void relay_operation(void);
void sensor_operation(void);

void testing(void);

void set_timer0(void);
void __interrupt() COUNTER(void);

void __interrupt() counter(void){
    if(INTCONbits.T0IF){
        TMR0 = 8;
        INTCONbits.T0IF = 0;
       
        ticks++;
        if(ticks >= 3500){
           
            ticks = 0;
        }
    }
}

void set_timer0(void){
    INTCONbits.GIE = 1;         // 1 = Enables all unmasked interrupts
    INTCONbits.T0IF = 0;        // 0 = TMR0 register did not overflow
    INTCONbits.T0IE = 1;        // 1 = Enables the TMR0 interrupt
    OPTION_REGbits.T0CS = 0;    // 0 = Internal instruction cycle clock (CLKOUT)
    OPTION_REGbits.PSA = 1;     // 1 = PAS preset scaler set to the WDT (Watch dog timer)
    OPTION_REGbits.PS0 = 1;     // The PS0,1,and 2 have been set to 1's which for the WDT is 1:128
    OPTION_REGbits.PS1 = 1;
    OPTION_REGbits.PS2 = 1;
}


// Main function
int main(void) {
    initialize();
    //lamp_test();  
    set_timer0();
    while (1) {
        //relay_operation();
        //button_operation();
        //sensor_operation();
    }
    return 0;
}

// Initialize function to configure I/O pins
void initialize(void) {
    ANSEL = 0x00;
   
    TRISA = 0x00;
    PORTA = 0x00;
//    TRISA = 0b001011;
//    PORTA = 0x00;
//    TRISC = 0b000111;
//    PORTC = 0x00;
   // PORTAbits.RA0 = 1;
   // PORTAbits.RA1 = 1;
   // OPTION_REGbits.nRAPU = 0;
   // WPUAbits.WPUA0 = 1;
   // WPUAbits.WPUA1 = 1;
}

void lamp_test(void){
    power_led = 1;
    __delay_ms(100);
    relay_led = 1;
    __delay_ms(100);
    led_1 = 1;
    __delay_ms(100);
    led_2 = 1;
    __delay_ms(100);
    auto_led = 1;
    __delay_ms(300);
   
    auto_led = 0;
    __delay_ms(100);
    led_2 = 0;
    __delay_ms(100);
    led_1 = 0;
    __delay_ms(100);
    relay_led = 0;
    __delay_ms(100);
    power_led = 0;
    __delay_ms(100);
   
    auto_led = 1;
}

void relay_operation(void){
    if(relay_flag == 1){
        relay = 1;
        relay_led = 1;
    }
    else{
        relay = 0;
        relay_led = 0;
    }
}

void button_operation(void){
    //if any button is pressed
    //then other button press will not work
    if((auto_button == PRESSED) && (auto_flag == 0)){
        auto_led = !auto_led;
        auto_flag = 1;
    }
    else if((auto_button == !PRESSED) && (auto_flag == 1)){
        auto_flag = 0;
    }
    if(auto_led == 0){
       //MANUAL MODE
        if((on_button == PRESSED)&& (off_button == !PRESSED)){
        relay_flag = 1;
        }
        if((off_button == PRESSED) && (on_button == !PRESSED)){
            relay_flag = 0;
        }
    }
    else{
        //AUTO MODE
        if((sensor_1 == 0) && (sensor_2 == 0)){
            //enable SEMI AUTO MODE
            if((on_button == PRESSED)&& (off_button == !PRESSED)){
            relay_flag = 1;
            }
            if((off_button == PRESSED) && (on_button == !PRESSED)){
                relay_flag = 0;
            }
        }
    }
}
   
void sensor_operation(void){
    //NOT A LEVEL DISPLAY, JUST LEVEL INDICATOR STYLE USED HERE...
    if(error_flag == 0){
        //normal sensor operation
        if((sensor_1 == 0) && (sensor_2 == 0)){
            //do nothing, here buttons can work
            led_2 = 0;
            led_1 = 0;
        }
        else if((sensor_1 == 0) && (sensor_2 == 1)){
             //tank is full
            led_1 = 1;
            led_2 = 0;
        }
        else if((sensor_1 == 1) && (sensor_2 == 0)){
            //tank is empty
            led_2 = 1;
            led_1 = 0;
        }
        //assess the error condition in the timer.
    }
}
Also I must state that I am a beginner when it comes to PIC devices but I got some experience in C as I program AVR devices all the time :). Hope that helps.
 

Sensacell

Joined Jun 19, 2012
3,328
For PIC IO, always WRITE to the LATCH registers and READ from the PORT registers.

This avoids the read-modify-write nasty trap.
 

Thread Starter

anshumaan

Joined Feb 25, 2020
6
@Sensacell I request you to please explain me more because I don't think that you can use LAT register for PIC16f676 or maybe I am using the wrong register and you are hinting to another. Thanks for the advice though help me to implement it. I can't see any LAT register for PIC16f676 ,currently I use only PORT register to read and write or use the pin bit directly (like RA5 = 1). Isn't this how these pins should be set?
 

Thread Starter

anshumaan

Joined Feb 25, 2020
6
@MrChips thanks for hinting that I have to set the CMCON registers as well along with the TRIS as well as ANSEL registers to completely set the PORTA as input/output. Thanks for giving me the hint. I had set the CMCON registers to 0xff and it served my purpose. Thanks for the hint kind sir. My code started to work. Thanks again. Can't thank you enough.
 

Sensacell

Joined Jun 19, 2012
3,328
@Sensacell I request you to please explain me more because I don't think that you can use LAT register for PIC16f676 or maybe I am using the wrong register and you are hinting to another. Thanks for the advice though help me to implement it. I can't see any LAT register for PIC16f676 ,currently I use only PORT register to read and write or use the pin bit directly (like RA5 = 1). Isn't this how these pins should be set?
I think your compiler takes care of this- but you can double check by looking at the code it generates.
 

Thread Starter

anshumaan

Joined Feb 25, 2020
6
@Senascell Good Sir, as I have stated earlier that I am a beginner with PIC devices that is why I am unable to study the code that the compiler provides. What is the code called which the compiler provides and where to look it?
 

Ian Rogers

Joined Dec 12, 2012
1,133
Dont worry about the LAT register.. You are using digital input LAT is for output.
Just need to do what McChips said "ANSEL = 0; " CMCON needs to be 7 ( OFF ) "CMCON = 7;"
 
Top