Sari la conținut
ELFORUM - Forumul electronistilor

pic16f887+LCD +18s20 [mikroC]


ducu

Postări Recomandate

Salut, am facut de curand un test cu acest microcontroler[pic16f887] lcd[2x16] si senzor[18s20] de temperatura, totul functioneaza ireprosabil, mai putin afisarea simbolului "-" [minus] cand detecteaza temperaturi negative.

Mentionez ca testul a constat in simulare [Proteus] si fizic pe o placa breadboard.Concluzia?!, acelasi rezultat.

Nu reusesc sa imi dau seama ce nu e in regula.

Limbajul folosit este mikroC.

Puteti sa imi dati o mana de ajutor in aceasta privinta?

Programul:

//TERMOMETRU ELECTRONIC CU PIC16F887 LCD 2X16 SI SENZOR DE TEMPERATURA DS18S20

// declara conexiunea lcd

sbit LCD_RS at RB4_bit;

sbit LCD_EN at RB5_bit;

sbit LCD_D4 at RB0_bit;

sbit LCD_D5 at RB1_bit;

sbit LCD_D6 at RB2_bit;

sbit LCD_D7 at RB3_bit;

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;

// sfarsit de declaratie

 

const unsigned short TEMP_RESOLUTION = 9;

char *text = "000.0000";

unsigned temp;

 

void Display_Temperature(unsigned int temp2write) {

const unsigned short RES_SHIFT = TEMP_RESOLUTION - 8;

char temp_whole;

unsigned int temp_fraction;

 

// verificare pentru temperaturi negative

if (temp2write & 0x8000) {

text[0] = '-';

temp2write = ~temp2write + 1;

}

// extrage temp_whole

temp_whole = temp2write >> RES_SHIFT ;

 

// converteste temp_whole in caractere

if (temp_whole/100)

text[0] = temp_whole/100 + 48;

else

text[0] = '0';

 

text[1] = (temp_whole/10)%10 + 48; // extrage zecimi

text[2] = temp_whole%10 + 48; // extrage unitati

 

// extrage temp_fraction si converteste in unsigned int

temp_fraction = temp2write << (4-RES_SHIFT);

temp_fraction &= 0x000F;

temp_fraction *= 625;

 

// converteste temp_fraction in caractere

text[4] = temp_fraction/1000 + 48; // extrage miile

text[5] = (temp_fraction/100)%10 + 48; // extrage sutele

text[6] = (temp_fraction/10)%10 + 48; // extrage zecile

text[7] = temp_fraction%10 + 48; // extrage unitatile

 

// afisare temp. pe LCD

Lcd_Out(2, 5, text);

}

 

void main() {

ANSEL = 0; // Configureaza pinii AN ca i/o digitali

ANSELH = 0;

C1ON_bit = 0; // comparator dezactivat

C2ON_bit = 0;

 

Lcd_Init(); // Initializeaza LCD

Lcd_Cmd(_LCD_CLEAR); // curata LCD

Lcd_Cmd(_LCD_CURSOR_OFF); // cursor off

Lcd_Out(1, 1, " Temperatura: ");

 

// aviseaza caracterul, 'C' pentru grade Celsius

Lcd_Chr(2,13,223); // char code pentru lcd 178 sau 223 [afiseaza grade]

 

Lcd_Chr(2,14,'C');

 

//--- bucla principala

do {

//--- citire temperatura

Ow_Reset(&PORTE, 2); // Onewire semnal de reset

Ow_Write(&PORTE, 2, 0xCC); // comanda SKIP_ROM

Ow_Write(&PORTE, 2, 0x44); // comanda CONVERT_T

Delay_us(120);

Ow_Reset(&PORTE, 2);

Ow_Write(&PORTE, 2, 0xCC); // comanda SKIP_ROM

Ow_Write(&PORTE, 2, 0xBE); // comanda READ_SCRATCHPAD

temp = Ow_Read(&PORTE, 2);

temp = (Ow_Read(&PORTE, 2) << 8) + temp;

 

//--- formati si afisare pe lcd

Display_Temperature(temp);

Delay_ms(500);

} while (1);

}

 

Rezultatul:

Posted Image

Link spre comentariu
  • Răspunsuri 10
  • Creat
  • Ultimul Răspuns

Top autori în acest subiect

  • ducu

    6

  • Liviu M

    3

  • A_L_E_X

    1

  • gabrielmrc

    1

Top autori în acest subiect

Eu cred ca suprascrii "-" din text[0] cand convertesti in caractere.

 

// verificare pentru temperaturi negativeif (temp2write & 0x8000) {text[0] = '-';temp2write = ~temp2write + 1;}

// converteste temp_whole in caractereif (temp_whole/100)text[0] = temp_whole/100 + 48;elsetext[0] = '0';
Link spre comentariu

Pai e normal.

Ar trebui o locatie independenta la inceputul textului in care sa scrii sau nu '-'.

O varianta ar fi sa "lungesti" text[] cu un caracter, semnul, pentru care o sa afisezi '-' sau ' '/'':

 

// verificare pentru temperaturi negativeif (temp2write & 0x8000) {    text[0] = '-';   temp2write = ~temp2write + 1;}else    text[0] = ' ';  //blank sau nimic

Pentru afisatul numarului, incepi cu text[1] pentru sute (aduni o unitate la indexul afisarii numarului).

 

O alta varianta ar fi sa scrii direct semnul inainte de restul numarului si sa lasi afisarea numarului asa cum e:

 

// verificare pentru temperaturi negativeif (temp2write & 0x8000) {    Lcd_Out(2, 4, '-');    temp2write = ~temp2write + 1;}else    Lcd_Out(2, 4, ' ');

In functie de cum e definitn Lcd_Out(), sunt sanse sa trebuiasca sa scrii - sub forma de sir:

Lcd_Out(2, 4, "-");
Link spre comentariu

Multumesc Liviu M pentru asistenta, am incercat ce ai spus, functioneaza pe jumatate ambele variante, temperatura negativa este afisata dar cand vin pe temperatura pozitiva ramane blocat pe 8 grade celsius, indiferent de caracterul ales pentru + si -. din variantele tale am observat ca ai scos:

temp_whole = temp2write >> RES_SHIFT;

// convert temp_whole to characters

if (temp_whole/100)

// 48 is the decimal character code value for displaying 0 on LCD

temp[0] = temp_whole/100 + 48;

__________________________________________________________

aici e problema zic eu pentru ca daca aduc un delay_ms(1000) la declaratiile scoase de tine din program

observ cum oscileaza intre simbolul "-" si "+", atunci cand sunt pe temperaturi negative.

 

Ciundat mi se pare si faptul ca cei de la Mikroelektronika au scris in cartea lor despre microcontrolere, ca varianta este functionala dar, la teste se comporta ca in cazul de fata.

Link spre comentariu

Eu n-am vrut sa scot nimic din program, :jytuiyu voiam doar sa modific partea cu semnul.

Sper ca ai inteles ce voiam sa fac: mie mi s-a parut ca dupa ce setezi semnul pe minus, il "tergi" cu caracterul pentru sute.

In prima varianta, ti-am aratat cum as face eu sa afiseze si minus; stergerea lui in cazul numerelor pozitive n-am implementat-o.

In variatele din mesajul anterior, ma ocupam pe indelete de semn in ambele cazuri, dar fara sa incerc modificarea altei parti din program.

Bucatelele mele trebuie sa inlocuiasca fix blocul cu detectia si afisarea minusului din programul original. Exceptand eventual indecsii lui text[], restul programului original trebuie sa ramana cum era.

 

LE Daca ai indenta textul:

void Display_Temperature(unsigned int temp2write) {   const unsigned short RES_SHIFT = TEMP_RESOLUTION - 8;   char temp_whole;   unsigned int temp_fraction;// verificare pentru temperaturi negative   if (temp2write & 0x8000) {      text[0] = '-';      temp2write = ~temp2write + 1;   }// extrage temp_whole   temp_whole = temp2write >> RES_SHIFT ;// converteste temp_whole in caractere   if (temp_whole/100)        text[0] = temp_whole/100 + 48;   else        text[0] = '0';   text[1] = (temp_whole/10)%10 + 48; // extrage zecimi   text[2] = temp_whole%10 + 48; // extrage unitati// extrage temp_fraction si converteste in unsigned int   temp_fraction = temp2write << (4-RES_SHIFT);   temp_fraction &= 0x000F;   temp_fraction *= 625;// converteste temp_fraction in caractere   text[4] = temp_fraction/1000 + 48; // extrage miile   text[5] = (temp_fraction/100)%10 + 48; // extrage sutele   text[6] = (temp_fraction/10)%10 + 48; // extrage zecile   text[7] = temp_fraction%10 + 48; // extrage unitatile// afisare temp. pe LCD   Lcd_Out(2, 5, text);}
ai vedea ca atribuirile pe care zici ca le-am "pierdut" nu fac parte din blocul de detectie a semnului.
Link spre comentariu

Nici o problema Liviu M, am inteles eu ce ai incercat sa faci, am facut si asta deja dar cand vin pe temperatura negativa oscileaza rapid intre "0" si "-", asta nu inteleg eu, de ce intra in fibrilatie, sa zic asa.am schimbat si locatia caracterului pe lcd dar tot asa face.Ciudat tare.

Link spre comentariu

Am reusit sa rezolv problema. Testul de fata este facut cu ds18b20 dar programul este aproape identic.

Se poate modifica softul sa functioneze si pe alte microcontrolere, foarte simplu.

Rezultatul il postez mai jos.

Am creat un marker care modifica la randul sau flag-ul pentru a nu suprascrie peste "temp[0]".

Codul functional este acesta:

//Microcontroller P16f887//Oscilator intern 8MHz//Domeniu de masurare in grade Celsius [-55~+128] cu pas de 0,1 grade Celsius// LCD module connectionssbit LCD_RS at RB4_bit;sbit LCD_EN at RB5_bit;sbit LCD_D4 at RB0_bit;sbit LCD_D5 at RB1_bit;sbit LCD_D6 at RB2_bit;sbit LCD_D7 at RB3_bit;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;// End LCD module connections//  Set TEMP_RESOLUTION to the corresponding resolution of used DS18x20 sensor://  18S20: 9  (default setting; can be 9,10,11,or 12)//  18B20: 12const unsigned short TEMP_RESOLUTION = 12;char *text = "000,0";unsigned temp;void Display_Temperature(unsigned int temp2write) {  const unsigned short RES_SHIFT = TEMP_RESOLUTION - 8;  char temp_whole;  unsigned int temp_fraction;  unsigned short isNegative = 0x00;  // Check if temperature is negative  if (temp2write & 0x8000) {     text[0] = '-';     temp2write = ~temp2write + 1;     isNegative = 1;     }  // Extract temp_whole  temp_whole = temp2write >> RES_SHIFT ;  // Convert temp_whole to characters  if (!isNegative){  if (temp_whole/100)  text[0] = temp_whole/100  + 48;  else  text[0] = '+';  }  text[1] = (temp_whole/10)%10 + 48;             // Extract tens digit  text[2] =  temp_whole%10     + 48;             // Extract ones digit  // Extract temp_fraction and convert it to unsigned int  temp_fraction  = temp2write << (4-RES_SHIFT);  temp_fraction &= 0x000F;  temp_fraction *= 625;  // Convert temp_fraction to characters  text[4] =  temp_fraction/1000    + 48;         // Extract thousands digit  //text[5] = (temp_fraction/100)%10 + 48;         // Extract hundreds digit  //text[6] = (temp_fraction/10)%10  + 48;         // Extract tens digit  //text[7] =  temp_fraction%10      + 48;         // Extract ones digit  // Print temperature on LCD  Lcd_Out(2, 5, text);}const char character[] = {4,10,4,0,0,0,0,0};void CustomChar(char pos_row, char pos_char) {  char i;    Lcd_Cmd(64);    for (i = 0; i<=7; i++) Lcd_Chr_CP(character[i]);    Lcd_Cmd(_LCD_RETURN_HOME);    Lcd_Chr(pos_row, pos_char, 0);}void main() {  CMCON |=7;  Lcd_Init();                                    // Initialize LCD  Lcd_Cmd(_LCD_CLEAR);                           // Clear LCD  Lcd_Cmd(_LCD_CURSOR_OFF);                      // Turn cursor off  Lcd_Out(1, 3, "Temperatura:");  // Print degree character, 'C' for Centigrades  CustomChar(2,10);                             // Different LCD displays have different char code for degree                                                 // If you see greek alpha letter try typing 178 instead of 223  Lcd_Chr(2,11,'C');  //--- Main loop  do {    //--- Perform temperature reading    Ow_Reset(&PORTA, 1);                         // Onewire reset signal    Ow_Write(&PORTA, 1, 0xCC);                   // Issue command SKIP_ROM    Ow_Write(&PORTA, 1, 0x44);                   // Issue command CONVERT_T    Delay_us(600);    Ow_Reset(&PORTA, 1);    Ow_Write(&PORTA, 1, 0xCC);                   // Issue command SKIP_ROM    Ow_Write(&PORTA, 1, 0xBE);                   // Issue command READ_SCRATCHPAD    temp =  Ow_Read(&PORTA, 1);    temp = (Ow_Read(&PORTA, 1) << 8) + temp;    //--- Format and display result on Lcd    Display_Temperature(temp);    Delay_ms(400);  } while (1);}
Mentionez de asemenea ca modificarile au fost facute de catre Aleksandar. Multumirile mele catre dansul.

Datorita donatie facute acum ceva timp de catre sofian, in care am primit printre multe altele si doua picuri 16f628A, am reusit sa realizez si practic acest poriect.Multumirile mele profunde catre sofian.

 

Rezultatul testului:

Posted Image

 

Posted Image

Posted Image

Link spre comentariu
  • 10 luni mai târziu...

Am reusit sa rezolv problema. Testul de fata este facut cu ds18b20 dar programul este aproape identic.

Se poate modifica softul sa functioneze si pe alte microcontrolere, foarte simplu.

Rezultatul il postez mai jos.

Am creat un marker care modifica la randul sau flag-ul pentru a nu suprascrie peste "temp[0]".

Codul functional este acesta:

//Microcontroller P16f887//Oscilator intern 8MHz//Domeniu de masurare in grade Celsius [-55~+128] cu pas de 0,1 grade Celsius// LCD module connectionssbit LCD_RS at RB4_bit;sbit LCD_EN at RB5_bit;sbit LCD_D4 at RB0_bit;sbit LCD_D5 at RB1_bit;sbit LCD_D6 at RB2_bit;sbit LCD_D7 at RB3_bit;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;// End LCD module connections//  Set TEMP_RESOLUTION to the corresponding resolution of used DS18x20 sensor://  18S20: 9  (default setting; can be 9,10,11,or 12)//  18B20: 12const unsigned short TEMP_RESOLUTION = 12;char *text = "000,0";unsigned temp;void Display_Temperature(unsigned int temp2write) {  const unsigned short RES_SHIFT = TEMP_RESOLUTION - 8;  char temp_whole;  unsigned int temp_fraction;  unsigned short isNegative = 0x00;  // Check if temperature is negative  if (temp2write & 0x8000) {     text[0] = '-';     temp2write = ~temp2write + 1;     isNegative = 1;     }  // Extract temp_whole  temp_whole = temp2write >> RES_SHIFT ;  // Convert temp_whole to characters  if (!isNegative){  if (temp_whole/100)  text[0] = temp_whole/100  + 48;  else  text[0] = '+';  }  text[1] = (temp_whole/10)%10 + 48;             // Extract tens digit  text[2] =  temp_whole%10     + 48;             // Extract ones digit  // Extract temp_fraction and convert it to unsigned int  temp_fraction  = temp2write << (4-RES_SHIFT);  temp_fraction &= 0x000F;  temp_fraction *= 625;  // Convert temp_fraction to characters  text[4] =  temp_fraction/1000    + 48;         // Extract thousands digit  //text[5] = (temp_fraction/100)%10 + 48;         // Extract hundreds digit  //text[6] = (temp_fraction/10)%10  + 48;         // Extract tens digit  //text[7] =  temp_fraction%10      + 48;         // Extract ones digit  // Print temperature on LCD  Lcd_Out(2, 5, text);}const char character[] = {4,10,4,0,0,0,0,0};void CustomChar(char pos_row, char pos_char) {  char i;    Lcd_Cmd(64);    for (i = 0; i<=7; i++) Lcd_Chr_CP(character[i]);    Lcd_Cmd(_LCD_RETURN_HOME);    Lcd_Chr(pos_row, pos_char, 0);}void main() {  CMCON |=7;  Lcd_Init();                                    // Initialize LCD  Lcd_Cmd(_LCD_CLEAR);                           // Clear LCD  Lcd_Cmd(_LCD_CURSOR_OFF);                      // Turn cursor off  Lcd_Out(1, 3, "Temperatura:");  // Print degree character, 'C' for Centigrades  CustomChar(2,10);                             // Different LCD displays have different char code for degree                                                 // If you see greek alpha letter try typing 178 instead of 223  Lcd_Chr(2,11,'C');  //--- Main loop  do {    //--- Perform temperature reading    Ow_Reset(&PORTA, 1);                         // Onewire reset signal    Ow_Write(&PORTA, 1, 0xCC);                   // Issue command SKIP_ROM    Ow_Write(&PORTA, 1, 0x44);                   // Issue command CONVERT_T    Delay_us(600);    Ow_Reset(&PORTA, 1);    Ow_Write(&PORTA, 1, 0xCC);                   // Issue command SKIP_ROM    Ow_Write(&PORTA, 1, 0xBE);                   // Issue command READ_SCRATCHPAD    temp =  Ow_Read(&PORTA, 1);    temp = (Ow_Read(&PORTA, 1) << 8) + temp;    //--- Format and display result on Lcd    Display_Temperature(temp);    Delay_ms(400);  } while (1);}
Mentionez de asemenea ca modificarile au fost facute de catre Aleksandar. Multumirile mele catre dansul.

Datorita donatie facute acum ceva timp de catre sofian, in care am primit printre multe altele si doua picuri 16f628A, am reusit sa realizez si practic acest poriect.Multumirile mele profunde catre sofian.

 

Rezultatul testului:

Posted Image

 

Posted Image

Posted Image

raspunsul meu nu prea ajuta cu nimic pe mine m-ar interesa schema electrica a circuitului pe care l-ai realizat.ms anticipat

Link spre comentariu
  • 6 luni mai târziu...

Creează un cont sau autentifică-te pentru a adăuga comentariu

Trebuie să fi un membru pentru a putea lăsa un comentariu.

Creează un cont

Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!

Înregistrează un nou cont

Autentificare

Ai deja un cont? Autentifică-te aici.

Autentifică-te acum



×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.Termeni de Utilizare si Ghidări