|
|
View previous topic :: View next topic |
Author |
Message |
hemnath
Joined: 03 Oct 2012 Posts: 242 Location: chennai
|
Graphic LCD |
Posted: Tue Jul 25, 2017 2:36 am |
|
|
I'm using PIC18F2520, Internal oscillator: 1MHz trying to interface with Graphic LCD: EA DOGM128W-6 (128 x 64 DOTS).
Below is the sample program:
Code: | #include "18F2520.h"
#fuses INTRC_IO, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP // Internal oscillator
#use delay(clock=1000000)
const unsigned char numbers_22[10][48] = {
{0x00, 0x00, 0x00, 0xC0, 0xFF, 0x00, 0xF0, 0xFF, 0x03, 0xFC, 0xFF, 0x0F,
0xFC, 0xFF, 0x0F, 0x3E, 0x00, 0x1F, 0x0E, 0x00, 0x1C, 0x0E, 0x00, 0x1C,
0x0E, 0x00, 0x1C, 0x3E, 0x00, 0x1F, 0xFC, 0xFF, 0x0F, 0xFC, 0xFF, 0x0F,
0xF0, 0xFF, 0x03, 0xC0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, 0x00, 0xE0, 0x01, 0x00,
0xE0, 0x01, 0x00, 0xF0, 0x00, 0x00, 0x78, 0x00, 0x00, 0xFC, 0xFF, 0x1F,
0xFE, 0xFF, 0x1F, 0xFE, 0xFF, 0x1F, 0xFE, 0xFF, 0x1F, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 1
{0x00, 0x00, 0x00, 0x60, 0x00, 0x18, 0x78, 0x00, 0x1E, 0x7C, 0x80, 0x1F,
0x7C, 0xC0, 0x1F, 0x1E, 0xE0, 0x1F, 0x0E, 0xF0, 0x1D, 0x0E, 0xF8, 0x1C,
0x0E, 0x7C, 0x1C, 0x1E, 0x3E, 0x1C, 0xFE, 0x1F, 0x1C, 0xFC, 0x0F, 0x1C,
0xF8, 0x07, 0x1C, 0xF0, 0x01, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 2
{0x00, 0x00, 0x00, 0x30, 0x80, 0x01, 0x38, 0x80, 0x07, 0x3C, 0x80, 0x0F,
0x3E, 0x80, 0x0F, 0x1E, 0x00, 0x1E, 0x0E, 0x07, 0x1C, 0x0E, 0x07, 0x1C,
0x9E, 0x07, 0x1C, 0xFE, 0x0F, 0x1E, 0xFC, 0xFF, 0x1F, 0xF8, 0xFD, 0x0F,
0xF0, 0xF8, 0x07, 0x00, 0xF0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 3
{0x00, 0xF8, 0x01, 0x00, 0xFC, 0x01, 0x00, 0xDE, 0x01, 0x00, 0xCF, 0x01,
0x80, 0xC7, 0x01, 0xC0, 0xC3, 0x01, 0xE0, 0xC1, 0x01, 0xF0, 0xC0, 0x01,
0xF8, 0xFF, 0x1F, 0xFC, 0xFF, 0x1F, 0xFE, 0xFF, 0x1F, 0xFE, 0xFF, 0x1F,
0x00, 0xC0, 0x01, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 4
{0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0xF8, 0x07, 0x07, 0xFE, 0x07, 0x0F,
0xFE, 0x07, 0x1F, 0x1E, 0x03, 0x1E, 0x8E, 0x03, 0x1C, 0x8E, 0x03, 0x1C,
0x8E, 0x03, 0x1C, 0x8E, 0x07, 0x1E, 0x8E, 0xFF, 0x1F, 0x0E, 0xFF, 0x0F,
0x0E, 0xFE, 0x07, 0x00, 0xFC, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 5
{0x00, 0x00, 0x00, 0x80, 0xFF, 0x00, 0xF0, 0xFF, 0x03, 0xF8, 0xFF, 0x07,
0xFC, 0xFF, 0x0F, 0x3C, 0x0E, 0x1E, 0x0E, 0x07, 0x1C, 0x0E, 0x07, 0x1C,
0x0E, 0x07, 0x1C, 0x1E, 0x0F, 0x1E, 0x3E, 0xFF, 0x0F, 0x3C, 0xFE, 0x0F,
0x38, 0xFC, 0x07, 0x30, 0xF0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 6
{0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0E, 0x00, 0x1E,
0x0E, 0xE0, 0x1F, 0x0E, 0xFC, 0x1F, 0x0E, 0xFF, 0x1F, 0x8E, 0xFF, 0x01,
0xEE, 0x1F, 0x00, 0xFE, 0x07, 0x00, 0xFE, 0x01, 0x00, 0x7E, 0x00, 0x00,
0x3E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 7
{0x00, 0x00, 0x00, 0xF0, 0xE0, 0x03, 0xF8, 0xF1, 0x07, 0xFC, 0xFB, 0x0F,
0xFE, 0xFF, 0x0F, 0x1E, 0x1F, 0x1E, 0x0E, 0x0E, 0x1C, 0x0E, 0x0E, 0x1C,
0x0E, 0x0E, 0x1C, 0x1E, 0x1F, 0x1E, 0xFE, 0xFF, 0x0F, 0xFC, 0xFB, 0x0F,
0xF8, 0xF1, 0x07, 0xF0, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 8
{0x00, 0x00, 0x00, 0xE0, 0x03, 0x03, 0xF8, 0x0F, 0x0F, 0xFC, 0x1F, 0x0F,
0xFC, 0x3F, 0x1F, 0x1E, 0x3C, 0x1E, 0x0E, 0x38, 0x1C, 0x0E, 0x38, 0x1C,
0x0E, 0x38, 0x1C, 0x1E, 0x1C, 0x0F, 0xFC, 0xFF, 0x0F, 0xF8, 0xFF, 0x07,
0xF0, 0xFF, 0x03, 0xC0, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // 9
};
#include "st7565.h"
#include "st7565-config.h"
#include "st7565.c"
void clear_screen();
void temp_display(char address, char upper_address, char lower_address);
void fill_screen();
char temp_value[8];
unsigned int i = 0;
int16 k;
void main()
{
// setup_oscillator(OSC_32MHZ); //This automatically selects the PLL
setup_comparator (NC_NC_NC_NC); // Disable comparator
output_low(PIN_B3);
glcd_init();
clear_screen();
glcd_command(0xAF); // display ON
glcd_contrast(7, 17);
clear_screen();
fill_screen();
clear_screen();
while(1)
{
for(k = 0; k < 101; k++)
{
sprintf(temp_value, "%5lu", k);
temp_display(0xB2, 0x11, 0x00);
}
}
}
void fill_screen()
{
unsigned int16 p = 0, c = 0;
for(p = 0; p < 8; p++)
{
glcd_command(0xB0 | p);
for(c = 0; c < 129; c++)
{
glcd_command(0x10 | (c & 0xf));
glcd_command(0x00 | ((c >> 4) & 0xf));
glcd_data(0xFF);
}
}
}
// Function to clear the screen
void clear_screen()
{
unsigned int16 p = 0, c = 0, q = 0;
for(p = 0; p < 8; p++)
{
glcd_command(0xB0 | p);
q = 16; // in hex 0x10 - starting address
for(q = 16; q < 25; q++)
{
glcd_command(q);
c = 0;
for(c = 0; c < 16; c++)
{
glcd_command(c);
glcd_data(0x00);
}
}
}
}
void temp_display(char address, char upper_address, char lower_address)
{
int x = 0;
int m = 0;
i = 0;
x = 0;
for(m = 0; m < 3; m++)
{
glcd_command(address+m);
glcd_command(upper_address);
glcd_command(lower_address); // column shift
for(i = 0; temp_value[i] != '\0'; i++)
{
for(x = m; x < 48; x = x+3)
{
glcd_data(numbers_22[temp_value[i]-48][x]);
}
}
}
} |
Display is updating at slower rate. How to display it in faster rate with same oscillator frequency? Please help. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Tue Jul 25, 2017 3:01 am |
|
|
Realistically, increase the oscillator frequency.
Remember there is nothing to stop you changing it 'up' for the graphics, and then back down as soon as you have finished drawing.
Problem is the sheer amount of data involved when dealing with a graphics screen..... |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Tue Jul 25, 2017 4:48 am |
|
|
I have to agree with Mr. T !
Not only will it be very,very slow when using the graphics module but everything else lke serial I/O, SPI, I2C, etc. Even 'math' routines will be painfully slow.
Is there a specific need to run that powerful PIC at only 1MHz?
Jay |
|
|
hemnath
Joined: 03 Oct 2012 Posts: 242 Location: chennai
|
|
Posted: Tue Jul 25, 2017 5:07 am |
|
|
I have to save the current consumption since it is battery operated :(
I thought my logic will be slow in displaying the value since I am not an expert. Need your help guys. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Tue Jul 25, 2017 5:29 am |
|
|
OK, that explains why.....
You should goto Microchip's website, find the 'application notes' section, then download the apnote about 'low power'. It'll be a low numbered apnote, probably 25 years old STILL valid today. They use an 8 pin PIC, A2D and several 'coin cell' batteries for the tests. It's really a 'must read', sorry I don't have my apnotes here,can't give you the #, but it is old....
In it they run PIC at several speeds (sleep, low speed, max,etc) and chart ACTUAL power usage with some surprises !!
Other options for battery powered devices...
Use a bigger battery. I know obvious but today you can get a LOT of power in a small package but you'll ALWAYS get more power in a bigger battery. I use 4 x AA sized batteries (series-parallel for 3V) for remote devices like data loggers.
Add a 'super cap' to your PC project. It'll help smooth the current demands nd prevent brownout resets
Be SURE to set every unused I/O pin to a '1' or '0' to reduce power.
Control the backlight of the LCD with PIC I/O pin.ONLY on when needed.
Also turn off every unused peripheral. ADC, Comp, UART, etc. All these internal peripherals take power, most can be turned off.
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Tue Jul 25, 2017 7:28 am |
|
|
Yes.
The key point in that note, is that it often uses more power to clock slowly!.....
Problem is that current consumption is not linear, and the overheads are there all the time.
So (for instance), you have a job that takes 1 second at 1Mhz, or 1/16th second at 16Mhz. The PIC draws perhaps 1uA at 1Mhz, and 10uA at 16MHz. So the power that has to be delivered to do the job at 16MHz, is 10uA*0.0625*3.4 (assuming 3.4v supply) = 2.125uW. At 1MHz, the same job uses 1*1*3.4 = 3.4uW. So it actually draws 1.6* as much power to do the job at the slower rate!.....
Do the job quickly, and then suspend the PIC as much as possible. Perhaps putting it completely to sleep.
Understand that in most programs the chip spends far more of it's time 'doing nothing' (waiting), than anything else. Because this is the largest part of the processor's time, this is where most power can be saved.... |
|
|
hemnath
Joined: 03 Oct 2012 Posts: 242 Location: chennai
|
|
Posted: Sun Jul 30, 2017 9:44 pm |
|
|
Thanks for your valuable comments. I have increased the clock frequency. Now it displays at faster rate.
Below is the routine I used to display the data. It is working good.
Code: |
const unsigned char negative_22[1][24] = {
0x06, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06,
0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
const unsigned char decimal_point_22[1][24] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E,
0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
const unsigned char space_22[1][48] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
void temp_display(char address, char upper_address, char lower_address)
{
int x = 0, m = 0;
i = 0; x = 0;
for(m = 0; m < 3; m++)
{
glcd_command(address+m);
glcd_command(upper_address);
glcd_command(lower_address); // column shift
for(i = 0; temp_value[i] != '\0'; i++)
{
if(temp_value[i] == '-')
{
for(x = m; x < 24; x = x+3)
{
glcd_data(negative_22[temp_value[i]-45][x]);
}
}
if(temp_value[i] == '.')
{
for(x = m; x < 24; x = x+3)
{
glcd_data(decimal_point_22[temp_value[i]-46][x]);
}
}
else if((temp_value[i] >= '0') && (temp_value[i] <= '9'))
{
for(x = m; x < 48; x = x+3)
{
glcd_data(numbers_22[temp_value[i]-48][x]);
}
}
else
{
for(x = m; x < 48; x = x+3)
{
glcd_data(space_22[temp_value[i]-32][x]);
}
}
}
}
} |
Since I'm not an expert in C language. I think my logic is time consuming since many for loops are used. Can you suggest any ideas? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Mon Jul 31, 2017 4:03 am |
|
|
There are several strange things here:
A two dimensional array, with the first element declared as [1], should only be declared as a one dimensional array.
Why on earth have an array containing just zeros?. This wastes a huge amount of time, when you could get rid of the array accesses completely... |
|
|
hemnath
Joined: 03 Oct 2012 Posts: 242 Location: chennai
|
|
Posted: Wed Aug 02, 2017 2:12 am |
|
|
How to write efficiently. Please help. |
|
|
hemnath
Joined: 03 Oct 2012 Posts: 242 Location: chennai
|
|
Posted: Wed Aug 02, 2017 3:15 am |
|
|
Facing another problem,
When i used to display like this, it works
Code: | sprintf(temp_value, "0 BAR ");
display_data(0xB1, 0x10, 0x0B); |
When I do,
Code: | const char MENU[] = {"0 BAR "};
// main code
sprintf(temp_value, "%c", MENU[0]);
display_data(0xB1, 0x10, 0x0B);
|
Its not working. How to print it? |
|
|
oxo
Joined: 13 Nov 2012 Posts: 219 Location: France
|
|
Posted: Wed Aug 02, 2017 3:39 am |
|
|
Either
Code: | sprintf(temp_value, "%c", MENU); |
or
Code: | sprintf(temp_value, "%c", &MENU[0]); |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Wed Aug 02, 2017 4:30 am |
|
|
If you look he is declaring an array. So need %s not %c as well....
%c means 'print one character'. %s is the command to print a 'string' from a character array.
He also needs the compiler directive 'PASS_STRINGS="IN_RAM"', for this to work. |
|
|
oxo
Joined: 13 Nov 2012 Posts: 219 Location: France
|
|
Posted: Wed Aug 02, 2017 5:02 am |
|
|
Gotta leave something for the student to do ;) |
|
|
hemnath
Joined: 03 Oct 2012 Posts: 242 Location: chennai
|
|
Posted: Wed Aug 02, 2017 9:31 pm |
|
|
I tried as,
Code: | strcpy(temp_value, MENU[0]);
display_data(0xB1, 0x10, 0x0B); |
It works. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Thu Aug 03, 2017 1:23 am |
|
|
First the syntax only works by fluke....
MENU[0] is the physical element at the first location in the array.
&MENU[0] is the address of this element.
MENU (on it's own), is a C short-cut for this address of this element.
MENU[0] only works because CCS internally automatically turns this into the address, if used in a function expecting an address. This has been commented on before but it means it won't work in other languages, and is not guaranteed to work with future versions....
Then why bother?. Use the compiler #device PASS_STRINGS option.
This automatically does the copy from ROM to RAM for you, and does it using only a tiny buffer. Doing it manually means you have to have a large enough buffer for the whole string. Probably OK for now, but 'long term' as you use larger chips and larger strings, not practical....
The only real reason now to use the strcpy syntax, would be if you are using an old compiler (PASS_STRINGS has worked well now for many dozens of versions).
A search here will find the explanation of 'why' you have to do one or the other. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|