CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

custom port pin mapping question

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

custom port pin mapping question
PostPosted: Fri Jul 07, 2006 1:03 pm     Reply with quote

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
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Jul 08, 2006 1:30 am     Reply with quote

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);
}
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Sat Jul 08, 2006 6:16 am     Reply with quote

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
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Jul 08, 2006 11:48 am     Reply with quote

I don't think that will work. It's got several things wrong with it.
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Mon Jul 10, 2006 9:16 am     Reply with quote

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
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Jul 10, 2006 12:30 pm     Reply with quote

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
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Mon Jul 10, 2006 12:33 pm     Reply with quote

Understood, thanks for your reply.

Rgds,

Dan
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group