Onewire pro LPC1114

Marek Sembol hwm.land na gmail.com
Pondělí Leden 27 20:12:06 CET 2014


Dekuji, to mi bude rozhodne stacit. V podstate klicove je
static void __INLINE DelayUs(uint16_t us)
{
    uint16_t cnts = DS_TIMER->CNT;
    while ((uint16_t)(DS_TIMER->CNT - cnts) < us);
}

Nedoslo mi jak jednoduse ty us cekacky udelat. Mrknu rad i na zbytek, dik
Marek



On Mon, Jan 27, 2014 at 7:45 PM, Jaroslav Buchta <jaroslav.buchta na hascomp.cz
> wrote:

>  Ja to implementoval na STM32, klicove je casovani tech kratkych
> intervalu desitek us, ja to delal prostrednictvim casovace. Samozrejme je
> problem vyuzivat nejaka preruseni behem techto kritickych useku, pro UART
> pouzivam DMA, FreeRTOS ma blokovana preruseni.
> Pro inspiraci zdrojak (neni jeste nejak ucesany):
>
>
>
> ///////////////////////////////////////////////////////////////////////////////
> #include "main.h"
> #include <string.h>
> #include "DS1820.h"
>
>
>
> ///////////////////////////////////////////////////////////////////////////////
>
> #define OW_ONE_BUS
> #define OW_OPENCOLL
>
> #define DS_PERIPHIO RCC_APB2Periph_GPIOB
> #define DS_PORT     GPIOB
> #define DS_PIN_I1    GPIO_Pin_6
> #define DS_PIN_O1    GPIO_Pin_7
> #define DS_PIN_I2    GPIO_Pin_8
> #define DS_PIN_O2    GPIO_Pin_9
> #define DS_PERIPHTM RCC_APB1Periph_TIM2
> #define DS_TIMER    TIM2
>
>
>
>
>
> ///////////////////////////////////////////////////////////////////////////////
>
> #define CRC8INIT    0x00
> #define CRC8POLY    0x18              //0X18 = X^8+X^5+X^4+X^0
>
> uint8_t    crc8 ( uint8_t *data_in, uint8_t number_of_bytes_to_read )
> {
>     uint8_t    crc;
>     uint8_t     loop_count;
>     uint8_t      bit_counter;
>     uint8_t      data;
>     uint8_t      feedback_bit;
>
>     crc = CRC8INIT;
>
>     for (loop_count = 0; loop_count != number_of_bytes_to_read;
> loop_count++)
>     {
>         data = data_in[loop_count];
>         bit_counter = 8;
>         do
>         {
>             feedback_bit = (crc ^ data) & 0x01;
>
>             if ( feedback_bit == 0x01 )
>             {
>                 crc = crc ^ CRC8POLY;
>             }
>             crc = (crc >> 1) & 0x7F;
>             if ( feedback_bit == 0x01 )
>             {
>                 crc = crc | 0x80;
>             }
>
>             data = data >> 1;
>             bit_counter--;
>
>         }
>         while (bit_counter > 0);
>     }
>
>     return crc;
> }
>
>
>
> ///////////////////////////////////////////////////////////////////////////////
>
> void ow_Init()
> {
>     // Init port pins
>     RCC_APB2PeriphClockCmd(DS_PERIPHIO, ENABLE);
>     GPIO_SetBits(DS_PORT, DS_PIN_O1 | DS_PIN_O2);
>     GPIO_InitTypeDef iodef_i = {DS_PIN_I1 | DS_PIN_I2, GPIO_Speed_10MHz,
> GPIO_Mode_IPU};
>     GPIO_Init(DS_PORT, &iodef_i);
>     GPIO_InitTypeDef iodef_o = {DS_PIN_O1 | DS_PIN_O2, GPIO_Speed_10MHz,
> GPIO_Mode_Out_PP};
>     GPIO_Init(DS_PORT, &iodef_o);
>
>     // Init timer
>     /* Compute the prescaler value */
>     uint16_t PrescalerValue = (uint16_t) (SystemCoreClock / 1000000UL) - 1;
>
>     TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
>     /* Time base configuration */
>     RCC_APB1PeriphClockCmd(DS_PERIPHTM, ENABLE);
>     TIM_TimeBaseStructure.TIM_Period = 65535;
>     TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
>     TIM_TimeBaseStructure.TIM_ClockDivision = 0;
>     TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
>     TIM_TimeBaseInit(DS_TIMER, &TIM_TimeBaseStructure);
>     TIM_Cmd(DS_TIMER, ENABLE);
> }
>
>
> static void __INLINE DelayUs(uint16_t us)
> {
>     uint16_t cnts = DS_TIMER->CNT;
>     while ((uint16_t)(DS_TIMER->CNT - cnts) < us);
> }
>
> /*******************************************/
>
> #define OW_MATCH_ROM    0x55
> #define OW_SKIP_ROM        0xCC
> #define    OW_SEARCH_ROM    0xF0
>
>
>
>
>
> uint8_t ow_reset(uint8_t devId)
> {
>     uint16_t err;
>     uint16_t pinO = devId == 0 ? DS_PIN_O1 : DS_PIN_O2;
>     uint16_t pinI = devId == 0 ? DS_PIN_I1 : DS_PIN_I2;
>
>     DS_PORT->BRR = pinO;
>     DelayUs(500);
>     DS_PORT->BSRR = pinO;
>     __disable_irq();
>     DelayUs(66);
>     err = DS_PORT->IDR & pinI;            // no presence detect
>     __enable_irq();
>     DelayUs(480-66);
>     if( (DS_PORT->IDR & pinI) == 0 )    // short circuit
>         err = 1;
>
>     return err;
> }
>
> /* Timing issue when using runtime-bus-selection (!OW_ONE_BUS):
>    The master should sample at the end of the 15-slot after initiating
>    the read-time-slot. The variable bus-settings need more
>    cycles than the constant ones so the delays had to be shortened
>    to achive a 15uS overall delay
>    Setting/clearing a bit in I/O Register needs 1 cyle in OW_ONE_BUS
>    but around 14 cyles in configureable bus (us-Delay is 4 cyles per uS) */
> uint8_t ow_bit_io( uint8_t b, uint8_t devId)
> {
>        uint16_t pinO = devId == 0 ? DS_PIN_O1 : DS_PIN_O2;
>     uint16_t pinI = devId == 0 ? DS_PIN_I1 : DS_PIN_I2;
>     __disable_irq();
>     DS_PORT->BRR = pinO;
>     DelayUs(2); // Recovery-Time wuffwuff was 1
>     if ( b )
>     {
>         DS_PORT->BSRR = pinO;
>     }
>     // wuffwuff delay was 15uS-1 see comment above
>     DelayUs(15-2);
>     if((DS_PORT->IDR & pinI) == 0) b = 0;  // sample at end of
> read-timeslot
>     DelayUs(60-15-2);
>     DS_PORT->BSRR = pinO;
>     __enable_irq();
>     DelayUs(15);
>     return b;
> }
>
>
> uint8_t ow_byte_wr( uint8_t b, uint8_t devId)
> {
>     uint8_t i = 8, j;
>
>     do {
>         j = ow_bit_io( b & 1, devId);
>         b >>= 1;
>         if( j ) b |= 0x80;
>     } while( --i );
>
>     return b;
> }
>
>
> uint8_t ow_byte_rd(uint8_t devId)
> {
>   // read by sending 0xff (a dontcare?)
>   return ow_byte_wr(0xFF, devId);
> }
>
>
> uint8_t ow_rom_search( uint8_t diff, uint8_t* id, uint8_t devId)
> {
>     uint8_t i, j, next_diff;
>     uint8_t b;
>
> DS_PORT->BRR = DS_PIN_O2;
>     if( ow_reset(devId) ) return OW_PRESENCE_ERR;    // error, no device
> found
> DS_PORT->BSRR = DS_PIN_O2;
>
>     ow_byte_wr( OW_SEARCH_ROM, devId );            // ROM search command
>     next_diff = OW_LAST_DEVICE;            // unchanged on last device
>
>     i = OW_ROMCODE_SIZE * 8;                    // 8 bytes
>
>     do
>     {
>         j = 8;                    // 8 bits
>         do
>         {
>             b = ow_bit_io( 1, devId );            // read bit
>             if( ow_bit_io( 1, devId ) )
>             {                            // read complement bit
>                 if( b )                    // 11
>                 return OW_DATA_ERR;            // data error
>             }
>             else
>             {
>                 if( !b ) {                // 00 = 2 devices
>                     if( diff > i || ((*id & 1) && diff != i) )
>                     {
>                         b = 1;                // now 1
>                         next_diff = i;        // next pass 0
>                     }
>                 }
>             }
>             ow_bit_io( b, devId );                 // write bit
>             *id >>= 1;
>             if( b ) *id |= 0x80;            // store bit
>
>             i--;
>
>         } while( --j );
>
>         id++;                    // next uint8_t
>
>     } while( i );
>
>     return next_diff;                // to continue search
> }
>
>
> void ow_command( uint8_t command, uint8_t *id, uint8_t devId)
> {
>     uint8_t i;
>
>     ow_reset(devId);
>
>     if( id )
>     {
>         ow_byte_wr( OW_MATCH_ROM, devId);            // to a single device
>         i = OW_ROMCODE_SIZE;
>         do
>         {
>             ow_byte_wr( *id, devId);
>             id++;
>         } while( --i );
>     }
>     else
>     {
>         ow_byte_wr( OW_SKIP_ROM, devId);            // to all devices
>     }
>
>     ow_byte_wr( command, devId);
> }
>
>
>
>
> /////////////////////////////////////////////////////////////////////////////
>
> ///////////////////////////////////////////////////////////////////////////////
>
> /* return values */
> #define DS18X20_OK          0x00
> #define DS18X20_ERROR       0x01
> #define DS18X20_START_FAIL  0x02
> #define DS18X20_ERROR_CRC   0x03
>
> #define DS18X20_POWER_PARASITE 0x00
> #define DS18X20_POWER_EXTERN   0x01
>
> /* DS18X20 specific values (see datasheet) */
> #define DS18S20_ID 0x10
> #define DS18B20_ID 0x28
>
> #define DS18X20_CONVERT_T    0x44
> #define DS18X20_READ        0xBE
> #define DS18X20_WRITE        0x4E
> #define DS18X20_EE_WRITE    0x48
> #define DS18X20_EE_RECALL    0xB8
> #define DS18X20_READ_POWER_SUPPLY 0xB4
>
> #define DS18B20_CONF_REG    4
> #define DS18B20_9_BIT       0
> #define DS18B20_10_BIT      (1<<5)
> #define DS18B20_11_BIT      (1<<6)
> #define DS18B20_12_BIT      ((1<<6)|(1<<5))
>
> // indefined bits in LSB if 18B20 != 12bit
> #define DS18B20_9_BIT_UNDF       ((1<<0)|(1<<1)|(1<<2))
> #define DS18B20_10_BIT_UNDF      ((1<<0)|(1<<1))
> #define DS18B20_11_BIT_UNDF      ((1<<0))
> #define DS18B20_12_BIT_UNDF      0
>
> // conversion times in ms
> #define DS18B20_TCONV_12BIT      750
> #define DS18B20_TCONV_11BIT      DS18B20_TCONV_12BIT/2
> #define DS18B20_TCONV_10BIT      DS18B20_TCONV_12BIT/4
> #define DS18B20_TCONV_9BIT       DS18B20_TCONV_12BIT/8
> #define DS18S20_TCONV            DS18B20_TCONV_12BIT
>
> // constant to convert the fraction bits to cel*(10^-4)
> #define DS18X20_FRACCONV         625
>
> #define DS18X20_SP_SIZE  9
>
> // DS18X20 EEPROM-Support
> #define DS18X20_WRITE_SCRATCHPAD  0x4E
> #define DS18X20_COPY_SCRATCHPAD   0x48
> #define DS18X20_RECALL_E2         0xB8
> #define DS18X20_COPYSP_DELAY      10 /* ms */
> #define DS18X20_TH_REG      2
> #define DS18X20_TL_REG      3
>
>
>
>
> ///////////////////////////////////////////////////////////////////////////////
>
> /* find DS18X20 Sensors on 1-Wire-Bus
>    input/ouput: diff is the result of the last rom-search
>    output: id is the rom-code of the sensor found */
> void DS18X20_find_sensor(uint8_t *diff, uint8_t *id, uint8_t devId)
> {
>     for (;;)
>     {
>         *diff = ow_rom_search( *diff, &id[0], devId);
>         if ( *diff==OW_PRESENCE_ERR || *diff==OW_DATA_ERR ||
>           *diff == OW_LAST_DEVICE ) return;
>         if ( id[0] == DS18B20_ID || id[0] == DS18S20_ID ) return;
>     }
> }
>
> /* get power status of DS18x20
>    input  : id = rom_code
>    returns: DS18X20_POWER_EXTERN or DS18X20_POWER_PARASITE */
> uint8_t    DS18X20_get_power_status(uint8_t *id, uint8_t devId)
> {
>     uint8_t pstat;
>     ow_reset(devId);
>     ow_command(DS18X20_READ_POWER_SUPPLY, id, devId);
>     pstat=ow_bit_io(1, devId); // pstat 0=is parasite/ !=0 ext. powered
>     ow_reset(devId);
>     return (pstat) ? DS18X20_POWER_EXTERN:DS18X20_POWER_PARASITE;
> }
>
> /* start measurement (CONVERT_T) for all sensors if input id==NULL
>    or for single sensor. then id is the rom-code */
> uint8_t DS18X20_start_meas(uint8_t *id, uint8_t devId)
> {
>     if (ow_reset(devId))
>         return DS18X20_ERROR; //**
>     ow_command( DS18X20_CONVERT_T, id, devId);
>     return DS18X20_OK;
> }
>
> /* reads temperature (scratchpad) of sensor with rom-code id
>    output: subzero==1 if temp.<0, cel: full celsius, mcel: frac
>    in millicelsius*0.1
>    i.e.: subzero=1, cel=18, millicel=5000 = -18,5000°C */
> uint8_t DS18X20_read_meas(uint8_t *id, uint16_t *tempRaw, uint8_t devId)
> {
>     uint8_t i;
>     uint8_t sp[DS18X20_SP_SIZE];
>     uint16_t meas;
>
>     if (ow_reset(devId))
>         return DS18X20_ERROR; //**
>     ow_command(DS18X20_READ, id, devId);
>     for ( i=0 ; i< DS18X20_SP_SIZE; i++ ) sp[i]=ow_byte_rd(devId);
>     if ( crc8( &sp[0], DS18X20_SP_SIZE ) )
>         return DS18X20_ERROR_CRC;
>
>     meas = sp[0];  // LSB
>     meas |= ((uint16_t)sp[1])<<8; // MSB
>     //meas = 0xff5e; meas = 0xfe6f;
>
>     //  only work on 12bit-base
>     if( id[0] == DS18S20_ID )
>     { // 9 -> 12 bit if 18S20
>         /* Extended measurements for DS18S20 contributed by Carsten Foss */
>         meas &= (uint16_t) 0xfffe;    // Discard LSB , needed for later
> extended precicion calc
>         meas <<= 3;                    // Convert to 12-bit , now degrees
> are in 1/16 degrees units
> //        meas += (16 - sp[6]) - 4;    // Add the compensation , and
> remember to subtract 0.25 degree (4/16)
>         meas += 16*((uint16_t)sp[7] - (uint16_t)sp[6])/(uint16_t)sp[7] -
> 4;    // Add the compensation , and remember to subtract 0.25 degree (4/16)
>     }
>     else
>     {
>         meas = 0;        // unsupported now
>     }
>
>     *tempRaw = meas;
>     return DS18X20_OK;
> }
>
> /*
> #ifdef DS18X20_EEPROMSUPPORT
>
> uint8_t DS18X20_write_scratchpad( uint8_t id[],
>     uint8_t th, uint8_t tl, uint8_t conf)
> {
>     ow_reset(); //
>     if( ow_input_pin_state() ) { // only send if bus is "idle" = high
>         ow_command( DS18X20_WRITE_SCRATCHPAD, id );
>         ow_byte_wr(th);
>         ow_byte_wr(tl);
>         if (id[0] == DS18B20_ID) ow_byte_wr(conf); // config avail. on B20
> only
>         return DS18X20_OK;
>     }
>     else {
>         #ifdef DS18X20_VERBOSE
>         uart_puts_P( "DS18X20_write_scratchpad: Short Circuit !\r\n" );
>         #endif
>         return DS18X20_ERROR;
>     }
> }
>
> uint8_t DS18X20_read_scratchpad( uint8_t id[], uint8_t sp[] )
> {
>     uint8_t i;
>
>     ow_reset(); //
>     if( ow_input_pin_state() ) { // only send if bus is "idle" = high
>         ow_command( DS18X20_READ, id );
>         for ( i=0 ; i< DS18X20_SP_SIZE; i++ )    sp[i]=ow_byte_rd();
>         return DS18X20_OK;
>     }
>     else {
>         #ifdef DS18X20_VERBOSE
>         uart_puts_P( "DS18X20_read_scratchpad: Short Circuit !\r\n" );
>         #endif
>         return DS18X20_ERROR;
>     }
> }
>
> uint8_t DS18X20_copy_scratchpad( uint8_t with_power_extern,
>     uint8_t id[] )
> {
>     ow_reset(); //
>     if( ow_input_pin_state() ) { // only send if bus is "idle" = high
>         ow_command( DS18X20_COPY_SCRATCHPAD, id );
>         if (with_power_extern != DS18X20_POWER_EXTERN)
>             ow_parasite_enable();
>         delay_ms(DS18X20_COPYSP_DELAY); // wait for 10 ms
>         if (with_power_extern != DS18X20_POWER_EXTERN)
>             ow_parasite_disable();
>         return DS18X20_OK;
>     }
>     else {
>         #ifdef DS18X20_VERBOSE
>         uart_puts_P( "DS18X20_copy_scratchpad: Short Circuit !\r\n" );
>         #endif
>         return DS18X20_START_FAIL;
>     }
> }
>
> uint8_t DS18X20_recall_E2( uint8_t id[] )
> {
>     ow_reset(); //
>     if( ow_input_pin_state() ) { // only send if bus is "idle" = high
>         ow_command( DS18X20_RECALL_E2, id );
>         // TODO: wait until status is "1" (then eeprom values
>         // have been copied). here simple delay to avoid timeout
>         // handling
>         delay_ms(DS18X20_COPYSP_DELAY);
>         return DS18X20_OK;
>     }
>     else {
>         #ifdef DS18X20_VERBOSE
>         uart_puts_P( "DS18X20_recall_E2: Short Circuit !\r\n" );
>         #endif
>         return DS18X20_ERROR;
>     }
> }
> #endif
> */
>
>
>
> ///////////////////////////////////////////////////////////////////////////////
>
> ///////////////////////////////////////////////////////////////////////////////
> DS18X20_DESC    DsTSensDesc1[OW_MAX_DEVICES];
> DS18X20_DESC    DsTSensDesc2[OW_MAX_DEVICES];
> uint8_t            DsTSensCount1;
> uint8_t            DsTSensCount2;
>
>
>
> ///////////////////////////////////////////////////////////////////////////////
>
> void TSens_Init()
> {
>     ow_Init();
>     memset(DsTSensDesc1, 0x00, sizeof(DsTSensDesc1));
>     memset(DsTSensDesc2, 0x00, sizeof(DsTSensDesc2));
>     DsTSensCount1 = 0;
>     DsTSensCount2 = 0;
> }
>
>
> ///////////////////////////////////////////////////////////////////////////////
>
> uint8_t TSens_ScanForDevices(uint8_t devId)
> {
>     uint8_t b;
>     uint8_t id[OW_ROMCODE_SIZE];
>
>     b = ow_reset(devId);
>     if (b) return TSENS_ERR_HW;
>
>     b = OW_SEARCH_FIRST;
>
>     if (devId== 0)
>     {
>         DsTSensCount1 = 0;
>         memset(DsTSensDesc1, 0x00, sizeof(DsTSensDesc1));
>
>         while (DsTSensCount1 < OW_MAX_DEVICES)
>         {
>             DS18X20_find_sensor(&b, id, devId);
>             if (b == OW_PRESENCE_ERR) return TSENS_ERR_HW;
>             if (b == OW_DATA_ERR) return TSENS_ERR_DATA;
>
>             PDS18X20_DESC pd = &DsTSensDesc1[DsTSensCount1++];
>             memcpy(pd->id, id, OW_ROMCODE_SIZE);
>             pd->status = TSENS_ERR_VOID;
>             if (b == OW_LAST_DEVICE) break;
>         }
>     }
>     else
>     {
>         DsTSensCount2 = 0;
>         memset(DsTSensDesc2, 0x00, sizeof(DsTSensDesc2));
>
>         while (DsTSensCount2 < OW_MAX_DEVICES)
>         {
>             DS18X20_find_sensor(&b, id, devId);
>             if (b == OW_PRESENCE_ERR) return TSENS_ERR_HW;
>             if (b == OW_DATA_ERR) return TSENS_ERR_DATA;
>
>             PDS18X20_DESC pd = &DsTSensDesc2[DsTSensCount2++];
>             memcpy(pd->id, id, OW_ROMCODE_SIZE);
>             pd->status = TSENS_ERR_VOID;
>             if (b == OW_LAST_DEVICE) break;
>         }
>     }
>     return TSENS_ERR_OK;
> }
>
>
> ///////////////////////////////////////////////////////////////////////////////
>
> uint8_t *TSens_GetCntPtr(uint8_t devId)
> {
>     if (devId== 0)     return &DsTSensCount1;
>     return &DsTSensCount2;
> }
>
>
> ///////////////////////////////////////////////////////////////////////////////
> PDS18X20_DESC TSens_GetConfPtr(uint8_t idx, uint8_t devId)
> {
>     if (devId == 0) return DsTSensDesc1+idx;
>     return DsTSensDesc2+idx;
> }
>
> ///////////////////////////////////////////////////////////////////////////////
>
> static int8_t  nDevIdx = -2;
> static uint32_t wStartTicks = 0;
>
> int TSens_SrvFunc (uint8_t devId)
> {
>     uint8_t bRes = DS18X20_OK;
>     PDS18X20_DESC pd = DsTSensDesc1;
>     uint8_t cnt = DsTSensCount1;
>     if (devId != 0)
>     {
>         pd = DsTSensDesc2;
>         cnt = DsTSensCount2;
>     }
>     if (nDevIdx == -2)
>     {
>         bRes = DS18X20_start_meas(NULL, devId);
>         wStartTicks = GetTickCount();
>         if (bRes != DS18X20_OK)
>         {
>             uint8_t idx;
>
>             for (idx=0; idx<cnt; idx++)
>             {
>                 pd++->status = TSENS_ERR_HW;
>             }
>         }
>         else
>         {
>             nDevIdx = -1;
>         }
>     }
>     else if (nDevIdx == -1)
>     {
>         if (GetTickCount() - wStartTicks > DS18S20_TCONV) nDevIdx = 0;
>     }
>     else if (nDevIdx < cnt)
>     {
>         bRes = DS18X20_read_meas(pd->id, &pd->tempRaw, devId);
>         if (bRes == DS18X20_OK)
>         {
>             pd->status = TSENS_ERR_OK;
>         }
>         else
>         {
>             pd->status = TSENS_ERR_HW;
>         }
>         nDevIdx++;
>     }
>     else
>     {
>         nDevIdx = -2;
>     }
>     return bRes == DS18X20_OK ? 1 : 0;
> }
>
>
>
> ///////////////////////////////////////////////////////////////////////////////
>
>
>
>
> Dne 27.1.2014 19:39, Marek Sembol napsal(a):
>
> Nemate nekdo odzkousenou implementaci 1-wire pro LPC1xxx?
> Marek
>
>
> _______________________________________________
> HW-list mailing list  -  sponsored by www.HW.czHw-list na list.hw.czhttp://list.hw.cz/mailman/listinfo/hw-list
>
>
>
>
> ------------------------------
>    <http://www.avast.com/>
>
> Tato zpráva neobsahuje viry ani jiný škodlivý kód -avast! Antivirus<http://www.avast.com/>je aktivní.
>
>
> _______________________________________________
> HW-list mailing list  -  sponsored by www.HW.cz
> Hw-list na list.hw.cz
> http://list.hw.cz/mailman/listinfo/hw-list
>
>
------------- další část ---------------
HTML příloha byla odstraněna...
URL: <http://list.hw.cz/pipermail/hw-list/attachments/20140127/586535ac/attachment.html>


Další informace o konferenci Hw-list