|
|
View previous topic :: View next topic |
Author |
Message |
valemike Guest
|
kbhit() works in 18F442, but not in 16F877 |
Posted: Mon Mar 29, 2004 3:59 pm |
|
|
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
|
|
Posted: Mon Mar 29, 2004 4:47 pm |
|
|
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... |
Posted: Mon Mar 29, 2004 5:00 pm |
|
|
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... |
Posted: Mon Mar 29, 2004 5:03 pm |
|
|
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
|
|
Posted: Tue Mar 30, 2004 9:01 am |
|
|
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
|
|
Posted: Tue Mar 30, 2004 11:27 am |
|
|
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... |
Posted: Wed Mar 31, 2004 8:14 pm |
|
|
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
|
|
Posted: Wed Mar 31, 2004 10:41 pm |
|
|
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... |
Posted: Thu Apr 01, 2004 8:02 am |
|
|
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! |
Posted: Thu Apr 01, 2004 8:15 am |
|
|
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
|
|
Posted: Thu Apr 01, 2004 9:42 am |
|
|
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. |
|
|
|
|
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
|