Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] 16F628A PORTA Problem

Status
Not open for further replies.

ranga88

Newbie level 6
Joined
Oct 31, 2014
Messages
12
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
0
Hi all,

I'm new to microcontroller programming and I wrote a simple code for 16F628A to make a LED chaser with PORTA. But it is not workin as expected. I simulated it with proteus and it runs onetime and stops. When I change the same code to work with PORTB it works as expected. What could be the problem? I will post the code below. Thnx..

Code:
// PIC16F628A Configuration Bit Settings

// 'C' source line config statements

#include <xc.h>

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

// CONFIG
#pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTOSC oscillator: CLKOUT function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF      // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD)
#pragma config BOREN = OFF      // Brown-out Detect Enable bit (BOD disabled)
#pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EE Memory Code Protection bit (Data memory code protection off)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

#define _XTAL_FREQ 4e6

int delay = 500;

 void MoveLeft()
    {
        while(RA4!=1)
        {
        PORTA=PORTA*2;
        __delay_ms(delay);
        }
    }

 void MoveRight()
    {
        while(RA0!=1)
        {
        PORTA=PORTA/2;
        __delay_ms(delay);
        }
    }

void main()
{
    CMCON=0x07;

    TRISA=0x00;

    PORTA=0b00011111;
    __delay_ms(500);

    PORTA=0b00000001;
    __delay_ms(500);

    while(1)
    {
        if(RA0==1)
        MoveLeft();
        if(RA4==1)
        MoveRight();
    }
}
 

From the datasheet:
"RA4 is a Schmitt Trigger input and an open drain output".
Apply a pullup resistor (eg 4k7) when using RA4 even as output.
 

I used a pull-up resister. But the PIC is not working in the way I expected.
 

Zip and post the MPLAB X XC* project files and Proteus file.


Code C - [expand]
1
2
CMCON = 0x07;
VRCON = 0x00;

 
Last edited:

It is a strange way of reversing the LED direction and as pointed out, you have to beware of the RA4 open drain issue. It needs a pull-up or it will constantly be read as zero.

I suspect your underlying problem is what we call RMW (Read Modify Write). When you read the state of the port pins you get the voltage levels on them at the instant of the read taking place. It is quite possible that capacitive charge on the pins and any circuit attached to them is delaying the change of logic level and you are reading it before it has stabilized. Code that directly manipulates bits in a port will always be prone to this problem and it is the reason Microchip introduced the LAT registers in later PICs. A far better method is to move the bits in a variable then write that variable to to port, this ensures you never read the port at all so avoiding the problem.

Another problem could be the "PORTA=PORTA/2;" instruction. I think you intend it to shift the bits one place to the right but you ignore that RA5 will be shifted into RA4.

I'm not sure why you make all the PORTA pins outputs then use them as inputs. The instruction "if(RA0==1)" and the equivalent for RA4 are reading the state of the pins but they are in output mode.

Incidentally, you might find the >> and << instructions work better than dividing and multiplying, especially if you are using the free version of XC8.

Brian.
 

take care of pull up resistors, and look in datasheet after features related& multiplexed with the interested port pin. Sometimes is also useful to virtually buffer the port with a globally declared variable. For example i experienced that RA1=~RA1; did not work, and d=~d;RA1=d; did work.
 

Should work even without pull-up. But anyway, I have no idea what for all of this.
Code:
char portstate = 0;
void MoveLeft()
    {
        while(portstate < (1<<4))
        {
           portstate = portstate << 1;
           PORTA = portstate ;
           __delay_ms(delay);
        }
    }

 void MoveRight()
    {
        while(portstate > 1)
        {
           portstate = portstate >> 1;
           PORTA = portstate;
        __delay_ms(delay);
        }
    }

void main()
{
    CMCON=0x07;

    TRISA=0x00;

    PORTA=0b00011111;
    __delay_ms(500);

    PORTA=0b00000001;
    __delay_ms(500);

    while(1)
    {
        if(portstate == 0)
        MoveLeft();
        if(portstate == (1<<4))
        MoveRight();
    }
}
 

If you are testing in Proteus I have to tell that some Proteus models have bugs.
 

If you are testing in Proteus I have to tell that some Proteus models have bugs

Although some Proteus models do have bugs, and there are some limitations of the model for the 16F628A the model on Proteus 7.10 is generally bug free, and in this case I am sure the problem is not with Proteus.
 

Are you using 4 MHz INTOSCIO ? How should the LEDs turn ON and OFF ?

- - - Updated - - -

I have attached two versions of code. One is PORTA version and another PORTB version. PORTB version works as expected. PORTA version works only in one direction in Proteus but works in both directions in debugger. I guess it is a bug of Proteus PIC16F628A model related to PORTA4. I have made small changes to code. Mine is mikroC PRO PIC Compiler codes. See attached video. It shows PORTA code working as expected. You can see the PORTA values to the right of the screen. See how the values shift in both directions.
 

Attachments

  • LED Chaser.rar
    119.9 KB · Views: 70
  • sim.rar
    274.2 KB · Views: 60

After reading all the comments, I thought of testing the code by building the actual circuit rather using simulators. So I I did few tests and results were as below,

So first I ignored RA4 and wrote the code only for RA0-RA3 as below. It worked as expected.

RA0-->RA1-->RA2-->RA3-->RA2-->RA1-->RA0-->continue

Code:
int delay = 500;

 void MoveLeft()
    {
        while(RA3!=1)
        {
        PORTA=PORTA*2;
        __delay_ms(delay);
        }
    }

 void MoveRight()
    {
        while(RA0!=1)
        {
        PORTA=PORTA/2;
        __delay_ms(delay);
        }
    }

void main()
{
    CMCON=0x07;
    VRCON=0x00;
    TRISA=0x00;

    PORTA=0b00001111;
    __delay_ms(500);

    PORTA=0b00000001;
    __delay_ms(500);

    while(1)
    {
        if(RA0==1)
        MoveLeft();
        if(RA3==1)
        MoveRight();
    }
}

Then I added RA4 to the above code, It worked resulted,

RA0-->RA1-->RA2-->RA3-->stops

Code:
int delay = 500;

 void MoveLeft()
    {
        while(RA4!=1)
        {
        PORTA=PORTA*2;
        __delay_ms(delay);
        }
    }

 void MoveRight()
    {
        while(RA0!=1)
        {
        PORTA=PORTA/2;
        __delay_ms(delay);
        }
    }

void main()
{
    CMCON=0x07;
    VRCON=0x00;
    TRISA=0x00;

    PORTA=0b00011111;
    __delay_ms(500);

    PORTA=0b00000001;
    __delay_ms(500);

    while(1)
    {
        if(RA0==1)
        MoveLeft();
        if(RA4==1)
        MoveRight();
    }
}

Additionally I tested the following simple code (includes RA4) and it gave me the expected result:

RA0-->RA1-->RA2-->RA3-->RA4-->RA3-->RA2-->RA1-->RA0-->continue

Code:
int delay = 500;

void main()
{
    CMCON=0x07;
    VRCON=0x00;
    TRISA=0xE0;

    PORTA=0b00011111;
    __delay_ms(500);

    PORTA=0b00000001;
    __delay_ms(500);

    while(1)
    {
     PORTA=0b00000010;
     __delay_ms(delay);
     PORTA=0b00000100;
     __delay_ms(delay);
     PORTA=0b00001000;
     __delay_ms(delay);
     PORTA=0b00010000;
     __delay_ms(delay);
     PORTA=0b00001000;
     __delay_ms(delay);
     PORTA=0b00000100;
     __delay_ms(delay);
     PORTA=0b00000010;
     __delay_ms(delay);
     PORTA=0b00000001;
     __delay_ms(delay);
    }
}

In the first two cases the Proteus simulation was not same as the result of the actual circuit but it indicated a problem in the simulation. In the third case both simulation and the actual circuit were the same and worked fine.

So I think the problem could be the reading from the RA4. When the bits were directly specified the RA4 works fine. However as I know writing code in this way will consume more space in the PIC.

I tested code posted by milan.rajik in post #11 but it was same as the case two above while used in the actual circuit.
 

Maybe PORTA4 cannot be read.

- - - Updated - - -

Now it works as you need. Here is the mikroC PRO PIC 6.4.0 code.

It now works both in Proteus and hardware.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
const unsigned long int delay = 1000;
short shift = 1;
 
void MoveLeft() {
 
      while(shift != 0x10) {
               PORTA = shift;
               shift <<= 1;
               Delay_ms(delay);
      }
}
 
 void MoveRight() {
      
      while(shift != 0x01) {
              PORTA = shift;
              shift >>= 1;
              Delay_ms(delay);
      }
}
 
void main()
{
    CMCON = 0x07;
    VRCON = 0x00;
    TRISA = 0x00;
    TRISB = 0x00;
    PORTB = 0x00;
 
    PORTA = 0b00011111;
    Delay_ms(1000);
 
    PORTA = 0b00000001;
 
    while(1) {
        MoveLeft();
        MoveRight();
    }
}

 
There are no bugs in Proteus with regard setting and reading the ports except a meta stability issue that may show itself after the code has been running a long time.

https://www.edaboard.com/threads/294964/#post1370641

I think that the problem could be due to the time it takes between setting portA RA4 and reading it back again. Due to the fact that it is an open collector output the rise times are considerably longer. One way of making it work in Proteus is to look at the properties of the resistors and LED and setting them to digital. As well as speeding up the simulation it will avoid this problem.
 

The OP tested it in hardware and the same problem exists in hardware. So, I have provided a code where PORTA is not read but a variable shift is used to shift the values and assign to PORTA in my previous post.
 

OK, now it works fine. But finally, can we add the RA6 and RA7 to the same code skipping RA5
 

Yes, you can add but RA5 will not glow and due to this there will be 2 second delay according to my code.
 

the night rider effects normally uses rotate commands in the assembly, so i think perhaps your status registers is getting effected wen you do this operation.. and yes one more thing, in most microchip the porta is initially assigned as ad convertor, so chk that also that it has to be set as digital input or output port , you can do that just by disabling the adcon register.. i hav made several nr's on all ports and never faced these issues.. gud luck
 

Thanks all.

I think I could solve my problem. :thumbsup:
 

Here is the MPLABX XC8 and mikroC PRO PIC projects. It works the way you want.
 

Attachments

  • LED Chase PORTA.rar
    35.1 KB · Views: 74
  • Test_628A_PORTA.X.rar
    64.2 KB · Views: 77

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top