|
|
View previous topic :: View next topic |
Author |
Message |
jacktaylor
Joined: 02 Sep 2017 Posts: 75
|
Program stopping in function #use delay () |
Posted: Fri Jan 26, 2018 6:42 am |
|
|
Hello friends, I am writing this simple library for a DS18B20 sensor in CCS, but when running the program in debug, I realized that the same in the unsigned function int read_temperature (); when trying to call delay_ms (750), the cursor is stopped in #use delay (clock = 4000000)
Could someone help me where the error is?
Code: | /* Library for DSb80b20 sensor. To start the reading and writing it is necessary to send 0 to the sensor data pin, this reset wakes the sensor and
and informs of the need for reading */
#include <16f877a.h>
#fuses xt, nowdt, nolvp, put, brownout
#use delay (clock = 4000000)
#use fast_io(a)
#use fast_io(b)
void escreve_zero();
void escreve_um();
void reset();
char leitura();
void escreve_comando (unsigned int comando);
unsigned int ler_memoria();
unsigned int ler_temperatura();
//Funcao de tempos Delays
//void time15us();
//void time70us();
//void time500us(); // Manual indicates delay of 480us
//void time750ms();
void main()
{
//set_tris_a(0x00);
set_tris_b(0x00); //TRISB = 0x00;
set_tris_c(0x00); //TRISC = 0x00;
output_b(0x00);
output_c(0x00);
while(1)
{
unsigned int temp = ler_temperatura();
output_b (temp); //PORTB= temp;
output_c(temp>>8); //PORTC= temp>>8;
}
}
void escreve_zero()
{
output_drive(PIN_A4); // this will set the tris bit for that pin to 0 (input)
output_low(PIN_A4); //PORTB_PIN_R4 = 0x00; // Coloca zero no pino
delay_us(70);
output_float(PIN_A4); // this will set the tris bit for that pin to 1 (output)
Minimum timeout 1us between each command sent requested in manual DS18B20
#asm NOP // The function asm NOP spends one machine cycle each or 2us for 4Mhz crystal
#endasm
#asm NOP
#endasm
}
void escreve_um()
{
output_drive(PIN_A4); // this will set the tris bit for that pin to 0 (output)
output_low(PIN_A4); //PORTB_PIN_R4 = 0x00; //
#asm goto ai; // in CCS Asm stay? #asm goto '$' + 1 to skip a line below // asm goto function spends two machine cycles GOTO needs a place to jump.
ai:
#endasm
output_float(PIN_A4); // this will set the tris bit for that pin to 1 (input)
delay_us(70);
}
char leitura() // lê o bit 1 ou 0
{
char valor;
output_drive(PIN_A4); // this will set the tris bit for that pin to 0 (output)
output_low(PIN_A4);//PORTB_PIN_R4 = 0x00; // Escreve zero
#asm goto '$'+1 //goto '$'+1 //#asm("goto $+1"); // Espera 2us
#endasm
output_float(PIN_A4); // this will set the tris bit for that pin to 1 (input)
#asm goto ap; //#asm("goto $+1"); // wait for 2us
ap:
#endasm
valor = PIN_A4 ;
delay_us(70);
return valor;
}
void reset()
{
output_drive(PIN_A4); // this will set the tris bit for that pin to 0 (output)
output_low(PIN_A4);// PORTB_PIN_R4 = 0x00;
delay_us(500);
output_float(PIN_A4); // this will set the tris bit for that pin to 1 (input)
delay_us(15);
while( input(PIN_A4== 1)) ;//PORTB_PIN_R4 == 1);
delay_us(500);
}
void escreve_comando (unsigned int comando)
{
int x = 0x00;
while (x<8) // writes the byte to the sensor
{
if (comando & 1) escreve_um(); // the function and (&) 1 + 1 = 1, if the first command bit is 1, then write 1
else escreve_zero();
comando = comando >>1;
x++;
}
}
unsigned int ler_memoria() // will read 2 byte bytes 0 and 1 of the temperature recorder
{
unsigned int valor = 0x00;
int x = 0x00;
while(x <16)
{
if (leitura()) // se leu bit =1
{
valor = (valor | (1 <<x));
}
x++;
}
reset();
return valor;
}
unsigned int ler_temperatura()
{ unsigned int resultado;
reset(); // inicia o sensor
escreve_comando(0xCC); // ROM boot command
escreve_comando(0x44); // Initiate temperature conversion
delay_ms(750);
reset(); // inicia o sensor
escreve_comando(0xCC);
escreve_comando(0xBE); // Reading sensor memory reading
resultado = ler_memoria();// The first 2 registers
return result;
}
|
Last edited by jacktaylor on Fri Jan 26, 2018 1:00 pm; edited 1 time in total |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19497
|
|
Posted: Fri Jan 26, 2018 8:21 am |
|
|
First thing, do you have a pull-up on pin A4?.
On this chip A4, is not a normal pin. It can only pull it's output down, not up. So to operate a reset line, there must be a pull up resistor on this, or it'll never go high...
You do realise you can get your two cycle delay with just delay_cycles(2);
This will actually code as a single jump forward.
The 80B20, uses the Maxim one wire interface, and there are drivers for this, supplied with the compiler (look for DS18B20.c), and in the code library.
Then there are some oddities with your comments:
Code: |
output_float(PIN_A4); // this will set the tris bit for that pin to 1 (output)
|
TRIS=1, is an Input. TRIS=0 implies Output.
You disagree with yourself and have the correct description later.
Now there is no mention of enabling DEBUG here. Are you using a debugger or a simulator?. If the latter a delay will take a long time. If using a debugger, what unit are you using?. What environment (CCS/MPLAB etc.)?. |
|
|
jacktaylor
Joined: 02 Sep 2017 Posts: 75
|
Thank Friend Ttelmah |
Posted: Fri Jan 26, 2018 12:57 pm |
|
|
Hi, friend Ttelmah. Thanks for the answer.
To create the program, I am using and querying the datasheet of the DS18B20 component, which indicates the use of a 4.7K resistor. My problem is only when executing delay_ms (750). I used delay_us (750000) and the program went to the next line non-stop in #use delay (clock = 4000000).
Yes I need tris TRIS = 1, is an Input. TRIS = 0 implies Output. When TRIS = 0 in the program I put Zero on the pin by the directive output_low (PIN_A4); When TRIS = 1 in the program, the pull-up resistor raises the pin level to 1. These are steps in the datasheet to configure the reading and writing of the DS18.
Yes, I realized that I can use delay_cycles(2) by reading the CCS manual, but I preferred to test by the asm code.
Friend Ttelmah, I'm in the apprenticeship phase, so I do not like at first to simply copy a library that is already ready, this slows the learning process, does not allow the programmer a reaction, because the library is ready. If it is just to copy libraries I would be using the Arduino. But the challenge is to learn.
To debug I am using the MPLAB IDE V8.92 with the CCS compiler.
This program ran perfect on another compiler, but I want to make it run on CCS I need to fix other steps. But I did not understand why I did not run the delay_ms (750). |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19497
|
|
Posted: Fri Jan 26, 2018 2:36 pm |
|
|
Thing is though that you need to start by being accurate with your comments.
Being in 'learning mode' is not an excuse to get remarks wrong. In fact it is exactly when you need to get them exactly right. Also you can see what the code does by simply looking at the listing, so doing things like goto's which are an excuse to make code go wrong, is a poor way to progress.
Now at least we have a little data. You are in MPLAB, and you do have a pull up resistor. However how are you powering the chip?. 4K7 is OK if you are powering the chip with a separate supply, but not if you are trying to power the chip off the bus. You need to be reading the data sheet. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Fri Jan 26, 2018 4:22 pm |
|
|
re:
when trying to call delay_ms (750), the cursor is stopped in #use delay (clock = 4000000)
Whenever a delay_ms(xx) or delay_us(yyy) is executed, the PIC will simply loop and decrement a counter(or 2) until the required time has elapsed.
'The cursor stopped' indicates you're using either a 'debug' or 'in circuit emulator'. Both of which slow down the PICs real speed unlike the 'release' version of the code.
As others have looked at your code, I won't comment on if it's constructed correctly, though there are some available in the Code Library here.
Jay |
|
|
jacktaylor
Joined: 02 Sep 2017 Posts: 75
|
Hi friend Temtronic |
Posted: Sat Jan 27, 2018 10:56 am |
|
|
Hello, Temtronic friend. What happens is that even when running the program in MPLAB debug and run mode, the green cursor that indicates the line of the program being executed is stopped in #use delay (clock = 4000000), this occurs when it reaches the line delay_ms ( 750);
in function:
Code: | unsigned int ler_temperatura()
{ unsigned int resultado;
reset(); // inicia o sensor
escreve_comando(0xCC); // ROM boot command
escreve_comando(0x44); // Initiate temperature conversion
delay_ms(750);
reset(); // inicia o sensor
escreve_comando(0xCC);
escreve_comando(0xBE); // Reading sensor memory reading
resultado = ler_memoria();// The first 2 registers
return result;
} |
if I put delay_us (750000) the program passes and executes all the programming. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19497
|
|
Posted: Sat Jan 27, 2018 11:43 am |
|
|
That's probably giving you a shorter delay....
Value is larger than the maximum the function supports.....
|
|
|
jacktaylor
Joined: 02 Sep 2017 Posts: 75
|
Thnak you friend Ttelmah |
Posted: Sat Jan 27, 2018 12:01 pm |
|
|
Yes my friend Ttelmah, it is bigger, but as I mentioned the program is not running when using delay_ms (750), this would be the correct value for being at 0-65535. I will review more details in this program.
Ttelmah wrote: | That's probably giving you a shorter delay....
Value is larger than the maximum the function supports.....
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19497
|
|
Posted: Sat Jan 27, 2018 12:18 pm |
|
|
By being larger, it is resulting in a shorter delay. You already know shorter delays work.
The key thing is you need to learn to do things one step at a time.
If you have a problem with debugging when delays are 750mSec, then test this:
Code: |
#include <16f877a.h>
#fuses xt, nowdt, nolvp, put, brownout
#use delay (clock = 4000000)
void main(void)
{
while(TRUE);
{
delay_ms(750);
output_toggle(PIN_A0); //change to a pin OK for you
}
}
|
Test your debugging. You can put a break on the toggle line and see what happens.
Now you have still not actually told us what the environment is. Yes. MPLAB, but what ICD?. What board holding the processor?. One thing that will give the behaviour you are describing is that the programmer is not erasing the fuses, and the watchdog is actually on.
What compiler version?. There was an issue with longer delays on a very old version (about 3.200ish).
As Temtronic was trying to explain, this may simply be what happens when you have a long delay:
<http://www.ccsinfo.com/forum/viewtopic.php?t=1787> |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jan 28, 2018 10:21 am |
|
|
jacktaylor wrote: |
The green cursor that indicates the line of the program being executed is
stopped in #use delay (clock = 4000000), this occurs when it reaches the
line delay_ms (750);
|
If you change the delay to 10us, the debugger will not hang in #use delay().
Example:
This was tested with CCS vs. 5.075, MPLAB vs. 8.92, and a PicKit 3
and a 16F1847 running at 5v. |
|
|
jacktaylor
Joined: 02 Sep 2017 Posts: 75
|
Hi friend Ttelmah |
Posted: Sun Jan 28, 2018 10:43 am |
|
|
I tested the code below. In Proteus I placed the oscilloscope in the output PIN_A0, but no oscillation occurred.
I created this function to timer.
Code: |
void time750ms()
{
for (unsigned int16 x=0 ; x<5; x++);
} |
The whole program I send does not run on Proteus, not debug. The output not changed to PIN_A0 does not oscillate. But in the debug in MPLAB V8.92 it works normally runs all the lines of the program
Code: |
/* Library for DSb80b20 sensor. To start the reading and writing it is necessary to send 0 to the sensor data pin, this reset wakes the sensor and
and informs of the need for reading */
#include <16f877a.h>
#fuses xt, nowdt, nolvp, put, brownout
#use delay(clock = 4000000)
#use fast_io(a)
#use fast_io(b)
void escreve_zero();
void escreve_um();
void reset();
char leitura();
void escreve_comando (unsigned int comando);
unsigned int ler_ler_memDS18();
unsigned int ler_tempDS18();
//Funcao de tempos Delays
void time15us();
void time70us();
void time500us(); // O manual pede delay de 480us
void time750ms();
void main()
{
//set_tris_a(0x00);
set_tris_b(0x00); //TRISB = 0x00;
set_tris_c(0x00); //TRISC = 0x00;
output_b(0x00);
output_c(0x00);
while(1)
{
unsigned int temp = ler_tempDS18();
output_b (temp); //PORTB= temp;
output_c(temp>>8); //PORTC= temp>>8;
}
}
void escreve_zero()
{
output_drive(PIN_A4); // this will set the tris bit for that pin to 0 (input)
output_low(PIN_A4); //PORTB_PIN_R4 = 0x00; // Coloca zero no pino
time70us();
//delay_us(70);
output_float(PIN_A4); // this will set the tris bit for that pin to 1 (output)
//#asm ("NOP") uso em outro compilador xom parenteses e colchetes. Tempo de intervalo minimo 1us entre cada comando enviado pedido no manual DS18B20
#asm NOP // A funcao asm NOP gasta um ciclo de máquina cada uma ou 2us para cristal de 4Mhz
#endasm
#asm NOP
#endasm
}
void escreve_um()
{
OUTPUT_DRIVE(PIN_A4); // THIS WILL SET THE TRIS BIT FOR THAT PIN TO 0 (OUTPUT)
OUTPUT_LOW(PIN_A4); //PORTB_PIN_R4 = 0X00; //
#ASM GOTO AI; //NO CCS ASM FICA? #ASM GOTO '$'+1 PARA SALTAR UMA LINHA ABAIXO // FUNCAO ASM GOTO GASTA DOIS CICLOS DE MAQUINA GOTO PRECISA DE UM LOCAL PARA SALTAR.
AI: // O MANUAL PEDE NO MINIMO 1US PARA MANTER O PINO=0
#ENDASM
OUTPUT_FLOAT(PIN_A4); // THIS WILL SET THE TRIS BIT FOR THAT PIN TO 1 (INPUT)
time70us();
//delay_us(70);
}
//*********Funções de tempo********
void time15us()
{
int x = 0x00;
while (x<1) x++;
}
void time70us()
{
int x = 0x00;
while (x<6) x++;
}
void time500us()
{
int x = 0x00;
while(x<49) x++;
}
void time750ms()
{
for (unsigned int16 x=0 ; x<5; x++);
}
//******inicio funcao leitura***************
char leitura() // lê bit 1 ou 0 na linha do sensor temperatura
{
char valor;
output_drive(PIN_A4); // this will set the tris bit for that pin to 0 (output)
output_low(PIN_A4); //PORTB_PIN_R4 = 0x00; // Escreve zero
//delay_cycles(2);
#asm NOP
#endasm
output_float(PIN_A4); // this will set the tris bit for that pin to 1 (input)
delay_cycles(2); // tem a mesma fucao de NOP, 2 ciclos de maquina
// #asm NOP <- este comando #asm saltar linha funcionou
// #endasm // com este-> #asm goto '$'+1, o programa nao executa a funcao leitura
valor = PIN_A4 ; // Leu o pino com 0 ou 1 e armazena em valor.
time70us();
//delay_us(70);
return valor; // retorna valor 0 ou 1
}// Fim funcao leitura
//******inicio funcao reset***************
void reset()
{
output_drive(PIN_A4); // this will set the tris bit for that pin to 0 (output)
output_low(PIN_A4);// PORTB_PIN_R4 = 0x00;
time500us();
//delay_us(500);
output_float(PIN_A4); // this will set the tris bit for that pin to 1 (input)
time15us();
//delay_us(15);
while( input(PIN_A4== 1)) ;// fica preso neste laço enquanto pino=1, qdo sensor responder ele envia para a linha a 0.
time500us();
//delay_us(500);
} //****Fim fucano reset
//******inicio funcao comando***************
void escreve_comando (unsigned int comando)
{
int x = 0x00;
while (x<8) // escreve o byte no sensor
{
if (comando & 1) escreve_um(); // a funcao and(&) 1+1=1, se primerio bit de comando é 1, entao escreve 1
else escreve_zero();
comando = comando >>1; // desloca o bit para direita
x++;
}
}//****Fim funcao comando
unsigned int ler_memDS18() // vai ler 2 bytes byte 0 e 1 do registrador de temperatura
{
unsigned int valor = 0x00;
int x = 0x00;
while(x <16)
{
if (leitura()) // se leitura tem bit = 1, Leu um bit. executa valor
{
valor = (valor | (1 <<x));
}
x++;
}
reset();
return valor;
} // **fim funcao comando
unsigned int ler_tempDS18()
{
unsigned int resultado;
reset(); // inicia o sensor
escreve_comando(0xCC); // Comando de inicio da memoria ROM
escreve_comando(0x44); // Inicia conversao da temperatura
time750ms(); // tempo necsessario para conversao
//delay_ms(750); //O compilador esta gerando erro na exucucao do progrma ao usar ms(750), nao gera erro ao usar us(750000)
reset(); // inicia o sensor
escreve_comando(0xCC); // Comando de inicio da memoria ROM
escreve_comando(0xBE); // Comando de ler memoria do sensor
resultado = ler_memDS18(); // Le os 2 primeros registradores
return resultado;
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jan 28, 2018 11:00 am |
|
|
I can't understand your comments. Do you still have a problem ? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19497
|
|
Posted: Sun Jan 28, 2018 11:34 am |
|
|
Read the 'Sticky' at the head of the forum about Proteus.
It is fundamentally flawed. Do not waste time trying to work with it for PIC emulation. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Sun Jan 28, 2018 11:39 am |
|
|
this...
Quote: | The whole program I send does not run on Proteus, |
is WHY I've said for years to NOT use Proteus ! It's so full of 'busted code' and a HUGE time waster. See PIC101 sticky.
As for DS18B20 code, there is some in the code library, which works and I'll add that if you want to use multiple devices, it's easier to just copy the 'driver', renaming as required, for each device. These sensors are 'time critical' and this way is probably the best solution.
Jay |
|
|
jacktaylor
Joined: 02 Sep 2017 Posts: 75
|
Friend Temtronic |
Posted: Sun Jan 28, 2018 12:47 pm |
|
|
Friend the program you sent also did not run in the MPLAB IDE, ie the PIN_A0 does not change the state between 0 and 1. I did the simulation using the step into MPLBA.
temtronic wrote: | this...
Quote: | The whole program I send does not run on Proteus, |
is WHY I've said for years to NOT use Proteus ! It's so full of 'busted code' and a HUGE time waster. See PIC101 sticky.
As for DS18B20 code, there is some in the code library, which works and I'll add that if you want to use multiple devices, it's easier to just copy the 'driver', renaming as required, for each device. These sensors are 'time critical' and this way is probably the best solution.
Jay |
|
|
|
|
|
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
|