View previous topic :: View next topic |
Author |
Message |
dan king
Joined: 22 Sep 2003 Posts: 119
|
custom port pin mapping question |
Posted: Fri Jul 07, 2006 1:03 pm |
|
|
I'm trying to use a 16c505 keyscan a keypad but the problem is that the wake on change pins are b0, b1, b3 skipping b2. How can I set a value to the i/o pins skipping b2? What I would like to be able to do is read b0, b1, and b3 in one variable, if it weren't for b2 this wouldn't be a problem.
i.e.
struct {
int1 PORTB0:1;
int1 PORTB1:1;
int1 unused:1;
int1 PORTB3:1;
} data;
with data mapped to 0x06 skipping b2
so I can use
if (data == 0b110)
do something;
Thanks,
Dan |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Jul 08, 2006 1:30 am |
|
|
I don't think there's a way to make the compiler pack disjoint bitfields.
I think it has to be done in code.
The following program shows one way to do it, using a short inline
function. It compiles to 12 instructions. The TRIS for PortB is set
for all inputs upon power-up, so I didn't need to set it. I used a
temp variable in the function so that PortB would only have to be
read once. I think it's cleaner to do it that way for an input function.
Code: |
#include <16F877>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#byte PortB = 6
#bit B3 = PortB.3
#inline
int8 get_data(void)
{
int8 temp;
temp = PortB;
return(bit_test(temp, 3) ? (temp & 0x03) | 0x04 : (temp & 0x03));
}
//========================
void main()
{
int c;
c = get_data();
while(1);
} |
|
|
![](templates/subSilver/images/spacer.gif) |
dan king
Joined: 22 Sep 2003 Posts: 119
|
|
Posted: Sat Jul 08, 2006 6:16 am |
|
|
That's what I thought, hadn't seen any posts here that did what I was looking for. Thanks for the sample code, I tried someting in the meantime. Do you think this would work? It compiles but I don't have the hardware with me to test it.
Code: | void read_button(void)
{
button = PORTB0;
button = (button <<1) & PORTB1;
button = (button <<1) & PORTB3;
button = button & 0b00000111;
} |
Thanks,
Dan |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Jul 08, 2006 11:48 am |
|
|
I don't think that will work. It's got several things wrong with it. |
|
![](templates/subSilver/images/spacer.gif) |
dan king
Joined: 22 Sep 2003 Posts: 119
|
|
Posted: Mon Jul 10, 2006 9:16 am |
|
|
I managed to get my example to work with a read function, fixing the problems that you alluded to.
Code: | button = 0b00000001 & PORTB3;
button = (button << 1) | PORTB1;
button = (button << 1) | PORTB0;
button = button & 0b00000111;
|
The only reasons why I didn't take your suggested code is that I don't like to use any more built in functions than necessary so the code is more portable. Also, I like simple operators so that when I revisit code I can remember where my head was when I wrote it.
Anyhow, is there any advantages to the version you wrote? I looked at the list file for my code and is compiles down to 24 lines so it obviously takes more ROM. I guess part of my question is what are the stack implications from one version to the next? The 16c505 only has a 2 level deep stack so this can be a real concern. Is that why you used the inline statement? Does that help in this case?
Thanks,
Dan |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jul 10, 2006 12:30 pm |
|
|
Then change it to this, which uses an AND operation to detect if bit 3
is set:
Code: | #include <16F877.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#byte PortB = 6
#bit B3 = PortB.3
#inline
int8 get_data(void)
{
int8 temp;
temp = PortB;
return((temp & 0x08) ? (temp & 0x03) | 0x04 : (temp & 0x03));
}
//========================
void main()
{
int c;
c = get_data();
while(1);
} |
The get_data() function only takes 12 lines of ASM code.
The #inline directive will prevent the compiler from doing a CALL
to the function. Instead, a new copy of the function will be placed
"inline" in the program whenever it is called. So, it will save stack
space at the expense of using more ROM. (Assuming the function
is called more than once).
Last edited by PCM programmer on Mon Jul 10, 2006 12:38 pm; edited 1 time in total |
|
![](templates/subSilver/images/spacer.gif) |
dan king
Joined: 22 Sep 2003 Posts: 119
|
|
Posted: Mon Jul 10, 2006 12:33 pm |
|
|
Understood, thanks for your reply.
Rgds,
Dan |
|
![](templates/subSilver/images/spacer.gif) |
|