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] 12F629 TWO PORTS Switching ON

Status
Not open for further replies.

vdurgaidass

Junior Member level 3
Junior Member level 3
Joined
Jul 13, 2009
Messages
27
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Location
India
Visit site
Activity points
1,525
Hi All
Request help for the following code. I am trying to toggle two LEDs at GPIO0 and GPIO1 of PIC12F629 with 0.5Sec delay. Problem is If I comment out any one LED other one toggles as desired.

But when I include both LEDs only one Toggles and other one is NOT Toggling ( remains ON always ). If I change the order of switching the LEDs, the one which was toggling remains ON and the other one is now toggling.

I have tried both MPASM and HiTech C in MPLAB IDE V8.53. I have replaced the 12F629 with new one also. But problem remains same.

If I introduce a delay of 100mS the commented out lines in the code below between the two port pin operation then both LEDs Toggling but one with different interval (not equal to 0.5 Sec). Any Help is welcome.

Thanks
V Durgaidass


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
LED 
        bsf     GPIO,pin6       ;turn off LED2
;       call    Del1
        bcf     GPIO,pin7       ;turn on LED1       
        call    Del 
        bcf     GPIO,pin6       ;turn on LED2
;       call    Del1
        bsf     GPIO,pin7       ;turn off LED1
        call    Del
 
        goto    LED 
 
////////////////////
while(1)
{           
            LED1 = 1;
//          __delay_ms(100);
 
            LED1 = 0;
            __delay_ms(500);
            LED2 = 1;
//          __delay_ms(100);
            LED2 = 0;
            __delay_ms(500);
            }

 
Last edited by a moderator:

Try this code.


Code C - [expand]
1
2
3
4
5
6
7
8
while(1) {
    LED1 = 1;
    LED2 = 1;
    __delay_ms(500);
    LED1 = 0;
    LED2 = 0;
    __delay_ms(500);
}

 

You have LED1 set to on then the next line of code sets it off then delay and do the same for the other led. What is happening is on the first clock cycle you turn the led on, then the next clock cycle you turn it off, then delay 500ms and repeat for the other led.
If your clock is say 10Mhz then each clock cycle is 100ns, so you are turning on and off the led really fast. You need to have a delay between turning on and back off.
Code:
While(1){
LED1=1
LED2=1
_delay_ms(500)
LED1=0
LED2=0
_delay_ms(500)

This will toggle them at the same time. If you want them to toggle independently you can set up interrupts that trigger the leds separately.
 
Last edited by a moderator:

Sounds to me like the classic "read-modify-write' problem (and pic.programmer's suggestion will probably have the same issue - depends on how the compiler generates the code).
Depending on how "LED1" and "LED2" are defined (and I assume they are bits on the GPIO register) then you will need to code around this. Perhaps the easiest way is with a "shadow" register where you set the bits you want in a memory-based variable and then write that variable (as a whole) to the GPIO register.
Another way is to update both LED's at the same time (in effect what the shadow register does).
Alternatively add a bit of a delay between subsequent RMW operations on the GPIO register - a microsecond or two should be sufficient. This normally could be achieved by spacing the two RMW operations around other code but that may not work with a simple test program such as this.
Susan
 
Thanks pic.programmer
I already tried this. Only LED1 is toggling LED2 always ON.
if I make your Line 2 to LED2 = 1; Line 3 to LED1 = 1; then only LED2 toggles and LED1 remains ON.

- - - Updated - - -

Thanks Pyrchm
I have already tried your code. Problem remains.
Also sorry for posting a code with mistake. My actual C code if
Code:
while(1)
{           
            LED1 = 1;
//          __delay_ms(100);
 
            LED2 = 0;
            __delay_ms(500);
            LED2 = 1;
//          __delay_ms(100);
            LED1 = 0;
            __delay_ms(500);
            }
Regards

See my reply to pic.programmer.
 
Last edited by a moderator:

If the pins used for LEDs have ADC or Comparator functions then they should be disabled using ADCON1 or ANSELx or CMCON registers.
 

Thanks Aussie Susan
It seems "read-modify-write" (RMW)problem
I Modified the code as below and it is working as desired.

Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
uchar ports;
#define LED1 0x01
#define LED2 0x02
 
    while(1){
ports &= ~LED1;
ports |= LED2;
GPIO = ports;
__delay_ms(500);
ports &= ~LED2;
ports |= LED1;
GPIO = ports;
__delay_ms(500);
}




I have used codes like

Code C - [expand]
1
2
3
4
5
6
#define LED1 RB0
#define LED2 RB1
 
LED1 = 1;LED2 = 0;
Delay
LED1 = 0;LED2 = 1;



In PIC16f873 PIC16f877 and not faced this 'RMW' problems.
Is this problem is for 12Fs?

Regards

- - - Updated - - -

Thanks pic.programmer

12F629 does not have ADC, so ADCON, ANSEL are not applicable / supported in the register definition of 12F629.

Regards
 
Last edited by a moderator:

This is my code, like the first asm code:

Code:
//#include <pic.h>
#include <htc.h>

__CONFIG(FOSC_INTRCIO & WDTE_OFF & PWRTE_OFF & MCLRE_OFF & BOREN_OFF & CP_OFF & CPD_OFF);

#ifndef _XTAL_FREQ
 // Unless already defined assume 4MHz system frequency
 // This definition is required to calibrate __delay_us() and __delay_ms()
 #define _XTAL_FREQ 4000000
#endif

#define	LED1	GPIO0
#define	LED2	GPIO1
#define	LED3	GPIO2
#define	BUTTON	GPIO3
#define	LED4	GPIO4
#define	LED5	GPIO5

void main(void)
{
	OSCCAL	= 0x3ff;
	GPIO	= 0x00;	
	CMCON	= 0x07;	 	 		//							76543210 
	TRISIO	= 0b00001000;		// GP3 ALWAYS INPUT 	- 	00001000
	LED1=0;
	LED2=0;
	LED3=0;
	LED4=0;
	LED5=0;

    for(;;)
    {
		
		LED1=1;
		__delay_ms(100);
		LED2=0;
		__delay_ms(500);
		LED1=0;
		__delay_ms(100);
		LED2=1;
		__delay_ms(500);
		
	}
}

01.png
 
Last edited:

Thanks nagkiller

I tried like your code, it is working. But my doubt was why that 100ms delay is required between modifying the Two port pins. I have not used any delay for modifying two or more port pins in PIC16F873 and PIC16F877s. I faced this problem only in PIC12F508 and PIC12F629.


Regards
 

In a loop while(1) (in my case the for(;;)) will always be running that are inside {} ... and this is done at a very high frequency(without the delay function). With delay, there is POV, then one can see the effect of d LED on/off. If that's what I understood of your doubts.

Post your complete code using the other mcu. The other code is similar???

You can use this too...

Code:
//#include <pic.h>
#include <htc.h>

__CONFIG(FOSC_INTRCIO & WDTE_OFF & PWRTE_OFF & MCLRE_OFF & BOREN_OFF & CP_OFF & CPD_OFF);

#ifndef _XTAL_FREQ
 // Unless already defined assume 4MHz system frequency
 // This definition is required to calibrate __delay_us() and __delay_ms()
 #define _XTAL_FREQ 4000000
#endif

#define	LED1	GPIO0
#define	LED2	GPIO1
#define	LED3	GPIO2
#define	BUTTON	GPIO3
#define	LED4	GPIO4
#define	LED5	GPIO5

void main(void)
{
	OSCCAL	= 0x3ff;
	GPIO	= 0x00;	
	CMCON	= 0x07;	 	 		//							76543210 
	TRISIO	= 0b00001000;		// GP3 ALWAYS INPUT 	- 	00001000
	LED1=0;
	LED2=0;
	LED3=0;
	LED4=0;
	LED5=0;

    for(;;)
    {
		
		LED1=1;
		LED2=0;
		__delay_ms(500);
		LED1=0;
		LED2=1;
		__delay_ms(500);		
	}
}
 
Last edited:

Dear nagkiller

Here is my code where one LED only will toggle but not both as desired and this is for PIC12508 controller.
I have already marked this post as 'Solved'
Thanks for your info.
Code:
#define _XTAL_FREQ 4000000

//===============
#include  <htc.h>
#include "delay508.h"

// config: int reset, no code protect, no watchdog, int 4MHz clock
__CONFIG(MCLRDIS & UNPROTECT & WDTDIS & INTRC);


#define SWWW GP2
#define SWSS GP5
#define LED2 GP1
#define LED1 GP0
void main(void)
{
//	uchar tmp_key,i,first_loop;


	TRIS = 0b111100; // GP1, GP0: digital outputs

	GPIO = 0x00;

	while(1){
			nop();
			LED1 = 1;  LED2 = 0;
			__delay_ms(500);__delay_ms(500);
			LED1 = 0;LED2 = 1;
			__delay_ms(500);__delay_ms(500);
			}
}
 

You have already been given the answer. You can show for yourself that this is still a RMW issue by:
- instead of using "LED1 = 1; LED2 = 0;" just write 0x02 to the GPIO port
- instead of using "LED1 = 0; LED2 = 1;" just write 0x01 to the GPIO port
The end result will be the same BUT you will be updating both bits at the same time and this will NOT require the hardware to read the port as you are not doing a bit operation. (I am looking at the code in your 'while' loop - I know that you have some other #defines for other GPIO bits but you do not seem to be using those for now.)
When you find that this will make the program work as required, you should accept that you will need to use some other technique (such as the shadow register mentioned above), or to put some other code in between setting one bit and the next.
Susan
 
Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top