View previous topic :: View next topic |
Author |
Message |
_olaf_
Joined: 24 Feb 2005 Posts: 32
|
Writing variable Port Pins with one statement |
Posted: Mon Apr 14, 2008 11:57 pm |
|
|
Hello,
how can I write on variable Port Pins with one statement.
E.g. I use PortA0..3, PortB0..3 on a PIC. Now I will write these ports with one 8bit value like: PortAB=0xFF (PortA0..3 is the high nibble, PortB0..3 the low nibble). The problem is that I have to change the value of this "PortAB" very often and setting every port discrete is not very nice.
How can I do this?
Best Regards
Olaf
Edit:
Compiler PCM 3.223
MPlab 8.02 |
|
|
crystal_lattice
Joined: 13 Jun 2006 Posts: 164
|
Something like this?? |
Posted: Tue Apr 15, 2008 12:44 am |
|
|
Code: |
Output_AB(int8 byte)
{
output_a((byte << 4));
output_b((byte >> 4));
}
|
|
|
|
_olaf_
Joined: 24 Feb 2005 Posts: 32
|
|
Posted: Tue Apr 15, 2008 4:46 am |
|
|
Hello,
I think it’s just the opposite.
I want a variable called PortAB (e.g. char).
If I write:
PortAB=0xFF;
PortA should be 0x0F (PortPinA0..3=1)
PortB should be 0x0F (PortPinB0..3=1)
Olaf |
|
|
sohailkhanonline
Joined: 06 Mar 2008 Posts: 35 Location: pakistan
|
Re: Something like this?? |
Posted: Tue Apr 15, 2008 5:07 am |
|
|
crystal_lattice wrote: | Code: |
Output_AB(int8 byte)
{
output_a((byte << 4));
output_b((byte >> 4));
}
|
|
can you explain it please.
|
|
|
_olaf_
Joined: 24 Feb 2005 Posts: 32
|
|
Posted: Tue Apr 15, 2008 6:17 am |
|
|
I think the question was easy to misunderstand. I want to define a variable with different ports. It wasn't good to define it with two Ports with increasing Pin-Numbers.
I think it should be like this
Code: |
char ISR_Flags=0x00;
#Locate ISR_Flags = 0x00A0
#bit INTF_START = ISR_FLAGS.0
#bit INTF_RB = ISR_FLAGS.1
#bit INTF_DATOK = ISR_FLAGS.2
#bit INTF_Light = ISR_FLAGS.3
#bit INTF_TMREND = ISR_FLAGS.4
|
Can I do similar things with the port.
For example
Code: |
char PortAB=0x00;
#bit Enable=PortA.0
#bit Disable=PortA.1
#bit Data_0=PortA.2
#bit Data_1=PortA.3
#bit Data_2=PortA.4
#bit Data_3=PortB.2
#bit Data_4=PortB.4
#bit Read_Write=PortC.1
|
Or how do I have to do it
Best Regards
Olaf |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
|
_olaf_
Joined: 24 Feb 2005 Posts: 32
|
|
Posted: Tue Apr 15, 2008 11:36 am |
|
|
Hi,
I tried the following
PIN-Description in the header-file
Code: |
#define LCD_DB0 PIN_A0
#define LCD_DB1 PIN_A1
#define LCD_DB2 PIN_A2
#define LCD_DB3 PIN_A3
#define LCD_DB4 PIN_A4
#define LCD_DB5 PIN_A5
#define LCD_DB6 PIN_C0
#define LCD_DB7 PIN_C1
|
in the *.c I defined the databyte
Code: |
#define databyte(x) \
LCD_DB0 = x & 1; \
LCD_DB1 = (x >> 1) & 1; \
LCD_DB2 = (x >> 2) & 1; \
LCD_DB3 = (x >> 3) & 1; \
LCD_DB4 = (x >> 4) & 1; \
LCD_DB5 = (x >> 5) & 1; \
LCD_DB6 = (x >> 6) & 1; \
LCD_DB7 = (x >> 7) & 1;
|
then I want to set the databyte with the new value.
but if I compile the program I get the following error message 8 times. I think for every statement below the "#define databyte"
Expecting LVALUE such as a variable name or * expression
|
|
|
crystal_lattice
Joined: 13 Jun 2006 Posts: 164
|
Spliting bytes |
Posted: Tue Apr 15, 2008 12:02 pm |
|
|
There are many ways of doing this i suppose but this is what i came up with given limited free time...
Code: |
Port_AB(int8 byte) //you can call this function anything you like
{
output_a(byte && 0x0f)); //Mask the nibble on LSB side to get a output of 0000XXXX and ignore the high nibble
output_b((byte >> 4)); //Shift the MSB side nibble to the LSB side
}
// to use the function
Port_AB(0xff);
//or
Port_AB(any_int8_variable);
| [/code] |
|
|
_olaf_
Joined: 24 Feb 2005 Posts: 32
|
|
Posted: Tue Apr 15, 2008 12:22 pm |
|
|
Thanks,
but with this code I have the problem, that output_b() sets the whole output. But the other pins of the output should be unchanged. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Apr 15, 2008 12:48 pm |
|
|
You can read the value of the port into a temporary variable, change
the bits that you want to change, and then write the byte variable back
to the port register.
You didn't say what PIC you're using. The 18F series have an important
advantage over the 16F. The 18F PICs have "Latch" registers for the
i/o ports. Example: LATB is the latch register for Port B.
The latch register isn't directly connected to the i/o pins, so when
you do a read-modify-write operation on the Latch register, the value
can't be corrupted due to whatever load you may have on the i/o pin.
Read the LATB register into a temporary variable (int8) and modify the
desired bits in it, and write the value back to the LATB register. All of
the PortB i/o pins will be updated at the same time. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Tue Apr 15, 2008 2:16 pm |
|
|
Quote: | but if I compile the program I get the following error message 8 times. I think for every statement below the "#define databyte"
Expecting LVALUE such as a variable name or * expression | Have a closer look at the code from the provided link, you didn't make an exact copy. The defined values PIN_xx are constants, you can't assign a value to a constant and that is why you got the error message.
You could have written the code as: Code: | // The addresses shown below are for a PIC18 processor.
// PIC16 processors don't have a Latch register so you
// will have to write directly to the Port registers
// running into the risk of the read-modify-write problem.
#byte LATA = 0xF89
#byte LATC = 0xF8B
// Define the bit addresses of the spare pins.
#bit LCD_DB0 = LATA.0
#bit LCD_DB1 = LATA.1
#bit LCD_DB2 = LATA.2
#bit LCD_DB3 = LATA.3
#bit LCD_DB4 = LATA.4
#bit LCD_DB5 = LATA.5
#bit LCD_DB6 = LATC.0
#bit LCD_DB7 = LATC.1
#define databyte(x) \
LCD_DB0 = x & 1; \
LCD_DB1 = (x >> 1) & 1; \
LCD_DB2 = (x >> 2) & 1; \
LCD_DB3 = (x >> 3) & 1; \
LCD_DB4 = (x >> 4) & 1; \
LCD_DB5 = (x >> 5) & 1; \
LCD_DB6 = (x >> 6) & 1; \
LCD_DB7 = (x >> 7) & 1; |
|
|
|
_olaf_
Joined: 24 Feb 2005 Posts: 32
|
|
Posted: Wed Apr 16, 2008 1:24 pm |
|
|
Hi again,
I use a 16F873A. I had a look at the flex_lcd
I think the following code fragment defines the output-data
Code: |
struct lcd_pin_map
{
BOOLEAN dummy; // PinA0 is not used
BOOLEAN enable; // PinA1
BOOLEAN rw; // PinA2
BOOLEAN rs; // PinA3
int unusedA : 4; // The rest of portA
int unusedB; // portB is not used
int unusedC; // portC is not used
int data : 4; // lower nibble of portD is used for data lines
int unusedD : 4; // The rest of portD
} lcd;
|
But how is the port defined? I do not see how the ports are set to the variables. Where is the statement that PINA1 is "enable"? In the header-file is the statement for PIN_A0 as follows.
How is this made in the struct?
Olaf |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Apr 16, 2008 1:31 pm |
|
|
That code is from Mark's lcd driver in the Code Library, here:
http://www.ccsinfo.com/forum/viewtopic.php?t=20182
Quote: | But how is the port defined? I do not see how the ports are set to the variables. |
Look at the #locate statements below the structure, as shown in bold
below. That's where it's done.
Quote: | struct lcd_pin_map
{
BOOLEAN dummy; // PinA0 is not used
BOOLEAN enable; // PinA1
BOOLEAN rw; // PinA2
BOOLEAN rs; // PinA3
int unusedA : 4; // The rest of portA
int unusedB; // portB is not used
int unusedC; // portC is not used
int data : 4; // lower nibble of portD is used for data lines
int unusedD : 4; // The rest of portD
} lcd;
#if defined(__PCH__)
#locate lcd = 0xF80
#else
#locate lcd = 5
#endif |
Quote: | Where is the statement that PIN A1 is "enable"? |
The structure base addresses is set to the register address of Port A. So
the first byte in the structure is for Port A, the next byte is for Port B, etc.
A "boolean" is a bit. The first bit, "dummy", is for bit 0 of port A. The
next one, "enable", is for bit 1 of Port A, and so on. |
|
|
_olaf_
Joined: 24 Feb 2005 Posts: 32
|
|
Posted: Wed Apr 16, 2008 11:45 pm |
|
|
Just to say it with my own words. It is the same as I do it with my ISR_Flags?
Code: |
char ISR_Flags=0x00;
#Locate ISR_Flags = 0x00A0
#bit INTF_START = ISR_FLAGS.0
#bit INTF_RB = ISR_FLAGS.1
#bit INTF_DATOK = ISR_FLAGS.2
#bit INTF_Light = ISR_FLAGS.3
#bit INTF_TMREND = ISR_FLAGS.4
|
for the 16F873 I have to locate the struct in the first PORT Address (0x05). The used bit address range of each Port is 8Bit. If I start with Port_A. I define the 6 Port_A Bit (A0..A5) and then 2 unused bits. And then continuing with Port_B... .
Olaf |
|
|
|