CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

There's any way to handle One protocol without delay?

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
E_Blue



Joined: 13 Apr 2011
Posts: 410

View user's profile Send private message

There's any way to handle One protocol without delay?
PostPosted: Wed Mar 06, 2024 11:51 am     Reply with quote

I have a routine that handles 2 one wire devices by a separate pins.
The first one can read temperature devices and iButton IDs. The second one only read temperature devices.

The problem is that the One Wire protocol has some change in the data line that must be wait it until some change or timeout occur.

The whole reset signal took around 736mS.

I'm checking sensor number 1 every 1 second and sensor number 2 every 1 minute.

I'm disabling interrupts during those delays but I don't like that approach.
A delay_us(500) is a lot of time for a microcontroller that is handling USB, and 2 UARTs at 115.2Kbps

What can I do to let the interrupt keep running and don't loose One Wire data?
_________________
Electric Blue
temtronic



Joined: 01 Jul 2010
Posts: 9100
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Mar 06, 2024 1:21 pm     Reply with quote

When I used the DS18B20 (? been awhile...) temperature sensors I had the external RTC module send an interrupt every second ( I called it the 'heartbeat' ).
So every second main() would call 'readdstempsensor()'. That function got the LAST data from the sensor,then told sensor to read and store (or whatever the command is called ). yeah it's been almost a decade and grey cells are aging....

The reality is temperature doesn't vary fast so reading the LAST value is OK.

main() ..
do nothing

on RTC interrupt..set flag..

main() now does
read old temp sensor 1 data
read old temp sensor 2 data
read old temp sensor 3 data
read old temp sensor 4 data
do control stuff
update LCD module
send data to PC in CSV format
....

Each sensor was on it's own I/O pin, parasite mode.

While it does make for a larger program( 1 driver per pin ), it was a quick and easy way to get around 'nasty' several devices on one pin.

I eventually worked out code to 'scan for new devices' then confirm they were there,got around the oops, wire open/shorted problem.
gaugeguy



Joined: 05 Apr 2011
Posts: 288

View user's profile Send private message

PostPosted: Wed Mar 06, 2024 1:43 pm     Reply with quote

You can poll interrupt flags during non-critical parts of the data stream or you can offload the one-wire timing to an I2C-to-1wire IC.
E_Blue



Joined: 13 Apr 2011
Posts: 410

View user's profile Send private message

PostPosted: Wed Mar 06, 2024 2:24 pm     Reply with quote

In my case I must to check if the sensor still there because they are optional, so the can be connected or not and even disconnected with the device running.

I have a routine that calls the ReadTemp() routine but that routine calls another routines like ResetOneWire1(),WriteOneWire1() and ReadOneWire1() and those routines has delays inside that are critical to read the 1-Wire devices properly.

@gaugeguy
I can't add a new IC to the PCB, the device is in production state and I think that my boss will not be happy with the idea to change the design.

I can stop UART1 because use the RTS but on UART2 I have a GPS module and doesn't have any RTS line.
_________________
Electric Blue
gaugeguy



Joined: 05 Apr 2011
Posts: 288

View user's profile Send private message

PostPosted: Wed Mar 06, 2024 2:51 pm     Reply with quote

You don't need interrupts blocked for 500us for the 1-wire timing. During the reset pulse 480us pulse is the minimum, so extra delays in this are OK. The critical time during the reset pulse is only about 70us.
When sending or reading data, the critical time is during the bit transfer, so again only about 80us. A delay between bits is OK. If you look at the timing diagram the delay between bits is 1us minimum and infinity maximum.
Having interrupts disabled for 80us will not result in any lost data at 115k.
E_Blue



Joined: 13 Apr 2011
Posts: 410

View user's profile Send private message

PostPosted: Wed Mar 06, 2024 3:31 pm     Reply with quote

I changed a the a code a bit. Would you check if there's some flaw?

The code for the second sensor is pretty the same but with another pin.

Code:
unsigned int8 crc8(unsigned int8 *addr,unsigned int8 len)
{
    unsigned int8 crc=0;

    for(unsigned int8 i=0;i<len;i++)
    {
        unsigned int8 inbyte = addr[i];

        for(unsigned int8 j=0;j<8;j++)
        {
            unsigned int8 mix=(crc^inbyte)&0x01;

            crc>>=1;

            if(mix)
            {
                crc^=0x8C;
            }

            inbyte >>=1;
        }
    }
    return crc;
}
short ResetOneWire1() //Resetea y detecta si hay sensor presente
{
    unsigned int8 Time=0;
    short P=FALSE;
    short RTS_Bkp;   

    //La salida pasa a traves de un trasistor asi que se debe trabajar con los niveles logicos invertidos.
    output_high(WDO1);
    delay_us(500);
   
   disable_interrupts(GLOBAL);
   RTS_Bkp=input(RTS);
    output_high(RTS); //Paro el puerto del modem.
   
    output_low(WDO1);
    delay_us(15);
    //A partir de aqui deberia haber un pulso de presencia los proximos 60 a 240uS

    while(Time<24) //Espera hasta 240uS
    {
        delay_us(10);

        if(input(WDI1))//El sensor bajo la linea?
        {
            P=TRUE; //Si- Esperar de 60 a 240 uS
            break;
        }

        Time++;
    }

    if(RTS_Bkp)
    {
        output_high(RTS); //Si estaba en 1 queda en 1
    }
    else
    {
        output_low(RTS);//Si estaba en 0 queda en 0.
    }

    enable_interrupts(GLOBAL);//Se asume que las interrupciones estan activas siempre

    while(Time<24) //Espera hasta 300uS - Deberia tardar entre 60 y 240uS
    {
        delay_us(10);

        if(!input(WDI1))//Espero que la linea vuelva a subir
        {
            break;
        }

        Time++;
    }

    return P;   //No se detecto pulso de presencia;
}
void WriteOneWire1(unsigned int8 Data)
{
   unsigned int8 x;
   short RTS_Bkp;

   disable_interrupts(GLOBAL);

   RTS_Bkp=input(RTS);
   output_high(RTS); //Paro el puerto del modem.

   for(x=0;x<8;x++)
   {
            disable_interrupts(GLOBAL);

            output_high(WDO1);

            if((Data&0x01)==0)
            {
                delay_us(60);
                output_low(WDO1);
            }
            else
            {
                delay_us(5);
                output_low(WDO1);
                delay_us(55);
            }

            enable_interrupts(GLOBAL);
            delay_us(5);
            Data/=2;
   }

   if(RTS_Bkp)
   {
        output_high(RTS); //Si estaba en 1 queda en 1
   }
   else
   {
        output_low(RTS);//Si estaba en 0 queda en 0.
   }
}
unsigned int8 1
{
    unsigned int8 x;
    unsigned int8 Data=0;
    short RTS_Bkp;

    disable_interrupts(GLOBAL);
   
    RTS_Bkp=input(RTS);
    output_high(RTS); //Paro el puerto del modem.

    for(x=0;x<8;x++)
    {
        disable_interrupts(GLOBAL);
        output_high(WDO1);
        delay_us(3);
        output_low(WDO1);

        delay_us(14);

        Data/=2;

        if(!input(WDI1))
        {
            bit_set(Data,7);
        }
        else
        {
            bit_clear(Data,7);
        }

        enable_interrupts(GLOBAL);
        delay_us(60);
    }
   
    if(RTS_Bkp)
    {
        output_high(RTS); //Si estaba en 1 queda en 1
    }
    else
    {
        output_low(RTS);//Si estaba en 0 queda en 0.
    }

    return Data;
}

_________________
Electric Blue
gaugeguy



Joined: 05 Apr 2011
Posts: 288

View user's profile Send private message

PostPosted: Wed Mar 06, 2024 3:57 pm     Reply with quote

I don't think you are understanding the reset pulse diagram.
The bus must be kept low a minimum of 480us (with no maximum)
Once the bus goes high, the slave will respond with a presence pulse starting somewhere from 15us to 60us. The presence pulse from the slave can last from 60us - 240us.
If you wait 70us after the reset pulse is released you can just test the line then.
If a device is present the line will be low. If no device is present the line will be high. There is no need to keep looping and looking for the moment it changes.
E_Blue



Joined: 13 Apr 2011
Posts: 410

View user's profile Send private message

PostPosted: Wed Mar 06, 2024 10:28 pm     Reply with quote

Ok. Thanks, I will make some changes to my code.
_________________
Electric Blue
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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