Basic programming question.

Thread Starter

Nick Bacon

Joined Nov 7, 2016
130
I have purchased my for PIC16F18875 and a PICKIT3 programmer.

I have everything set up and am able to compile and program no problem.

I am completely new to this and finding it a little confusing as to what works with what pic. I have found that :
TRISBbits.TRISB0 = 0; //Set Port B Bit 0 as output, works for me as PORTBbits etc
I managed to get the standard LED and LED flashing beginner programmes to work but I can not work out how to get the led to go on and off dependant on the input from another pin.

Below I have set B0 as the output to an LED and D1 as the input switch.
I assume by connecting D1 to the 5V rail then this would activate the pin and make the LED illuminate. No matter what I do the input has no effect on the LED.

What am I doing wrong? Please be kind as I have only just started. I have watched loads of videos and followed tutorials but just cant figure it out.

#include <xc.h>
#define _XTAL_FREQ 8000000

void main(void)

{
TRISBbits.TRISB0 = 0; //Set Port B Bit 0 as Output
TRISDbits.TRISD1 = 1; // Set Port A Bit 0 as Input

while (1)
{
if (LATDbits.LATD1==1)
{
__delay_ms(200);

if (LATDbits.LATD1==1)
{
LATBbits.LATB0=1;

}
}

}
}
 

Kjeldgaard

Joined Apr 7, 2016
476
You are missing that on the newer PIC16 and (all) PIC18, the management of a Port Bit consists of three registers: TRISx, PORTx and LATHx.

Managing whether a Port Bit is input or output is with TRISx.

Reading a Port Bit is the PORTx register to use.

Writing to a Port Bit can be either the PORTx or LATHx register, but will physically occur to LATHx
 

vead

Joined Nov 24, 2011
629
I have purchased my for PIC16F18875 and a PICKIT3 programmer.

I have everything set up and am able to compile and program no problem.

I am completely new to this and finding it a little confusing as to what works with what pic. I have found that :
TRISBbits.TRISB0 = 0; //Set Port B Bit 0 as output, works for me as PORTBbits etc
I managed to get the standard LED and LED flashing beginner programmes to work but I can not work out how to get the led to go on and off dependant on the input from another pin.

Below I have set B0 as the output to an LED and D1 as the input switch.
I assume by connecting D1 to the 5V rail then this would activate the pin and make the LED illuminate. No matter what I do the input has no effect on the LED.

What am I doing wrong? Please be kind as I have only just started. I have watched loads of videos and followed tutorials but just cant figure it out.

#include <xc.h>
#define _XTAL_FREQ 8000000

void main(void)

{
TRISBbits.TRISB0 = 0; //Set Port B Bit 0 as Output
TRISDbits.TRISD1 = 1; // Set Port A Bit 0 as Input

while (1)
{
if (LATDbits.LATD1==1)
{
__delay_ms(200);

if (LATDbits.LATD1==1)
{
LATBbits.LATB0=1;

}
}

}
}
you can use code tags. go to insert than select code
Code:
#include <xc.h>
#define _XTAL_FREQ 8000000

void main(void)

{
TRISBbits.TRISB0 = 0; //Set Port B Bit 0 as Output
TRISDbits.TRISD1 = 1; // Set Port A Bit 0 as Input

while (1)
{
if (LATDbits.LATD1==1)
{
__delay_ms(200);

if (LATDbits.LATD1==1)
{
LATBbits.LATB0=1;

}
}

}
}
 

Thread Starter

Nick Bacon

Joined Nov 7, 2016
130
You are missing that on the newer PIC16 and (all) PIC18, the management of a Port Bit consists of three registers: TRISx, PORTx and LATHx.

Managing whether a Port Bit is input or output is with TRISx.

Reading a Port Bit is the PORTx register to use.

Writing to a Port Bit can be either the PORTx or LATHx register, but will physically occur to LATHx

Hi,

I can see changing the last port statement to LAT statement is correct, but it still does not work.

#include <xc.h>
#define _XTAL_FREQ 8000000

void main(void)

{

TRISBbits.TRISB0 = 0; //Set Port B Bit 0 as Output
TRISDbits.TRISD1 = 1; // Set Port A Bit 0 as Input


while (1)
{

if (PORTDbits.RD1=1)
{
__delay_ms(200);

if (PORTDbits.RD1=1)
{
LATBbits.LATB0 = 1;


}
}


}
}
 

Thread Starter

Nick Bacon

Joined Nov 7, 2016
130
you can use code tags. go to insert than select code
Code:
#include <xc.h>
#define _XTAL_FREQ 8000000

void main(void)

{
TRISBbits.TRISB0 = 0; //Set Port B Bit 0 as Output
TRISDbits.TRISD1 = 1; // Set Port A Bit 0 as Input

while (1)
{
if (LATDbits.LATD1==1)
{
__delay_ms(200);

if (LATDbits.LATD1==1)
{
LATBbits.LATB0=1;

}
}

}
}

Thanks for the reply. Is it that I am missing something on the input side. Surely by connecting to 5V rail or 0V rail will give the digital 1 or 0 needed for the microcontroller to switch the LED? It does not want to switch.
 

Kjeldgaard

Joined Apr 7, 2016
476
These lines should "copy" a switch on an Input Bit to an Output Bit:
Code:
while (1)
{
    if (PORTDbits.RD1 == 1)
    {
        LATBbits.LATB0 = 1;
    }
    if (PORTDbits.RD1 == 0)
    {
        LATBbits.LATB0 = 0;
    }
}
 

Thread Starter

Nick Bacon

Joined Nov 7, 2016
130
I have tried all the codes in all the different formats but nothing will make the LED switch. Am I right in thinking that connecting the pin to 5V should make the led illuminate?
 

AlbertHall

Joined Jun 4, 2014
12,345
I have tried all the codes in all the different formats but nothing will make the LED switch. Am I right in thinking that connecting the pin to 5V should make the led illuminate?
On power up all port B and port D pins are set to be analog inputs. To use them for digital I/O you need to clear the ANSEL bits:
ANSELB = 0;
ANSELD = 0;

If it still doesn't work, post the code that you are using now (preferably in CODE tags) so we can where you are at.
 

Thread Starter

Nick Bacon

Joined Nov 7, 2016
130
On power up all port B and port D pins are set to be analog inputs. To use them for digital I/O you need to clear the ANSEL bits:
ANSELB = 0;
ANSELD = 0;

If it still doesn't work, post the code that you are using now (preferably in CODE tags) so we can where you are at.
Thanks for that..... I had just found this out and was trying to figure out how to set the pins to digital. Tried a few things that did not work. I have added the ANSEL code and it is now working, have expanded to 4 leds and all working.

Code:
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>

#define _XTAL_FREQ 8000000

void main(void)
{
TRISBbits.TRISB0 = 0; //Set Port B Bit 0 as Output
TRISBbits.TRISB1 = 0; //Set Port B Bit 1 as Output
TRISBbits.TRISB2 = 0; //Set Port B Bit 2 as Output
TRISBbits.TRISB3 = 0; //Set Port B Bit 3 as Output

TRISAbits.TRISA1 = 1; // Set Port A Bit 1 as Input
TRISAbits.TRISA2 = 1; // Set Port A Bit 2 as Input
TRISAbits.TRISA3 = 1; // Set Port A Bit 3 as Input
TRISAbits.TRISA4 = 1; // Set Port A Bit 4 as Input

ANSELB = 0;
ANSELA = 0;
while (1)

{
    if (PORTAbits.RA1 == 1)
    { LATBbits.LATB0 = 1; }
    if (PORTAbits.RA1 == 0)
    { LATBbits.LATB0 = 0; }
   
     if (PORTAbits.RA2 == 1)
    { LATBbits.LATB1 = 1; }
    if (PORTAbits.RA2 == 0)
    { LATBbits.LATB1 = 0; }
   
     if (PORTAbits.RA3 == 1)
    { LATBbits.LATB2 = 1; }
    if (PORTAbits.RA3 == 0)
    { LATBbits.LATB2 = 0; }
   
     if (PORTAbits.RA4 == 1)
    { LATBbits.LATB3 = 1; }
    if (PORTAbits.RA4 == 0)
    { LATBbits.LATB3 = 0; }
}
}
 

MrChips

Joined Oct 2, 2009
30,708
Here are some improvements.
You don't have to test the input port twice. One test will do:
Code:
if (PORTAbits.RA1 == 1)
  { LATBbits.LATB0 = 1; }
else
  { LATBbits.LATB0 = 0; }
The if statement is testing for logical TRUE which is any non-zero value. You can do this:
Code:
if (PORTAbits.RA1)
  { LATBbits.LATB0 = 1; }
else
  { LATBbits.LATB0 = 0; }
Finally, there is no need to use the if statement. Simply set the output equal to the input.
Code:
    LATBbits.LATB0 = PORTAbits.RA1;
 

Thread Starter

Nick Bacon

Joined Nov 7, 2016
130
Here are some improvements.
You don't have to test the input port twice. One test will do:
Code:
if (PORTAbits.RA1 == 1)
  { LATBbits.LATB0 = 1; }
else
  { LATBbits.LATB0 = 0; }
The if statement is testing for logical TRUE which is any non-zero value. You can do this:
Code:
if (PORTAbits.RA1)
  { LATBbits.LATB0 = 1; }
else
  { LATBbits.LATB0 = 0; }
Finally, there is no need to use the if statement. Simply set the output equal to the input.
Code:
    LATBbits.LATB0 = PORTAbits.RA1;
Thankyou, that is very helpful, just trying to work out with the simplified code how to have two leds, if, else. If input is 1 then green led lit, if input is 0 then red led lit. I can do it in longer code.
 

MrChips

Joined Oct 2, 2009
30,708
Thankyou, that is very helpful, just trying to work out with the simplified code how to have two leds, if, else. If input is 1 then green led lit, if input is 0 then red led lit. I can do it in longer code.
You turn on, turn off the different LEDs in the same block of code.

Start learning to use pseudo-code before writing computer code:
Code:
if (switch is pressed)
{
  turn on GREEN
  turn off RED
}
else
{
  turn off GREEN
  turn on RED
}
The simple version is:

Green = Switch
Red = not Switch

Code:
LATBbits.LATB0 = PORTAbits.RA1;
LATBbits.LATB1 = ~PORTAbits.RA1;
 

Thread Starter

Nick Bacon

Joined Nov 7, 2016
130
You turn on, turn off the different LEDs in the same block of code.

Start learning to use pseudo-code before writing computer code:
Code:
if (switch is pressed)
{
  turn on GREEN
  turn off RED
}
else
{
  turn off GREEN
  turn on RED
}
The simple version is:

Green = Switch
Red = not Switch

Code:
LATBbits.LATB0 = PORTAbits.RA1;
LATBbits.LATB1 = ~PORTAbits.RA1;
You are a star....... It is more about learning the code and the ~ makes all the difference.

Thankyou. I have learned a lot from you today.
 

Thread Starter

Nick Bacon

Joined Nov 7, 2016
130
I think I am getting the hang of it now. Moving on, I would like to compare the inputs on each channel, 16 in total. On a digital basis I would like to check so that the is no 0 below a 1 in a vertical column.

Lets say for arguments sake that the inputs were RA1 to RA16. RA1 at the bottom . If any channel has a 0 input and any channel above it had a 1 input then a fault would be declared.

Maybe something like
If RA1 = 0 AND RA2 = 1 then fault
If RA2 = 0 AND RA3 = 1 then fault
If RA3 = 0 AND RA4 = 1 then fault
ETC

Any ideas on the easiest way of doing this.?

This is what I have come up with, just need to see if it works

Code:
if ((PORTAbits.RA2 == 0) && (PORTAbits.RA3 == 1))
{LATBbits.LATB5 = 1;}
else
{LATBbits.LATB5 = 0;}
 
Last edited:

MrChips

Joined Oct 2, 2009
30,708
I think I am getting the hang of it now. Moving on, I would like to compare the inputs on each channel, 16 in total. On a digital basis I would like to check so that the is no 0 below a 1 in a vertical column.

Lets say for arguments sake that the inputs were RA1 to RA16. RA1 at the bottom . If any channel has a 0 input and any channel above it had a 1 input then a fault would be declared.

Maybe something like
If RA1 = 0 AND RA2 = 1 then fault
If RA2 = 0 AND RA3 = 1 then fault
If RA3 = 0 AND RA4 = 1 then fault
ETC

Any ideas on the easiest way of doing this.?
There are many ways to tackle this problem. This is not a simple problem for a first time programmer to solve.

The simplest way requires an understanding of how binary numbers are used to represent decimal numbers.

Rather than reading individual switches, you can read an entire port as one byte (8 bits).
You can concatenate (join together) two 8-bit bytes to form 16-bits.

Let us write down all possible no-fault conditions with their equivalent decimal values:

0000000000000000 = 0
0000000000000001 = 1
0000000000000011 = 3
0000000000000111 = 7
0000000000001111 = 15
0000000000011111 = 31
0000000000111111 = 63
0000000001111111 = 127
0000000011111111 = 255
0000000111111111 = 511
0000001111111111 = 1023
0000011111111111 = 2047
0000111111111111 = 4095
0001111111111111 = 8191
0011111111111111 = 16383
0111111111111111 = 32767
1111111111111111 = 65535

Now again, it is not an easy answer going from here. There are many possible ways of doing this.

Here is how I would attempt this on first thinking.

If the number is less than 32768, multiply by 2 and add 1.
(This is equivalent to shifting all bits one position to the left, making sure the LSB = least significant bit, is set to 1).

In C programming:

number = (number << 1) + 1;

Repeat this until number is no longer less than 32768.

If the result is not equal to 65535, you have a fault condition.
 

Thread Starter

Nick Bacon

Joined Nov 7, 2016
130
Thanks again. I will have a look at it today.

One thing I will need to do is have an input micro-controller that gathers all the inputs and then output micro-controllers on each display, these will illuminate the LEDS as per the inputs and programming of the input controller. The controllers will communicate over RS485 (built into the controllers).

Can you give me a hint on how this is coded so one processor reads the information from the other?
 

MrChips

Joined Oct 2, 2009
30,708
Thanks again. I will have a look at it today.

One thing I will need to do is have an input micro-controller that gathers all the inputs and then output micro-controllers on each display, these will illuminate the LEDS as per the inputs and programming of the input controller. The controllers will communicate over RS485 (built into the controllers).

Can you give me a hint on how this is coded so one processor reads the information from the other?
I will answer this question in your other thread on RS-485 so as to not confuscate the two threads.

https://forum.allaboutcircuits.com/threads/revisiting-rs485-setup.134928/
 

Thread Starter

Nick Bacon

Joined Nov 7, 2016
130
Hi guys,

I am working my way through things and have a number of features working. I would like to see if I can simplify the code a bit. I have only coded for 8 channels, there are 24 in total.

This is one section

Code:
//Fault logic steam below water

if ((PORTAbits.RA0 == 0) && (PORTAbits.RA1 == 1))
{LATDbits.LATD0 = 1;} else {LATDbits.LATD0 = 0;}

if ((PORTAbits.RA1 == 0) && (PORTAbits.RA2 == 1))
{LATDbits.LATD0 = 1;} else {LATDbits.LATD0 = 0;}

if ((PORTAbits.RA2 == 0) && (PORTAbits.RA3 == 1))
{LATDbits.LATD0 = 1;} else {LATDbits.LATD0 = 0;}

if ((PORTAbits.RA3 == 0) && (PORTAbits.RA4 == 1))
{LATDbits.LATD0 = 1;} else {LATDbits.LATD0 = 0;}

if ((PORTAbits.RA4 == 0) && (PORTAbits.RA5 == 1))
{LATDbits.LATD0 = 1;} else {LATDbits.LATD0 = 0;}

if ((PORTAbits.RA5 == 0) && (PORTCbits.RC2 == 1))
{LATDbits.LATD0 = 1;} else {LATDbits.LATD0 = 0;}

if ((PORTCbits.RC2 == 0) && (PORTCbits.RC3 == 1))
{LATDbits.LATD0 = 1;} else {LATDbits.LATD0 = 0;}


This is the second section

Code:
//Low level trip channels 1,2,3 - E0 linked

if ((PORTEbits.RE0 ==1) && (PORTAbits.RA0 == 0) && (PORTAbits.RA1 == 0))
{LATDbits.LATD1 = 1;} else {LATDbits.LATD1 = 0;}

if ((PORTEbits.RE0 ==1) && (PORTAbits.RA1 == 0) && (PORTAbits.RA2 == 0))
{LATDbits.LATD1 = 1;} else {LATDbits.LATD1 = 0;}

if ((PORTEbits.RE0 ==1) && (PORTAbits.RA0 == 0) && (PORTAbits.RA2 == 0))
{LATDbits.LATD1 = 1;} else {LATDbits.LATD1 = 0;}

//Low level trip channels 2,3,4 - E1 linked

if ((PORTEbits.RE1 ==1) && (PORTAbits.RA1 == 0) && (PORTAbits.RA2 == 0))
{LATDbits.LATD1 = 1;} else {LATDbits.LATD1 = 0;}

if ((PORTEbits.RE1 ==1) && (PORTAbits.RA2 == 0) && (PORTAbits.RA3 == 0))
{LATDbits.LATD1 = 1;} else {LATDbits.LATD1 = 0;}

if ((PORTEbits.RE1 ==1) && (PORTAbits.RA1 == 0) && (PORTAbits.RA3 == 0))
{LATDbits.LATD1 = 1;} else {LATDbits.LATD1 = 0;}

//Low level trip channels 3,4,5 - E2 linked

if ((PORTEbits.RE2 ==1) && (PORTAbits.RA2 == 0) && (PORTAbits.RA3 == 0))
{LATDbits.LATD1 = 1;} else {LATDbits.LATD1 = 0;}

if ((PORTEbits.RE2 ==1) && (PORTAbits.RA3 == 0) && (PORTAbits.RA4 == 0))
{LATDbits.LATD1 = 1;} else {LATDbits.LATD1 = 0;}

if ((PORTEbits.RE2 ==1) && (PORTAbits.RA2 == 0) && (PORTAbits.RA4 == 0))
{LATDbits.LATD1 = 1;} else {LATDbits.LATD1 = 0;}
 
Top