1-wire preko UART-a

Tu bo govora o vseh mogočih mikrokontrolerjih ne glede na tip ali zgradbo

Moderator: tilz0R

1-wire preko UART-a

Postby tilz0R » 08 Apr 2018, 23:14

1-Wire protokol je lep in direkt paše na UART periferijo na mikrokontrolerju. Spodaj bom naštel, zakaj se mi zdi uporaba 1-Wire protokola preko UART bolj smiselna kot preko GPIO bit-banging.

Prednosti:
- Veliko MCU-jev ima 2+ UART periferij
- Danes bolj kot ne vsi MCU-ji vsebujo nastavljiv tip izhoda (open-drain, push-pull), zato zunanji pretvornik ni potreben
- Za timing skrbi hardware in ne software
- Omogoča enostavno uporabo z RTOS sistemi
- Primeren za low-power aplikacije
- Potrebuješ le 9600 + 115200 baud-ov
- Omogoča DMA, kar je danes skoraj nujno za efektivno uporabo MCUja
- Efektivna uporaba pri 100+MHz MCU-jih, ker ni potrebnih delay-ov (sploh, če je RTOS + DMA vključen)

Slabosti:
- Mali MCU-ji imajo (ponavadi) le 1 UART
- Potrebuješ 2 pina povezana skupaj (TX in RX) v open-drain načinu (na enega vsiljuješ samo 0, na drugem bereš, če je kakšen sensor vsilil 0). Če MCU ne podpira HW Open-Drain načina, potrebuješ zunanje vezje z dvema mosfetoma + nekaj upori (shema na spodnjem linku).

Več o 1-Wire over UART

Implementacija je na voljo na Github-u. Knjižnica je platform-independent, ker je UART layer ločen od 1-Wire layer-ja.
Knowledge sharing is people' caring., T. MAJERLE
User avatar
tilz0R
 
Posts: 1393
Joined: 18 Jan 2015, 00:12
Location: Črnomelj
Has thanked: 182 times
Been thanked: 341 times
Uporabnika povabil: s56rga
Število neizkoriščenih povabil: 255

Re: 1-wire preko UART-a

Postby LiPo » 10 Apr 2018, 18:14

Stvar je "kul". Samo ne vem zakaj bi menjal za nekaj kar dela?

LPG
User avatar
LiPo
 
Posts: 670
Joined: 04 Apr 2015, 17:30
Location: LJUBLJANA
Has thanked: 22 times
Been thanked: 82 times
Uporabnika povabil: cimabella
Število neizkoriščenih povabil: 16

Re: 1-wire preko UART-a

Postby tilz0R » 10 Apr 2018, 18:20

LiPo wrote:Stvar je "kul". Samo ne vem zakaj bi menjal za nekaj kar dela?

LPG


Zato ker delam aplikacije samo še z RTOS-om, in ne mislim disablat interruptov medtem ko 1-wire posilja in s tem blokirat vse ostalo na 400MHz MCU-ju.

Drugače pa,kadar je možno, uporabiš HW. Zakaj bi se matral v SW?
Knowledge sharing is people' caring., T. MAJERLE
User avatar
tilz0R
 
Posts: 1393
Joined: 18 Jan 2015, 00:12
Location: Črnomelj
Has thanked: 182 times
Been thanked: 341 times
Uporabnika povabil: s56rga
Število neizkoriščenih povabil: 255

Re: 1-wire preko UART-a

Postby zanka » 10 Apr 2018, 19:30

Ne poznam RTOS. Kako hitro menja med nitmi?

Še en SW 1-wire v petdesetih vrsticah.
Code: Select all
static uint8_t ow_bit(uint8_t i)
{
  //__disable_irq();
  GPIOB->MODER |= GPIO_MODER_MODER9_0;
  _delay_us(1);
  if (i) {
    GPIOB->MODER &= ~GPIO_MODER_MODER9_Msk;
  }
  _delay_us(15 - 1);
  if (!(GPIOB->IDR & GPIO_IDR_9)) {
    i = 0;
  }
  _delay_us(61 - 15);
  GPIOB->MODER &= ~GPIO_MODER_MODER9_Msk;
  _delay_us(1);
  //__enable_irq();
  return i;
}

uint8_t ow_byte_write(uint8_t b)
{
  uint8_t i = 8, j;

  while (i--) {
    j = ow_bit(b & 1);
    b >>= 1;
    if (j) {
      b |= 0x80;
    }
  }

  return b;
}

uint8_t ow_byte_read(void)
{
  return ow_byte_write(0xff);
}

uint8_t ow_reset(void)
{
  uint8_t present;
  GPIOB->MODER |= GPIO_MODER_MODER9_0;
  _delay_us(480);
  GPIOB->MODER &= ~GPIO_MODER_MODER9_Msk;
  _delay_us(60);
  present = 0;
  if (!(GPIOB->IDR & GPIO_IDR_9)) {
    present = 1;
  }
  _delay_us(480 - 60);
  return present;
}


Pa še začetek.
Code: Select all
  GPIOB->OTYPER |= GPIO_OTYPER_OT_9; /* Open drain. */
  GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR9_1 | GPIO_OSPEEDER_OSPEEDR9_0;
  GPIOB->BSRR |= GPIO_BSRR_BR_9;
User avatar
zanka
 
Posts: 1793
Joined: 17 Mar 2016, 01:16
Location: Krško
Has thanked: 93 times
Been thanked: 153 times
Uporabnika povabil: DusanK
Število neizkoriščenih povabil: 29

Re: 1-wire preko UART-a

Postby TilenS » 10 Apr 2018, 20:38

Se ravno ukvarjam z 1Wire oz. predelavo le te.

1WIRE UART ima še eno pomanjkljivost. Z UART-om že v osnovi porabiš 2 pina in če hočeš dokaj zanesljiv 1WIRE za branje DS senzorjev (99.9% za kar uporabljam 1wire) potem parazitni način napajanja ni dobra pot, vedno uporabim dodatni strong pull-up in tako z UART načinom porabim "3WIRE" za 1WIRE vodilo :mrgreen:

Če bi imel proste pine in UART grem v sekundi v UART varijanto ampak sem ponavadi ravno z obojim omejen.

Meni najboljši način bi bil bit-banging iz interupt rutine + strong pull-up (rabiš 2 pina oz. če je interni uC FET dovolj potem samo 1 pin za podatke in napajanje) in ravno to sem hotel naredit. Sem pa zaenkrat dal tole zadevo na čakanje in na hitro raje predelal klasično while() metodo tako, da sem najdaljši CPU cikel spravil iz cca. 40ms na 14ms kar je že nekako pogojno uporabno.
TilenS
 
Posts: 298
Joined: 05 Feb 2015, 00:40
Has thanked: 0 time
Been thanked: 41 times
Uporabnika povabil: DusanK
Število neizkoriščenih povabil: 8

Re: 1-wire preko UART-a

Postby zanka » 10 Apr 2018, 20:39

Čemu pull-up ne na napajanje?
User avatar
zanka
 
Posts: 1793
Joined: 17 Mar 2016, 01:16
Location: Krško
Has thanked: 93 times
Been thanked: 153 times
Uporabnika povabil: DusanK
Število neizkoriščenih povabil: 29

Re: 1-wire preko UART-a

Postby tilz0R » 10 Apr 2018, 20:42

zanka wrote:Ne poznam RTOS. Kako hitro menja med nitmi?

Še en SW 1-wire v petdesetih vrsticah.
Code: Select all
static uint8_t ow_bit(uint8_t i)
{
  //__disable_irq();
  GPIOB->MODER |= GPIO_MODER_MODER9_0;
  _delay_us(1);
  if (i) {
    GPIOB->MODER &= ~GPIO_MODER_MODER9_Msk;
  }
  _delay_us(15 - 1);
  if (!(GPIOB->IDR & GPIO_IDR_9)) {
    i = 0;
  }
  _delay_us(61 - 15);
  GPIOB->MODER &= ~GPIO_MODER_MODER9_Msk;
  _delay_us(1);
  //__enable_irq();
  return i;
}

uint8_t ow_byte_write(uint8_t b)
{
  uint8_t i = 8, j;

  while (i--) {
    j = ow_bit(b & 1);
    b >>= 1;
    if (j) {
      b |= 0x80;
    }
  }

  return b;
}

uint8_t ow_byte_read(void)
{
  return ow_byte_write(0xff);
}

uint8_t ow_reset(void)
{
  uint8_t present;
  GPIOB->MODER |= GPIO_MODER_MODER9_0;
  _delay_us(480);
  GPIOB->MODER &= ~GPIO_MODER_MODER9_Msk;
  _delay_us(60);
  present = 0;
  if (!(GPIOB->IDR & GPIO_IDR_9)) {
    present = 1;
  }
  _delay_us(480 - 60);
  return present;
}


Pa še začetek.
Code: Select all
  GPIOB->OTYPER |= GPIO_OTYPER_OT_9; /* Open drain. */
  GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR9_1 | GPIO_OSPEEDER_OSPEEDR9_0;
  GPIOB->BSRR |= GPIO_BSRR_BR_9;

Zdej pa dej tole v OS sistem in poročaj.
Knowledge sharing is people' caring., T. MAJERLE
User avatar
tilz0R
 
Posts: 1393
Joined: 18 Jan 2015, 00:12
Location: Črnomelj
Has thanked: 182 times
Been thanked: 341 times
Uporabnika povabil: s56rga
Število neizkoriščenih povabil: 255

Re: 1-wire preko UART-a

Postby tilz0R » 10 Apr 2018, 20:57

TilenS wrote:1WIRE UART ima še eno pomanjkljivost. Z UART-om že v osnovi porabiš 2 pina in če hočeš dokaj zanesljiv 1WIRE za branje DS senzorjev (99.9% za kar uporabljam 1wire) potem parazitni način napajanja ni dobra pot, vedno uporabim dodatni strong pull-up in tako z UART načinom porabim "3WIRE" za 1WIRE vodilo :mrgreen:

Če povežeš TX in RX pina skupaj direktno in uporabiš 2k2 ali manjši pull-up za parazitno napajanje, mislim da si še skoraj zmagal :)

Drugače pa se strinjam, da je najboljša varianta interrupt za vsako spremembo linije, ki jo mora narediti output.
Lepota 1-wire-ja je tudi to, da čas med dvema bitoma "ne obstaja", tako da ko pošlješ 1-bit lahko čakaš n-časa preden pošlješ naslednjega. To omogoča, da tudi če RTOS switcha task medtem, ko ti pošiljaš, bo tekoči frame preko UART-a poslal normalno in ko prideš nazaj v ta task, preprosto samo nadaljuješ.

Če imaš pa DMA, pa enostavno uporabiš semafor za sinhronizacijo, potem si gre pa thread v blocked state in CPU ne žre resourcev dokler ni poslano.
Knowledge sharing is people' caring., T. MAJERLE
User avatar
tilz0R
 
Posts: 1393
Joined: 18 Jan 2015, 00:12
Location: Črnomelj
Has thanked: 182 times
Been thanked: 341 times
Uporabnika povabil: s56rga
Število neizkoriščenih povabil: 255


Return to Hardware

Who is online

Users browsing this forum: CCBot/2.0 and 0 guests