AtMega 328PU and 20x4 LCD pfleury libraries

Go To Last Post
148 posts / 0 new

Pages

Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello guys...

 

It has been a while since my last time here!

 

Now, most of things have been forgotten but I pretend to get them back.

 

I'm trying to connect an HD44780 based 20x4 LCD to my AtMega328PU ucontroller and I'm using Peter Fleury's libraries and I can't remember how some of the lcd.h parameters are configured to my LCD module!

 

I'm talking particularly about this piece of code:

 

#ifndef LCD_LINES
#define LCD_LINES           2     /**< number of visible lines of the display */
#endif
#ifndef LCD_DISP_LENGTH
#define LCD_DISP_LENGTH    16     /**< visibles characters per line of the display */
#endif
#ifndef LCD_LINE_LENGTH
#define LCD_LINE_LENGTH  0x40     /**< internal line length of the display    */
#endif
#ifndef LCD_START_LINE1
#define LCD_START_LINE1  0x00     /**< DDRAM address of first char of line 1 */
#endif
#ifndef LCD_START_LINE2
#define LCD_START_LINE2  0x40     /**< DDRAM address of first char of line 2 */
#endif
#ifndef LCD_START_LINE3
#define LCD_START_LINE3  0x14     /**< DDRAM address of first char of line 3 */
#endif
#ifndef LCD_START_LINE4
#define LCD_START_LINE4  0x54     /**< DDRAM address of first char of line 4 */
#endif
#ifndef LCD_WRAP_LINES
#define LCD_WRAP_LINES      0     /**< 0: no wrap, 1: wrap at end of visibile line */
#endif

I'm not sure how to configure those lines for a 20x4 LCD.

I already tried to look for the addresses in the HD44780 datasheet but I can only find reference to 16x2 LCD addresses as it's stated in this document at page 12.

 

I hope I provided all information needed!

 

 

Edited;

Is it like this:

#ifndef LCD_LINES
#define LCD_LINES           4     /**< number of visible lines of the display */
#endif
#ifndef LCD_DISP_LENGTH
#define LCD_DISP_LENGTH    20     /**< visibles characters per line of the display */
#endif
#ifndef LCD_LINE_LENGTH
#define LCD_LINE_LENGTH  0x40     /**< internal line length of the display    */
#endif
#ifndef LCD_START_LINE1
#define LCD_START_LINE1  0x00     /**< DDRAM address of first char of line 1 */
#endif
#ifndef LCD_START_LINE2
#define LCD_START_LINE2  0x28     /**< DDRAM address of first char of line 2 */
#endif
#ifndef LCD_START_LINE3
#define LCD_START_LINE3  0x14     /**< DDRAM address of first char of line 3 */
#endif
#ifndef LCD_START_LINE4
#define LCD_START_LINE4  0x3C     /**< DDRAM address of first char of line 4 */
#endif
#ifndef LCD_WRAP_LINES
#define LCD_WRAP_LINES      0     /**< 0: no wrap, 1: wrap at end of visibile line */
#endif

 

Edit 2;

This topic has a solution.
Last Edited: Fri. Jul 21, 2017 - 09:22 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A pretty easy way to debug ram locations is to write a big continuous string of data to the display.

A letter followed by 3 digits is easily recognisable and debuggable.

A000A001A002A003A004...

You will overflow the whole data buffer and it will wrap around so when you do not write too fast (10Hz or so) you can even determine approximate addresses from the order in which you see your display filled with data.

 

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

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

For a standard 4x20 LCD in the .h file modify these two lines:


/**
 *  @name  Definitions for Display Size
 *  Change these definitions to adapt setting to your display
 */
#define LCD_LINES           2     /**< number of visible lines of the display */
#define LCD_DISP_LENGTH    16     /**< visibles characters per line of the display */

 

To this:

 


/**
 *  @name  Definitions for Display Size
 *  Change these definitions to adapt setting to your display
 */
#define LCD_LINES           4     /**< number of visible lines of the display */
#define LCD_DISP_LENGTH    20     /**< visibles characters per line of the display */

 

 

And also in the .h  file these lines here:

#define LCD_PORT         PORTA        /**< port for the LCD lines   */
#define LCD_DATA0_PORT   LCD_PORT     /**< port for 4bit data bit 0 */
#define LCD_DATA1_PORT   LCD_PORT     /**< port for 4bit data bit 1 */
#define LCD_DATA2_PORT   LCD_PORT     /**< port for 4bit data bit 2 */
#define LCD_DATA3_PORT   LCD_PORT     /**< port for 4bit data bit 3 */
#define LCD_DATA0_PIN    0            /**< pin for 4bit data bit 0  */
#define LCD_DATA1_PIN    1            /**< pin for 4bit data bit 1  */
#define LCD_DATA2_PIN    2            /**< pin for 4bit data bit 2  */
#define LCD_DATA3_PIN    3            /**< pin for 4bit data bit 3  */
#define LCD_RS_PORT      LCD_PORT     /**< port for RS line         */
#define LCD_RS_PIN       4            /**< pin  for RS line         */
#define LCD_RW_PORT      LCD_PORT     /**< port for RW line         */
#define LCD_RW_PIN       5            /**< pin  for RW line         */
#define LCD_E_PORT       LCD_PORT     /**< port for Enable line     */
#define LCD_E_PIN        6            /**< pin  for Enable line     */

is where you set the port you will connect the LCD to, and what port pins are to do what.

 

All the other addressing and such you do not need to do.  as long as you haven't touched anything the library does it for you.

 

Jim

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

Last Edited: Fri. Jul 21, 2017 - 12:08 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, I recall now somethings.

 

But I find it weird that the default lcd.h has a PORTA defined to LCD_PORT and AtMega328PU does not have a PORTA. I'll assume that lcd.h file was made for some other ucontroller that possibly had a PORTA. I'll change it to one of B, C, or D ports!

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

I'm confused right now! I need to connect 7 wires from LCD. PORTB has pin PB6 and PB7 reserved to XTAL and this port goes from PB0 to PB7. PORTC has PB6 reserved to reset needed to load firmware onto the ucontroller and this port goes fromPC0 to PC6. PORTD has PD0 and PD1 reserved to Rx and Tx and this port goes from PD0 to PD7. So where am I going to connect 7 wires from the LCD?

 

 

Edited;

I got it... Ignore this!

Last Edited: Fri. Jul 21, 2017 - 06:57 PM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:
But I find it weird that the default lcd.h has a PORTA defined to LCD_PORT and AtMega328PU does not have a PORTA.

 

So YOU CHANGE the port to whatever you want.  THe library does not care.

 

PsySc0rpi0n wrote:
So where am I going to connect 7 wires from the LCD?

Easy.  Break it up between two ports.

 

Look:

#define LCD_PORT         PORTA        /**< port for the LCD lines   */
#define LCD_DATA0_PORT   LCD_PORT     /**< port for 4bit data bit 0 */
#define LCD_DATA1_PORT   LCD_PORT     /**< port for 4bit data bit 1 */
#define LCD_DATA2_PORT   LCD_PORT     /**< port for 4bit data bit 2 */
#define LCD_DATA3_PORT   LCD_PORT     /**< port for 4bit data bit 3 */

and:

#define LCD_DATA0_PIN    0            /**< pin for 4bit data bit 0  */
#define LCD_DATA1_PIN    1            /**< pin for 4bit data bit 1  */
#define LCD_DATA2_PIN    2            /**< pin for 4bit data bit 2  */
#define LCD_DATA3_PIN    3            /**< pin for 4bit data bit 3  */
#define LCD_RS_PORT      LCD_PORT     /**< port for RS line         */
#define LCD_RS_PIN       4            /**< pin  for RS line         */
#define LCD_RW_PORT      LCD_PORT     /**< port for RW line         */
#define LCD_RW_PIN       5            /**< pin  for RW line         */
#define LCD_E_PORT       LCD_PORT     /**< port for Enable line     */
#define LCD_E_PIN        6            /**< pin  for Enable line     */

 

If you simply change the first part:

#define LCD_PORT         PORTB        /**< port for the LCD lines   */
#define LCD_DATA0_PORT   PORTC    /**< port for 4bit data bit 0 */
#define LCD_DATA1_PORT   PORTC     /**< port for 4bit data bit 1 */
#define LCD_DATA2_PORT   PORTC    /**< port for 4bit data bit 2 */
#define LCD_DATA3_PORT   PORTC     /**< port for 4bit data bit 3 */

 

And this to the second part:

#define LCD_DATA0_PIN    0            /**< pin for 4bit data bit 0  */
#define LCD_DATA1_PIN    1            /**< pin for 4bit data bit 1  */
#define LCD_DATA2_PIN    2            /**< pin for 4bit data bit 2  */
#define LCD_DATA3_PIN    3            /**< pin for 4bit data bit 3  */
#define LCD_RS_PORT      LCD_PORT     /**< port for RS line         */
#define LCD_RS_PIN       0            /**< pin  for RS line         */
#define LCD_RW_PORT      LCD_PORT     /**< port for RW line         */
#define LCD_RW_PIN       1            /**< pin  for RW line         */
#define LCD_E_PORT       LCD_PORT     /**< port for Enable line     */
#define LCD_E_PIN        2            /**< pin  for Enable line     */

 

Now the LCD CONTROL lines are on PORTB pins 0, 1, and 2.

 

The LCD DATA lines are on PORTC Pins 0, 1, 2, and 3.

 

Jim

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

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

@jgmdesign, done! Now I just need to recall the 3 commands to compile, convert to intel hex and upload the code to the ucontroller! Anyone has those commands? I deleted a file accidentally where I kept the commands!

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

PsySc0rpi0n wrote:
Anyone has those commands?

Not unless you tell us

- What toolchain (i.e compiler etc) you are using, and

- What operating system you are using, and

- What programmer you have, and

- What programming software you used the last time (if possible to recall)

 

Without any of that information there will be hundreds of combinations of the above things. We can't list them all..

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

PsySc0rpi0n wrote:

@jgmdesign, done! Now I just need to recall the 3 commands to compile, convert to intel hex and upload the code to the ucontroller! Anyone has those commands? I deleted a file accidentally where I kept the commands!

 

In the beginning,  God invented AVR Studio 4 (AS4) and it was good.

We now have Atmel Studio 7.0 (AS7) and it works too.

 

If you are on Linux,  there is probably a program called MFile that will create an appropriate Makefile for your project.

 

Hand-crafting commands is unwise.    Let the IDE or MFile do this for you.

 

David.

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

In the beginning,  God invented AVR Studio 4 (AS4) and it was good.

You young kids!! I started with AS3 which was just out and I still have AS2.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

@JohanEkdahl, I'm sorry I missed that information!

 

I'm using Debian 9, 64bit and AVR Tool Chain, avr-gcc-4.9.2, avrdude 6.3! I don't remember very well what "programmer" was since I make a mess with those names in my mind because I also have used Arduino in the past. I already have to use Arduino to burn, I think, a bootloader to my AtMega328's and I remember I used something called a programmer like ISP or so! But I also remember to see something like stk500 when loading firmware into AtMega328P, so I'm a little confused!

 

Edited;

Ok, I break the first step... Get along with avr-gcc-4.9.2 first option.

I was using:

 

avr-gcc-4.9.2 -mmcpu=atmega328p lcd.c -o lcd.o

when I should use

avr-gcc-4.9.2 -mmcu=atmega328p lcd.c -o lcd.o

 

but now I get the following errors that I need help with:

 

~/avr_projects/Peter_Fleury_LCD$ avr-gcc-4.9.2 -mmcu=atmega328p lcd.c -o lcd.o
In file included from lcd.c:15:0:
/usr/lib/avr/include/util/delay.h:95:3: warning: #warning "Compiler optimizations disabled; functions from <util/delay.h> won't work as designed" [-Wcpp]
 # warning "Compiler optimizations disabled; functions from <util/delay.h> won't work as designed"
   ^
/tmp/ccd1kNY1.o: In function `main':
lcd.c:(.text+0x18c): undefined reference to `lcd_init'
lcd.c:(.text+0x190): undefined reference to `lcd_clrscr'
lcd.c:(.text+0x198): undefined reference to `lcd_puts'
lcd.c:(.text+0x1a0): undefined reference to `lcd_puts'
lcd.c:(.text+0x1a8): undefined reference to `lcd_gotoxy'
lcd.c:(.text+0x1ae): undefined reference to `lcd_putc'
lcd.c:(.text+0x1b8): undefined reference to `lcd_command'
lcd.c:(.text+0x1c0): undefined reference to `lcd_puts'
lcd.c:(.text+0x1c8): undefined reference to `lcd_clrscr'
lcd.c:(.text+0x1d0): undefined reference to `lcd_puts_p'
lcd.c:(.text+0x1d8): undefined reference to `lcd_puts_p'
lcd.c:(.text+0x1de): undefined reference to `lcd_command'
lcd.c:(.text+0x1e8): undefined reference to `lcd_command'
lcd.c:(.text+0x1ec): undefined reference to `lcd_clrscr'
lcd.c:(.text+0x208): undefined reference to `lcd_puts'
lcd.c:(.text+0x210): undefined reference to `lcd_clrscr'
lcd.c:(.text+0x218): undefined reference to `lcd_puts'
lcd.c:(.text+0x21e): undefined reference to `lcd_command'
lcd.c:(.text+0x240): undefined reference to `lcd_data'
lcd.c:(.text+0x254): undefined reference to `lcd_gotoxy'
lcd.c:(.text+0x25a): undefined reference to `lcd_putc'
lcd.c:(.text+0x260): undefined reference to `lcd_putc'
collect2: error: ld returned 1 exit status

The only change I made to lcd.c Peter Fleury file was to add

#define F_CPU 16000000UL

before line

#include <util/delay.h>

like this:

/*************************************************************************
Title:         Testing output to a HD44780 based LCD display.
Author:        Peter Fleury  <pfleury@gmx.ch>  http://tinyurl.com/peterfleury
Modded Author: PsySc0rpi0n <psysc0rpi0n@gmail.com>
File:          $Id: test_lcd.c,v 1.8 2015/01/31 18:04:08 peter Exp $
Software:      AVR-GCC 4.x
Hardware:      HD44780 compatible LCD text display
               AVR with external SRAM interface if memory-mapped LCD interface is used
               any AVR with 7 free I/O pins if 4-bit IO port mode is used
**************************************************************************/
#include <stdlib.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#define F_CPU 16000000UL
#include <util/delay.h>
#include "lcd.h"

 

Last Edited: Fri. Jul 21, 2017 - 10:48 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I got it again... I was missing lcd.c content and pasting test_lcd.c content into lcd.c...

 

Edited;

 

Well the errors still there! :(

Last Edited: Sat. Jul 22, 2017 - 08:39 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You need to read up on the compiler command line, and how to compile multiple file projects.

 

In order to get the warning about optimization out of the way, specify an optimization level like -O3 or (preferrably?) -Os.

 

For the long list of "undefined reference", there is a "usual suspect" but I can not confirm this. It seems you have not posted the command you use to compile main.c. Show the command you use to compile main.c!

 

(I am also missing a "undefined reference to main" error that is to be expected using the compile command for lcd.c that you have. If in doubt, rather post a little to much of build output than risk cutting away important info!)

 


 

There are a lot more required or recommended options to give at the gcc command line. I suggest you avoid doing this all by hand  and instead use GNU Make and a makefile to get your build done. Now, makefiles are not so easy to write for a beginner, but luckily there is a utility called Mfile that will help you with this. Get it here: http://www.sax.de/~joerg/mfile/

 

Whaqt you do, is you start this utility and then use some menu options to tell what source files you have, what optimization level you what etc and then save the resulting makefile to the same directory where you have your source files. Then, on a command line, in that directory, you simply type "make" and the build will happen. If your code is not correct then you will still get build errors, but not due to a faulty build process. AND that makefile will create the hex file for you too! 

 

I have attached a makefile for a project with two source files named main.c and lcd.c, for an ATmega328, optimization level -Os. You might be able to use that..

Attachment(s): 

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Sat. Jul 22, 2017 - 08:55 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:
I got it again... I was missing lcd.c content and pasting test_lcd.c content into lcd.c...   Edited;   Well the errors still there! :(

You're very confusing now.

 

Do this:

1. Clear/reset your terminal window.

2. Issue the commands you use to compile your files.

3. Copy the commands and their output, the complet ecommands and the entire output, and pate it in a post here.

 


 

The normal way of building a project with multiple source files is to compile each source file separately, and only compile it (you need to be specific about that, or else the cimpiler will try to compile and link in one go). After that you issue a final command to link together the results of the earlier compilations. Something like this:

 

# Compiling...

avr-gcc -c lcd.c -o lcd.o
avr-gcc -c main.c -o main.o

# Linking...
avr-gcc main.o lcd.o -o theProgram.elf

Note that the above is not complete, missing a lot of options (e.g. optimization) etc. It is only an illustration of the "flow of the process". After the above you need to make a .hex file based on he .elf file. For this you use the objcopy command, something like this (again an example, not complete)

 

objcopy -o ihex -R theProgram.elf theProgram.hex

So you see this is not a trivial thing, with just a few short'n'simple commands involved.

 

really recommend the MFile utility to get you started. It will let you focus on the code rather than fighting with poor build processes.

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Ok, I know I can get lost very easily. Anyway, I used the avr-libc default Makefile from here and looks like it's working!

 

So, now I just need to recall/find/google the correct avrdude command to send the firmware to the AtMega328PU ucontroller and check if the code is working!

 

The Makefile I used was this:

 

PRG            = test_lcd
OBJ            = test_lcd.o lcd.c
#MCU_TARGET     = at90s2313
#MCU_TARGET     = at90s2333
#MCU_TARGET     = at90s4414
#MCU_TARGET     = at90s4433
#MCU_TARGET     = at90s4434
#MCU_TARGET     = at90s8515
#MCU_TARGET     = at90s8535
#MCU_TARGET     = atmega128
#MCU_TARGET     = atmega1280
#MCU_TARGET     = atmega1281
#MCU_TARGET     = atmega1284p
#MCU_TARGET     = atmega16
#MCU_TARGET     = atmega163
#MCU_TARGET     = atmega164p
#MCU_TARGET     = atmega165
#MCU_TARGET     = atmega165p
#MCU_TARGET     = atmega168
#MCU_TARGET     = atmega169
#MCU_TARGET     = atmega169p
#MCU_TARGET     = atmega2560
#MCU_TARGET     = atmega2561
#MCU_TARGET     = atmega32
#MCU_TARGET     = atmega324p
#MCU_TARGET     = atmega325
#MCU_TARGET     = atmega3250
#MCU_TARGET     = atmega329
#MCU_TARGET     = atmega3290
#MCU_TARGET     = atmega32u4
#MCU_TARGET     = atmega48
#MCU_TARGET     = atmega64
#MCU_TARGET     = atmega640
#MCU_TARGET     = atmega644
#MCU_TARGET     = atmega644p
#MCU_TARGET     = atmega645
#MCU_TARGET     = atmega6450
#MCU_TARGET     = atmega649
#MCU_TARGET     = atmega6490
#MCU_TARGET     = atmega8
#MCU_TARGET     = atmega8515
#MCU_TARGET     = atmega8535
#MCU_TARGET     = atmega88
#MCU_TARGET     = attiny2313
#MCU_TARGET     = attiny24
#MCU_TARGET     = attiny25
#MCU_TARGET     = attiny26
#MCU_TARGET     = attiny261
#MCU_TARGET     = attiny44
#MCU_TARGET     = attiny45
#MCU_TARGET     = attiny461
#MCU_TARGET     = attiny84
#MCU_TARGET     = attiny85
#MCU_TARGET     = attiny861
MCU_TARGET		= atmega328p

OPTIMIZE       = -O2
DEFS           =
LIBS           =
# You should not have to change anything below here.
CC             = avr-gcc
# Override is only needed by avr-lib build system.
override CFLAGS        = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFS) -DF_CPU=16000000UL
override LDFLAGS       = -Wl,-Map,$(PRG).map
OBJCOPY        = avr-objcopy
OBJDUMP        = avr-objdump
all: $(PRG).elf lst text eeprom
$(PRG).elf: $(OBJ)
	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
# dependency:
lcd.o: lcd.c lcd.h
test_lcd.o: test_lcd.c lcd.h
clean:
	rm -rf *.o $(PRG).elf *.eps *.png *.pdf *.bak
	rm -rf *.lst *.map $(EXTRA_CLEAN_FILES)
lst:  $(PRG).lst
%.lst: %.elf
	$(OBJDUMP) -h -S $< > $@
# Rules for building the .text rom images
text: hex bin srec
hex:  $(PRG).hex
bin:  $(PRG).bin
srec: $(PRG).srec
%.hex: %.elf
	$(OBJCOPY) -j .text -j .data -O ihex $< $@
%.srec: %.elf
	$(OBJCOPY) -j .text -j .data -O srec $< $@
%.bin: %.elf
	$(OBJCOPY) -j .text -j .data -O binary $< $@
# Rules for building the .eeprom rom images
eeprom: ehex ebin esrec
ehex:  $(PRG)_eeprom.hex
ebin:  $(PRG)_eeprom.bin
esrec: $(PRG)_eeprom.srec
%_eeprom.hex: %.elf
	$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@ \
	|| { echo empty $@ not generated; exit 0; }
%_eeprom.srec: %.elf
	$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O srec $< $@ \
	|| { echo empty $@ not generated; exit 0; }
%_eeprom.bin: %.elf
	$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O binary $< $@ \
	|| { echo empty $@ not generated; exit 0; }
# Every thing below here is used by avr-libc's build system and can be ignored
# by the casual user.
FIG2DEV                 = fig2dev
EXTRA_CLEAN_FILES       = *.hex *.bin *.srec
dox: eps png pdf
eps: $(PRG).eps
png: $(PRG).png
pdf: $(PRG).pdf
%.eps: %.fig
	$(FIG2DEV) -L eps $< $@
%.pdf: %.fig
	$(FIG2DEV) -L pdf $< $@
%.png: %.fig
	$(FIG2DEV) -L png $< $@

 

Now, I'll try to figure out the avrdude command!

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

I'm using the following command:

avrdude -c stk500v2 -p m328p -P /dev/ttyUSB0 -U flash:w:test_lcd.hex:i -vvvv

but it can't contact the uController!

 

I get this:

 

avrdude: Version 6.3, compiled on Oct  2 2016 at 23:15:04
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "/usr/local/etc/avrdude.conf"
         User configuration file is "/home/narayan/.avrduderc"
         User configuration file does not exist or is not a regular file, skipping

         Using Port                    : /dev/ttyUSB0
         Using Programmer              : stk500v2
avrdude: Send: . [1b] . [01] . [00] . [01] . [0e] . [01] . [14]
avrdude: ser_recv(): programmer is not responding
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: Send: . [1b] . [01] . [00] . [01] . [0e] . [01] . [14]
avrdude: ser_recv(): programmer is not responding
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: Send: . [1b] . [01] . [00] . [01] . [0e] . [01] . [14]
avrdude: ser_recv(): programmer is not responding
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: Send: . [1b] . [01] . [00] . [01] . [0e] . [01] . [14]
avrdude: ser_recv(): programmer is not responding
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: Send: . [1b] . [01] . [00] . [01] . [0e] . [01] . [14]
avrdude: ser_recv(): programmer is not responding
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: Send: . [1b] . [01] . [00] . [01] . [0e] . [01] . [14]
avrdude: ser_recv(): programmer is not responding
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: stk500v2_getsync(): timeout communicating with programmer
         AVR Part                      : ATmega328P
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PC2
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

         Programmer Type : STK500V2
         Description     : Atmel STK500 Version 2.x firmware
         Programmer Model: Unknown
avrdude: Send: . [1b] . [01] . [00] . [02] . [0e] . [03] . [90] . [85]
avrdude: ser_recv(): programmer is not responding
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: Send: . [1b] . [01] . [00] . [01] . [0e] . [01] . [14]
avrdude: ser_recv(): programmer is not responding
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: Send: . [1b] . [01] . [00] . [01] . [0e] . [01] . [14]
^C

 

Wasn't there an option that would show us the voltage that the uController was at? My scope measures 4.80V from rail-to-rail of my breadboard.

 

 

 

 

 

And this is E pin activity on a reset button push

Last Edited: Sat. Jul 22, 2017 - 07:33 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:
OBJ = test_lcd.o lcd.c

Are you sure?

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

Ok, everything is working now!

It was a bad reset circuit wiring! :(

 

Anyway, I'm now going to try to recall how to use Peter Fleury's libraries! Any questions I have, I'll post them here!

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

Ok, I've sorted everything out electronically speaking!

 

Now I'm just trying to understand how to use Peter's libraries and I'm trying to make a simple raster in the LCD using asteriscs. I'm not sure if "raster" is the best wording choice but I'll explain what I want to do.

 

I'm just trying to print '*'s one by one in each position of the LCD until the LCD is filled with them. Then I clear the screen, and start all over again!

 

But this is what is happening:

Video link

 

Code:

#include <stdlib.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include "lcd.h"

int main(void){
   uint8_t xx = 0, yy = 0;

   lcd_init(LCD_DISP_ON_CURSOR);
   lcd_clrscr();

   for(;;){
      if(xx == 20 && yy == 4){
         lcd_clrscr();
         xx = 0, yy = 0;
      }
      if(xx == 20){
         yy++, xx = 0;
      }
      lcd_gotoxy(xx++, yy);
      lcd_putc('*');
      _delay_ms(125);
   }
}

 

Settings in lcd.h to a 20x4 LCD

#ifndef LCD_LINES
#define LCD_LINES           4     /**< number of visible lines of the display */
#endif
#ifndef LCD_DISP_LENGTH
#define LCD_DISP_LENGTH    20     /**< visibles characters per line of the display */
#endif
#ifndef LCD_LINE_LENGTH
#define LCD_LINE_LENGTH  0x40     /**< internal line length of the display    */
#endif
#ifndef LCD_START_LINE1
#define LCD_START_LINE1  0x00     /**< DDRAM address of first char of line 1 */
#endif
#ifndef LCD_START_LINE2
#define LCD_START_LINE2  0x40     /**< DDRAM address of first char of line 2 */
#endif
#ifndef LCD_START_LINE3
#define LCD_START_LINE3  0x14     /**< DDRAM address of first char of line 3 */
#endif
#ifndef LCD_START_LINE4
#define LCD_START_LINE4  0x54     /**< DDRAM address of first char of line 4 */
#endif
#ifndef LCD_WRAP_LINES
#define LCD_WRAP_LINES      0     /**< 0: no wrap, 1: wrap at end of visibile line */
#endif

 

So, just need help to fix those minor bugs in the video!

Thanks

Last Edited: Tue. Jul 25, 2017 - 09:34 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It is pretty close, isn't it?

 

I'd leave the cursor off in the final animation, but suit yourself.

 

Examine your yy logic.  Don't you want your test when yy == 3 ?

 

Next you can try a simple loop outputting 80 asterisks after a clear screen.  The driver should do the line wrapping for you.

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

theusch wrote:

It is pretty close, isn't it?

 

I'd leave the cursor off in the final animation, but suit yourself.

 

Examine your yy logic.  Don't you want your test when yy == 3 ?

 

Next you can try a simple loop outputting 80 asterisks after a clear screen.  The driver should do the line wrapping for you.

 

 

 

Oh yes... I changed xx == 21 to xx == 20 and forgot to do the same to yy... About the cursor, maybe you're correct too! heheh

Thanks

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

I'm watching that video standing on my head. It hurts.. ;-)

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

JohanEkdahl wrote:

I'm watching that video standing on my head. It hurts.. ;-)

 

I posted the link but it is gone!... Trying again:

 

Video

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

Ok, I'll byte, what are you having issues with understanding Mr. Fleury's code?  It is very well commented right out of the box.

 

JIm

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

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

jgmdesign wrote:

Ok, I'll byte, what are you having issues with understanding Mr. Fleury's code?  It is very well commented right out of the box.

 

JIm

 

I'm still exploring!

 

I have tried to make a raster and it's done!

Now I'm trying to create and use CGRAM Custom chars! I think in Peter's page there is no example on how to use functions or print those custom chars! This is my next task!

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

Just to say that "rasterization" is probably the wrong term when a character LCD rather than a GLCD is being used.

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

PsySc0rpi0n wrote:
I think in Peter's page there is no example on how to use [...]

When you downloaded the "library" from Peters site, it came with an example. Look in test_lcd.c. It defines custom characters and prints.

 

BTW, that test_lcd.c should have been the first program you tried..

 

PsySc0rpi0n wrote:
I think in Peter's page there is no example on how to [...] print those custom chars!

Just print any characer 0 .. 7. E.g.:

lcd_putc(4);  // Prints the fifth character defined in CGRAM

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Thu. Jul 27, 2017 - 10:09 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Every time I read a thread about HD44780 and custom characters my first thought is "did they make a mistake by not selecting a GLCD?" cheeky

 

(that "only 8 definable" is often going to bite one in the posterior!)

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

clawson wrote:

Just to say that "rasterization" is probably the wrong term when a character LCD rather than a GLCD is being used.

 

I just used that word because it is a simple '*' filling the LCD one at a time... Anyway, I got your point!

 

JohanEkdahl wrote:

PsySc0rpi0n wrote:

I think in Peter's page there is no example on how to use [...]

 

When you downloaded the "library" from Peters site, it came with an example. Look in test_lcd.c. It defines custom characters and prints.

 

BTW, that test_lcd.c should have been the first program you tried..

 

 

PsySc0rpi0n wrote:

I think in Peter's page there is no example on how to [...] print those custom chars!

 

Just print any characer 0 .. 7. E.g.:

lcd_putc(4);  // Prints the fifth character defined in CGRAM

 

There is something I'm not familiar with in Peter's code

 

How do we store the custom chars in CGRAM?

I know it's done by these lines, but don't know how!

 

lcd_command(_BV(LCD_CGRAM));  /* set CG RAM start address 0 */
      for(i=0; i<16; i++){
         lcd_data(pgm_read_byte_near(&copyRightChar[i]));
      }

 

I don't know exactly what that pgm_.... function is doing and how it stores the chars in CGRAM.

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

There is something I'm not familiar with in Peter's code

 

How do we store the custom chars in CGRAM?

I know it's done by these lines, but don't know how!

 

lcd_command(_BV(LCD_CGRAM));  /* set CG RAM start address 0 */
      for(i=0; i<16; i++){
         lcd_data(pgm_read_byte_near(&copyRightChar[i]));
      }

 

I don't know exactly what that pgm_.... function is doing and how it stores the chars in CGRAM.

 

You need to take this on in a structured way. What are the unknowns? Well, probably..

 

First:  The pgm_read_byte_near( ...) function. Do an internet search for that and you will soon find that it is a function to read data out of flash (rather than RAM) of the AVR. You will fins that it is a part of the avrlibc library - the support library for your compiler. You can the go to the avrlibc documentation, and you will find more info on it here: http://www.nongnu.org/avr-libc/u...

 

Second: A parameter to pgm_read_byte_near() is 

&copyRightChar[i]

so look in the source code for where copyRightChar is defined. It looks like this:

 

static const PROGMEM unsigned char copyRightChar[] =
{
	0x07, 0x08, 0x13, 0x14, 0x14, 0x13, 0x08, 0x07,
	0x00, 0x10, 0x08, 0x08, 0x08, 0x08, 0x10, 0x00
};

Once again, PROGMEM is something that helps to store data in flash rather than RAM, so again look in the avrlibc documentation linked to above.

 

Now for the data. Let's translate those values in there to binary. 0x07 is binary 00000111, 0x08 is 00001000 and so on. Taking the whole first line (forming one user defined character) and placing each binary byte on its own line, we have

00000111
00001000
00010011
00010100
00010100
00010011
00001000
00000111

Doesn't make much sense yet. Let's continue! Well place the bytes of the second line to the right of the bytes of the first line:

 

00000111 00000000
00001000 00001010
00010011 00001000
00010100 00001000
00010100 00001000
00010011 00001000
00001000 00001010
00000111 00000000

A little hard to read. Let's reform that, substituting  * where we have a 1 and a blank where we have a 0.

     ***         
    *       *  
   *  **     *   
   * *       *   
   * *       *   
   *  **     *   
    *       *    
     ***         

Do you see a, somewhat ill formed, copyright sign ( © )? The space column between th left and right part is somewhat disturbing. Peter has chosen to use two character cells for a copyright sign and there will always be a blank column between two character cells on an 44780-base LCD display. He could have opted for a copyright sign taking up only one character cell, e.g. 

 

  ****
 *    *
*  **  *
* *    *
* *    *
*  **  *
 *    *
  ****

but that is not what he is doing, so to stay with his example let's leave that one-character-cell-copyright-sign for now.

 

So, the big picture is: To define a custom character you set up a "bitmap" defining which pixels in the charater cell should be set and which should be clear.

 

Peter has opted to store this in flash, which complicates his example a bit, but do understand that this has nothing do do with the defining of a custom character as such. He's just preserving precious RAM, sacrificing less precious flash memory.

 

So the loop  you pointed out reads the bitmap, byte by byte, out of flash and calls lcd_data() with the byte ass parameter. The lcd_data() function is a function in Peters librry so you can go analyze it on your own.

 

Also note that the call to 

lcd_command(_BV(LCD_CGRAM));  /* set CG RAM start address 0 */

says that what follows is the first spacial character of the eight that the 44780 can handle. Remember that each character is defined by 8 bytes. This means that the second special character is defined in the eight bytes starting at _BV(LCD_CGRAM) + 8. In general, to define special character n  you need to 

lcd_command(_BV(LCD_CGRAM) + n * 8);  /* set CG RAM to define spacial character n */

 

You'll have enough to investigate now with this help, I believe. Remember to try to sort out any detail you don't know about by searching, reading documentation  etc. Then try to put it together to see the bigger picture.

 

This document is invaluable for understanding the controller chip on your display: https://www.sparkfun.com/datashe... . Download it and keep it close to you when working with the 44780. It is technically "dense" but holds information about how defining a special character works, from the perspective of the 44780 LCD controller.

 

If you want to get rid of the complication of PROGMEM and pgm_read_byte... to begin with, change Peters example so that you have

 

static const unsigned char copyRightChar[] = // "PROGMEM" removed
{
	0x07, 0x08, 0x13, 0x14, 0x14, 0x13, 0x08, 0x07,
	0x00, 0x10, 0x08, 0x08, 0x08, 0x08, 0x10, 0x00
};



    .
    .
    .
    
       lcd_command(_BV(LCD_CGRAM));
       for(i=0; i<16; i++)
       {
           lcd_data(&copyRightChar[i]);   // pgm_read_byte_near( ... ) removed
       }

 

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Thank you a lot for the thorough explanation.

 

I know about the custom chars generation. My questions were about how to store each custom char in CGRAM and then how to print them on the LCD! Which commands do we need to use to accomplish these two tasks!

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

His manual:

 

http://homepage.hispeed.ch/peter...

 

says you send commands to the LCD with lcd_command() and that there is LCD_CGRAM defined to set the address for writing to CG locations. In fact that is exactly what Johan showed above:

lcd_command(_BV(LCD_CGRAM));  /* set CG RAM start address 0 */
      for(i=0; i<16; i++){
         lcd_data(pgm_read_byte_near(&copyRightChar[i]));
      }

So you start by issuing the LCD_CGRAM command (with optional offset if you aren't going to set all characters from address 0) then you keep calling lcd_data() to send the bytes that define the characters.

 

The characters you define are 0 .. 7. So just as you might use lcd_putc(0x41) or lcd_putc('A') to print an 'A' you use lcd_putc(3) to print the 4th user defined character.

 

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

PsySc0rpi0n wrote:
My questions were about how to store each custom char in CGRAM and then how to print them on the LCD! Which commands do we need to use to accomplish these two tasks!

Should I give up? Re storing in CGRAM, this is exactly what I pointed to in Peters test program. It does exactly that.

 

To be explicit, this: 

lcd_command(_BV(LCD_CGRAM));  /* set CG RAM start address 0 */
      for(i=0; i<16; i++){
         lcd_data(pgm_read_byte_near(&copyRightChar[i]));
      }

Re how to then print them this is also done in Peters test program:

 

       /* display user defined (c), built using two user defined chars */
       lcd_putc(0);
       lcd_putc(1);

I can't help to think that the comment sort of reveals that this  is the place where the characters are printed out..

 

Suggest you read through the whole example program. It's not more than 167 lines. Then read it again..

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Ok guys... I read it and tried it and it's not working!

 

This is what I have!

#include <stdlib.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include "lcd.h"

int main(void){
   const unsigned char customChar[8] = {
      0x0F,
	   0x10,
	   0x0A,
	   0x0F,
	   0x0A,
	   0x08,
	   0x10,
	   0x0F
   };

   lcd_init(LCD_DISP_ON);
   lcd_clrscr();

   lcd_command(_BV(LCD_CGRAM));  /* set CG RAM start address 0 */
   for(int i = 0; i < 8; i++){
      lcd_data(pgm_read_byte_near(&customChar[i]));
   }

   for(;;){
      lcd_gotoxy(0, 9);
      lcd_putc(0);
      _delay_ms(500);
   }
}

I used Peter's functions and only changed the first for loop exit condition from "i < 16" to "i < 8".

 

Then used the second loop just in the same way. Tried to set the position where I wanted to print the char and then I tried to print customChar at position 0 of CGRAM... It just printed a filled char in first position of last line of LCD, like in (0, 3) or column 0, line 3. So, the code is not working and I tried to the just like what is in Peter example!

 

 

Edited;

 

I spotted an error that is the coordinate order! It should be 9, 0 instead! But I didn't want to use that PROGMEM and that weird function and it only works if I use the static const PROGMEM and that weird function!

 

Isn't there any other way?

Last Edited: Fri. Jul 28, 2017 - 07:05 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm not a GCC guru, but what makes you think "const" will put customChar into flash?

 

That was gone into in #30.  Your code managed to combine two approaches.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

As Lee says, your bitmap for the character is not in flash. You removed the PROGMEM as I suggested.

But then you should not try to read the bitmap out of flash!

 

Change

      lcd_data(pgm_read_byte_near(&customChar[i]));

to 

      lcd_data(&customChar[i]);

as I said in #30.

 

Those two changes go together.

EITHER have bitmap in flash (PROGMEM) and read out of flash (pgm_read_byte...),

 OR have bitmap in RAM (no PROGMEM) and read out of RAM (no pgm_read_byte...).

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Fri. Jul 28, 2017 - 07:53 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

One & too many ;-)

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

theusch wrote:

I'm not a GCC guru, but what makes you think "const" will put customChar into flash?

 

That was gone into in #30.  Your code managed to combine two approaches.

 

It doesn't ... It's just in Peter's code!

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

JohanEkdahl wrote:

As Lee says, your bitmap for the character is not in flash. You removed the PROGMEM as I suggested.

But then you should not try to read the bitmap out of flash!

 

Change

      lcd_data(pgm_read_byte_near(&customChar[i]));

to 

      lcd_data(&customChar[i]);

as I said in #30.

 

Those two changes go together.

EITHER have bitmap in flash (PROGMEM) and read out of flash (pgm_read_byte...),

 OR have bitmap in RAM (no PROGMEM) and read out of RAM (no pgm_read_byte...).

 

Ok, going to try! Thanks

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

PsySc0rpi0n wrote:
It doesn't ... It's just in Peter's code!

No, it is not.  And it was completely explained in #30, as well as #36.

 

From "Peter's code":

/*
** constant definitions
*/
static const PROGMEM unsigned char copyRightChar[] =
{
	0x07, 0x08, 0x13, 0x14, 0x14, 0x13, 0x08, 0x07,
	0x00, 0x10, 0x08, 0x08, 0x08, 0x08, 0x10, 0x00
};
...
       /*
        * load two userdefined characters from program memory
        * into LCD controller CG RAM location 0 and 1
        */
       lcd_command(_BV(LCD_CGRAM));  /* set CG RAM start address 0 */
       for(i=0; i<16; i++)
       {
           lcd_data(pgm_read_byte_near(&copyRightChar[i]));
       }

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Ok, I think I have one more question.

 

in lcd.h the following is set:

 

#define LCD_CGRAM             6      /* DB6: set CG RAM address             */

 

I don't understand how this "says" that the custoChar is going to be stored in 1st position of the 8 available in CGRAM.

 

Let's say I want to store 3 customChars. They will be "magically stored in CGRAM. How do I access to one of the 3 customChars? How do I know which customChar is at which position in CGRAM?

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

You will have to stress a bit more and try to understand my ASM code wink this is from an old project for the music store HMV (RIP)

 

These are the 8 special graphics, at this stage they are just flash data

 

cg_codes:
;0x00 or 0x08
.db	0,0,0,7,5,6,5,0		;"Repeat" graphic

;0x01 or 0x09
.db	16,24,28,30,28,24,16,0	;"Play" graphic

;0x02 or 0x0a
.db	28,16,28,7,29,6,5,0	;"Shuffle" + "Repeat" graphic

;0x03 or 0x0b
.db	27,27,27,27,27,27,27,0	;"Pause" graphic

;0x04 or 0x0c
.db	28,16,24,23,29,7,1,0	;"Eq" graphic

;0x05 or 0x0d
.db	31,31,31,31,31,31,31,0	;"Stop" graphic

;0x06 or 0x0e
.db	0x01,0x03,0x07,0x0f,0x07,0x03,0x01,0x00	;< Reverse graphic

;07 or 0x0f
.db	0,0,0,7,5,6,5,0		;"Repeat" graphic

during the initialization  that data is copied to the LCD cg ram location using the control write command with a loop of 8 counts.

 

To display the corresponding graphic at run time you call the print routine with the code (say 0x05 for Stop graphic) instead of say A, B etc.

 

Sorry no C code that I can remember, maybe I have one but don't know where.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

Last Edited: Fri. Jul 28, 2017 - 10:13 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No problem... I got the first part! I understand your ASM code... That's just defining the custom chars to create icons, so to speak...

 

What I didn't understood an dnow I already understand is that I was used to send a command 0x40 to the LCD when I used an 8051 and I was not understanding why with AVR uC and Peter's libraries, a 6 was being used as the "set CGRAM address" command! Now I understand that, after the _BV macro is executed with that 6, it becomes THE 0x40 I was used to, by means of 1 << 6 == 0x40... That was my struggle. I couldn't understand the reason of that 6.

 

Now I tried the following code but it's not working either, but now I think it's a C code problem and not any configuration:

 

I use ideone as it's a little long code due to the customChars I created!

 

http://ideone.com/zXlRs3

 

Edited;

I found the error and fixed it...

It's working now!

Last Edited: Fri. Jul 28, 2017 - 10:52 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:
Let's say I want to store 3 customChars. They will be "magically stored in CGRAM. How do I access to one of the 3 customChars? How do I know which customChar is at which position in CGRAM?

 

OK it is now clear that you aren't reading what we post, or are reading sloppily. In #30 I wrote

 

Also note that the call to 

lcd_command(_BV(LCD_CGRAM));  /* set CG RAM start address 0 */

says that what follows is the first spacial character of the eight that the 44780 can handle. Remember that each character is defined by 8 bytes. This means that the second special character is defined in the eight bytes starting at _BV(LCD_CGRAM) + 8. In general, to define special character n  you need to 

lcd_command(_BV(LCD_CGRAM) + n * 8);  /* set CG RAM to define spacial character n */

It is not the _BV(LCD_CGRAM) that specifies where in CGRAM the special character ends up. The _BV(LCD_CGRAM) bit tells the LCD that this whole byte is to set the CGRAM address. It is the rest of the byte is the address where the first byte of the bitmap is to end up. And then every write will auto-increment the address into CGRAM with 1. This probably would have been clear if you had opened up the Hitachi PDF that I linked to somewhere above, and read there about CGRAM.

 

To write to the first special character in CGRAM you start at byte 0 in CGRAM. With my general code from above that would be:

lcd_command(_BV(LCD_CGRAM) + 0 * 8);  /* set CG RAM to define spacial character 0 */

and since 0 * 8 == 0, and thus can be left out, Peters code simply says

lcd_command(_BV(LCD_CGRAM));  /* set CG RAM to define spacial character 0 */

 

I believe I have spent at least two hours thinking out and typing posts to you. Typing a lengthy post to try to explain something thoroughly, only to then find it was not read (or read sloppily) is frustrating and feels like a complete waste of time.

 

 I will not spend any more time here until you start reading. (Begin with e.g. browsing the Hitachi document from beginning to end so that you have a hunch about what's in there. Not everything is excellent info, but there are a lot of things are important and useful.)

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

JohanEkdahl you may not believe me, but I read every single line of each post that was posted here! I'm not English and sometimes there are technical terms I'm not absolutely comfortable with. And believe it or not, I have like 12 sites open regarding AVR, avr-gcc, Atmel and some other sites, including HD44780 controller datasheet.

 

This is actually my Google Chrome window. You can see the amount of sites I have been reading and exploring!

google chrome

 

I'm sorry if I'm disappointing and not meeting your expectations! I can't make anyone to help me. But as this forum is the best one related to Atmel and AVR, I'm here asking help! I'll be sad and mad with myself if I get to a point where no one is willing to help me. That will force me to seek help somewhere else that probably won't have the quality and expertise I find here!

 

Regarding your post, specifically this:

 

says that what follows is the first spacial character of the eight that the 44780 can handle.

I have no idea of what a "spacial character" is... And if you meant "special" instead of "spacial", I'm really sorry I didn't noticed that earlier! 

 

And about the way you say I need to follow to write custom chars in CGRAM, I did it without the way you explained, I mean the 

lcd_command(_BV(LCD_CGRAM) + 0 * 8);  /* set CG RAM to define spacial character 0 */

way. I did it differently and I got what I was expecting! Probably it's a dumb way of doing things but it was the way I found!

Last Edited: Fri. Jul 28, 2017 - 11:15 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:
I have no idea of what a "spacial character" is...

 

Same thing as a Custom Character.

 

 

Hmmmm, Maybe you need to take a little break from all of this and go outside for a day or so and catch your breath ! smiley

 

 

 

Jim

 

EDIT:

After I read through the posts in this thread I started wondering about the Custom Character RAM and how its used etc.  I put the following into GOOGLE:

 

creating custom characters for HD44780

 

The return hits were quite helpful.  Since I do not know how your returns may show up here are the first few that came back for me:

 

This is a utility for creating the values for your character

https://omerk.github.io/lcdcharg...

 

Another great utility:

https://www.quinapalus.com/hd447...

 

This link gives a basic, yet decent understanding of how it works:

http://www.circuitvalley.com/201...

 

 

If you put the same search term, but add AVR to teh end of it you get several threads and projects from this site as well....and Johan is ion the thick of those threads too!

 

I may put together a little test program of my own just to see what happens using the threads I posted above.

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

Last Edited: Sat. Jul 29, 2017 - 01:42 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PsySc0rpi0n wrote:
My questions were about how to store each custom char in CGRAM and then how to print them on the LCD! Which commands do we need to use to accomplish these two tasks!

How we do it in the old day

http://www.circuitvalley.com/2012/02/lcd-custom-character-hd44780-16x2.html

 

Sorry for big picture. I don't know how to resize it. Need help!

 

The code

lcdInit();
gotoXy(0,0);
prints("custom font");

//save 7 custom char
lcdCmd(0x40);
lcdData(0xe);
lcdData(0x1b);
lcdData(0x11);
lcdData(0x11);
lcdData(0x11);
lcdData(0x11);
lcdData(0x11);
lcdData(0x1f);

lcdData(0xe);
lcdData(0x1b);
lcdData(0x11);
lcdData(0x11);
lcdData(0x11);
lcdData(0x11);
lcdData(0x1F);
lcdData(0x1f);

lcdData(0xe);
lcdData(0x1b);
lcdData(0x11);
lcdData(0x11);
lcdData(0x11);
lcdData(0x1F);
lcdData(0x1F);
lcdData(0x1f);

lcdData(0xe);
lcdData(0x1b);
lcdData(0x11);
lcdData(0x11);
lcdData(0x1F);
lcdData(0x1F);
lcdData(0x1F);
lcdData(0x1f);

lcdData(0xe);
lcdData(0x1b);
lcdData(0x11);
lcdData(0x1F);
lcdData(0x1F);
lcdData(0x1F);
lcdData(0x1F);
lcdData(0x1f);

lcdData(0xe);
lcdData(0x1b);
lcdData(0x1F);
lcdData(0x1F);
lcdData(0x1F);
lcdData(0x1F);
lcdData(0x1F);
lcdData(0x1f);

lcdData(0xe);
lcdData(0x1F);
lcdData(0x1F);
lcdData(0x1F);
lcdData(0x1F);
lcdData(0x1F);
lcdData(0x1F);
lcdData(0x1f);



//next line
gotoXy(0,1);

//Show custom char
lcdData(0x00);
lcdData(0x01);
lcdData(0x02);
lcdData(0x03);
lcdData(0x04);
lcdData(0x05);
lcdData(0x06);
prints(" BATTERY ");

 

MG

I don't know why I'm still doing this hobby

Last Edited: Sat. Jul 29, 2017 - 03:29 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well instead of me doing work I was supposed to do tonight I instead elected to try making my own custom characters and then load them from FLASH to CGRAM and display them.

 

It was actually easier than I thought.  While I apologise in advance for my crude custom characters, they are what I created using one of the utilities I posted a link to above to get the HEX values.  I then used the tips in the third link, and I also used a command or two from Peter Fleury's Example program.

 

Essentially all I am doing is displaying one line of text in sequence with a 250 millisecond delay in between writes.  THe last line of the screen contains both canned text, and the custom characters.