Autor Tema: Problemas con Delay  (Leído 2427 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Kspids

  • PIC16
  • ***
  • Mensajes: 192
Problemas con Delay
« en: 19 de Diciembre de 2019, 04:28:57 »
Hola a todos! Qué tal va el final del año???
Verán, tengo un problemilla con unos delays en mi código.
Estoy utilizando un sensor de Tª (ds18b20) en mi micro STM32F469. Me he basado en unos ejemplos de configuración que vi en la red y parece ser que al ser 1 wire precisa de delays para trasferencia de datos. El problema que tengo es que mientras este sensor toma muestra me para el programa entonces mi pregunta es:
¿cómo puedo hacer para que no haga esto? Dónde puedo ubicar el código del sensor para que esté trabajando siempre sin que me afecte al programa principal?
Como pueden ver en el programa, tengo repetido siempre la parte del sensor y es para que no afecte entre transición y transición pero claro, los delays me siguen parando la ejecución dentro de cada bucle if...
Código: [Seleccionar]
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);

GPIO_InitTypeDef GPIO_InitStruct;

void gpio_set_input (void)
{
  GPIO_InitStruct.Pin = GPIO_PIN_3;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
}


void gpio_set_output (void)
{
  GPIO_InitStruct.Pin = GPIO_PIN_3;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
}

uint8_t check =2, temp_l, temp_h;
uint16_t temp;
float temperature;

uint8_t ds18b20_init (void)
{
   gpio_set_output ();   // set the pin as output
   HAL_GPIO_WritePin (GPIOE, GPIO_PIN_3, 0);  // pull the pin low
   DWT_Delay_us (480);   // delay according to datasheet

   gpio_set_input ();    // set the pin as input
   DWT_Delay_us (80);    // delay according to datasheet

   if (!(HAL_GPIO_ReadPin (GPIOE, GPIO_PIN_3))){    // if the pin is low i.e the presence pulse is there
   DWT_Delay_us (400);  // wait for 400 us
   return 0;
   }
   else{
   DWT_Delay_us (400);
   return 1;
   }
   }


void write (uint8_t data){
gpio_set_output ();   // set as output
for (int i=0; i<8; i++){
if ((data & (1<<i))!=0){  // if the bit is high
// write 1
gpio_set_output ();  // set as output
HAL_GPIO_WritePin (GPIOE, GPIO_PIN_3, 0);  // pull the pin LOW
DWT_Delay_us (1);  // wait for  us

gpio_set_input ();  // set as input
DWT_Delay_us (60);  // wait for 60 us
}
else{  // if the bit is low
// write 0
gpio_set_output ();
HAL_GPIO_WritePin (GPIOE, GPIO_PIN_3, 0);  // pull the pin LOW
DWT_Delay_us (60);  // wait for 60 us
gpio_set_input ();
}
}
}

uint8_t read (void){
uint8_t value=0;
gpio_set_input ();

for (int i=0;i<8;i++){
gpio_set_output ();   // set as output
HAL_GPIO_WritePin (GPIOE, GPIO_PIN_3, 0);  // pull the data pin LOW
DWT_Delay_us (2);  // wait for 2 us

gpio_set_input ();  // set as input
if (HAL_GPIO_ReadPin (GPIOE, GPIO_PIN_3)){ // if the pin is HIGH
value |= 1<<i;  // read = 1
}
DWT_Delay_us (60);  // wait for 60 us
}
return value;
}

int main(void) {

char line[41]; // To build lines for the lcd

// STM32F7xx HAL library initialization
if (HAL_Init() != HAL_OK) {
blink_error_code(ERROR_HAL_INIT);
}

// Configure the system clock
SystemClock_Config();
lcdInit();
DWT_Delay_Init ();

// Verificar si es un reset de iwdg
if (__HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST) != RESET) {
__HAL_RCC_CLEAR_RESET_FLAGS();
lcdPutsCenter(0, "RESET POR");
lcdPutsCenter(1, "WATCHDOG");
HAL_Delay(2000);
}

// Inicializar iwdg
IwdgHandle.Instance = IWDG;
IwdgHandle.Init.Prescaler = IWDG_PRESCALER_128;
IwdgHandle.Init.Reload = 0x8ff;

HAL_IWDG_Init(&IwdgHandle);


////// Main loop //////
while (1) {

// Refrescar watch dog
HAL_IWDG_Refresh(&IwdgHandle);

//JUEGO DE LUCES//
if (TEST_IN_STATE == IS_TEST_IN_ON) {
LED_R1_OFF;
LED_R2_OFF;
HAL_Delay(200);
LED_V1_ON;
LED_V2_ON;
}

if (CAMBIO_IN_STATE == IS_CAMBIO_IN_ON) {
LED_ERR_ON;
HAL_Delay(1000);
if ((DM1_IN_STATE == IS_DM1_IN_ON)||(DM2_IN_STATE == IS_DM2_IN_ON)||(DM3_IN_STATE == IS_DM3_IN_ON)){
LED_ERR_OFF;
}
else{
LED_ERR_ON;
}
}

else if (CO2_IN_STATE == IS_CO2_IN_ON) {
sprintf(line, "SIN CO2");
lcdPutsCenter(1, line);
LED_ERR_ON;

if (CERO_IN_STATE == IS_CERO_IN_ON){
LED_ERR_OFF;
}
else{
sprintf(line, "NAME");
lcdPutsCenter(1, line);
}
}

if ((DM1_IN_STATE == IS_DM1_IN_ON)&&(DM2_IN_STATE == IS_DM2_IN_ON)&&(DM3_IN_STATE == IS_DM3_IN_ON)) {

if(CERO_IN_STATE == IS_CERO_IN_OFF){
LED_ERR_ON;
}
else{
LED_ERR_OFF;
}
if (((HAL_GetTick() - tiempo) > 30000)){
check = ds18b20_init ();
write (0xCC);  // skip ROM
write (0x44);  // convert t
HAL_Delay (94);

ds18b20_init ();
write (0xCC);  // skip ROM
write (0xBE);  // Read Scratchpad

temp_l = read();
temp_h = read();
temp = (temp_h<<8)|temp_l;
temperature = (float)temp/16;

sprintf(line, "TEMP6:");
lcdPutsCenter(1, line);

HAL_Delay(400);

check = ds18b20_init ();
write (0xCC);  // skip ROM
write (0x44);  // convert t
HAL_Delay (94);

ds18b20_init ();
write (0xCC);  // skip ROM
write (0xBE);  // Read Scratchpad

temp_l = read();
temp_h = read();
temp = (temp_h<<8)|temp_l;
temperature = (float)temp/16;

sprintf(line, "TEMP6: %d \337C ",(int)(temperature));
lcdPutsCenter(1, line);
tiempo = HAL_GetTick();
}
}


else if ((DM1_IN_STATE == IS_DM1_IN_ON)&&(DM2_IN_STATE == IS_DM2_IN_ON)&&(DM3_IN_STATE == IS_DM3_IN_OFF)) {

if(SW3_IN_STATE == IS_SW3_IN_OFF){
LED_ERR_ON;
}
else{
LED_ERR_OFF;
HAL_Delay(1000);
}

if (((HAL_GetTick() - tiempo) > 30000)){
check = ds18b20_init ();
write (0xCC);  // skip ROM
write (0x44);  // convert t
HAL_Delay (94);

ds18b20_init ();
write (0xCC);  // skip ROM
write (0xBE);  // Read Scratchpad

temp_l = read();
temp_h = read();
temp = (temp_h<<8)|temp_l;
temperature = (float)temp/16;

sprintf(line, "TEMP6:");
lcdPutsCenter(1, line);

HAL_Delay(400);

check = ds18b20_init ();
write (0xCC);  // skip ROM
write (0x44);  // convert t
HAL_Delay (94);

ds18b20_init ();
write (0xCC);  // skip ROM
write (0xBE);  // Read Scratchpad

temp_l = read();
temp_h = read();
temp = (temp_h<<8)|temp_l;
temperature = (float)temp/16;

sprintf(line, "TEMP6: %d \337C ",(int)(temperature));
lcdPutsCenter(1, line);
tiempo = HAL_GetTick();
}
}

else if ((DM1_IN_STATE == IS_DM1_IN_ON)&&(DM2_IN_STATE == IS_DM2_IN_OFF)&&(DM3_IN_STATE == IS_DM3_IN_ON)) {

if(SW2_IN_STATE == IS_SW2_IN_OFF){
LED_ERR_ON;
}
else{
LED_ERR_OFF;
HAL_Delay(1000);
}
if (((HAL_GetTick() - tiempo) > 30000)){
check = ds18b20_init ();
write (0xCC);  // skip ROM
write (0x44);  // convert t
HAL_Delay (94);

ds18b20_init ();
write (0xCC);  // skip ROM
write (0xBE);  // Read Scratchpad

temp_l = read();
temp_h = read();
temp = (temp_h<<8)|temp_l;
temperature = (float)temp/16;

sprintf(line, "TEMP6:");
lcdPutsCenter(1, line);

HAL_Delay(400);

check = ds18b20_init ();
write (0xCC);  // skip ROM
write (0x44);  // convert t
HAL_Delay (94);

ds18b20_init ();
write (0xCC);  // skip ROM
write (0xBE);  // Read Scratchpad

temp_l = read();
temp_h = read();
temp = (temp_h<<8)|temp_l;
temperature = (float)temp/16;

sprintf(line, "TEMP6: %d \337C ",(int)(temperature));
lcdPutsCenter(1, line);
tiempo = HAL_GetTick();
}
}

else if ((DM1_IN_STATE == IS_DM1_IN_OFF)&&(DM2_IN_STATE == IS_DM2_IN_ON)&&(DM3_IN_STATE == IS_DM3_IN_ON)) {

if(SW1_IN_STATE == IS_SW1_IN_OFF){
LED_ERR_ON;
}
else{
LED_ERR_OFF;
HAL_Delay(1000);
}

if (((HAL_GetTick() - tiempo) > 30000)){
check = ds18b20_init ();
write (0xCC);  // skip ROM
write (0x44);  // convert t
HAL_Delay (94);

ds18b20_init ();
write (0xCC);  // skip ROM
write (0xBE);  // Read Scratchpad

temp_l = read();
temp_h = read();
temp = (temp_h<<8)|temp_l;
temperature = (float)temp/16;

sprintf(line, "TEMP6:");
lcdPutsCenter(1, line);


HAL_Delay(400);

check = ds18b20_init ();
write (0xCC);  // skip ROM
write (0x44);  // convert t
HAL_Delay (94);

ds18b20_init ();
write (0xCC);  // skip ROM
write (0xBE);  // Read Scratchpad

temp_l = read();
temp_h = read();
temp = (temp_h<<8)|temp_l;
temperature = (float)temp/16;

sprintf(line, "TEMP6: %d \337C ",(int)(temperature));
lcdPutsCenter(1, line);
tiempo = HAL_GetTick();
}
}
}
}

}

Espero su ayuda compañeros!!

Desconectado Kspids

  • PIC16
  • ***
  • Mensajes: 192
Re:Problemas con Delay
« Respuesta #1 en: 23 de Diciembre de 2019, 04:37:45 »
Alguna idea???

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Problemas con Delay
« Respuesta #2 en: 23 de Diciembre de 2019, 07:22:15 »
Como evitar que te detengan el programa:
- Evitar los delays largos
- Evitar delays seguidos y cortos (50us a mas) ( que hagan como uno demasiado largo)

Si los delays son muy largos:
- Tratar de usar timers/Ticks y que cuando se cumpla el tiempo proceder a hacer lo que sigue. Esto exige que tu programa principal tampoco tenga demasiados delays. O poner un delay para todo.
- Podes usar interrupciones para lo anterior.


Todo va a depender del programa que tengas y el tiempo de los delays.
Y seguramente debas cambiar enteramente la forma del programa.

Desconectado scrwld

  • PIC12
  • **
  • Mensajes: 59
Re:Problemas con Delay
« Respuesta #3 en: 23 de Diciembre de 2019, 23:43:28 »
hola kspids. prueba adaptando lo que sigue, lo tome del foro de melabs y lo uso con una tarjeta que  usa un ds18b20
uso picbasic

'////////////////////////CARGO TIMER 1 USO LECTURA TEMPERATURA ////////////////////////////////
T1CON = %00110001      ' Prescaler 1:8; TMR1 Preload = 3036; Actual Interrupt Time : 100 ms
TMR1H = T1HI           ' cada 10 overflow igual 1 seg.
TMR1L = T1LO
'************************** INICIALIZO TIMER1  ***********************
O_FLOWS=0              ' clear overflow count
PIR1.0=0               ' clear timer1 overflow flag
T1CON.0=1              ' start timer1

 '**********************************************
' Note: Timer1 overflows every 0.2 seconds, so we have time to execute
' a whopping 200,000 single-cycle instructions before this section is
' executed
IF PIR1.0 THEN           ' if timer1 overflow then
    O_FLOWS=O_FLOWS+1     ' inc oveflow counter
      IF O_FLOWS=10 THEN     ' if 1 second elapsed then
         OWOUT DQ,1,[$CC,$44]
      ENDIF
      IF O_FLOWS=100 THEN     ' if 1 second elapsed then
         O_FLOWS=0          ' reset overflow counter
         gosub readtemp    ' aqui leo temperatura
      ENDIF     
      PIR1.0=0              ' clear timer1 overflow flag
      T1CON.0 = 0           ' stop timer1
      TMR1L = TMR1L + T1LO  ' add in low byte
      IF TMR1L < T1LO THEN  TMR1H = TMR1H + 1  ' if low byte overflow, increment high byte
      TMR1H = TMR1H + T1HI  ' add in high byte
      T1CON.0=1             ' re-start timer1
ENDIF

*********************************************
ReadTemp:
OWOut DQ, 1, [$CC, $BE]      ' INICIALIZO LECTURAS TEMPERATURA
'******************************************************************************
IF DS18XX=16 THEN  ' SI EL SENSOR ES DS1820 - DS18S20
    OWIn DQ, 0, [temperature.LOWBYTE, temperature.HIGHBYTE, Skip 4, count_remain, count_per_c]
        If Temperature.HighBit = 1 Then ;check for < 0C
            ;Subtract from 0 to read below 0 value
            Temperature =  $0000-Temperature'Temperature = ~Temperature+1'
            Temperature = -Temperature
        endif
    temperature = (((temperature >> 1) * 100) - 25) + (((count_per_c - count_remain) * 100) / count_per_c)
ENDIF
IF DS18XX=40 THEN  'SI SENSOR ES DS18B20
    OWIn DQ, 0, [temperature.LOWBYTE, temperature.HIGHBYTE]
        If Temperature.HighBit = 1 Then ;check for < 0C
            ;Subtract from 0 to read below 0 value
            Temperature = $0000-Temperature
            Temperature = -Temperature
        endif
    temperature=(625*temperature)/100       
ENDIF               
IF temperature>10000 THEN RETURN
REM if TEmpDs18[0]>0 and (abs(temperature-TEmpDs18[0])>60) then return
IF DECIMALES=1 THEN  temperature=temperature/10
IF DECIMALES=0 THEN  temperature=temperature/100
TEmpDs18[0] = Temperature
return
********************************************************

espero te sirva

saludos

luis lopez

Desconectado Kspids

  • PIC16
  • ***
  • Mensajes: 192
Re:Problemas con Delay
« Respuesta #4 en: 24 de Diciembre de 2019, 05:35:40 »
Gracias por las aportaciones!

No hay alguna forma para que la temperatura trabaje en paralelo con mi programa? de manera que no se afecten entre ellos?

Saludos!! y Feliz Noche Buena! :-/

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Problemas con Delay
« Respuesta #5 en: 24 de Diciembre de 2019, 08:48:47 »
Si y te lo dije... Si te basas en lo que hiciste aca:

Código: C
  1. if (((HAL_GetTick() - tiempo) > 30000)){


En todos los delays que tenes , vas a hacerlo "paralelo" como vos queres.
Acostumbrate que el delay no es mas de unos microsegundos, todo lo demaslo vas a tener que hacer de otra forma.