HX711 ADC рд▓рд╛рдИ NRF52832 рдорд╛ рдХрд╕рд░реА рдЬрдбрд╛рди рдЧрд░реНрдиреЗ

реи. рдкрд░рд┐рдЪрдп

рдПрдЬреЗрдиреНрдбрд╛рдорд╛ рджреБрдИ рдЖрдзрд╛-рдмреНрд░рд┐рдЬ рдЪрд┐рдирд┐рдпрд╛рдБ рд╕реНрдЯреНрд░реЗрди рдЧреЗрдЬрд╣рд░реВрдХреЛ рд╕рд╛рде nrf52832 рдорд╛рдЗрдХреНрд░реЛрдХрдиреНрдЯреНрд░реЛрд▓рд░рдХреЛ рд▓рд╛рдЧрд┐ рд╕рдЮреНрдЪрд╛рд░ рдкреНрд░реЛрдЯреЛрдХрд▓ рд╡рд┐рдХрд╛рд╕ рдЧрд░реНрдиреЗ рдХрд╛рд░реНрдп рдерд┐рдпреЛред

рдпреЛ рдХрд╛рд░реНрдп рд╕рдЬрд┐рд▓реЛ рдерд┐рдПрди, рдХрд┐рдирдХрд┐ рдореИрд▓реЗ рдХреБрдиреИ рдкрдирд┐ рд╕реБрдЧрдо рдЬрд╛рдирдХрд╛рд░реАрдХреЛ рдЕрднрд╛рд╡рдХреЛ рд╕рд╛рдордирд╛ рдЧрд░реНрдиреБрдкрд░реЗрдХреЛ рдерд┐рдпреЛред рдпреЛ рдЕрдзрд┐рдХ рд╕рдореНрднрд╛рд╡рдирд╛ рдЫ рдХрд┐ "рдЦрд░рд╛рдмрдХреЛ рдЬрд░рд╛" Nordic Semiconductor рдмрд╛рдЯ SDK рдорд╛ рдЫ - рдирд┐рд░рдиреНрддрд░ рд╕рдВрд╕реНрдХрд░рдг рдЕрджреНрдпрд╛рд╡рдзрд┐рдХрд╣рд░реВ, рдХреЗрд╣рд┐ рдЕрдирд╛рд╡рд╢реНрдпрдХрддрд╛ рд░ рднреНрд░рд╛рдордХ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ред рдореИрд▓реЗ рд╕реНрдХреНрд░реНрдпрд╛рдЪрдмрд╛рдЯ рд╕рдмреИ рд▓реЗрдЦреНрдиреБрдкрд░реНрдереНрдпреЛред

рдорд▓рд╛рдИ рд▓рд╛рдЧреНрдЫ рдХрд┐ рдпреЛ рд╡рд┐рд╖рдп рдпрд╕ рддрдереНрдпрдХреЛ рдЖрдзрд╛рд░рдорд╛ рдПрдХрджрдо рд╕рд╛рдиреНрджрд░реНрднрд┐рдХ рдЫ рдХрд┐ рдпрд╕ рдЪрд┐рдкрдорд╛ BLE рд╕реНрдЯреНрдпрд╛рдХ рд░ рдКрд░реНрдЬрд╛ рдмрдЪрдд рдореЛрдбрдХреЛ рд▓рд╛рдЧрд┐ "рдЧреБрдбреАрд╣рд░реВ" рдХреЛ рд╕рдореНрдкреВрд░реНрдг рд╕реЗрдЯ рдЫред рддрд░ рдо рдкреНрд░рд╛рд╡рд┐рдзрд┐рдХ рднрд╛рдЧрдорд╛ рдзреЗрд░реИ рдЧрд╣рд┐рд░реЛ рдЬрд╛рдиреЗ рдЫреИрди, рдХрд┐рдирдХрд┐ рдпрд╕ рд╡рд┐рд╖рдпрдорд╛ рдзреЗрд░реИ рд▓реЗрдЦрд╣рд░реВ рд▓реЗрдЦрд┐рдПрдХрд╛ рдЫрдиреНред

2. рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╡рд┐рд╡рд░рдг

HX711 ADC рд▓рд╛рдИ NRF52832 рдорд╛ рдХрд╕рд░реА рдЬрдбрд╛рди рдЧрд░реНрдиреЗ

рдлрд▓рд╛рдо:

  • Adafruit Feather nRF52 Bluefruit LE (рд╣рд╛рддрдорд╛ рдХреЗ рднрдпреЛ)
  • HX711 ADC
  • рдЪрд┐рдирд┐рдпрд╛рдБ рддрдирд╛рд╡ рдЧреЗрдЬ 2 рдкреАрд╕реАред (релрежxреи рдХрд┐рд▓реЛ)
  • рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ ST-LINK V2

рд╕рдлреНрдЯрд╡реЗрдпрд░:

  • IDE VSCODE
  • NRF SDK резрем
  • рдУрд╕реАрдбреА рдЦреЛрд▓реНрдиреБрд╣реЛрд╕реН
  • рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ ST-LINK V2

рд╕рдмреИ рдХреБрд░рд╛ рдПрдЙрдЯреИ рдкрд░рд┐рдпреЛрдЬрдирд╛рдорд╛ тАЛтАЛрдЫ, рддрдкрд╛рдИрдВрд▓реЗ рднрд░реНрдЦрд░реИ рдореЗрдХрдлрд╛рдЗрд▓ рдЯреНрд╡реАрдХ рдЧрд░реНрдиреБрдкрд░реНрдЫ (рддрдкрд╛рдИрдВрдХреЛ SDK рдХреЛ рд╕реНрдерд╛рди рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдЧрд░реНрдиреБрд╣реЛрд╕реН)ред

3. рдХреЛрдбрдХреЛ рд╡рд┐рд╡рд░рдг

рд╣рд╛рдореАрд▓реЗ GPIOTE рдореЛрдбреНрдпреБрд▓рд▓рд╛рдИ рдХрд╛рд░реНрдп рд░ рдШрдЯрдирд╛рд╣рд░реВрдХреЛ рдмрд╛рдЗрдиреНрдбрд┐рдЩрдорд╛ рдЖрдзрд╛рд░рд┐рдд рдкрд░рд┐рдзреАрдпрд╣рд░реВрд╕рдБрдЧ рдХрд╛рдо рдЧрд░реНрди рдкреНрд░рдпреЛрдЧ рдЧрд░реНрдиреЗрдЫреМрдВ, рд╕рд╛рдереИ PPI рдореЛрдбреНрдпреБрд▓рд▓рд╛рдИ рдкреНрд░реЛрд╕реЗрд╕рд░рдХреЛ рд╕рд╣рднрд╛рдЧрд┐рддрд╛ рдмрд┐рдирд╛ рдПрдХ рдкрд░рд┐рдзреАрдпрдмрд╛рдЯ рдЕрд░реНрдХреЛрдорд╛ рдбрд╛рдЯрд╛ рд╕реНрдерд╛рдирд╛рдиреНрддрд░рдг рдЧрд░реНрдирдХрд╛ рд▓рд╛рдЧрд┐ред

ret_code_t err_code;
   err_code = nrf_drv_gpiote_out_init(PD_SCK, &config);//╨╜╨░╤Б╤В╤А╨░╨╡╨▓╨░╨╡╨╝ ╨╜╨░ ╨▓╤Л╤Е╨╛╨┤
   nrf_drv_gpiote_out_config_t config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(false);//╨▒╤Г╨┤╨╡╨╝ ╨┐╨╡╤А╨╡╨┤╨╡╤А╨│╨╕╨▓╨░╤В╤М ╨┐╨╕╨╜ ╨┤╨╗╤П ╨╕╨╝╨┐╤Г╨╗╤М╤Б╨░
   err_code = nrf_drv_gpiote_out_init(PD_SCK, &config);//╨╜╨░╤Б╤В╤А╨░╨╡╨▓╨░╨╡╨╝ ╨╜╨░ ╨▓╤Л╤Е╨╛╨┤

рд╣рд╛рдореАрд▓реЗ PD_SCL рд╕рд┐рдЩреНрдХреНрд░реЛрдирд╛рдЗрдЬреЗрд╕рди рд▓рд╛рдЗрдирд▓рд╛рдИ рдЖрдЙрдЯрдкреБрдЯрдорд╛ 10 ╬╝s рдХреЛ рдЕрд╡рдзрд┐рдорд╛ рджрд╛рд▓рд╣рд░реВ рдЙрддреНрдкрдиреНрди рдЧрд░реНрди рдХрдиреНрдлрд┐рдЧрд░ рдЧрд░реНрдЫреМрдВред

   nrf_drv_gpiote_in_config_t  gpiote_config = GPIOTE_CONFIG_IN_SENSE_HITOLO(false);// ╨┐╨╡╤А╨╡╤Е╨╛╨┤ ╤Г╤А╨╛╨▓╨╜╤П ╤Б ╨▓╤Л╤Б╨╛╨║╨╛╨│╨╛ ╨╜╨░ ╨╜╨╕╨╖╨║╨╕╨╣
   nrf_gpio_cfg_input(DOUT, NRF_GPIO_PIN_NOPULL);// ╨╜╨░ ╨▓╤Е╨╛╨┤ ╨▒╨╡╨╖ ╨┐╨╛╨┤╤В╤П╨╢╨║╨╕
   err_code = nrf_drv_gpiote_in_init(DOUT, &gpiote_config, gpiote_evt_handler); 

static void gpiote_evt_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
    nrf_drv_gpiote_in_event_disable(DOUT);//╨╛╤В╨║╨╗╤О╤З╨░╨╡╨╝ ╨┐╤А╨╡╤А╤Л╨▓╨░╨╜╨╕╨╡
    nrf_drv_timer_enable(&m_timer0);//╨▓╨║╨╗╤О╤З╨░╨╡╨╝ ╤В╨░╨╣╨╝╨╡╤А
}
 

рд╣рд╛рдореА HX711 рдХреЛ рддрдпрд╛рд░реА рдЕрд╡рд╕реНрдерд╛ рдкрдвреНрди DOUT рдбреЗрдЯрд╛ рд▓рд╛рдЗрди рдХрдиреНрдлрд┐рдЧрд░ рдЧрд░реНрдЫреМрдВ; рдпрджрд┐ рддреНрдпрд╣рд╛рдБ рдХрдо рд╕реНрддрд░ рдЫ рднрдиреЗ, рдПрдХ рд╣реНрдпрд╛рдиреНрдбрд▓рд░ рдЯреНрд░рд┐рдЧрд░ рд╣реБрдиреНрдЫ рдЬрд╕рдорд╛ рд╣рд╛рдореАрд▓реЗ рдЕрд╡рд░реЛрдзрд▓рд╛рдИ рдЕрд╕рдХреНрд╖рдо рдкрд╛рд░реНрдЫреМрдВ рд░ PD_SCL рдЖрдЙрдЯрдкреБрдЯрдорд╛ рдШрдбреА рдкрд▓реНрд╕рд╣рд░реВ рдЙрддреНрдкрдиреНрди рдЧрд░реНрди рдЯрд╛рдЗрдорд░ рд╕реБрд░реБ рдЧрд░реНрдЫреМрдВред

 err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel1);
   APP_ERROR_CHECK(err_code);
   err_code = nrf_drv_ppi_channel_assign(m_ppi_channel1,                                         nrf_drv_timer_event_address_get(&m_timer0, NRF_TIMER_EVENT_COMPARE0),                                           nrf_drv_gpiote_out_task_addr_get(PD_SCK));// ╨┐╨╛╨┤╨║╨╗╤О╤З╨░╨╡╨╝ ╤В╨░╨╣╨╝╨╡╤А ╨║ ╨▓╤Л╤Е╨╛╨┤╤Г
   APP_ERROR_CHECK(err_code);
   err_code = nrf_drv_ppi_channel_enable(m_ppi_channel1);// ╨▓╨║╨╗╤О╤З╨░╨╡╨╝ ╨║╨░╨╜╨░╨╗
   APP_ERROR_CHECK(err_code);
   nrf_drv_gpiote_out_task_enable(PD_SCK); 

// gpiote рд╕рдХреНрд╖рдо рдЧрд░реНрдиреБрд╣реЛрд╕реН

рддреНрдпрд╕ рдкрдЫрд┐, рд╣рд╛рдореА PPI рдореЛрдбреНрдпреБрд▓ рдкреНрд░рд╛рд░рдореНрдн рдЧрд░реНрдЫреМрдВ рд░ рддреБрд▓рдирд╛рддреНрдордХ рдШрдЯрдирд╛ рд╣реБрдБрджрд╛ 10 ╬╝s рдХреЛ рдЕрд╡рдзрд┐рдорд╛ рдкрд▓реНрд╕ рдЙрддреНрдкрдиреНрди рдЧрд░реНрди PD_SCL рдЖрдЙрдЯрдкреБрдЯрдорд╛ рд╣рд╛рдореНрд░реЛ рдЯрд╛рдЗрдорд░ рдЬрдбрд╛рди рдЧрд░реНрдЫреМрдВ, рд░ GPIOTE рдореЛрдбреНрдпреБрд▓ рдкрдирд┐ рдЦреЛрд▓реНрдЫреМрдВред


nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;// ╨┐╨╛ ╤Г╨╝╨╛╨╗╤З╨░╨╜╨╕╤О
   timer_cfg.frequency = NRF_TIMER_FREQ_1MHz;// ╤В╨░╨║╤В╨╕╤А╤Г╨╡╨╝ ╨╜╨░ ╤З╨░╤Б╤В╨╛╤В╨╡ 1╨Ь╨│╤Ж
   ret_code_t err_code = nrf_drv_timer_init(&m_timer0, &timer_cfg, timer0_event_handler);
   APP_ERROR_CHECK(err_code);
   nrf_drv_timer_extended_compare(&m_timer0,
                                  NRF_TIMER_CC_CHANNEL0,
                                  nrf_drv_timer_us_to_ticks(&m_timer0,
                                                            10),
                                  NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
                                  true);// ╤Б╤А╨░╨▒╨░╤В╤Л╨▓╨░╨╡╤В ╨┐╨╛ ╤Б╤А╨░╨▓╨╜╨╡╨╜╨╕╤О

рд╣рд╛рдореА рд╢реВрдиреНрдп рдЯрд╛рдЗрдорд░ рд░ рдпрд╕рдХреЛ рд╣реНрдпрд╛рдиреНрдбрд▓рд░ рд╕реБрд░реБ рдЧрд░реНрдЫреМрдВред

  if(m_counter%2 != 0 && m_counter<=48){
       buffer <<= 1;// ╨┐╨╡╤А╨╡╨╝╨╡╨╜╨╜╨░╤П ╤Б╤З╨╕╤В╨░╨╜╨╜╤Л╤Е ╨┤╨░╨╜╤Л╤Е
        c_counter++;// ╤Б╤З╨╡╤В╤З╨╕╨║ ╨┐╨╛╨╗╨╛╨╢╨╕╤В╨╡╨╗╤М╨╜╤Л╤Е  ╨╕╨╝╨┐╤Г╨╗╤М╤Б╨╛╨▓
           if(nrf_gpio_pin_read(DOUT))buffer++;//╤Б╤З╨╕╤В╤Л╨▓╨░╨╡╨╝ ╤Б╨╛╤Б╤В╨╛╤П╨╜╨╕╨╡ ╨▓╤Е╨╛╨┤╨░
   }

рд╕рдмреИрднрдиреНрджрд╛ рд░реЛрдЪрдХ рдХреБрд░рд╛ рдЯрд╛рдЗрдорд░ рд╣реНрдпрд╛рдиреНрдбрд▓рд░рдорд╛ рд╣реБрдиреНрдЫред рдкрд▓реНрд╕ рдЕрд╡рдзрд┐ 20 ╬╝s рдЫред рд╣рд╛рдореА рд╡рд┐рд╖рдо рджрд╛рд▓рд╣рд░реВрдорд╛ рд░реБрдЪрд┐ рд░рд╛рдЦреНрдЫреМрдВ (рдмрдвреНрджреЛ рдХрд┐рдирд╛рд░рдорд╛) рд░ рддрд┐рдиреАрд╣рд░реВрдХреЛ рд╕рдВрдЦреНрдпрд╛ 24 рднрдиреНрджрд╛ рдмрдвреА рдЫреИрди рднрдиреЗ, рд░ рддреНрдпрд╣рд╛рдБ 48 рдШрдЯрдирд╛рд╣рд░реВ рдЫрдиреНред рдкреНрд░рддреНрдпреЗрдХ рд╡рд┐рд╖рдо рдШрдЯрдирд╛рдХреЛ рд▓рд╛рдЧрд┐, DOUT рдкрдврд┐рдиреНрдЫред

рдбрд╛рдЯрд╛рд╢реАрдЯрдмрд╛рдЯ рдпреЛ рдкрдЫреНрдпрд╛рдЙрдБрдЫ рдХрд┐ рджрд╛рд▓рд╣рд░реВрдХреЛ рд╕рдВрдЦреНрдпрд╛ рдХрдореНрддрд┐рдорд╛ 25 рд╣реБрдиреБрдкрд░реНрдЫ, рдЬреБрди 128 рдХреЛ рд▓рд╛рднрд╕рдБрдЧ рдореЗрд▓ рдЦрд╛рдиреНрдЫ (рдХреЛрдбрдорд╛ рдореИрд▓реЗ 25 рджрд╛рд▓рд╣рд░реВ рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрдВ), рдпреЛ 50 рдЯрд╛рдЗрдорд░ рдШрдЯрдирд╛рд╣рд░реВрдХреЛ рдмрд░рд╛рдмрд░ рд╣реЛ, рдЬрд╕рд▓реЗ рдбреЗрдЯрд╛ рдлреНрд░реЗрдордХреЛ рдЕрдиреНрддреНрдпрд▓рд╛рдИ рд╕рдВрдХреЗрдд рдЧрд░реНрджрдЫред

 ++m_counter;// ╤Б╤З╨╡╤В╤З╨╕╨║ ╤Б╨╛╨▒╤Л╤В╨╕╨╣
if(m_counter==50){
      nrf_drv_timer_disable(&m_timer0);// ╨╛╤В╨║╨╗╤О╤З╨░╨╡╨╝ ╤В╨░╨╣╨╝╨╡╤А
       m_simple_timer_state = SIMPLE_TIMER_STATE_STOPPED;//
       buffer = buffer ^ 0x800000;
       hx711_stop();//j╨╛╤В╨║╨╗╤О╤З╨░╨╡╨╝ hx711
       }
   

рдпрд╕ рдкрдЫрд┐, рд╣рд╛рдореА рдЯрд╛рдЗрдорд░ рдмрдиреНрдж рдЧрд░реНрдЫреМрдВ рд░ рдбрд╛рдЯрд╛ (рдбреЗрдЯрд╛рд╕рд┐рдЯ рдЕрдиреБрд╕рд╛рд░) рдкреНрд░рд╢реЛрдзрди рдЧрд░реНрдЫреМрдВ рд░ HX711 рд▓рд╛рдИ рдХрдо рдкрд╛рд╡рд░ рдЦрдкрдд рдореЛрдбрдорд╛ рд╕реНрд╡рд┐рдЪ рдЧрд░реНрдЫреМрдВред


static void repeated_timer_handler(void * p_context)
{
   nrf_drv_gpiote_out_toggle(LED_2);
   if(m_simple_timer_state == SIMPLE_TIMER_STATE_STOPPED){
      	hx711_start();// ╨▓╨║╨╗╤О╤З╨░╨╡╨╝ hx711
       nrf_drv_gpiote_out_toggle(LED_1);
       m_simple_timer_state = SIMPLE_TIMER_STATE_STARTED;
   }
  
}
/**@brief Create timers.
*/
static void create_timers()
{
   ret_code_t err_code;
 
   // Create timers
   err_code = app_timer_create(&m_repeated_timer_id,
                               APP_TIMER_MODE_REPEATED,
                               repeated_timer_handler);
   APP_ERROR_CHECK(err_code);
}

рд╣рд╛рдореА RTC рдЯрд╛рдЗрдорд░рдмрд╛рдЯ резреж рд╕реЗрдХреЗрдиреНрдбрдХреЛ рдЕрдиреНрддрд░рд╛рд▓рдорд╛ рдШрдЯрдирд╛рд╣рд░реВ рдЖрд╢рд╛ рдЧрд░реНрдЫреМрдВ (рдпреЛ рддрдкрд╛рдИрдВрдХреЛ рд╡рд┐рд╡реЗрдХрдорд╛ рдЫ) рд░ рд╣реНрдпрд╛рдиреНрдбрд▓рд░рдорд╛ HX10 рд▓рдиреНрдЪ рдЧрд░реНрдЫреМрдВ, рдЬрд╕рд▓реЗ DOUT рд▓рд╛рдЗрдирдорд╛ рдЕрд╡рд░реЛрдз рдЙрддреНрдкрдиреНрди рдЧрд░реНрдЫред

рддреНрдпрд╣рд╛рдБ рдПрдХ рдердк рдмрд┐рдиреНрджреБ рдЫ, рд▓рдЧрд╣рд░реВ UART рдорд╛рд░реНрдлрдд рдЖрдЙрдЯрдкреБрдЯ рд╣реБрдиреНрдЫрдиреН (baud рджрд░ 115200, TX - 6 рдкрд┐рди, RX - 8 рдкрд┐рди) рд╕рдмреИ рд╕реЗрдЯрд┐рдЩрд╣рд░реВ sdk_config.h рдорд╛ рдЫрдиреНред

HX711 ADC рд▓рд╛рдИ NRF52832 рдорд╛ рдХрд╕рд░реА рдЬрдбрд╛рди рдЧрд░реНрдиреЗ

рдирд┐рд╖реНрдХрд░реНрд╖

рддрдкрд╛рдИрдВрдХреЛ рдзреНрдпрд╛рдирдХреЛ рд▓рд╛рдЧрд┐ рд╕рдмреИрд▓рд╛рдИ рдзрдиреНрдпрд╡рд╛рдж, рдорд▓рд╛рдИ рдЖрд╢рд╛ рдЫ рдХрд┐ рдпреЛ рд▓реЗрдЦ рдЙрдкрдпреЛрдЧреА рд╣реБрдиреЗрдЫ рд░ рд╡рд┐рдХрд╛рд╕рдХрд░реНрддрд╛рд╣рд░реВрдХреЛ рд▓рд╛рдЧрд┐ рд╕рдорд╛рдзрд╛рди рдЦреЛрдЬреНрдирдХреЛ рд▓рд╛рдЧрд┐ рдмрд╣реБрдореВрд▓реНрдп рд╕рдордп рдШрдЯрд╛рдЙрдиреЗрдЫред рдо рднрдиреНрди рдЪрд╛рд╣рдиреНрдЫреБ рдХрд┐ рдирд░реНрдбрд┐рдХрд▓реЗ рдпрд╕рдХреЛ рдкреНрд▓реЗрдЯрдлрд░реНрдорд╣рд░реВрдорд╛ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрдиреЗ рдкреНрд░рд╛рд╡рд┐рдзрд┐рдХ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдКрд░реНрдЬрд╛ рджрдХреНрд╖рддрд╛рдХреЛ рджреГрд╖реНрдЯрд┐рдХреЛрдгрдмрд╛рдЯ рдзреЗрд░реИ рд░реЛрдЪрдХ рдЫред

PS

рдкрд░рд┐рдпреЛрдЬрдирд╛ рдЕрдЭреИ рд╡рд┐рдХрд╛рд╕ рдЕрдиреНрддрд░реНрдЧрдд рдЫ, рддреНрдпрд╕реИрд▓реЗ рдпрджрд┐ рдпреЛ рд╡рд┐рд╖рдп рдЪрд╛рд╕реЛрдХреЛ рдЫ рднрдиреЗ, рдЕрд░реНрдХреЛ рд▓реЗрдЦрдорд╛ рдо рд╡рдЬрди рд╕реЗрдиреНрд╕рд░рд╣рд░реВ, рд╕рд╛рдереИ BLE рд╕реНрдЯреНрдпрд╛рдХ рдЬрдбрд╛рди рдЧрд░реНрдирдХреЛ рд▓рд╛рдЧрд┐ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рд╡рд░реНрдгрди рдЧрд░реНрдиреЗ рдкреНрд░рдпрд╛рд╕ рдЧрд░реНрдиреЗрдЫреБред

рд╕рд╛рдордЧреНрд░реА

рд╕реНрд░реЛрдд: www.habr.com

рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдердкреНрди