Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

hi-tech lcd_puts() function vs. interrupts

Status
Not open for further replies.

dsc

Member
hi-tech lcd_puts() function vs. interrupts (+ PWM toggle question)

Hi all,

I've noticed a strange thing when using the lcd_puts() function with the Hi-Tech complier. It works fine with the following bit of code:

Code:
void show_time(void)	//update LCD with new time value
{
itoa(buf, time, 10);
if(time<10) {buf[3] = buf[0]; buf[0] = '0'; buf[1] = '0'; buf[2] = '.';}
if(time>=10 && time<100) {buf[3] = buf[1]; buf[1] = buf[0]; buf[0] = '0'; buf[2] = '.'; }
if(time>=100) {buf[3] = buf[2]; buf[2] = '.';}

lcd_goto(0x46);
lcd_puts(buf);
}

[effectively moving around digits in a number to fit a 4 digit space ie. display 9 as 00.9, 99 as 09.9 and 999 as 99.9]

Later on I've added an interrupt service routine and noticed that the above function shows values on the LCD, but also displays a strange Chinese looking character at the end of each number, for example instead of 09.9 I'd see 09.9#, where # is the strange character (it's not a hash character though, it's one I couldn't even find on ASCII tables :O). That character changes as I change the value displayed, I can see at some point is simply follows the ASCII table up/down depending what I do with the displayed value (it's controlled of a rotary encoder).

Now the funny thing, buf is defined as a variable buf[4]. Without the interrupt service routine that works ok, with an interrupt routine it shows a character at the end, but if I make buf a longer array and use buf[5], it works good again. Here's lcd_puts():

Code:
void lcd_puts(const char * s)
{
LCD_RS = 1; // write characters
while(*s)
lcd_write(*s++);
}

Anyone knows why?

Regards,
T.
 
Last edited:
I'll need to see your code to comment... But it seems as if your interrupt routine is using the very next variable after the buff.... To correctly use strings you need to null terminate the string

ie "99.9",0 this is a FIVE byte array not four.. If there is no NULL ( 0) character then then the LCDputs routine will not stop at the character its supposed to.

You WILL need a five character array and you will also need to fill buf[4] with zero....
 
Thanks a lot for the reply Ian, I've had the termination character / +1 on the size of char arrays in the back of my mind from times when I've done C in DOS. This is the reason why I've tried to declare buf[5] instead of buf[4]. Glad to know for sure now:)

As for the next variable, here's variable declarations:

Code:
char temp;
char time_tens;
char time_ones;
char time_dec;
char old; 
char new;
char buf[5];
char out[5];
char ROT_PB_int;
char PB0_int;
char PB1_int;	
char ROT_int;
char PORTB_shadow;	//shadow register for PORTB

and the ISR:

Code:
void interrupt ISR()
{
if (RE1 == 0) {if (select == 0) time++; else sett++;}
else {if (select == 0) time--; else sett--;}

ROT_int = 0;
INTCON = 0b10000000;
}

Cheers,
T.
 
Incidentally!! Its a good Idea, when using pic's, to declare variables used by two functions... ie the interrupt and main... as volatile ..

This stops the compiler from optimizing the variable.... It can sometimes happen, the interrupt cannot access the variable at run time because the variable has been "optimized" and mapped to a memory bank... This causes major upset when you least expect it...
 
I always declare buffers at least twice as large I think they need to be.. if I run out of memory then I start optimizing.
 
Twice as large? That's pretty excessive. I assume that's just for development, then once the code is done you make the buffers the proper size?

Many of the projects I do are a bit tight on resources, I couldn't imagine running buffers at double size as a general rule!

I make them about 1 or 2 bytes larger than needed to allow some tolerance of fence post errors in testing. Then when going to final version I sometimes shrink them to the correct size or sometimes don't bother. As they are only 1-2 vars larger than needed it's not likely to be a problem with RAM usage.
 
Thanks for all the replies gents. I'll go for volatile when using variables between functions.

Another quick question I have is PWM outputs on the 16ff887, what's the best way to toggle them on / off? currently I take the duty cycle to 0, although I'm thinking that changing the pin assignment from output to input will also work (I'm using PORTC pin 2, so do TRISC2 = 1). Am I correct? I don't want to start another thread for such a short question so I'll just amend the thread name of this one.

Regards,
T.
 
Twice as large? That's pretty excessive. I assume that's just for development, then once the code is done you make the buffers the proper size?

Well, for tx/rx buffers etc. I make them excessively large if I have the memory. Standard way of handling dynamic memory allocation is to double the allocated memory when you run out. I don't trim anything if the microcontroller has enough memory.. usually there is plenty of memory.
 
Last edited:
...
Another quick question I have is PWM outputs on the 16ff887, what's the best way to toggle them on / off? currently I take the duty cycle to 0, although I'm thinking that changing the pin assignment from output to input will also work (I'm using PORTC pin 2, so do TRISC2 = 1). ...
...

Changing to an input is a bad solution as the pin will float. Two standard methods are to leave the PWM module on but just change the duty to zero, or, turn the PWM module off so the pin defaults back to a digital output and is set by PORTC. Personally I think turning the PWM module off is the best way. :)

To MisterT; thanks for explaining. :)
 
Thanks for the reply RB, you mention disabling the PWM altogether, I'm guessing you mean clearing the CCP1CON register?

Regards,
T.
 
Status
Not open for further replies.

Latest threads

Back
Top