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

kbhit() works in 18F442, but not in 16F877

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







kbhit() works in 18F442, but not in 16F877
PostPosted: Mon Mar 29, 2004 3:59 pm     Reply with quote

Hi,
I've read thru the past posts regarding the 16F877 and uart problems, there was usually a programming error that needed correction in the past posts.

Here's my problem today:
I'm hooked up to a PICDEM-2+ board. Printf() to Hyperterminal works fine in both the 18F442 and 16F877. However, kbhit() isn't working at all in 16F877, but it works fine in the 18F442.

All I did was swap the #include <16F877.h> and #include <18F442.h> directives depending on the chip i had on the board at the moment.

The only things i do with the uart is: printf(), kbhit(). And like I said, kbhit() doesn't work right on the 16F877.

This is not a showstopper for me, since i won't be using the uart in the final product (instead will be using a keypad matrix rather than the computer keyboard used in debugging).

But i'm just curious where my problem lies. the compiler version is 3.187.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Mar 29, 2004 4:47 pm     Reply with quote

1. Post your version of the compiler.

2. Post a very small program that demonstrates the problem.
Be sure to post all pre-processor statements, such as #use,
#fuses, etc., etc. Don't leave anything out.

Test this demo program before you post it, to be sure that
it shows the problem.
valemike
Guest







will do...
PostPosted: Mon Mar 29, 2004 5:00 pm     Reply with quote

I'll make a sample program to verify it, but i'm going to have to strip my code down to show a snippet. By tomorrow, i'll put up some full code. (Or a follow-up that says "I found my problem"...)

In the meantime, here is some info:

Version 3.187 of the compiler.

Code:
//#include <16F877.h>
#include <18F442.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000) /* one instruction=1us? */
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#use I2C(master, SCL=PIN_C3, SDA=PIN_C4)


As you can see, i comment out the .h file that i'm not using.
Printf works fine as i said earlier, so thus "xmit" and "rcv" are correctly specified.

Code:
void scan_keys(void)
{
   char retval;
   int16 *this_mask = &scan_mask;

   /* Find out if some keys got hit */
   /* For now, I will pretend the keyboard is the keypad. */
   if (kbhit())
   {
       *this_mask = 0x00;
       retval = getc();
        switch (retval)
        {
           case '0':
               *this_mask = 0x00 | KEY_ZERO;
               break;

           case '1':
               *this_mask = 0x00 | KEY_ONE;
               break;

           case '2':
               *this_mask = 0x00 | KEY_TWO;
               break;
......



scan_keys() is called from the main loop, and looks like:


Code:

void main(void)
{
.....
    while(1)
    {
        ......
        scan_keys();
    }
valemike
Guest







another observation...
PostPosted: Mon Mar 29, 2004 5:03 pm     Reply with quote

I even tried putting the mplab ICD debugger to break inside the "if kbhit()" switch-case routine, but it never even gets inside, which makes me assume that kbhit() is not returning a TRUE.
Guest








PostPosted: Tue Mar 30, 2004 9:01 am     Reply with quote

The simple code below works just fine, even with interleaved printfs().

Code:
#include <16F877.h>
//#include <18F442.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

int counter;

void scan_keys(void);

void main(void)
{
   counter = 0;
   printf("Testing the uart on the PIC\r\n");
   while(1)
   {
      scan_keys();
   }
}

void scan_keys(void)
{
    char this_char;
   
   if (kbhit())
   {
       this_char = getc();
      counter++;
       printf("Keyboard hit %d times\r\n", counter);
    }
}



The snippet above is simple. In my bigger program where originally brought up the problem, as far as the uart/rs232 goes, i am only calling the following functions: printf(), kbhit(), and getc().

Is there anything else (such as a timer1 interrrupt, timer0, or external rb0 interrupt) that can "undo" a pending kbhit()? Like i said, i get the problem on the PCM compiler but not the PCH. And i do have 3.187 running.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Mar 30, 2004 11:27 am     Reply with quote

You need to examine the assembly listing. Check to see if
the proper ASM code is being created. Also check to see
if the program flow actually reaches the kbhit() code.
valemike
Guest







wasn't in the kbhit(); rather in my pointer...
PostPosted: Wed Mar 31, 2004 8:14 pm     Reply with quote

I tediously stepped through the kbhit() routine in both the 442 and the 877. I found that it does in fact go through that code.

What I did notice is that, for some reason, my pointer isn't working properly in the 877 code.

Is there a problem with allowing a pointer to point to a global variable, and then passing the address "&myglobalvar" to a function placed anywhere in the code, regardless of what page or pclath (?) settting? I assume CCS takes care of all this even in the PCM compiler. I know my syntax is correct, but don't know if PCM is handling it properly. (Then again, i might as well just directly manipulate that global var directly rather than manipulating a pointer to it).

I think i'm having paging problems due to the long address range between my function and the pointer and the global variable and the code etc.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Mar 31, 2004 10:41 pm     Reply with quote

Look at the .SYM file generated by the compiler. See what the
address is for scan_mask. Is the address at 0x100 or above ?

See, I can make it fail by using this construct above main():
Code:
int16 scan_mask;
#locate scan_mask = 0x120

That places the global variable scan_mask at address 0x120.

Here is part of the symbol table for the program (it's the same,
with or without 16-bit pointers enabled).
Code:

scan_keys.retval            00000021
scan_keys.this_mask         00000022
scan_mask                   00000120
scan_keys                   00000012

But since I don't have 16-bit pointers enabled, it only copies the LSB
of the address of scan_mask. That's not going to work.
Code:

0000               00325 ...........    int16 *this_mask = &scan_mask;   
0012 3020       00326 MOVLW  20
0013 00A2       00327 MOVWF  22

Only the LSB of the address is used.

If I enable 16-bit pointers, then it copies the full 16-bit pointer address:
Code:
0000               00327 .....    int16 *this_mask = &scan_mask;   
0012 3020       00328 MOVLW  20
0013 00A2       00329 MOVWF  22
0014 3001       00330 MOVLW  01
0015 00A3       00331 MOVWF  23

So I wonder if you're doing something like this -- using #locate to
put variables in high memory, but then not enabling 16 bit pointers ?


[4-1-04 Edited for grammer]


Last edited by PCM programmer on Thu Apr 01, 2004 11:59 am; edited 2 times in total
valemike
Guest







You're right...
PostPosted: Thu Apr 01, 2004 8:02 am     Reply with quote

I'm not enabling 16 bit pointers nor doing a #locate!

I'm going to try it now, and see what happens
valemike
Guest







yikes more errors!
PostPosted: Thu Apr 01, 2004 8:15 am     Reply with quote

I tried configuring 16 bit pointers by doing a:
"#device *=16"

and ended up getting the following compile error, whereas i didn't get it before:

fxn_state_program_entry
Seg 0800-0FFF, 0547 left, need 095F
Seg 1000-17FF, 0800 left, need 095F
Seg 1800-1FFF, 0800 left, need 095F
Seg 0000-0003, 0000 left, need 095F
Seg 0004-07FF, 0013 left, need 095F

main
~~~~~~~~~~~~~~~~~~
I guess i'm going to have to play with where I locate this function, huh?
valemike
Guest







PostPosted: Thu Apr 01, 2004 9:42 am     Reply with quote

Quote:
Look at the .SYM file generated by the compiler. See what the
address is for scan_mask. Is the address at 0x100 or above ?


I looked at the .SYM file and find that scan_mask is as follows:
scan_mask is at 05a

I'm not doing any #locate directives, so i hope CCS is putting things automatically into place.
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