SparkFun Forums 

Where electronics enthusiasts find answers.

Your source for all things Atmel.
By old_dave
#66735
I'm having a problem calling a function multiple times when the same parameters are passed to it. I am using AtTiny24 with AVR Studio 4.15 build 623. The function will work correctly the first time and again as long as the parameters passed to it are different. For example my WriteLcd() function, if I do

WriteLcd("MSG",3); //works fine
WriteLcd("MSG1",4); //Works fine
WriteLcd("MSG",3); //Stops Working and prints // to the LCD
WriteLcd("MSG2",4); //Works fine
WriteLcd("MSG2",4); //Stops Working and prints // to the LCD
Like wise if I do

WriteLcd(string,strlen(string)); //Works fine
WriteLcd(string,strlen(string)); //Stops Working and prints // to the LCD

I have tried setting different optimizations with no luck. Any help would be appreciated.

Code: Select all
#define F_CPU 8000000UL

#include <avr/io.h>
#include <util/delay.h>

// LCD is connected to PA0 
#define LCDPIN 0

// Button is connected to PA1
#define BTNPIN 1

//Write string to LCD at 9600 baud
void WriteLcd(char *string,int len);
void WriteLcd(char *string,int len)
{
	int bitloop,charloop;
	for(charloop=0;charloop<len;charloop++)
	{
		PORTA&=~(_BV(LCDPIN)); //Start Signal
		_delay_us(104);
		for(bitloop=0;bitloop<8;bitloop++)
		{
			if(string[charloop]&0x01)
			{
				PORTA |= _BV(LCDPIN);
			}
			else
			{
				PORTA&=~(_BV(LCDPIN));
			}
			string[charloop]>>=1;
			_delay_us(104);
		}
		PORTA |= _BV(LCDPIN); //Stop Signal
		_delay_us(104);
	}
}
int main(void)
{
	DDRA=0xFD; // Pin A1 input, others output
	PORTA = 0x03; // Enable internal pull-up resistor on PA1 and set others low
	char string[]="Hello";
	_delay_ms(300);
	WriteLcd("HI",2); //prints fine
	WriteLcd("HI",2); //prints garbage
	
	while(1)
	{
		
		if(bit_is_clear(PINA, BTNPIN))
		{	
			WriteLcd(string,6);
			while(bit_is_clear(PINA, BTNPIN));
		}

	}
	
	return 0;
}
By stevech
#66740
old_dave wrote:I'm having a problem calling a function multiple times when the same parameters are passed to it. I am using AtTiny24 with AVR Studio 4.15 build 623. The function will work correctly the first time and again as long as the parameters passed to it are different. For example my WriteLcd() function, if I do

WriteLcd("MSG",3); //works fine
WriteLcd("MSG1",4); //Works fine
WriteLcd("MSG",3); //Stops Working and prints // to the LCD
WriteLcd("MSG2",4); //Works fine
WriteLcd("MSG2",4); //Stops Working and prints // to the LCD
Like wise if I do

WriteLcd(string,strlen(string)); //Works fine
WriteLcd(string,strlen(string)); //Stops Working and prints // to the LCD

I have tried setting different optimizations with no luck. Any help would be appreciated.

Code: Select all
#define F_CPU 8000000UL

#include <avr/io.h>
#include <util/delay.h>

// LCD is connected to PA0 
#define LCDPIN 0

// Button is connected to PA1
#define BTNPIN 1

//Write string to LCD at 9600 baud
void WriteLcd(char *string,int len);
void WriteLcd(char *string,int len)
{
	int bitloop,charloop;
	for(charloop=0;charloop<len;charloop++)
	{
		PORTA&=~(_BV(LCDPIN)); //Start Signal
		_delay_us(104);
		for(bitloop=0;bitloop<8;bitloop++)
		{
			if(string[charloop]&0x01)
			{
				PORTA |= _BV(LCDPIN);
			}
			else
			{
				PORTA&=~(_BV(LCDPIN));
			}
			string[charloop]>>=1;
			_delay_us(104);
		}
		PORTA |= _BV(LCDPIN); //Stop Signal
		_delay_us(104);
	}
}
int main(void)
{
	DDRA=0xFD; // Pin A1 input, others output
	PORTA = 0x03; // Enable internal pull-up resistor on PA1 and set others low
	char string[]="Hello";
	_delay_ms(300);
	WriteLcd("HI",2); //prints fine
	WriteLcd("HI",2); //prints garbage
	
	while(1)
	{
		
		if(bit_is_clear(PINA, BTNPIN))
		{	
			WriteLcd(string,6);
			while(bit_is_clear(PINA, BTNPIN));
		}

	}
	
	return 0;
}
I can't see anything obvious, but

in the bit shift loop, I'd code it to copy string[n] to a byte, then shift that byte rather than shifting the called parameter which is a constant stored in RAM.

Or use a bit mask that shifts from 0x01 to 0x80 then and that with the called string's char. Some compilers would prohibit altering a constant like "HI".

Note also that if you have a lot of strings, you should tell the compiler to store them in flash. As is, they'll be stored in flash and copied to RAM in the C startup.

PORTA&=~(_BV(LCDPIN));
makes me nervous, versus
PORTA &= ~(_BV(LCDPIN));

The _BV() macro was retired long ago. Most often you see instead something like
PORTA &= ~(1<<LCDPIN);

Note too that a string constant in C by definition has a null byte added to the end, so that "HI" is stored as three bytes, the last being 0. So you can loop until you see that null, rather than using a count.
By old_dave
#66745
Thank you for your help. The problem was resolved by copying the value into a byte first like you suggested.