Can wise men explain this code to me?

Thread Starter

Jaden5165

Joined Sep 9, 2011
69
Rich (BB code):
#include <htc.h>
#define _XTAL_FREQ 4000000
__CONFIG(0x3F39);
void main()
{
unsigned char sGPIO=0;  //shadow copy of GPIO
unsigned char dcnt;     //delay counter
//initialisation
 
TRISIO=~(1<<1);  //configure GP1 (only) as an output
 
//Main loop
for(;;)
{
 //toggle GP1
 sGPIO ^= 1<<1;//flip shadow bit corresponding to GP1
 GPIO = sGPIO;//write to GPIO
//delay 500ms
for(dcnt=0;dcnt<5;dcnt++)
{
__delay_ms(100);
}
}//repeat
}


I got this code from this website
http://www.gooligum.com.au/tutorials/midrange/PIC_Mid_C_1.pdf
it's a pdf file and the code is taken from page[16]


can you explain to me in a more simple way or modify the code to a more understanfable code.
especially those highlighted(what shadow and what symbol represent for that ^=1<<1).
assume if change to using pic16f877a instead of using the same pic as this example.this example is using pic12f629.
i need to understand this before going to the following page especially page[21] that about switch debounce.
 
Last edited:

debjit625

Joined Apr 17, 2010
790
Its very simple,its like this......oohh wait I guess I am not wise enough....

A shadow variable is nothing but a variable which stores the current contents of some register like GPIO1,For example if GPIO1's current value is 100 then
Rich (BB code):
unsigned int shadow = 0x00;
shadow = GPIO1;
using this code you can store the value of GPIO1 into shadow variable, so that you can use it later without modifying or accessing GPIO1.Think its like a shadow of some register and here the shadow means the value of that register.

what symbol represent for that ^=1<<1
For that you have to understand binary operations in language C i.e.. you have to learn about bitwise operators. Google for C tutorial and check out about bitwise operators.
The program flash a LED on GP1 with 50% duty cycle, here is how you can do it with PIC16F877A instead of GP1 which is not their in this PIC I am using RB1

Rich (BB code):
#include "htc.h"
#ifndef _XTAL_FREQ
#define _XTAL_FREQ 4000000
#endif
void main()
{
 unsigned int shadow = 0x00;//shadow copy of PORTB
 unsigned int count = 0x00;//delay counter
 PORTB = 0x00;
 TRISB = 0x00; //Config PORTB as outputs
 shadow = PORTB;
 for(;;)
 {
   shadow ^= (1<<1);//toggle bit 1 ,bit 1 of shadow is bit 1 of PORTB i.e.. RB1
   PORTB = shadow;//assign the shadow's value to PORTB.
 
  //make a delay for 1sec
  for(count = 0;count<10;count++)
  {
   __delay_ms(100);
   }
 }
}
Check datasheet for configuration bit settings...

Good Luck
 
Last edited:

Thread Starter

Jaden5165

Joined Sep 9, 2011
69
Rich (BB code):
#include <htc.h>
__CONFIG(0x3F39);
#define _XTAL_FREQ 4000000
void main()
{
 unsigned char shadow = 0x00;//shadow copy of PORTB
 unsigned char count = 0x00;//delay counter
 TRISB = 0x00; //Config PORTB as outputs
 PORTB = 0x00;
 
 shadow = PORTB;
 for(;;)
 {
   shadow^=0b00000010;      //toggle bit 1 ,bit 1 of shadow is bit 1 of PORTB i.e.. RB1
   PORTB = shadow;                //assign the shadow's value to PORTB.
 
  //make a delay for 1sec
  for(count = 0;count<10;count++)
  {
   __delay_ms(100);
   }
 }
}

when i program this code into my pic my led cannot turn on.any problem?but it can be successfully built.
 

John P

Joined Oct 14, 2008
2,026
Have you tried a do-nothing program like this?

Rich (BB code):
TRISB = 0x00;
PORTB = 0xFF;
while(1) ;
If the LED doesn't come on, you've got something wrong with your wiring.
 

ErnieM

Joined Apr 24, 2011
8,377
Geezer, I hope this wasn't code from a instructional tutorial. That is some excellent examples of C code being "write-only" (meaning only the person who wrote it could ever understand it).

However, I have seen where obscure code such as this actually compiles to fewer steps in the final program, and once where I needed every byte I wrote such code too.

OK, shadow register was covered, but not the WHY. One thing PICs have a problem with is something called "read-modify-write" (or r-m-w) which is how bits get set. Inside one statement the register is read (read), the value changed (modify), then it is written back (write). Now in some cases the read portion gets the wrong value, especially when the bit is an output pin (it may not have reached it's new value yet, so is read wrong).

Doing the "real work" on a shadow register then copping the shadow to the read register is a good way around the r-m-w problem.

Rich (BB code):
TRISIO=~(1<<1);
In pieces: The "<<" is a shift command, "a<<b" means "shift a to the left b times." So 1<<1 means shift 1 left once, so you start with 0000 0001 and you get 0000 0010.

Next piece is the tilda ~: it means compliment or bitwise inversion. If you put 0000 0010 in you get 1111 1101 out. In PICs setting TRIS to 0 is 0utput and to 1 means 1nput. So that value sets TRISIO1 as output, the rest as input.

Rich (BB code):
sGPIO ^= 1<<1;//flip shadow bit corresponding to GP1
The ^ thing is a bitwise exclusive or, here using to invert a single bit.

But before we use that, start from before the equals sign. C has a shorthand for things like:

A = A + 1;

By letting you say:

A += 1;

So we already covered what 1<<1 means (0000 0010) so sGPIO ^= 0b00000010 will just flip the second bit and leave everything else the same.


Rich (BB code):
GPIO = sGPIO;//write to GPIO
Note he used the shadow register to create his value, then copies the shadow to the real register.
 

cheezewizz

Joined Apr 16, 2009
82
"OK, shadow register was covered, but not the WHY."

That's not entirely true, I really liked these tutorials when starting out, they helped immensely. IIRC they cover both the why and how to use shadow registers, and it does explain fairly early on that's it's not an introduction to C just the specifics concerned with C for microcontrollers...
 

debjit625

Joined Apr 17, 2010
790
when i program this code into my pic my led cannot turn on.any problem?but it can be successfully built.

First of all the code was for PIC16F877A ,I think you are using that.Now to solve this problem we need some more info i.e..
1) Schematic i.e.. Circuit diagram.
2) Which programmer you are using and does it confirms about a successful programming
3) Is your programmer capable to load configuration bit settings from hex file, if not you have to set it in your programmer otherwise it will not work.

@John P
what do you mean by a do nothing program?
A program which just tests a simple task of the mcu to verify that the circuit for the mcu is ok.In case of John P, he set PORTB as output and set all the pins high so that while running the circuit you could check this simple stuff and be sure the circuit is working properly. If not there is some hardware problem.

Why we are using this simple code to test, not any other code, because other codes might contain library functions and use of some integrated modules which can lead to complex code and their may be some code bugs (errors) and we can’t be sure of the exact problem i.e.. hardware or software.And with simple PORT test we can be sure that their will be no problem with the software part, but remember many PIC’s PORT pins are multiplexed with other modules so setting them might not be so easy. Like in this case PORTA is multiplexed with ADC module to set the PORTA’s pins you have to disable ADC first.

Good luck
 

Thread Starter

Jaden5165

Joined Sep 9, 2011
69
First of all the code was for PIC16F877A ,I think you are using that.Now to solve this problem we need some more info i.e..
1) Schematic i.e.. Circuit diagram.
2) Which programmer you are using and does it confirms about a successful programming
3) Is your programmer capable to load configuration bit settings from hex file, if not you have to set it in your programmer otherwise it will not work.


A program which just tests a simple task of the mcu to verify that the circuit for the mcu is ok.In case of John P, he set PORTB as output and set all the pins high so that while running the circuit you could check this simple stuff and be sure the circuit is working properly. If not there is some hardware problem.

Why we are using this simple code to test, not any other code, because other codes might contain library functions and use of some integrated modules which can lead to complex code and their may be some code bugs (errors) and we can’t be sure of the exact problem i.e.. hardware or software.And with simple PORT test we can be sure that their will be no problem with the software part, but remember many PIC’s PORT pins are multiplexed with other modules so setting them might not be so easy. Like in this case PORTA is multiplexed with ADC module to set the PORTA’s pins you have to disable ADC first.

Good luck



finally,my pic can work with the code.thank for your opinions.i check again my programmer and reprogram my pic then it can work.^^
 

Thread Starter

Jaden5165

Joined Sep 9, 2011
69
Rich (BB code):
GPIO1=GPIO1 ? 0 : 1;
what is this code mean?


Rich (BB code):
GPIO=GPIO3 ? 0: 0b000010;
and what about this?
 

ErnieM

Joined Apr 24, 2011
8,377
More obscure c code, gotta love this. I actually like that format, and once you get comfortable with it you can use it to good advantage in writing some compact code.

The ? means test, followed by a true and a false value. So:
Rich (BB code):
GPIO1=GPIO1 ? 0 : 1;
has the same meaning as:
Rich (BB code):
if (GPIO1)
    GPIO1=0;
else
    GPIO1=1;
Note that "if (GPIO1)" is false when GPIO1 is zero, otherwise true.

I prefer to use parenthesis to make the intent a bit clearer:
Rich (BB code):
LD0 = (LedState & 0x01) ? LED_ON : LED_OFF;
 

Thread Starter

Jaden5165

Joined Sep 9, 2011
69
More obscure c code, gotta love this. I actually like that format, and once you get comfortable with it you can use it to good advantage in writing some compact code.

The ? means test, followed by a true and a false value. So:
Rich (BB code):
GPIO1=GPIO1 ? 0 : 1;
has the same meaning as:
Rich (BB code):
if (GPIO1)
    GPIO1=0;
else
    GPIO1=1;
Note that "if (GPIO1)" is false when GPIO1 is zero, otherwise true.

I prefer to use parenthesis to make the intent a bit clearer:
Rich (BB code):
LD0 = (LedState & 0x01) ? LED_ON : LED_OFF;



wow,feel good.learn a lot from you guys!!!
 

debjit625

Joined Apr 17, 2010
790
ErnieM already explained how that code works but remember it is not same as "if-else", it is known as ternary operator in language C and its a true operator rather a conditional statement like if-else. The if-else statement will not produce a value but this ternary operator will, it’s like this
Rich (BB code):
a = (--b) ? (b) : (b = 100) ;
Before explaining the above code you should understand this ,in language C/C++ the value of 0 is taken as false and any other non zero value is taken as true like 1,2,-1 etc.So in the above code a will be assigned to the value of b if the result of decrementing of b is non zero i.e.. true ,else if b becomes zero i.e.. false then a and b both are assigned to 100.Many times people are confused with ternary operators so if you are too ,then no need to use them just use if-else statement like ErnieM showed.

Good Luck
 
Last edited:
Top