Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] 16F887 > MikroC > minus « - » never display on lcd for negative values ...

Status
Not open for further replies.

Eric_O

Advanced Member level 4
Full Member level 1
Joined
May 31, 2020
Messages
107
Helped
0
Reputation
0
Reaction score
0
Trophy points
16
Visit site
Activity points
1,024
Here under a former code obtained here. I insert a new routine for conversion of long to char ... but minus never display on LCD while counting negatives values ...
Some body have an idea ? 🤔
Merci !

Here under my code ...

C:
// LCD module connections :

                                        // VSS (pin  1) -> GND
                                        // VDD (pin  2) -> VCC
                                        // VEE (pin  3) -> middle pin contrast potentiometer
sbit LCD_RS at RB4_bit;                 // RS  (pin  4) -> portB.b4 (pin 37)
// RW not used.                         // RW  (pin  5) -> GND
sbit LCD_EN at RB5_bit;                 // EN  (pin  6) -> portB.b5 (pin 38)
                                        // D0  (pin  7) -> GND
                                        // D1  (pin  8) -> GND
                                        // D2  (pin  9) -> GND
                                        // D3  (pin 10) -> GND
sbit LCD_D4 at RB0_bit;                 // D4  (pin 11) -> portB.b0 (pin 33)
sbit LCD_D5 at RB1_bit;                 // D5  (pin 12) -> portB.b1 (pin 34)
sbit LCD_D6 at RB2_bit;                 // D6  (pin 13) -> portB.b2 (pin 35)
sbit LCD_D7 at RB3_bit;                 // D7  (pin 14) -> portB.b3 (pin 36)
                                        //     (pin 15) -> GND
                                        //     (pin 16) -> GND
sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;
/******************************************************************************/
// Declaration of variables :
float sec;                              // - 1.5 x 10 puissance 45 to + 3.4 x 10 puissance 38
//double sec;                           // - 1.5 x 10 puissance 45 to + 3.4 x 10 puissance 38
//long sec;
char texte[64];                         // 0 to 255
                                        // Pour Essais 16.3, 16.4 :
                                        // Variables ci-dessous sorties du main() pour les déclarer en global.
                                        // Le PIC 16F a moins de mémoire RAM et ROM que le PIC 18F.
unsigned char *pointeur_de_char;        // Déclaration d'un pointeur (*) de char "pointeur_de_char".
//char texte[] = "Counting ...";        // Déclaration d'un tableau "texte" de type char et initialisé avec la chaine de caractères "Counting ..." :
                                        // En n'indiquant aucun chiffre entre les cochets [], le compilateur ajustera automatiquement la taille du
                                        // tableau, et allouera en mémoire RAM, le bon nombre d'éléménts, soit 13 ...
char txt[13];
// Routines :
void LCD_E_pulse(void)
{
LCD_EN = 1;
Delay_us(5);
LCD_EN = 0;
}
void LCD_Write_Cmd(unsigned char octet)                        
LCD_RS = 0;                                                      // Select Command Register.
                                                                  // Send upper nibble.
LCD_D4 = ((octet & 0x10) == 0x10) ? 1 : 0;                       // Si ((octet & 0x10) == 0x10) alors LCD_D4 = 1 sinon = 0.
LCD_D5 = ((octet & 0x20) == 0x20) ? 1 : 0;                       // Si ((octet & 0x20) == 0x20) alors LCD_D5 = 1 sinon = 0.
LCD_D6 = ((octet & 0x40) == 0x40) ? 1 : 0;                       // Si ((octet & 0x40) == 0x40) alors LCD_D6 = 1 sinon = 0.
LCD_D7 = ((octet & 0x80) == 0x80) ? 1 : 0;                       // Si ((octet & 0x80) == 0x80) alors LCD_D7 = 1 sinon = 0.
LCD_E_Pulse();
                                                                  // Send lower nibble.
LCD_D4 = ((octet & 0x01) == 0x01) ? 1 : 0;                       // Si ((octet & 0x01) == 0x01) alors LCD_D4 = 1 sinon = 0.
LCD_D5 = ((octet & 0x02) == 0x02) ? 1 : 0;                       // Si ((octet & 0x02) == 0x02) alors LCD_D5 = 1 sinon = 0.
LCD_D6 = ((octet & 0x04) == 0x04) ? 1 : 0;                       // Si ((octet & 0x04) == 0x04) alors LCD_D6 = 1 sinon = 0.
LCD_D7 = ((octet & 0x08) == 0x08) ? 1 : 0;                       // Si ((octet & 0x08) == 0x08) alors LCD_D7 = 1 sinon = 0.
void LCD_Write_Data(char octet)                                
LCD_RS = 1;                                                      // Select Data Register.
void strConstRamCpy(unsigned char *dest, const code char *source)
while (*source)*dest ++ = *source ++;
*dest = 0;                                                       // Terminateur "0" fin de chaine de caractère.
void LCD_Write_CString_v2(char *msg)
int k;
k = 0;
//while(*(msg) > 0)                                              // FAIL.
while(*(msg + k) > 0)
  LCD_Write_Data(*(msg + k));                                     // Data pointée par (msg + k).
  k++;
  if (k > 15) break;                                              // Si k > 15 sortie de la boucle while ...
void LCD_CString_Position_v2(char row, char col, char *msg)
if (row == 1)
    {
     LCD_Write_Cmd((col & 0x0F)|0x80);                            // Print message on 1st row and desired location.
    }
else if (row == 2)
     LCD_Write_Cmd((col & 0x0F)|0xC0);                            // Print message on 2nd row and desired location.
LCD_Write_CString_v2(msg);                                       // OK.
void print_float_v7(char *flt, long number, char digits)
if (number < 0)
     number = - number;
     *(flt) = 45;                                                 // 45 = '-'
     *(flt + 1) = 32;                                             // 32 = space
if (number >= 0)
     *(flt) = 32;                                                 // 32 = space
  
if (digits == 2)
     *(flt + 2) = number / 1000000 + 48;
     //if (*(flt + 2) == 48) *(flt + 2) = 32;                     // 32 = space
     *(flt + 3) = ((number % 1000000) / 100000) + 48;
     *(flt + 4) = ((number % 100000) / 10000) + 48;
     *(flt + 5) = ((number % 10000) / 1000) + 48;
     *(flt + 6) = ((number % 1000) / 100) + 48;
     *(flt + 7) = ((number % 100) / 10) + 48;
     *(flt + 8) = ((number % 10) / 1) + 48;
     *(flt + 9) = 44;                                             // 44 = ','
     *(flt + 10) = ((number % 100) / 10) + 48;
     *(flt + 11) = (number % 10) + 48;
     *(flt + 12) = 0;
    else
       {
        *(flt + 2) = number / 100000 + 48;
        //if (*(flt + 2) == 48) *(flt + 2) = 32;                  // 32 = space
        *(flt + 3) = ((number % 100000) / 10000) + 48;
        *(flt + 4) = ((number % 10000) / 1000) + 48;
        *(flt + 5) = ((number % 1000) / 100) + 48;
        *(flt + 6) = ((number % 100) / 10) + 48;
        *(flt + 7) = 44;                                          // 44 = ','
        *(flt + 8) = (number % 10) + 48;
        *(flt + 9) = 0;
       }
void LCD_Init_v4 (void)                                        
Delay_ms(15);                                                    // LCD power ON initialization time >= 15 mS.
LCD_Write_Cmd(0x30);                                             // 4 datas bits > Initialization of LCD with nibble method (4 datas bits).
LCD_Write_Cmd(0x02);                                             // 4 datas bits > Initialization of LCD with nibble method (4 datas bits).
LCD_Write_Cmd(0x28);                                             // 4 datas bits > 2 lines display, 5 × 8 dot character font.
LCD_Write_Cmd(0x0C);                                             // 4 datas bits > Display ON. Cursor OFF.
LCD_Write_Cmd(0x06);                                             // 4 datas bits > Auto increment cursor.
LCD_Write_Cmd(0x01);                                             // 4 datas bits > Clear display.
Delay_ms(1);                                                     // Ajustable ... (indispensable, sinon affichage erratique à la mise sous tension)
// Main program :
void main()
ANSEL = 0;                                                // Configure AN pins as digital I/O.
ANSELH = 0;
C1ON_bit = 0;                                             // Disable Comparator 1.
C2ON_bit = 0;                                             // Disable Comparator 2.
PORTB = 0;
TRISB = 0;
PORTC = 0;
TRISC = 0;
// Essai 18.1 : OK
Lcd_Init_v4();                                            // Initialize LCD.
while(1)                                                  // Endless loop.
  unsigned char *pointeur_de_char;                         // Déclaration d'un pointeur (*) de char "pointeur_de_char".
  //char texte[] = "Counting ...";                         // Déclaration d'un tableau "texte" de type char et initialisé avec la chaine de caractères "Counting ..." :
                                                           // En n'indiquant aucun chiffre entre les cochets [], le compilateur ajustera automatiquement la taille du
                                                           // tableau, et allouera en mémoire RAM, le bon nombre d'éléménts, soit 13 ...
  char txt[13];
  pointeur_de_char = &texte[0];                            // pointeur_de_char pointe sur le premier élément du tableau "texte", soit texte[0].
                                                           // Autrement dit, pointeur_de_char contient l'adresse (&) de texte[0].
  //for(sec = -1000000; sec <= 1000000; sec = sec + 0.5)   // sec déclarée en float. OK.
  //for(sec = -8000000; sec <= 8000000; sec = sec + 0.5)   // sec déclarée en float. OK.
  for(sec = -8388607; sec <= 8388607; sec = sec + 0.5)     // sec déclarée en float. OK. Plage maximale : 8388607 = (2 puissance 23) - 1.
  //for(sec = -8388608; sec <= 8388608; sec = sec + 0.5)   // sec déclarée en float. FAIL. 8388608 = 2 puissance 23.
  //for(sec = -9000000; sec <= 9000000; sec = sec + 0.5)   // sec déclarée en float. FAIL.
     {
      portc.b2 = 1;                                        // LED yellow ON.
      strConstRamCpy(pointeur_de_char, "Counting ...");    // OK.
      LCD_CString_Position_v2(1, 0, pointeur_de_char);     // OK. Voir dans void LCD_Write_CString_v2(char *msg), le while(*(msg + k) > 0).
      //LCD_CString_Position_v2(1, 0, "Counting ...");
      //print_float(sec, txt, 8);                          // On LCD : Line 1 : Decounting ... Line 2 : nothing
      //print_float_v2(sec, txt, 8);                       // On LCD : Line 1 : Decounting ... Line 2 : nothing
      //print_float_v3(sec, txt, 8);                       // On LCD : Line 1 : Decounting ... Line 2 : unreadable 16 characters
      //print_float_v4(sec, txt, 8);                       // On LCD : Line 1 : Decounting ... Line 2 : unreadable 16 characters
      //print_float_v5(&txt[0], sec, 2);                   // On LCD : Line 1 : Decounting ... Line 2 : Count from 00.00 to 99.99.
      //print_float_v6(&txt[0], sec, 2);                   //
      print_float_v7(&txt[0], sec, 2);
    
      //LCD_CString_Position_v2(2, 0, txt);                // Write txt in 2nd row, starting at 1st digit.
      LCD_CString_Position_v2(2, 0, &txt[0]);
      LCD_CString_Position_v2(2, 13, "uS");                // Write "uS" in 2nd row, starting at 14th digit
      Delay_us(1);
     }
  portc.b2 = 0;                                            // LED yellow OFF.
  portc.b3 = 1;                                            // LED green ON.
  portc.b4 = 1;                                            // BUZZER ON.
  Delay_ms(5000);
  portc.b3 = 0;                                            // LED green OFF.
  portc.b4 = 0;                                            // BUZZER OFF.

}
 
Last edited by a moderator:

Solution
Hello!

Could you explain what you are trying to do here?

C:
void LCD_Write_Data(char octet)
{
    LCD_RS = 1;                                                                 // Select Data Register.
    // Send upper nibble.
    LCD_D4 = ((octet & 0x10) == 0x10) ? 1 : 0;                                  // Si ((octet & 0x10) == 0x10) alors LCD_D4 = 1 sinon = 0.
    LCD_D5 = ((octet & 0x20) == 0x20) ? 1 : 0;                                  // Si ((octet & 0x20) == 0x20) alors LCD_D5 = 1 sinon = 0.
    LCD_D6 = ((octet & 0x40) == 0x40) ? 1 : 0;                                  // Si ((octet & 0x40) == 0x40) alors LCD_D6 = 1 sinon = 0.
    LCD_D7 = ((octet & 0x80) == 0x80) ? 1 : 0;                                  // Si ((octet &...
Hi,

Please send a new post, because I´m not sure which post you want to refer to.
You may also try to [Edit] the previous post - but there is a timeout for editing.

*****

Inserting code:
1633422108264.png

Simply press the [ CODE ] button. The rest is self-explanatory.

Or read the very detailed PM that I wrote especially for you on Aug 5.

Klaus
 

Hello!

I had a look at your code, and there are many things to be improved.

1. LCD row.
You may consider defining this:
char ROW[] = {0x80, 0xC0};
So if you start numbering your rows at 0, you can do:

Code:
void LCD_CString_Position_v2(char row, char col, char *msg) {
    LCD_Write_Cmd((col & 0x0F)| ROW[row]);    // Print message on 1st row and desired location.
    LCD_Write_CString_v2(msg);                // OK.
}

Advantages:
- You don't need to test if else for rows.
- If you ever use a 4 lines display, you just modify the line:
char row[] = {a, b, c, f}; // a, b, c, d are the codes fro the 4 lines.
And you can use the exact same function.

2. In your print float function.
You have better options:
Use <stdio.h> (but that can be string.h in some environments)
and you end up with
sprintf(flt, "%f", your_float_number) in which case you can even
specify the number of decimals, the length, etc.
Example: sprintf(flt, "%8.3f", your_float_number);

Advantages:
This code has been tested for decades, it will always work.
Drawbacks:
It will use quite some code memory, so your "manual" method might be good depending on
how much memory you want to spend.

BUT: if you really want to make your own brew of printing a float number,
you have to try a bit smarter. For instance, removing the heading zeroes
can be done better with a loop.

Beside this: you have used '0' when suppressing the useless 0s. You should also
do this when calculating the number instead of 48 or 0x30.

Next: you shouldn't have 2 cases, if (digits == 2), you should do it on a more
generic way. Beside this, why calling digit something that should be named "decimals",
i.e. number of digits after the point.

Next: don't use hardcoded values. If k>15 is good for your LCD. If you change it to
a 4x20 LCD, your code will still work, but it will not use the 4 extra chars of every line.
Use a #define LCD_COLS 16, #define LCD_ROWS 2 and replace in your code.

About the naming:
Why calling a function LCD_CString_Position_v2? What is v2? Is it the second version
of this function? That should not appear in the code (1).
Apparently the only role of this one is to write a string at a given position.
Why not calling it WriteStringAt(x, y, string)? Everybody would understand at once
what it does. Why CString? String already says everything, and since the program
is in C...

(1). I would also recommend a versioning system, for example tortoise git if you are
using windows. It probably already happened to you a few times: you have a working
program, you modify something and nothing works anymore and you don't know what caused
it to fail. Then you spend hours looking at what you made wrong. A versioning system
helps you to point out everything you have modified and you can come back instantly to
an earlier version.

Regards,

Dora.
Bonjour Dora,
Thanks for your help and all your advices. I will try them soon.
But, in order to run my code, after your previous advice in your post #15 of saturday, which point in your last answer should I modify ?
Merci.
Eric
 

Hi,

using basic functions of edaboard should be rather self explanatory, like:
[ Edit ] and [ Reply ] at the bottom of every post
1633430788358.png


and a preview in the reply editor window....

Please use it.

Klaus
 

Hello!

I had a look at your code, and there are many things to be improved.

1. LCD row.
You may consider defining this:
char ROW[] = {0x80, 0xC0};
So if you start numbering your rows at 0, you can do:

Code:
void LCD_CString_Position_v2(char row, char col, char *msg) {
    LCD_Write_Cmd((col & 0x0F)| ROW[row]);    // Print message on 1st row and desired location.
    LCD_Write_CString_v2(msg);                // OK.
}

Advantages:
- You don't need to test if else for rows.
- If you ever use a 4 lines display, you just modify the line:
char row[] = {a, b, c, f}; // a, b, c, d are the codes fro the 4 lines.
And you can use the exact same function.

2. In your print float function.
You have better options:
Use <stdio.h> (but that can be string.h in some environments)
and you end up with
sprintf(flt, "%f", your_float_number) in which case you can even
specify the number of decimals, the length, etc.
Example: sprintf(flt, "%8.3f", your_float_number);

Advantages:
This code has been tested for decades, it will always work.
Drawbacks:
It will use quite some code memory, so your "manual" method might be good depending on
how much memory you want to spend.

BUT: if you really want to make your own brew of printing a float number,
you have to try a bit smarter. For instance, removing the heading zeroes
can be done better with a loop.

Beside this: you have used '0' when suppressing the useless 0s. You should also
do this when calculating the number instead of 48 or 0x30.

Next: you shouldn't have 2 cases, if (digits == 2), you should do it on a more
generic way. Beside this, why calling digit something that should be named "decimals",
i.e. number of digits after the point.

Next: don't use hardcoded values. If k>15 is good for your LCD. If you change it to
a 4x20 LCD, your code will still work, but it will not use the 4 extra chars of every line.
Use a #define LCD_COLS 16, #define LCD_ROWS 2 and replace in your code.

About the naming:
Why calling a function LCD_CString_Position_v2? What is v2? Is it the second version
of this function? That should not appear in the code (1).
Apparently the only role of this one is to write a string at a given position.
Why not calling it WriteStringAt(x, y, string)? Everybody would understand at once
what it does. Why CString? String already says everything, and since the program
is in C...

(1). I would also recommend a versioning system, for example tortoise git if you are
using windows. It probably already happened to you a few times: you have a working
program, you modify something and nothing works anymore and you don't know what caused
it to fail. Then you spend hours looking at what you made wrong. A versioning system
helps you to point out everything you have modified and you can come back instantly to
an earlier version.

Regards,

Dora.

Konichiwa Dora San,

Finally my code runs after your first advice. Have to change the 4 bits shift and formula of low and high in void LCD_Write_Data and void LCD_Write_Cmd in my code because of that ...

sbit LCD_D4 at RB0_bit; // D4 (pin 11) -> portB.b0 (pin 33)
sbit LCD_D5 at RB1_bit; // D5 (pin 12) -> portB.b1 (pin 34)
sbit LCD_D6 at RB2_bit; // D6 (pin 13) -> portB.b2 (pin 35)
sbit LCD_D7 at RB3_bit; // D7 (pin 14) -> portB.b3 (pin 36)

... instead of using RB4 to RB7 on D4 to D7.

Sometimes don’t have enough time to troubleshoot deeper and ask more questions by posts.

Glad to took more time yesterday evening to resolve by my own.

Now will test new version with all your advices.

Eric
 

Hello!

I had a look at your code, and there are many things to be improved.

1. LCD row.
You may consider defining this:
char ROW[] = {0x80, 0xC0};
So if you start numbering your rows at 0, you can do:

Code:
void LCD_CString_Position_v2(char row, char col, char *msg) {
    LCD_Write_Cmd((col & 0x0F)| ROW[row]);    // Print message on 1st row and desired location.
    LCD_Write_CString_v2(msg);                // OK.
}

Advantages:
- You don't need to test if else for rows.
- If you ever use a 4 lines display, you just modify the line:
char row[] = {a, b, c, f}; // a, b, c, d are the codes fro the 4 lines.
And you can use the exact same function.

2. In your print float function.
You have better options:
Use <stdio.h> (but that can be string.h in some environments)
and you end up with
sprintf(flt, "%f", your_float_number) in which case you can even
specify the number of decimals, the length, etc.
Example: sprintf(flt, "%8.3f", your_float_number);

Advantages:
This code has been tested for decades, it will always work.
Drawbacks:
It will use quite some code memory, so your "manual" method might be good depending on
how much memory you want to spend.

BUT: if you really want to make your own brew of printing a float number,
you have to try a bit smarter. For instance, removing the heading zeroes
can be done better with a loop.

Beside this: you have used '0' when suppressing the useless 0s. You should also
do this when calculating the number instead of 48 or 0x30.

Next: you shouldn't have 2 cases, if (digits == 2), you should do it on a more
generic way. Beside this, why calling digit something that should be named "decimals",
i.e. number of digits after the point.

Next: don't use hardcoded values. If k>15 is good for your LCD. If you change it to
a 4x20 LCD, your code will still work, but it will not use the 4 extra chars of every line.
Use a #define LCD_COLS 16, #define LCD_ROWS 2 and replace in your code.

About the naming:
Why calling a function LCD_CString_Position_v2? What is v2? Is it the second version
of this function? That should not appear in the code (1).
Apparently the only role of this one is to write a string at a given position.
Why not calling it WriteStringAt(x, y, string)? Everybody would understand at once
what it does. Why CString? String already says everything, and since the program
is in C...

(1). I would also recommend a versioning system, for example tortoise git if you are
using windows. It probably already happened to you a few times: you have a working
program, you modify something and nothing works anymore and you don't know what caused
it to fail. Then you spend hours looking at what you made wrong. A versioning system
helps you to point out everything you have modified and you can come back instantly to
an earlier version.

Regards,

Dora.
Kambawa Dora San,

I implement my code here under with almost all your advices. 1 error while compiling the code.
Compiler, at line #99, says "Pointer required".

To be honest, I'm not very familar and easy doing with pointers enough. Can you enlighten me please ?

Merci beaucoup.

Eric

Code:
// LCD module connections :
                                        // VSS (pin  1) -> GND
                                        // VDD (pin  2) -> VCC
                                        // VEE (pin  3) -> middle pin contrast potentiometer
sbit LCD_RS at RB4_bit;                 // RS  (pin  4) -> portB.b4 (pin 37)
// RW not used.                         // RW  (pin  5) -> GND
sbit LCD_EN at RB5_bit;                 // EN  (pin  6) -> portB.b5 (pin 38)
                                        // D0  (pin  7) -> GND
                                        // D1  (pin  8) -> GND
                                        // D2  (pin  9) -> GND
                                        // D3  (pin 10) -> GND
sbit LCD_D4 at RB0_bit;                 // D4  (pin 11) -> portB.b0 (pin 33)
sbit LCD_D5 at RB1_bit;                 // D5  (pin 12) -> portB.b1 (pin 34)
sbit LCD_D6 at RB2_bit;                 // D6  (pin 13) -> portB.b2 (pin 35)
sbit LCD_D7 at RB3_bit;                 // D7  (pin 14) -> portB.b3 (pin 36)
                                        //     (pin 15) -> GND
                                        //     (pin 16) -> GND

sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;

/******************************************************************************/

#define CMD 0
#define DATA 1
#define LCD_PORT PORTB
#define LCD_COLUMNS 16
#define LCD_ROWS 2

/******************************************************************************/

// Declaration of variables :

float sec;                              // - 1.5 x 10 puissance 45 to + 3.4 x 10 puissance 38
//double sec;                           // - 1.5 x 10 puissance 45 to + 3.4 x 10 puissance 38
//long sec;                             // - 2147483648 to 2147483647
char texte[64];                         // 0 to 255
                                        // Variables ci-dessous sorties du main() pour les déclarer en global.
                                        // Le PIC 16F a moins de mémoire RAM et ROM que le PIC 18F.
unsigned char *pointeur_de_char;        // Déclaration d'un pointeur (*) de char "pointeur_de_char".
//char texte[] = "Counting ...";        // Déclaration d'un tableau "texte" de type char et initialisé avec la chaine de caractères "Counting ..." :
                                        // En n'indiquant aucun chiffre entre les cochets [], le compilateur ajustera automatiquement la taille du
                                        // tableau, et allouera en mémoire RAM, le bon nombre d'éléments, soit 13 ...
char txt[13];

char ROW[] = {0x80, 0xC0};

/******************************************************************************/

// Routines :

void LCD_E_Pulse(void)
{
 LCD_EN = 1;
 Delay_us(8);                                                     // Delay between 5 uS and 10 uS.
 LCD_EN = 0;
 Delay_us(500);                                                   // Delay between 5 uS and 1000 uS (1 mS).
}

void LCD_Write(unsigned char cmd_or_data, unsigned char byte)
{
 unsigned char low, high;
 high = (byte >> 4) & 0x0F;                                       // b7 b6 b5 b4 of byte are shifted to b3 b2 b1 b0 of _byte and saved in high.
 low = byte & 0x0F;                                               // b3 b2 b1 b0 of byte are saved in low.
 LCD_PORT = high;                                                 // Send higher nibble of byte to the LCD.
 LCD_RS = cmd_or_data;
 LCD_E_Pulse();
 LCD_PORT = low;                                                  // Send lower nibble of byte to the LCD.
 LCD_RS = cmd_or_data;
 LCD_E_Pulse();
}

void StrConstRamCpy(unsigned char *dest, const code char *source) // Copie le texte de la FLASH ROM vers la RAM.
{
 while (*source)*dest ++ = *source ++;
 *dest = 0;                                                       // Terminateur "0" fin de chaine de caractère.
}

void LCD_Write_String(char *msg)                                  // Variante avec pointeur msg non modifié.
{
 int k;
 k = 0;
 //while(*(msg) > 0)                                              // FAIL.
 while(*(msg + k) > 0)                                            // OK.
 {
  LCD_Write(DATA, (*(msg + k)));                                  // Data pointée par (msg + k).
  k++;
  //if (k > 15) break;                                            // Si k > 15 sortie de la boucle while ...
  if (k == LCD_COLUMNS) break;
 }
}

void LCD_Write_String_At(char row, char col, char *msg)
{
 LCD_Write(CMD, (col & 0x0F)|(ROW[row]));                         // Print message on desired row and desired column.
 LCD_Write_String(msg);                                           // OK.
}

void print_float_v4(char *flt, long number, char decimals)
{
 if (number < 0)
    {
     number = - number;
     *(flt) = '-';
    }
    else
       {
        *(flt) = ' ';
       }

 *(flt + 1) = ' ';

 if (decimals == 2)
    {
     *(flt + 2) = number / 1000000 + 48;
     *(flt + 3) = ((number % 1000000) / 100000) + 48;
     *(flt + 4) = ((number % 100000) / 10000) + 48;
     *(flt + 5) = ((number % 10000) / 1000) + 48;
     *(flt + 6) = ((number % 1000) / 100) + 48;
     *(flt + 7) = ((number % 100) / 10) + 48;
     *(flt + 8) = ((number % 10) / 1) + 48;
     *(flt + 9) = ',';
     *(flt + 10) = ((number % 100) / 10) + 48;
     *(flt + 11) = (number % 10) + 48;
     *(flt + 12) = 0;
    }
    else
       {
        *(flt + 2) = number / 100000 + 48;
        *(flt + 3) = ((number % 100000) / 10000) + 48;
        *(flt + 4) = ((number % 10000) / 1000) + 48;
        *(flt + 5) = ((number % 1000) / 100) + 48;
        *(flt + 6) = ((number % 100) / 10) + 48;
        *(flt + 7) = ',';
        *(flt + 8) = (number % 10) + 48;
        *(flt + 9) = 0;
       }

 if (*(flt + 2) == '0')                                           // Suppression des zéros inutiles.
    {
     *(flt + 2) = ' ';
     if (*(flt + 3) == '0')
        {
         *(flt + 3) = ' ';
         if (*(flt + 4) == '0')
            {
             *(flt + 4) = ' ';
             if (*(flt + 5) == '0')
                {
                 *(flt + 5) = ' ';
                 if (*(flt + 6) == '0')
                    {
                     *(flt + 6) = ' ';
                     if (*(flt + 7) == '0')
                        {
                         *(flt + 7) = ' ';
                        }
                    }
                }
            }
        }
    }
}

void LCD_Init_v4 (void)                                           // OK. https://www.edaboard.com/threads/pic-16f887-lcd-2-x-16-4-datas-bits-can-not-print-on-lcd-a-char-or-a-string.397268/#post-1709271
{
 Delay_ms(15);                                                    // LCD power ON initialization time >= 15 mS.
 LCD_Write(CMD, 0x30);                                            // 4 datas bits > Initialization of LCD with nibble method (4 datas bits).
 LCD_Write(CMD, 0x02);                                            // 4 datas bits > Initialization of LCD with nibble method (4 datas bits).
 LCD_Write(CMD, 0x28);                                            // 4 datas bits > 2 lines display, 5 × 8 dot character font.
 LCD_Write(CMD, 0x0C);                                            // 4 datas bits > Display ON. Cursor OFF.
 LCD_Write(CMD, 0x06);                                            // 4 datas bits > Auto increment cursor.
 LCD_Write(CMD, 0x01);                                            // 4 datas bits > Clear display.
 Delay_ms(1);                                                     // Ajustable ... (indispensable, sinon affichage erratique à la mise sous tension)
}

/******************************************************************************/

// Main program :

void main()
{
 ANSEL = 0;                                                // Configure AN pins as digital I/O.
 ANSELH = 0;
 C1ON_bit = 0;                                             // Disable Comparator 1.
 C2ON_bit = 0;                                             // Disable Comparator 2.

 PORTB = 0;
 TRISB = 0;

 PORTC = 0;
 TRISC = 0;

 // Essai 19.1 : OK

 Lcd_Init_v4();                                            // Initialize LCD.

 while(1)                                                  // Endless loop.
 {
  unsigned char *pointeur_de_char;                         // Déclaration d'un pointeur (*) de char "pointeur_de_char".
  //char texte[] = "Counting ...";                         // Déclaration d'un tableau "texte" de type char et initialisé avec la chaine de caractères "Counting ..." :
                                                           // En n'indiquant aucun chiffre entre les cochets [], le compilateur ajustera automatiquement la taille du
                                                           // tableau, et allouera en mémoire RAM, le bon nombre d'éléménts, soit 13 ...
  char txt[13];
  pointeur_de_char = &texte[0];                            // pointeur_de_char pointe sur le premier élément du tableau "texte", soit texte[0].
                                                           // Autrement dit, pointeur_de_char contient l'adresse (&) de texte[0].

  for(sec = -8388607; sec <= 8388607; sec = sec + 0.5)     // sec déclarée en float. OK. Plage maximale : 8388607 = (2 puissance 23) - 1.

     {
      portc.b2 = 1;                                        // LED yellow ON.

      StrConstRamCpy(pointeur_de_char, "Counting ...");    // OK.
      LCD_Write_String_At(ROW[0], 0, pointeur_de_char);    // OK.

      print_float_v4(&txt[0], sec, 2);                     // OK.

      LCD_Write_String_At(ROW[1], 0, &txt[0]);             // Write txt in 2nd row, starting at 1st digit.
      LCD_Write_String_At(ROW[1], 13, "uS");               // Write "uS" in 2nd row, starting at 14th digit

      Delay_us(1);
     }

  portc.b2 = 0;                                            // LED yellow OFF.
  portc.b3 = 1;                                            // LED green ON.
  portc.b4 = 1;                                            // BUZZER ON.
  Delay_ms(5000);
  portc.b3 = 0;                                            // LED green OFF.
  portc.b4 = 0;                                            // BUZZER OFF.
 }
}
 

Hello!

"Kambawa" -> Konbanha.
-> It's "on" not "an"
-> There is no rule saying that you should use a m before a b
-> n missing
-> it's written "ha" and pronounced "wa".

1 error while compiling the code.
Compiler, at line #99, says "Pointer required".

It depends where this happens.

Pointers is not a big deal, it's just the address of some data in your memory space.
If you declare char text[txt_len], then you open space in the memory for some text,
it's a static allocation.
You can indeed write textptr = (char *)(&text[0]); but in fact you have already the address.
When you declare char text[len]; it means that you will have an array of characters, and
its address is simply text. Therefore, text = &text[0];

So in you code, textptr = text should work. It's simply a variable, a kind of cursor that you
put on your fixed array, and that you can increment or decrement at will.

And that's about all you have to know about pointers.

Some examples of use:
char txt[0x100]; // Statically defined array. Depending on the compiler, may contain anything,
but usually 0.
char * txtptr = txt

for(uint8 i = 0; i < 26 ; ++i) {
txt[i++] = 'a' +i;
}
At this point, the original string should contain the alphabet.
Just in case, you can add a 0 at the end.

Now instead of you hardcoded method to suppress the leading zeroes, you could
try to iterate a text pointer to find the first non-zero character, then replace all the
leading zeroes by spaces. You can even write the '-' one step before the first non-zero
number, you have to also think of the particular case of one single 0 before the dot.
Etc...

Dora.
 

Hello!

"Kambawa" -> Konbanha.
-> It's "on" not "an"
-> There is no rule saying that you should use a m before a b
-> n missing
-> it's written "ha" and pronounced "wa".



It depends where this happens.

Pointers is not a big deal, it's just the address of some data in your memory space.
If you declare char text[txt_len], then you open space in the memory for some text,
it's a static allocation.
You can indeed write textptr = (char *)(&text[0]); but in fact you have already the address.
When you declare char text[len]; it means that you will have an array of characters, and
its address is simply text. Therefore, text = &text[0];

So in you code, textptr = text should work. It's simply a variable, a kind of cursor that you
put on your fixed array, and that you can increment or decrement at will.

And that's about all you have to know about pointers.

Some examples of use:
char txt[0x100]; // Statically defined array. Depending on the compiler, may contain anything,
but usually 0.
char * txtptr = txt

for(uint8 i = 0; i < 26 ; ++i) {
txt[i++] = 'a' +i;
}
At this point, the original string should contain the alphabet.
Just in case, you can add a 0 at the end.

Now instead of you hardcoded method to suppress the leading zeroes, you could
try to iterate a text pointer to find the first non-zero character, then replace all the
leading zeroes by spaces. You can even write the '-' one step before the first non-zero
number, you have to also think of the particular case of one single 0 before the dot.
Etc...

Dora.

Merci Dora San.

Clear explanations. Will try.
Compiler error appears in first line of the following subroutine :

void LCD_Write_String_At(char row, char col, char *msg)
{
LCD_Write(CMD, (col & 0x0F)|(ROW[row]));
LCD_Write_String(msg);
}

Éric
 

where is define LCD_Write_String ?

Code:
void LCD_Write_String_At(char row, char col, char *msg)
{
LCD_Write(CMD, (col & 0x0F)|(ROW[row]));
LCD_Out(msg);
}
Just above void LCD_Write_String_At in the code.

Here under the routine :

Code:
void LCD_Write_String(char *msg)                               
{
 int k;
 k = 0;
 //while(*(msg) > 0)                                           
 while(*(msg + k) > 0)                                           
 {
  LCD_Write(DATA, (*(msg + k)));                               
  k++;
  //if (k > 15) break;                                         
  if (k == LCD_COLUMNS) break;
 }
}
 
Last edited by a moderator:

Hello!

"Kambawa" -> Konbanha.
-> It's "on" not "an"
-> There is no rule saying that you should use a m before a b
-> n missing
-> it's written "ha" and pronounced "wa".



It depends where this happens.

Pointers is not a big deal, it's just the address of some data in your memory space.
If you declare char text[txt_len], then you open space in the memory for some text,
it's a static allocation.
You can indeed write textptr = (char *)(&text[0]); but in fact you have already the address.
When you declare char text[len]; it means that you will have an array of characters, and
its address is simply text. Therefore, text = &text[0];

So in you code, textptr = text should work. It's simply a variable, a kind of cursor that you
put on your fixed array, and that you can increment or decrement at will.

And that's about all you have to know about pointers.

Some examples of use:
char txt[0x100]; // Statically defined array. Depending on the compiler, may contain anything,
but usually 0.
char * txtptr = txt

for(uint8 i = 0; i < 26 ; ++i) {
txt[i++] = 'a' +i;
}
At this point, the original string should contain the alphabet.
Just in case, you can add a 0 at the end.

Now instead of you hardcoded method to suppress the leading zeroes, you could
try to iterate a text pointer to find the first non-zero character, then replace all the
leading zeroes by spaces. You can even write the '-' one step before the first non-zero
number, you have to also think of the particular case of one single 0 before the dot.
Etc...

Dora.
Bonjour Doraemon San,

Thanks for all your advices. I will write a short code in order to test pointers and watching values inside table, index, variables, pointers with the Debbuger of MikroC.
Will try your advice concerning to avoid hardcoded method to suppress the leading zeroes ...

Already an other question, how could I scrolling the first line with the string “Counting ...” ?
I already found some links talking about the DDRAM adresses mapping of the HD4480 ...

Merci.

Eric
 

Hello!

Already an other question, how could I scrolling the first line with the string “Counting ...” ?

You can consider a string as an array of characters. You can do it the "dumb" (but easy) way:
For example if you scroll left:
- Store the first character
- Move the characters from 1 to end of line to the left....
Well, it will be easier in pseudo code:

Code:
char line[LINE_LENGTH];
char mem;
mem = line[0];
for(uint8 i = 1 ; i < LINE_LENGTH ; ++i) {
    char[i-1] = char[i];
}
char[LINE_LENGTH-1] = mem;

Make a function of this, name if for example lscroll, call it periodically and display
line after you called the function.

A smarter way: make a write function that can limit the number of characters.
Name it for example write_chunk(pointer, len);

Code:
uint8 scrollval;
move_to(line, 0); // Move to the beginning of the line you want to scroll
write_chunk(line+scrollval, LINE_LENGTH - scrollval); // Write from the character at position = scrollval
write_chunk(line, scrollval); // write the beginning of the line to the right.

It is smarter because you don't have to do time (and processor) consuming shifts.
You don't shift anything, you just write.

Dora.
 

Hello!



You can consider a string as an array of characters. You can do it the "dumb" (but easy) way:
For example if you scroll left:
- Store the first character
- Move the characters from 1 to end of line to the left....
Well, it will be easier in pseudo code:

Code:
char line[LINE_LENGTH];
char mem;
mem = line[0];
for(uint8 i = 1 ; i < LINE_LENGTH ; ++i) {
    char[i-1] = char[i];
}
char[LINE_LENGTH-1] = mem;

Make a function of this, name if for example lscroll, call it periodically and display
line after you called the function.

A smarter way: make a write function that can limit the number of characters.
Name it for example write_chunk(pointer, len);

Code:
uint8 scrollval;
move_to(line, 0); // Move to the beginning of the line you want to scroll
write_chunk(line+scrollval, LINE_LENGTH - scrollval); // Write from the character at position = scrollval
write_chunk(line, scrollval); // write the beginning of the line to the right.

It is smarter because you don't have to do time (and processor) consuming shifts.
You don't shift anything, you just write.

Dora.
Merci Dora for your advices.
Examples of codes a little bit to smart for me. :confused:
Looking on some other vebsites, I wrote this ... Not too bad, but ... :unsure:
First line of LCD, "Counting ..." arrives from left to right like "C", than "Co", than "Cou" ... till the end. Then the all string scrolls to the right ... But never recycle ... Result : first line is blank.
Then counting starts on the second line properly.
I would prefer that the string on first line continuously scrolls while counting is running on second line.
I guess I have a problem with do ... while loops ? I tried differents ways but was worse ! :eek:
And how could I improve the code(*) which manage the scrolling with pointers (lines 221 to 241) ?
* : start with while(texte[position]!='\0')
Arigatou.
Eric

Code:
// LCD module connections :
                                        // VSS (pin  1) -> GND
                                        // VDD (pin  2) -> VCC
                                        // VEE (pin  3) -> middle pin contrast potentiometer
sbit LCD_RS at RB4_bit;                 // RS  (pin  4) -> portB.b4 (pin 37)
// RW not used.                         // RW  (pin  5) -> GND
sbit LCD_EN at RB5_bit;                 // EN  (pin  6) -> portB.b5 (pin 38)
                                        // D0  (pin  7) -> GND
                                        // D1  (pin  8) -> GND
                                        // D2  (pin  9) -> GND
                                        // D3  (pin 10) -> GND
sbit LCD_D4 at RB0_bit;                 // D4  (pin 11) -> portB.b0 (pin 33)
sbit LCD_D5 at RB1_bit;                 // D5  (pin 12) -> portB.b1 (pin 34)
sbit LCD_D6 at RB2_bit;                 // D6  (pin 13) -> portB.b2 (pin 35)
sbit LCD_D7 at RB3_bit;                 // D7  (pin 14) -> portB.b3 (pin 36)
                                        //     (pin 15) -> GND
                                        //     (pin 16) -> GND

sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;

/******************************************************************************/

#define CMD 0
#define DATA 1
#define LCD_PORT PORTB
#define LCD_COLUMNS 16
#define LCD_ROWS 2
#define LCD_LINE_LENGHT 16

/******************************************************************************/

// Declaration of variables :

float sec;                              // - 1.5 x 10 puissance 45 to + 3.4 x 10 puissance 38
//double sec;                           // - 1.5 x 10 puissance 45 to + 3.4 x 10 puissance 38
//long sec;                             // - 2147483648 to 2147483647
char texte[64];                         // 0 to 255
                                        // Variables ci-dessous sorties du main() pour les déclarer en global.
                                        // Le PIC 16F a moins de mémoire RAM et ROM que le PIC 18F.
unsigned char *pointeur_de_char;        // Déclaration d'un pointeur (*) de char "pointeur_de_char".
//char texte[] = "Counting ...";        // Déclaration d'un tableau "texte" de type char et initialisé avec la chaine de caractères "Counting ..." :
                                        // En n'indiquant aucun chiffre entre les cochets [], le compilateur ajustera automatiquement la taille du
                                        // tableau, et allouera en mémoire RAM, le bon nombre d'éléments, soit 13 ...
char txt[13];

char ROW[] = {0x80, 0xC0};

char ligne[LCD_LINE_LENGHT];

char position, i;

/******************************************************************************/

// Routines :

void LCD_E_Pulse(void)
{
LCD_EN = 1;
Delay_us(8);                                                     // Delay between 5 uS and 10 uS.
LCD_EN = 0;
Delay_us(500);                                                   // Delay between 5 uS and 1000 uS (1 mS).
}

void LCD_Write(unsigned char cmd_or_data, unsigned char byte)
{
unsigned char low, high;
high = (byte >> 4) & 0x0F;                                       // b7 b6 b5 b4 of byte are shifted to b3 b2 b1 b0 of byte and saved in high.
low = byte & 0x0F;                                               // b3 b2 b1 b0 of byte are saved in low.
LCD_PORT = high;                                                 // Send higher nibble of byte to the LCD.
LCD_RS = cmd_or_data;
LCD_E_Pulse();
LCD_PORT = low;                                                  // Send lower nibble of byte to the LCD.
LCD_RS = cmd_or_data;
LCD_E_Pulse();
}

void StrConstRamCpy(unsigned char *dest, const code char *source) // Copie le texte de la FLASH ROM vers la RAM.
                                                                  // const code char *source puts *source in program memory.
                                                                  // const code memory specifier is used in order to create *source as a constant. As a constant, values of *sources are placed in ROM.
                                                                  // Values of constants can not be changed while program is running.
{
while (*source)*dest ++ = *source ++;                            // Values of *sources are copying from ROM to *dest in RAM.
*dest = 0;                                                       // Terminateur "0" fin de chaine de caractère.
}

void LCD_Write_String(char *msg)                                  // Variante avec pointeur msg non modifié. V
{
char k;
k = 0;
//while(*(msg) > 0)                                              // FAIL.
while(*(msg + k) > 0)                                            // OK.
{
  LCD_Write(DATA, (*(msg + k)));                                  // Data pointée par (msg + k).
  k++;
  if (k == LCD_COLUMNS) break;                                    // Si k = 16 sortie de la boucle while ...
}
}

void LCD_Write_String_At(char line, char column, char *msg)
{
LCD_Write(CMD, ROW[line]|(column & 0x0F));                       // Print message on desired line and desired column.
LCD_Write_String(msg);
}

void print_float_v4(char *flt, long number, char decimals)
{
if (number < 0)
    {
     number = - number;
     *(flt) = '-';
    }
    else
       {
        *(flt) = ' ';
       }

*(flt + 1) = ' ';

if (decimals == 2)
    {
     *(flt + 2) = number / 1000000 + 48;
     *(flt + 3) = ((number % 1000000) / 100000) + 48;
     *(flt + 4) = ((number % 100000) / 10000) + 48;
     *(flt + 5) = ((number % 10000) / 1000) + 48;
     *(flt + 6) = ((number % 1000) / 100) + 48;
     *(flt + 7) = ((number % 100) / 10) + 48;
     *(flt + 8) = ((number % 10) / 1) + 48;
     *(flt + 9) = ',';
     *(flt + 10) = ((number % 100) / 10) + 48;
     *(flt + 11) = (number % 10) + 48;
     *(flt + 12) = 0;
    }
    else
       {
        *(flt + 2) = number / 100000 + 48;
        *(flt + 3) = ((number % 100000) / 10000) + 48;
        *(flt + 4) = ((number % 10000) / 1000) + 48;
        *(flt + 5) = ((number % 1000) / 100) + 48;
        *(flt + 6) = ((number % 100) / 10) + 48;
        *(flt + 7) = ',';
        *(flt + 8) = (number % 10) + 48;
        *(flt + 9) = 0;
       }

if (*(flt + 2) == '0')                                           // Suppression des zéros inutiles.
    {
     *(flt + 2) = ' ';
     if (*(flt + 3) == '0')
        {
         *(flt + 3) = ' ';
         if (*(flt + 4) == '0')
            {
             *(flt + 4) = ' ';
             if (*(flt + 5) == '0')
                {
                 *(flt + 5) = ' ';
                 if (*(flt + 6) == '0')
                    {
                     *(flt + 6) = ' ';
                     if (*(flt + 7) == '0')
                        {
                         *(flt + 7) = ' ';
                        }
                    }
                }
            }
        }
    }
}


void LCD_Init_v4 (void)                                           // OK. https://www.edaboard.com/threads/pic-16f887-lcd-2-x-16-4-datas-bits-can-not-print-on-lcd-a-char-or-a-string.397268/#post-1709271
{
Delay_ms(15);                                                    // LCD power ON initialization time >= 15 mS.
LCD_Write(CMD, 0x30);                                            // 4 datas bits > Initialization of LCD with nibble method (4 datas bits).
LCD_Write(CMD, 0x02);                                            // 4 datas bits > Initialization of LCD with nibble method (4 datas bits).
LCD_Write(CMD, 0x28);                                            // 4 datas bits > 2 lines display, 5 × 8 dot character font.
LCD_Write(CMD, 0x0C);                                            // 4 datas bits > Display ON. Cursor OFF.
LCD_Write(CMD, 0x06);                                            // 4 datas bits > Auto increment cursor.
LCD_Write(CMD, 0x01);                                            // 4 datas bits > Clear display.
Delay_ms(1);                                                     // Ajustable ... (indispensable, sinon affichage erratique à la mise sous tension)
}

/******************************************************************************/

// Main program :

void main()
{
ANSEL = 0;                                                // Configure AN pins as digital I/O.
ANSELH = 0;
C1ON_bit = 0;                                             // Disable Comparator 1.
C2ON_bit = 0;                                             // Disable Comparator 2.

PORTB = 0;
TRISB = 0;

PORTC = 0;
TRISC = 0;

// Essai 20.3 : DEBBUGING ...

Lcd_Init_v4();                                            // Initialize LCD.

while(1)                                                  // Endless loop.
{
  unsigned char *pointeur_de_char;                         // Déclaration d'un pointeur (*) de char "pointeur_de_char".
  char texte[] = "Counting ...";                           // Déclaration d'un tableau "texte" de type char et initialisé avec la chaine de caractères "Counting ..." :
                                                           // En n'indiquant aucun chiffre entre les cochets [], le compilateur ajustera automatiquement la taille du
                                                           // tableau, et allouera en mémoire RAM, le bon nombre d'éléments, soit 13 ...
  char txt[13];
  pointeur_de_char = &texte[0];                            // pointeur_de_char pointe sur le premier élément du tableau "texte", soit texte[0].
                                                           // Autrement dit, pointeur_de_char contient l'adresse (&) de texte[0].
  position = 0;

  while(texte[position]!='\0')
  {
   LCD_Write(DATA, texte[position]);
   Delay_ms(100);                                          // Ou rien ...
   position ++;
   if (position == 12)
      {
       portc.b3 = 1;                                       // LED green ON.
       i = LCD_LINE_LENGHT;

       while(i > 0)
       {
        portc.b3 = 1;                                      // LED green ON.
        LCD_Write(CMD, 0x1C);                              // Right scroll. Shift entire display right.
        Delay_ms(100);
        i--;
       }
       portc.b3 = 0;                                       // LED green OFF.
      }
  }

  //LCD_Write(CMD, 0xC0);                                  // 0x80 + 0x40 = 0xC0
  //LCD_Write(CMD, 0x40);                                  // 0x00 + 0x40 = 0x40

  LCD_Write(CMD, 0x01);                                    // Clear display.

  for(sec = -20; sec <= 20; sec = sec + 0.5)               // For testing rapidely the count passing thru 0.
     {
      portc.b2 = 1;                                        // LED yellow ON.

      //StrConstRamCpy(pointeur_de_char, "Counting ...");  // OK.
      //LCD_Write_String_At(0, 0, pointeur_de_char);       // OK. Voir dans void LCD_Write_String(char *msg), le while(*(msg + k) > 0).

      print_float_v4(&txt[0], sec, 2);                     // OK.

      LCD_Write_String_At(1, 0, &txt[0]);                  // Write txt in 2nd row, starting at 1st digit.
      LCD_Write_String_At(1, 13, "uS");                    // Write "uS" in 2nd row, starting at 14th digit

      Delay_us(1);
     }

  portc.b2 = 0;                                            // LED yellow OFF.
  portc.b3 = 1;                                            // LED green ON.
  portc.b4 = 1;                                            // BUZZER ON.
  Delay_ms(1000);
  portc.b4 = 0;                                            // BUZZER OFF.
  portc.b3 = 0;                                            // LED green OFF.

  LCD_Write(CMD, 0x01);                                    // Clear display.

  Delay_ms(500);
}

}
 

Hello!



You can consider a string as an array of characters. You can do it the "dumb" (but easy) way:
For example if you scroll left:
- Store the first character
- Move the characters from 1 to end of line to the left....
Well, it will be easier in pseudo code:

Code:
char line[LINE_LENGTH];
char mem;
mem = line[0];
for(uint8 i = 1 ; i < LINE_LENGTH ; ++i) {
    char[i-1] = char[i];
}
char[LINE_LENGTH-1] = mem;

Make a function of this, name if for example lscroll, call it periodically and display
line after you called the function.

A smarter way: make a write function that can limit the number of characters.
Name it for example write_chunk(pointer, len);

Code:
uint8 scrollval;
move_to(line, 0); // Move to the beginning of the line you want to scroll
write_chunk(line+scrollval, LINE_LENGTH - scrollval); // Write from the character at position = scrollval
write_chunk(line, scrollval); // write the beginning of the line to the right.

It is smarter because you don't have to do time (and processor) consuming shifts.
You don't shift anything, you just write.

Dora.
Bonsoir Dora,
Due to a lack of time I wrote a code which is simplier as yours, which I understand better, but scrolling doesn’t run properly …

Code 1 :

Srolling of ERIC left to right runs properly on first line.
“ERIC” starts on the left and disappears characters after characters on the right and re
appears on the left.

Code:
colonne = 0x00;
  LCD_Write(CMD, 0x80 + colonne);                          // Set cursor to address location 0x00.

  while(colonne < 0x11)
  {
   LCD_Write_String("ERIC");
   Delay_ms(500);
   LCD_Write(CMD, 0x80 + colonne);
   LCD_Write_String(" ");
   colonne ++;
  }
Code 2 :

Srolling of ERIC left to right runs on first line, but starts at column 3.
On the left side I would prefer to watch C, then IC than RIC, than ERIC appears before scrolling to right.
Code:
  colonne = 0x24;
  LCD_Write(CMD, 0x80 + colonne);                          // Set cursor to address location 0x00.
  while(colonne < 0x11)
  {
   LCD_Write_String("ERIC");
   Delay_ms(500);
   LCD_Write(CMD, 0x80 + colonne);
   LCD_Write_String(" ");
   colonne ++
  }

Can you enlighten me ?

Eric
 
Last edited by a moderator:

Hello!

Sorry, but I don't see any differentce between your 2 codes except that one starts
at 0 and the other at 0x24. Am I missing something?

“ERIC” starts on the left and disappears characters after characters on the right and re
appears on the left.

So basically you would like it to disappear, right?
In fact, the RAM inside of the LCD (as far as I remember) increases its index automatically.
Therefore if you write something after the right of the screen, then it comes back on the
left. Depending on the mode, it can also show up at the beginning of the next line, etc...
That must be configurable. I'm not sure of the detail, so if anybody knows...
So when you are close to the end of the line, you should write ERIC, then on the next step
ERI, then ER, etc...

Dora.
 

Hello!

Sorry, but I don't see any differentce between your 2 codes except that one starts
at 0 and the other at 0x24. Am I missing something?



So basically you would like it to disappear, right?
In fact, the RAM inside of the LCD (as far as I remember) increases its index automatically.
Therefore if you write something after the right of the screen, then it comes back on the
left. Depending on the mode, it can also show up at the beginning of the next line, etc...
That must be configurable. I'm not sure of the detail, so if anybody knows...
So when you are close to the end of the line, you should write ERIC, then on the next step
ERI, then ER, etc...

Dora.
Now it works ! Now can improve the code with pointers in order to gain size. Will try a little bit alone, than will be back in case of …
 

Attachments

  • IMG_5346.MOV
    12.1 MB

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top