|
|
View previous topic :: View next topic |
Author |
Message |
pic14
Joined: 13 Apr 2014 Posts: 2
|
Why getch() blocks for more than 3 characters? |
Posted: Sun Apr 13, 2014 9:34 am |
|
|
Hello,
I wish to acquire the coordinates of a frame NMEA GPS EM-506 UART on a PIC16F88, and display on a Nokia 5110.
$ GPGGA, 064036.289,4836.5375, N, 00740.9373, E, 1,04,3.2,200.2, M,, 0000 * 0E
I use MPLAB and CCS 8 5.021d.
The test sending 3 characters on the serial port works well, but why getch() command blocks for more than 3 characters?
How else?
Partial program:
Code: |
#use RS232 (Baud=4800,parity=N,rcv=PIN_B2,xmit=PIN_B5,STOP=2,BITS=8)
.
.
#INT_RDA
void rx_data(void)
{
data_gps[i++]=getch();
count++;
if(i>77||count>77)
{
count=i;
i=0;
}
nokia_gotoxy(4,2);
printf(nokia_printchar,"lettre = %c",data_gps[0]);
nokia_gotoxy(4,3);
printf(nokia_printchar,"lettre = %c",data_gps[1]);
nokia_gotoxy(4,4);
printf(nokia_printchar,"lettre = %c",data_gps[2]);
nokia_gotoxy(4,5);
printf(nokia_printchar,"lettre = %c",data_gps[3]);
}
|
Thanks in advance |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9216 Location: Greensville,Ontario
|
|
Posted: Sun Apr 13, 2014 10:16 am |
|
|
It's called 'overrun'. The hardware UART has a 2-3 character buffer if you don't read the data as it comes in, the 4th data coming in causes the UART to get 'jammed'.
Add 'errors' to the use rs232(...options....). This adds a wee bit of code to clear the overrun condition.
You should though ALSO take a look at the CCS example called 'ex_sisr.c' as it allows proper operation of the UART as well as a circular buffer making it easy to receive data and parse it.
hth
jay |
|
|
ezflyr
Joined: 25 Oct 2010 Posts: 1019 Location: Tewksbury, MA
|
|
Posted: Sun Apr 13, 2014 5:16 pm |
|
|
Hi,
Another thing. Please repeat after me, "Never, ever, ever put a printf statement, a delay, or other time consuming process inside your int_rda serial interrupt handler! Instead, stuff the character into an array and get out fast, then process the array inside your Main() routine. Keep in mind that once a character is detected by the UART, and the int_rda interrupt fires, the interrupt is then disabled until the character is read, and the interrupt returns to the Main() program. In your case, the printf statements take significantly longer to execute than the receipt of a single character, so the UART buffer overflows while the interrupt is disabled and then hangs.
John |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1611 Location: Central Illinois, USA
|
|
Posted: Sun Apr 13, 2014 5:42 pm |
|
|
"Liking" ezflyer's comment.
ISRs should be fast and succinct. _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
gpsmikey
Joined: 16 Nov 2010 Posts: 588 Location: Kirkland, WA
|
|
Posted: Sun Apr 13, 2014 6:10 pm |
|
|
Depends - interrupts work best for the younger crowd - us old folks tend to start to service an interrupt then get another one and another one until we are exhausted and still have not finished the first one (or found our glasses)
mikey _________________ mikey
-- you can't have too many gadgets or too much disk space !
old engineering saying: 1+1 = 3 for sufficiently large values of 1 or small values of 3 |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19480
|
|
Posted: Mon Apr 14, 2014 12:27 am |
|
|
No, the ones who have been around for a while, learn to delegate, and go and play golf.
However, back to the original problem, temtronic's and exflyr's comments are spot on. I'm guessing that nokia_printchar routes to a routine to drive a nokia LCD. If so, these are _slow_. The routine sends ten characters to this, for every one received. Result, overflow/deadlock....
It gets worse, since this print is being done four times, for every single character received.
The old (oft repeated) mantra, is _keep interrupt handlers _quick_.
An interrupt handler should just do the job to handle what has been signalled. Nothing else. So INT_RDA (which signals one character has arrived), should just receive that character and get out again ASAP.
Gpsmikey's comment makes the point. It is as if a person receiving calls on a switchboard, instead of just receiving the call, insisted on reciting their life story to each caller. The switchboard would quickly grind to a halt. |
|
|
pic14
Joined: 13 Apr 2014 Posts: 2
|
|
Posted: Thu Apr 24, 2014 1:39 am |
|
|
Hello,
Thank you for your advice and see my solution below.
Solution that works with GPS (EM-506)-16F88 Nokia 5110
-> Reading Time and Latitude:
Program for PIC16F88:
Code: |
#include <16f88.h>
#include <Nokia5110.h>
#fuses XT,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP // quatz, pas de chien de garde
#use RS232 (Baud=4800,parity=N,rcv=PIN_B2,xmit=PIN_B5,STOP=2,BITS=8)
// Déclartion des adresses des ports E/S
#byte PORTA = 5 // adresse du PORT A
#byte PORTB = 6 // adresse du PORT B
#bit BP1=PORTA.1
#bit GPS_ON=PORTA.2
// PIN NOKIA 5110
//#define nok_cs PIN_A3
//#define nok_res PIN_A4
//#define nok_dc PIN_B3
//#define nok_sda PIN_B6
//#define nok_sclk PIN_B7
// déclaration des variables globales
#define BUFFER_SIZE 77
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;
int i=0;
// déclaration des constantes
// Fréquence du quartz
#use delay (clock=4000000) // Fréquence du quartz 4MHz
#int_rda
void serial_isr() {
int t=0;
buffer[next_in]=getc();
t=next_in;
next_in=(next_in+1) % BUFFER_SIZE;
if(next_in==next_out)
next_in=t; // Buffer full !!
}
#define bkbhit (next_in!=next_out)
BYTE bgetc() {
BYTE c;
while(!bkbhit) ;
c=buffer[next_out];
next_out=(next_out+1) % BUFFER_SIZE;
return(c);
}
void INIT_UC(void)
{
PORTA=0x00;
set_tris_a(0b11000); // port A en entrée
PORTB=0x00;
set_tris_b(0b10010110); // Port B en sortie
}
void main()
{
int data;
INIT_UC(); // Appel du sous-programme INIT_UC
nokia_init();
GPS_ON=1;
delay_ms(500);
nokia_gotoxy(0,0);
printf(nokia_printchar," GPS");
// delay_ms(500);
enable_interrupts(GLOBAL);
enable_interrupts(INT_RDA);
delay_ms(500);
GPS_ON=0;
while(1)
{
while(bkbhit)
{
data=bgetc();
if(data=='$')
{
data=bgetc();
if(data=='G')
{
data=bgetc();
if(data=='P')
{
data=bgetc();
if(data=='G')
{
data=bgetc();
if(data=='G')
{
data=bgetc();
if(data=='A')
{
data=bgetc();
if(data==',')
{
data=bgetc();
nokia_gotoxy(0,1);
printf(nokia_printchar,"Heure = ");
for(i=0;i<=5;i++) // 6 chiffres de l'heure
{
printf(nokia_printchar,"%c",data);
data=bgetc();
}
data=bgetc(); // virgule
while(data!=',') // jusqu'à virgule suivante
data=bgetc();
data=bgetc(); // virgule
nokia_gotoxy(0,2);
printf(nokia_printchar,"Lati=");
for(i=0;i<=8;i++) // 9 chiffres de Latitude
{
printf(nokia_printchar,"%c",data);
data=bgetc();
}
}
}
}
}
}
}
}
else
{
data=bgetc();
}
}
}
}
-------------------------------------------------------------------------------------
Programme nokia5110.h :
//Graphic LCD Nokia 3310 (LPH7779) routines v3
//CCS compiler
//by Michel Bavin 2004 --- bavin@skynet.be --- http://users.skynet.be/bk317494/ ---
//august 29, 2004
//*/
// ex:
//
// ...
// nokia_init();
// ...
// nokia_gotoxy(0,0);
// printf(nokia_printchar,"test???");
// ...
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define nok_cs PIN_A3
#define nok_res PIN_A4
#define nok_dc PIN_B3
#define nok_sda PIN_B6
#define nok_sclk PIN_B7
#use delay (clock=4000000)
char char_row,charsel,charpos,chardata; // for nokia_3310 lcd
int16 ddram;
//char plot_value;
int32 plot_value32;
int32 plot_umsb,plot_lmsb,plot_ulsb,plot_llsb;
BYTE const TABLE5[240]= {0x00,0x00,0x00,0x00,0x00, // 20 space ASCII table for NOKIA LCD: 96 rows * 5 bytes= 480 bytes
0x00,0x00,0x5f,0x00,0x00, // 21 !
0x00,0x07,0x00,0x07,0x00, // 22 "
0x14,0x7f,0x14,0x7f,0x14, // 23 #
0x24,0x2a,0x7f,0x2a,0x12, // 24 $
0x23,0x13,0x08,0x64,0x62, // 25 %
0x36,0x49,0x55,0x22,0x50, // 26 &
0x00,0x05,0x03,0x00,0x00, // 27 '
0x00,0x1c,0x22,0x41,0x00, // 28 (
0x00,0x41,0x22,0x1c,0x00, // 29 )
0x14,0x08,0x3e,0x08,0x14, // 2a *
0x08,0x08,0x3e,0x08,0x08, // 2b +
0x00,0x50,0x30,0x00,0x00, // 2c ,
0x08,0x08,0x08,0x08,0x08, // 2d -
0x00,0x60,0x60,0x00,0x00, // 2e .
0x20,0x10,0x08,0x04,0x02, // 2f /
0x3e,0x51,0x49,0x45,0x3e, // 30 0
0x00,0x42,0x7f,0x40,0x00, // 31 1
0x42,0x61,0x51,0x49,0x46, // 32 2
0x21,0x41,0x45,0x4b,0x31, // 33 3
0x18,0x14,0x12,0x7f,0x10, // 34 4
0x27,0x45,0x45,0x45,0x39, // 35 5
0x3c,0x4a,0x49,0x49,0x30, // 36 6
0x01,0x71,0x09,0x05,0x03, // 37 7
0x36,0x49,0x49,0x49,0x36, // 38 8
0x06,0x49,0x49,0x29,0x1e, // 39 9
0x00,0x36,0x36,0x00,0x00, // 3a :
0x00,0x56,0x36,0x00,0x00, // 3b ;
0x08,0x14,0x22,0x41,0x00, // 3c <
0x14,0x14,0x14,0x14,0x14, // 3d =
0x00,0x41,0x22,0x14,0x08, // 3e >
0x02,0x01,0x51,0x09,0x06, // 3f ?
0x32,0x49,0x79,0x41,0x3e, // 40 @
0x7e,0x11,0x11,0x11,0x7e, // 41 A
0x7f,0x49,0x49,0x49,0x36, // 42 B
0x3e,0x41,0x41,0x41,0x22, // 43 C
0x7f,0x41,0x41,0x22,0x1c, // 44 D
0x7f,0x49,0x49,0x49,0x41, // 45 E
0x7f,0x09,0x09,0x09,0x01, // 46 F
0x3e,0x41,0x49,0x49,0x7a, // 47 G
0x7f,0x08,0x08,0x08,0x7f, // 48 H
0x00,0x41,0x7f,0x41,0x00, // 49 I
0x20,0x40,0x41,0x3f,0x01, // 4a J
0x7f,0x08,0x14,0x22,0x41, // 4b K
0x7f,0x40,0x40,0x40,0x40, // 4c L
0x7f,0x02,0x0c,0x02,0x7f, // 4d M
0x7f,0x04,0x08,0x10,0x7f, // 4e N
0x3e,0x41,0x41,0x41,0x3e // 4f O
};
BYTE const TABLE6[240]= {0x7f,0x09,0x09,0x09,0x06, // 50 P
0x3e,0x41,0x51,0x21,0x5e, // 51 Q
0x7f,0x09,0x19,0x29,0x46, // 52 R
0x46,0x49,0x49,0x49,0x31, // 53 S
0x01,0x01,0x7f,0x01,0x01, // 54 T
0x3f,0x40,0x40,0x40,0x3f, // 55 U
0x1f,0x20,0x40,0x20,0x1f, // 56 V
0x3f,0x40,0x38,0x40,0x3f, // 57 W
0x63,0x14,0x08,0x14,0x63, // 58 X
0x07,0x08,0x70,0x08,0x07, // 59 Y
0x61,0x51,0x49,0x45,0x43, // 5a Z
0x00,0x7f,0x41,0x41,0x00, // 5b [
0x02,0x04,0x08,0x10,0x20, // 5c
0x00,0x41,0x41,0x7f,0x00, // 5d
0x04,0x02,0x01,0x02,0x04, // 5e
0x40,0x40,0x40,0x40,0x40, // 5f
0x00,0x01,0x02,0x04,0x00, // 60
0x20,0x54,0x54,0x54,0x78, // 61 a
0x7f,0x48,0x44,0x44,0x38, // 62 b
0x38,0x44,0x44,0x44,0x20, // 63 c
0x38,0x44,0x44,0x48,0x7f, // 64 d
0x38,0x54,0x54,0x54,0x18, // 65 e
0x08,0x7e,0x09,0x01,0x02, // 66 f
0x0c,0x52,0x52,0x52,0x3e, // 67 g
0x7f,0x08,0x04,0x04,0x78, // 68 h
0x00,0x44,0x7d,0x40,0x00, // 69 i
0x20,0x40,0x44,0x3d,0x00, // 6a j
0x7f,0x10,0x28,0x44,0x00, // 6b k
0x00,0x41,0x7f,0x40,0x00, // 6c l
0x7c,0x04,0x18,0x04,0x78, // 6d m
0x7c,0x08,0x04,0x04,0x78, // 6e n
0x38,0x44,0x44,0x44,0x38, // 6f o
0x7c,0x14,0x14,0x14,0x08, // 70 p
0x08,0x14,0x14,0x18,0x7c, // 71 q
0x7c,0x08,0x04,0x04,0x08, // 72 r
0x48,0x54,0x54,0x54,0x20, // 73 s
0x04,0x3f,0x44,0x40,0x20, // 74 t
0x3c,0x40,0x40,0x20,0x7c, // 75 u
0x1c,0x20,0x40,0x20,0x1c, // 76 v
0x3c,0x40,0x30,0x40,0x3c, // 77 w
0x44,0x28,0x10,0x28,0x44, // 78 x
0x0c,0x50,0x50,0x50,0x3c, // 79 y
0x44,0x64,0x54,0x4c,0x44, // 7a z
0x00,0x08,0x36,0x41,0x00, // 7b
0x00,0x00,0x7f,0x00,0x00, // 7c
0x00,0x41,0x36,0x08,0x00, // 7d
0x10,0x08,0x08,0x10,0x08, // 7e
0x78,0x46,0x41,0x46,0x78 // 7f
};
//
void nokia_init(void);
void nokia_write_command(char bytefornokia_command);
void nokia_write_data(char bytefornokia_data);
void nokia_write_dorc(char bytefornokia);
void nokia_gotoxy(int8 xnokia, int8 ynokia);
void nokia_erase_y(int8 ynokia);
void nokia_erase_x(int8 xnokia);
void nokia_printchar(int8 cvar);
void nokia_clean_ddram(void);
void table_to_nokialcd(void);
void nokia_plot(int8 xnokia,int8 plot_value8);
void nokia_write_data_inv(char bytefornokia_data_inv);
void nokia_clear_screen(void);
void nokia_clear_xy(int8 xnokia, int8 ynokia);
void nokia_print_uparrow(void);
void nokia_print_downarrow(void);
void nokia_print_leftarrow(void);
void nokia_print_rightarrow(void);
void nokia_print_degree(void);
void nokia_print_lowbatdegree(void);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void nokia_init(void)
{
output_high(nok_dc); // bytes are stored in the display data ram, address counter, incremented automatically
output_high(nok_cs); // chip disabled
output_low(nok_res); // reset chip during 250ms
// delay_ms(10); // works with less.....
output_high(nok_res);
nokia_write_command(0x21); // set extins extended instruction set
nokia_write_command(0xc2); // Vop v1: 0xc8 (for 3V)// v2: 0xa0 (for 3V) // v3: 0xc2 (2v6-5v) ********************************************************************************************************************
nokia_write_command(0x13); // bias
nokia_write_command(0x20); // horizontal mode from left to right, X axe are incremented automatically , 0x22 for vertical addressing ,back on normal instruction set too
nokia_write_command(0x09); // all on
nokia_clean_ddram(); // reset DDRAM, otherwise the lcd is blurred with random pixels
nokia_write_command(0x08); // mod control blank change (all off)
nokia_write_command(0x0c); // mod control normal change
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void nokia_clean_ddram(void)
{
nokia_gotoxy(0,0); // 84*6=504 clear LCD
for (ddram=504;ddram>0;ddram--){nokia_write_data(0x00);}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void nokia_write_command(char bytefornokia_command)
{
output_low(nok_dc); // byte is a command it is read with the eight SCLK pulse
output_low(nok_cs); // chip enabled
nokia_write_dorc(bytefornokia_command);
output_high(nok_cs); // chip disabled
}
/////////////////////////////////////////////////////////////////////////////////
void nokia_write_data(char bytefornokia_data)
{
output_high(nok_dc);
output_low(nok_cs); // chip enabled
nokia_write_dorc(bytefornokia_data);
output_high(nok_cs); // chip disabled
}
//////////////////////////////////////////////////////////////////////////////////
void nokia_write_dorc(char bytefornokia) // serial write data or command subroutine
{
char caa;
for (caa=8;caa>0;caa--) {
output_low(nok_sclk);
// delay_us(2);
if ((bytefornokia&0x80)==0){output_low(nok_sda);}
else {output_high(nok_sda);}
output_high(nok_sclk);
bytefornokia=bytefornokia<<1;
}
}
//////////////////////////////////////////////////////////////////////////////////
void nokia_gotoxy(int8 xnokia, int8 ynokia) // Nokia LCD 3310 Position cursor
{
nokia_write_command(0x40|(ynokia&0x07)); // Y axe initialisation: 0100 0yyy
nokia_write_command(0x80|(xnokia&0x7f)); // X axe initialisation: 1xxx xxxx
}
//////////////////////////////////////////////////////////////////////////////////
void nokia_erase_y(int8 ynokia)
{
nokia_gotoxy(0,ynokia);
printf(nokia_printchar," ");
}
//////////////////////////////////////////////////////////////////////////////////
void nokia_erase_x(int8 xnokia)
{
char column;
for (column=0;column!=6;column++){
nokia_gotoxy(xnokia,column);
nokia_write_data(0x00);
nokia_write_data(0x00);
nokia_write_data(0x00);
nokia_write_data(0x00);
nokia_write_data(0x00);
nokia_write_data(0x00);
}
}
//////////////////////////////////////////////////////////////////////////////////
void nokia_printchar(int8 cvar) // Write 1 character to LCD
{
charsel=cvar;
table_to_nokialcd();
}
//////////////////////////////////////////////////////////////////////////////////
void table_to_nokialcd(void) // extract ascii from tables & write to LCD
{
if (charsel<0x20)return;
if (charsel>0x7f)return;
for (char_row=0;char_row<5;char_row++) { // 5 bytes
if (charsel<0x50){charpos=(((charsel&0xff)-0x20)*5);chardata=TABLE5[(charpos+char_row)];} // use TABLE5
else if (charsel>0x4f){charpos=(((charsel&0xff)-0x50)*5);chardata=TABLE6[(charpos+char_row)];} // use TABLE6
nokia_write_data(chardata); // send data to nokia
}
nokia_write_data(0x00); // 1 byte (always blank)
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void nokia_plot(int8 xnokia,int8 plot_value8)
{
char i;
plot_value32=0;
// plot_value32|=1; // unremark this if you want dotgraph instead of bargraph
for (i=0;i!=plot_value8;i++){
plot_value32|=1; // remark this if you want dotgraph instead of bargraph
plot_value32<<=1;
}
plot_value32|=2; // bottom line is always filled
plot_llsb=(plot_value32&0xff);
plot_ulsb=((plot_value32>>8)&0xff);
plot_lmsb=((plot_value32>>16)&0xff);
plot_umsb=((plot_value32>>24)&0xff);
nokia_gotoxy(xnokia,1);
nokia_write_data_inv(plot_umsb);
nokia_gotoxy(xnokia,2);
nokia_write_data_inv(plot_lmsb);
nokia_gotoxy(xnokia,3);
nokia_write_data_inv(plot_ulsb);
nokia_gotoxy(xnokia,4);
nokia_write_data_inv(plot_llsb);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void nokia_write_data_inv(char bytefornokia_data_inv)
{
char caa;
output_high(nok_dc);
output_low(nok_cs); // chip enabled
for (caa=8;caa>0;caa--) {
output_low(nok_sclk);
// delay_us(2);
if ((bytefornokia_data_inv&0x01)==0){output_low(nok_sda);}
else {output_high(nok_sda);}
output_high(nok_sclk);
bytefornokia_data_inv=bytefornokia_data_inv>>1;
}
output_high(nok_cs); // chip disabled
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void nokia_clear_screen(void)
{
nokia_erase_y(0);
nokia_erase_y(1);
nokia_erase_y(2);
nokia_erase_y(3);
nokia_erase_y(4);
nokia_erase_y(5);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void nokia_clear_xy(int8 xnokia, int8 ynokia)
{
nokia_gotoxy(xnokia,ynokia);
nokia_printchar(" ");
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void nokia_print_uparrow(void)
{
nokia_write_data(0x04);
nokia_write_data(0x02);
nokia_write_data(0x7f);
nokia_write_data(0x02);
nokia_write_data(0x04);
nokia_write_data(0x00);
}
//
void nokia_print_downarrow(void)
{
nokia_write_data(0x10);
nokia_write_data(0x20);
nokia_write_data(0x7f);
nokia_write_data(0x20);
nokia_write_data(0x10);
nokia_write_data(0x00);
}
//
void nokia_print_leftarrow(void)
{
nokia_write_data(0x08);
nokia_write_data(0x1c);
nokia_write_data(0x2a);
nokia_write_data(0x08);
nokia_write_data(0x08);
nokia_write_data(0xf8);
}
//
void nokia_print_rightarrow(void)
{
nokia_write_data(0x08);
nokia_write_data(0x08);
nokia_write_data(0x2a);
nokia_write_data(0x1c);
nokia_write_data(0x08);
nokia_write_data(0x00);
}
//
void nokia_print_degree(void)
{
nokia_write_data(0x00);
nokia_write_data(0x06);
nokia_write_data(0x09);
nokia_write_data(0x09);
nokia_write_data(0x06);
nokia_write_data(0x00);
// nokia_printchar(" ");
}
//
void nokia_print_lowbatdegree(void)
{
nokia_write_data(0x00);
nokia_write_data(0x06);
nokia_write_data(0x0f);
nokia_write_data(0x0f);
nokia_write_data(0x06);
nokia_write_data(0x00);
// nokia_printchar(" ");
}
|
Cordially,
Pic14 |
|
|
|
|
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
|