1. Sissejuhatus
Küsimuseks oli arendada suhtlusprotokoll mikrokontrollerile nrf52832 koos kahe pool-sillaga Hiina jõuanduriga.
Ülesanne osutus keeruliseks, kuna kokku puutusin arusaamatute informatsioonide puudumisega. Tõenäoliselt peitub „kurja juur“ Nordic Semiconductori SDK-s endas — pidevad versiooniuuendused, teatud liigsed funktsioonid ja segadust tekitav funktsionaalsus. Tuli kõik nullist kirjutada.
Arvan, et see teema on üsna aktuaalne, arvestades, et see kiip toetab BLE stakki ja omab suurt hulka energiasäästu „maitsenuppe“. Kuid tehnilisse ossa ma liiga sügavale ei lähe, kuna sellel teemal on palju artikleid kirjutatud.
2. Projekti kirjeldus

Riistvara:
- Adafruit Feather nRF52 Bluefruit LE (see, mis käepärast oli)
- ADC HX711
- Hiina jõuandurid 2 tk (50х2 kg)
- Programmeerija ST-LINK V2
Tarkvara:
- IDE VSCODE
- NRF SDK 16
- OpenOCD
- Programmeerija ST-LINK V2
Kõik on ühes projektis, tuleb ainult Makefile'i natuke kohandada (näidata teie SDK asukoht).
3. Koodi kirjeldus
Kasutame GPIOTE moodulit, et töötada periferiaga, tuginedes ülesannete ja sündmuste seotusele, ning PPI moodulit, et edastada andmeid ühelt periferiast teisele ilma protsessori kaasamiseta.
ret_code_t err_code;
err_code = nrf_drv_gpiote_out_init(PD_SCK, &config); // seab välja
nrf_drv_gpiote_out_config_t config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(false); // pingutame pinni impulsi jaoks
err_code = nrf_drv_gpiote_out_init(PD_SCK, &config); // seab välja
Seame PD_SCL sünkroonimisliini väljundiks, et genereerida 10 µs impulsi.
nrf_drv_gpiote_in_config_t gpiote_config = GPIOTE_CONFIG_IN_SENSE_HITOLO(false); // taseme üleminek kõrgelt madalale
nrf_gpio_cfg_input(DOUT, NRF_GPIO_PIN_NOPULL); // otse sisend ilma tõmbamiseta
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); // külastame katkestuse
nrf_drv_timer_enable(&m_timer0); // lülitame taimeri sisse
}
Seame DOUT andmeliini HX711 valmisoleku staatuse lugemiseks, kui madal tase aktiveerub, kutsume esile töötleja, kus katkestame ja käivitame taimeri, et genereerida sünkroonimisimpulsse PD_SCL väljundis.
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));// connect timer to output
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_enable(m_ppi_channel1);// enable channel
APP_ERROR_CHECK(err_code);
nrf_drv_gpiote_out_task_enable(PD_SCK); // включаем gpiote
Seejärel initsieerime PPI mooduli ja ühendame meie ajasti PD_SCL väljundiga, et genereerida 10μs impulsi võrdlushetke saabumisel ning lülitame sisse GPIOTE mooduli.
nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;// default
timer_cfg.frequency = NRF_TIMER_FREQ_1MHz;// clocking at 1MHz
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);// triggers on comparisonInitsieerime null ajasti ja selle töötlejat.
if(m_counter%2 != 0 && m_counter<=48){
buffer <<= 1; // loetud andmete muutuja
c_counter++; // positiivsete impulsside loendur
if(nrf_gpio_pin_read(DOUT))buffer++; // loeme sisendi oleku
}
Kõige huvitavam toimub taimeri töötlemises. Impulsside periood on 20 µs. Meid huvitavad paaritud impulse (ülespoole minekul) ja tingimusel, et nende arv ei ületa 24 ning sündmusi on 48. Iga paaritu sündmuse korral loeme DOUTi
Datasheetist selgub, et impulsside arv peab olema vähemalt 25, mis vastab võimendustegurile 128 (koodis kasutasin 25 impulssi), see on ekvivalentne 50 taimerisündmusele, mis näitab andmeformaadi lõppu.
++m_counter; // sündmuste loendur
if(m_counter==50){
nrf_drv_timer_disable(&m_timer0); // peatame taimeri
m_simple_timer_state = SIMPLE_TIMER_STATE_STOPPED; //
buffer = buffer ^ 0x800000;
hx711_stop(); // peatame hx711
}
Pärast seda peatame taimeri ja töötleme andmeid (vastavalt datasheetile) ning lülitame HX711 madala energiatarbimise režiimi.
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();// käivitame hx711
nrf_drv_gpiote_out_toggle(LED_1);
m_simple_timer_state = SIMPLE_TIMER_STATE_STARTED;
}
}
/**@brief Looge taimerid.
*/
static void create_timers()
{
ret_code_t err_code;
// Looge taimerid
err_code = app_timer_create(&m_repeated_timer_id,
APP_TIMER_MODE_REPEATED,
repeated_timer_handler);
APP_ERROR_CHECK(err_code);
}
Ootame RTC taimeri sündmust, mis toimub 10 sekundi jooksul (see on teie otsustada), et aktiveerida HX711, kutsudes esile katkemise DOUT liinil.
On veel üks asi, logid edastatakse läbi UART (baud rate 115200, TX — 6 pin, RX — 8 pin), kõik seaded asuvad sdk_config.h failis.

Järeldused
Aitäh kõigile tähelepanu eest, loodan, et see artikkel on kasulik ja säästab arendajate väärtuslikku aega lahenduste leidmisel. Soovin öelda, et tehniline lähenemine, mida Nordic oma platvormidel kasutab, on üsna huvitav energiatõhususe seisukohalt.
P.S.
Projekt on veel arendamisel, seega kui see teema huvi pakub, püüan järgmises artiklis kirjeldada kaalumise sensorite kalibreerimise algoritmi ning BLE stacki ühendamist.
Materjalid
Allikas: habr.com
