AVR GCC error: expected ')' before '*' token in function deinition

Go To Last Post
20 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am facing an issue, not able to resolve for two days. This is the main.c file to write text to a 128x64 GLCD. Reproduced here below.

I get a compilation error: Severity                                                                                                 Code    Description    Project    File    Line
Error        expected ')' before '*' token    GLCD_text    G:\Microcontrollers\AVR\Programs\ATMega8\C_progs\GLCD_text\GLCD_text\main.c    122

 

Here is the code:

 

/* Text display with 128x6 GLCD - ATmega8 
This file edited for ATMega8 @ 8MHz.
This is an advanced version of the routine at G:\Microcontrollers\AVR\Programs\ATMega8\C_progs\GLCD_test\main.c
Incorporates PROGMEM space for font array, auto check for end of page on half sections of GLDC, end of entire display, 
proper spacing between chars.

glcd_text.h has prototype functions, font array.
*/

#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>
#include <stdint.h>
#include <avr/pgmspace.h>
#include <string.h>

#include "GLCD_text.h"

#define Data_Port                PORTD
#define Command_Port        PORTC
#define Data_Port_Dir          DDRD
#define Command_Port_Dir    DDRC

#define RS                          PC0        // Define control pins
#define RW                         PC1
#define EN                          PC2
#define CS1                        PC3
#define CS2                        PC4
#define RST                        PC5

 

//global variables
uint8_t column;
uint8_t yaddr;
uint8_t page;
unsigned char str_buffer[50];    //buffer to copy flash string to RAM

 

// function definitions

pulse_EN()    //pulses EN signal to write to glcd
{
    Command_Port &= ~(1 << EN);    // ensure EN is low
    _delay_us(5);                // some settling delay
    Command_Port |= (1 << EN);        // pulse EN hi -> lo
    _delay_us(5);
    Command_Port &= ~(1 << EN);
    _delay_us(5);
}

 

// used to write one font byte of [i][j] to one column of glcd
glcddata(data)    
{
    Data_Port = data;
    Command_Port |= (1 << RS);    // Make RS HI to select data reg
    Command_Port &= ~(1 << RW);    // Make RW LOW for writing
    pulse_EN();
}

 

glcdcmd(cmdbyte)
{
    Data_Port = cmdbyte;
    Command_Port &= ~(1 << RS);    // Make RS LOW to select cmd reg
    Command_Port &= ~(1 << RW);    // Make RW LOW for writing
    pulse_EN();
}

 

glcdinit()
{
    Command_Port |= ((1 << CS1) | (1 << CS2) | (1 << RST)); //enable both halves of glcd, RST hi
    _delay_ms(20);
    
    glcdcmd(0x3E);    //Display off
    glcdcmd(0xB8);    //Setting x-address page 0 is selected
    glcdcmd(0x40);    //Setting y-address
    glcdcmd(0xC0);    //Setting z-address start line 0
    glcdcmd(0x3F);    //Display on
}

 

glcdclear()        //clear entire display
{
    uint8_t i,j;
    // Select both left & right half of display
    Command_Port |= ((1 << CS1) | (1 << CS2));
    for(i = 0; i < 8; i++)
    {
        glcdcmd((0xB8) + i);    // Inc page each time after 64 col
        for(j = 0; j < 64; j++)
        {
            glcddata(0);    // Write zeros to all 64 col
        }
    }
    glcdcmd(0x40);        // reset Y address (column=0)
    glcdcmd(0xB8);        // reset x address (page=0)
    Command_Port |=(1 << CS1);    //reset CS to left half
    Command_Port &= ~(1 << CS2);
}

 

/*
glcdclrpage(ycol, xpage)        //to clear a particular page         =====have commented this function just to check the problem. This function is not used in this project.
{
    uint8_t i;
    if(ycol<64)
    {
        Command_Port |=(1 << CS1);// Enable left half display
        Command_Port &= ~(1 << CS2);
    }
    else
    {
        Command_Port |=(1 << CS2);// Enable right half display
        Command_Port &= ~(1 << CS1);
    }

    glcdcmd((0xB8) + xpage);    // set page (0-7) to be cleared
    for(i = 0; i < 64; i++)
    {
        glcddata(0);    // Write zeros to all 64 col of page
    }
}        */

 

//write string to glcd - check boundaries, retrieves font chars from flash, hence '_p'
glcdstring_p(page_no, *str_buffer)  <=================ERROR points here
{
    uint8_t i;
    unsigned char byte;
    uint8_t page_no;
    page=((0xb8)+page_no); //uint8_t page declared global
    
    glcdcmd(page);
    
    for(i=0; str_buffer[i]=0; i++)
    {
        //check if display is full
        if(yaddr > 1023)
            break;    //if full, break out
        
        //check overflow from any side
        if((yaddr)%64 ==0) //if yaddr overflow from left or right
        {
            glcdcmd(0x40);    //reset to first column
            Command_Port ^=(1 << CS1);// enable other half
            Command_Port ^=(1 << CS2);// of display
        }
        //write using font table in successive columns
        for(column=0; column<FontWidth; column++)
        {
            glcddata(pgm_read_byte(&(font[str_buffer-32][column])));    //write columns to glcd
            yaddr++;     //increment y address
        }
    }
}

int main(void)
{
    Data_Port_Dir = 0xFF;
    Command_Port_Dir = 0xFF;

    glcdinit();

    glcdclear();
    
    strcpy_p(str_buffer, flashstring);    //copy entire flash string to RAM buffer
    for(column=0; column<FontWidth; column++)
    {
        glcdstring_p(0, str_buffer);    
    }

    while(1); // stop here
    
} //end main()

 

I have a GLCD_TEXT.h file too. This has the font array, the flashstring in program space. I included <pgmspace.h>. Function prototypes are also in .h file. I have not posted he .h file since it has the entire ASCII font table in [i][5] format. 

I checked the code many times and could not find a missing ')'. Can someone please help. I am using Atmel Studio 7. The code is for ATMega8 @ 8 MHz.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Please see Tip #1 in my signature for how to properly post source code.

 

Why aren't there any type specifications for your parameters?

//write string to glcd - check boundaries, retrieves font chars from flash, hence '_p'
glcdstring_p( page_no, *str_buffer )  <=================ERROR points here
{

 

shouldn't that be something like:

glcdstring_p( int page_no, char *str_buffer )

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Fri. May 22, 2020 - 03:43 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My guess is that GLCD_text.h has a conflicting declaration for glcd_string.

Another guess is that you either have warnings turned off or are choosing not to look at them.

You are letting base types of function parameters default to int.  Not a good choice.

GLCD_text.h probably has its second parameter declared as pointer to char, not pointer to int.

Also, I note that you have given said argument the same name as a global.

Allowed, but often not a good choice.

 

Edit: tipo

Iluvatar is the better part of Valar.

Last Edited: Sun. May 24, 2020 - 01:23 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

amorawala wrote:
retrieves font chars from flash, hence '_p'

shouldn't that be '_P' (uppercase) ?

 

https://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Not only is "*str_buffer" missing "char *str_buffer" and the "page_no" is missing a type too but then a few lines later the function defines a stack frame automatic also called "page_no" which would then hide the function parameter anyway.
.
Oh and I'd be very careful about having both a global and a function parameter both called str_buffer. Inside the function I'd consider something more like "char * pBuff" or something like that.

Last Edited: Fri. May 22, 2020 - 04:55 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
unsigned char str_buffer[50];    //buffer to copy flash string to RAM

if this is for text strings, then it should be plain 'char' - drop the 'unsigned'

 

if it's not, then best not to give it a name & comment which suggest that it is

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'll bet you didn't mean this either:

 

    for(i=0; str_buffer[i]=0; i++)

Oh - I'll save you a couple of days debugging and correct it for you.

    for(i=0; str_buffer[i]!=0; i++)

 

OMG - Here's another:

             glcddata(pgm_read_byte(&(font[str_buffer-32][column])));    //write columns to glcd

I'd expect to see:

             glcddata(pgm_read_byte(&(font[str_buffer[i]-' '][column])));    //write columns to glcd

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Function definitions in the original code satisfy the syntax and other requirements of K&R-style (old-style) definitions (in combination with the no longer supported "implicit int" rule), which is why they successfully compile all the way to `glcdstring_p`. The latter is the first one that fits into neither the old nor the modern declaration style. Hence the error.

 

The OP has to decide what function definition style they are intending to use and stick to it. Of course, it is a better idea to use the modern style, i.e. a prototype-based one. And explicit specification of function return type is required in modern C. The original code is a mess.

Last Edited: Fri. May 22, 2020 - 10:12 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The function declarations are in glcd_text.h file as below:

#ifndef	GLCD_TEXT_H_
#define	GLCD_TEXT_H_

#include<avr/pgmspace.h>
#include<avr/io.h>
#include<stdio.h>


#define FontWidth 5

/* Define char fonts array in column by row in PROG memory */

 unsigned char font[][5]PROGMEM =	{
 {0x00, 0x00, 0x00, 0x00, 0x00} // 20 (Space) 
,{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
,{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 <-
};

//define constant string to be displayed 
char flashstring[] PROGMEM = "GLCD initialised and ready"

//Function prototypes

void pulse_EN();
void glcddata(char data);
void glcdcmd(char value);
//void glcdstring_p(char page_no, const char *byte) //write string from flash
void glcdinit();
void glcdclear();
void glcdclrpage(char ycol, char _page);

#endif

Hence in the function definitions, the parameter types are not necessary?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have used the attribute with _p before, in lower case. But if _P is the right way to code, I shall follow your advice. Thanks Awneil.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Athough I am not a coding expert, being just a hobby, I understand that unsigned char implies 0-255, while just char can mean both positive & negative chars 0-127. Since I am using ASCII table, I thought unsigned char was best. Please advise.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have used the decimal for ' ', which is SPACE. is it not proper to use decimal values when using lookup tables? Please advise. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In the GLCD_text.h file I had commented out the glcd_string function. This was a mistake on my part. But even after uncommenting and building the solution again I got errors. I have posted the entire code and error list as below: I cannot see any "conflicting types" I have used chars after declaring as "unsigned char". Does it make a difference using "unsigned char"?

Severity	Code	Description	Project	File	Line
Warning		conflicting types for 'glcdclear'	GLCD_text	G:\Microcontrollers\AVR\Programs\ATMega8\C_progs\GLCD_text\GLCD_text\main.c	80
Warning		conflicting types for 'glcdcmd'	GLCD_text	G:\Microcontrollers\AVR\Programs\ATMega8\C_progs\GLCD_text\GLCD_text\main.c	60
Warning		conflicting types for 'glcddata'	GLCD_text	G:\Microcontrollers\AVR\Programs\ATMega8\C_progs\GLCD_text\GLCD_text\main.c	52
Warning		conflicting types for 'glcdinit'	GLCD_text	G:\Microcontrollers\AVR\Programs\ATMega8\C_progs\GLCD_text\GLCD_text\main.c	68
Warning		conflicting types for 'pulse_EN'	GLCD_text	G:\Microcontrollers\AVR\Programs\ATMega8\C_progs\GLCD_text\GLCD_text\main.c	41
Error		expected ')' before '*' token	GLCD_text	G:\Microcontrollers\AVR\Programs\ATMega8\C_progs\GLCD_text\GLCD_text\main.c	122
Warning		implicit declaration of function 'strcpy_p' [-Wimplicit-function-declaration]	GLCD_text	G:\Microcontrollers\AVR\Programs\ATMega8\C_progs\GLCD_text\GLCD_text\main.c	163
Message		previous declaration of 'glcdclear' was here	GLCD_text	G:\Microcontrollers\AVR\Programs\ATMega8\C_progs\GLCD_text\GLCD_text\GLCD_text.h	123
Message		previous declaration of 'glcdcmd' was here	GLCD_text	G:\Microcontrollers\AVR\Programs\ATMega8\C_progs\GLCD_text\GLCD_text\GLCD_text.h	120
Message		previous declaration of 'glcddata' was here	GLCD_text	G:\Microcontrollers\AVR\Programs\ATMega8\C_progs\GLCD_text\GLCD_text\GLCD_text.h	119
Message		previous declaration of 'glcdinit' was here	GLCD_text	G:\Microcontrollers\AVR\Programs\ATMega8\C_progs\GLCD_text\GLCD_text\GLCD_text.h	122
Message		previous declaration of 'pulse_EN' was here	GLCD_text	G:\Microcontrollers\AVR\Programs\ATMega8\C_progs\GLCD_text\GLCD_text\GLCD_text.h	118
Error		recipe for target 'main.o' failed	GLCD_text	G:\Microcontrollers\AVR\Programs\ATMega8\C_progs\GLCD_text\GLCD_text\Debug\Makefile	76
Warning		return type defaults to 'int' [-Wimplicit-int]	GLCD_text	G:\Microcontrollers\AVR\Programs\ATMega8\C_progs\GLCD_text\GLCD_text\main.c	41
Warning		return type defaults to 'int' [-Wimplicit-int]	GLCD_text	G:\Microcontrollers\AVR\Programs\ATMega8\C_progs\GLCD_text\GLCD_text\main.c	52
Warning		return type defaults to 'int' [-Wimplicit-int]	GLCD_text	G:\Microcontrollers\AVR\Programs\ATMega8\C_progs\GLCD_text\GLCD_text\main.c	60
Warning		return type defaults to 'int' [-Wimplicit-int]	GLCD_text	G:\Microcontrollers\AVR\Programs\ATMega8\C_progs\GLCD_text\GLCD_text\main.c	68
Warning		return type defaults to 'int' [-Wimplicit-int]	GLCD_text	G:\Microcontrollers\AVR\Programs\ATMega8\C_progs\GLCD_text\GLCD_text\main.c	80
Warning		type of 'cmdbyte' defaults to 'int' [-Wimplicit-int]	GLCD_text	G:\Microcontrollers\AVR\Programs\ATMega8\C_progs\GLCD_text\GLCD_text\main.c	60
Warning		type of 'data' defaults to 'int' [-Wimplicit-int]	GLCD_text	G:\Microcontrollers\AVR\Programs\ATMega8\C_progs\GLCD_text\GLCD_text\main.c	52

Here is the GLCD_text.h code:
#ifndef	GLCD_TEXT_H_
#define	GLCD_TEXT_H_

#include <avr/pgmspace.h>
#include <avr/io.h>
#include <stdio.h>
#include <stdint.h> 
//#include <string.h>

#define FontWidth 5

/* Define char fonts array in column by row in PROG memory */

 unsigned const char font[][5]PROGMEM =	{
 {0x00, 0x00, 0x00, 0x00, 0x00} // 20 (Space) 
,{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
,{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 <-
};

//define constant string to be displayed 
const char flashstring[] PROGMEM = "GLCD initialised and ready";

//Function prototypes

void pulse_EN(void);
void glcddata(unsigned char data);
void glcdcmd(unsigned char value);
void glcdstring_p(uint8_t page_no, unsigned char *str_buffer); //write string from flash
void glcdinit(void);
void glcdclear(void);
//void glcdclrpage(char ycol, char _page); // not used in GLCD_text hence commented out

#endif

And this is the main prgram with some modifiations as advised by all in the posts

#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>
#include <stdint.h>
#include <avr/pgmspace.h>
#include <string.h>

#include "GLCD_text.h"


#define Data_Port		PORTD
#define Command_Port		PORTC
#define Data_Port_Dir		DDRD
#define Command_Port_Dir	DDRC

#define RS		PC0		// Define control pins
#define RW		PC1
#define EN		PC2
#define CS1		PC3
#define CS2		PC4
#define RST		PC5

//global variables
uint8_t column;
uint8_t yaddr;
uint8_t page;
unsigned char str_buffer[50];	//buffer to copy flash string to RAM

// function definitions

pulse_EN()	//pulses EN signal to write to glcd
{
	Command_Port &= ~(1 << EN);	// ensure EN is low
	_delay_us(5);				// some settling delay
	Command_Port |= (1 << EN);		// pulse EN hi -> lo
	_delay_us(5);
	Command_Port &= ~(1 << EN);
	_delay_us(5);
}

// used to write one font byte of [i][j] to one column of glcd
glcddata(data)	
{
	Data_Port = data;
	Command_Port |= (1 << RS);	// Make RS HI to select data reg
	Command_Port &= ~(1 << RW);	// Make RW LOW for writing
	pulse_EN();
}

glcdcmd(cmdbyte)
{
	Data_Port = cmdbyte;
	Command_Port &= ~(1 << RS);	// Make RS LOW to select cmd reg
	Command_Port &= ~(1 << RW);	// Make RW LOW for writing
	pulse_EN();
}

glcdinit()
{
	Command_Port |= ((1 << CS1) | (1 << CS2) | (1 << RST)); //enable both halves of glcd, RST hi
	_delay_ms(20);
	
	glcdcmd(0x3E);	//Display off
	glcdcmd(0xB8);    //Setting x-address page 0 is selected
	glcdcmd(0x40);    //Setting y-address
	glcdcmd(0xC0);    //Setting z-address start line 0
	glcdcmd(0x3F);    //Display on
}

glcdclear()		//clear entire display
{
	uint8_t i,j;
	// Select both left & right half of display
	Command_Port |= ((1 << CS1) | (1 << CS2));
	for(i = 0; i < 8; i++)
	{
		glcdcmd((0xB8) + i);	// Inc page each time after 64 col
		for(j = 0; j < 64; j++)
		{
			glcddata(0);	// Write zeros to all 64 col
		}
	}
	glcdcmd(0x40);		// reset Y address (column=0)
	glcdcmd(0xB8);		// reset x address (page=0)
	Command_Port |=(1 << CS1);	//reset CS to left half
	Command_Port &= ~(1 << CS2);
}

/*
glcdclrpage(ycol, xpage)		//to clear a particular page
{
	uint8_t i;
	if(ycol<64)
	{
		Command_Port |=(1 << CS1);// Enable left half display
		Command_Port &= ~(1 << CS2);
	}
	else
	{
		Command_Port |=(1 << CS2);// Enable right half display
		Command_Port &= ~(1 << CS1);
	}

	glcdcmd((0xB8) + xpage);	// set page (0-7) to be cleared
	for(i = 0; i < 64; i++)
	{
		glcddata(0);	// Write zeros to all 64 col of page
	}
}		*/

//write string to glcd - check boundaries, retrieves font chars from flash, hence '_p'
glcdstring_p(page_no, *str_buffer)   ERROR POINTS HERE
{
	uint8_t i;
	unsigned char byte;
	uint8_t page_no;
	page=((0xb8)+page_no); //uint8_t page declared global
	
	glcdcmd(page);
	
	for(i=0; str_buffer[i]!=0; i++)
	{
		//check if display is full
		if(yaddr > 1023)
			break;	//if full, break out
		
		//check overflow from any side
		if((yaddr)%64 ==0) //if yaddr overflow from left or right
		{
			glcdcmd(0x40);	//reset to first column
			Command_Port ^=(1 << CS1);// enable other half
			Command_Port ^=(1 << CS2);// of display
		}
		//write using font table in successive columns
		for(column=0; column<FontWidth; column++)
		{
			glcddata(pgm_read_byte(&(font[str_buffer-' '][column])));	//write columns to glcd
			yaddr++; 	//increment y address
		}
	}
}


int main(void)
{
	Data_Port_Dir = 0xFF;
	Command_Port_Dir = 0xFF;

	glcdinit();

	glcdclear();
	
	strcpy_p(str_buffer, flashstring);	//copy entire flash string to RAM buffer
	for(column=0; column<FontWidth; column++)
	{
		glcdstring_p(0, str_buffer);	
	}

	while(1); // stop here
	
} //end main()

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What compiler are you using?  It must be really ancient to not require "const" with all the PGMSPACE data...

 

In GCLD_text.h:

char flashstring[] PROGMEM = "GLCD initialised and ready"

Missing semicolon.

 

In main.c (?):

pulse_EN()    //pulses EN signal to write to glcd
glcddata(data)    
glcdcmd(cmdbyte)
glcdinit()
glcdclear()        //clear entire display
glcdstring_p(page_no, *str_buffer)

Bad function definitions - they need types for the return value and arguments that match the prototypes in the .h file.

 

    uint8_t page_no;

Local variable duplicates a parameter.

 

There are additional problems, as others have pointed out.  A new compiler (from https://www.microchip.com/mplab/... ) will get you different and perhaps more meaningful error messages.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you Westfw. I use Atmel Studio  which has a built in AVR GNU-C compiler. I will check out the new compiler and try to integrate with AS7.

But do all these tips (although best practices) have a bearing on the actual error message I get?

Some more details on AS7:

 

Atmel Studio 7 (Version: 7.0.2389 - )
© 2019 Microchip Technology, Inc.
All rights reserved.

OS Version: Microsoft Windows NT 6.2.9200.0
Platform: Win32NT

 

Installed Packages: Atmel Kits - 7.0.129
Atmel Kits
Version: 7.0.129
Package GUID: 6F4B8FE4-C464-4916-8B43-AC92431C1CDF
Company: Atmel

Installed Packages: AtmelToolchainProvider - 7.0.908
AtmelToolchainProvider
Version: 7.0.908
Package GUID: AtmelToolchainProvider.Atmel.10EF9C74-D8DA-4872-85F5-D8BB3101E245
Company: Atmel

 

Last Edited: Sat. May 23, 2020 - 04:34 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello everyone and thank you all for the best practices information offered.

I managed to solve the original issue taking the advice offered.

The main point was that the function definitions also require parameter types to be defined in the code, just declarations in the .h file is not sufficient, as pointed out by AndreT and Westfw.  

Next, stcpy_p was showing an error of undeclared function, which was solved by editing to strcpy_P. This was pointed out by  Awneil. In my own functions too I have replaced with _P just to follow standard practices.

I also rectified the line that reads the string buffer to 

glcddata(pgm_read_byte(&(font[str_buffer[i]-' '][column])));    //write columns to glcd

as advised by N. Winterbottom. Without the [i], the compiler was generating error: array subscript is not an integer.

 

On the whole, the compilation went off smoothly without any errors or warnings. 

Thanks a lot all of you fr your help.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the update.  You have no idea how frustrating it is to give people advice and never hear back as to whether they got any further with it!

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes Westfw. I thought I should record my appreciation for the support you all have given. Hope to get in touch again.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

amorawala wrote:
Hence in the function definitions, the parameter types are not necessary?

 

No, that's not the case. You still have to meticulously repeat all function "headers" in function definitions, [almost] exactly as they are spelled out in function declarations, including function return types.

 

The above "almost" means that parameter names can be omitted from declarations (but not from definitions), and that parameter names can be different between declarations and definitions. These are the only "flexibilities" you are allowed in this case.

 

Also note that `()` function declarations in your header file are anachronisms. The proper way to declare a parameter-less function in C is `(void)`. (Ironically, the upcoming C2x standard will almost surely make my remark an anachronism in itself, since it plans to outlaw K&R declaration style and make `()` synonymous with `(void)`. But we are not there yet.)

Last Edited: Sun. May 24, 2020 - 07:35 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello AndreyT. I you notice, in my last post dated Saturday, 23 May, I have done as you advised. I have replicated the function paramete types as in the header file and have placed (void) in teh declarations also.

This did solve many other issues. I could compile the code properly now.

Thank you for your advice and will implement this in my future codes.