1. Introdução
Na agenda estava a tarefa de desenvolver um protocolo de comunicação para o microcontrolador nrf52832 com dois extensômetros chineses de meia ponte.
A tarefa acabou não sendo fácil, pois me deparei com a falta de qualquer informação inteligível. É mais provável que a "raiz do mal" esteja no próprio SDK da Nordic Semiconductor - são atualizações constantes de versão, alguma redundância e confusão de funcionalidade. Tive que escrever tudo do zero.
Acho que este tópico é bastante relevante considerando que este chip possui uma pilha BLE e todo um conjunto de "doces" do modo de economia de energia. Mas não irei me aprofundar na parte técnica, já que muitos artigos foram escritos sobre esse assunto.
2. Descrição do projeto

Ferro:
- Adafruit Feather nRF52 Bluefruit LE (o que aconteceu para estar em mãos)
- ADC HX711
- Medidores de tensão chineses 2 unid. (50x2 kg)
- Programador ST-LINK V2
Programas:
- IDE VSCODE
- NRF SDK 16
- OpenOCD
- Programador ST-LINK V2
Tudo está em um projeto, você só precisa shaman Makefile (especificar a localização do seu SDK).
3. Descrição do código
Usaremos o módulo GPIOTE para trabalhar com periféricos baseado na vinculação de tarefas e eventos, bem como o módulo PPI para transferir dados de um periférico para outro sem a participação do processador.
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);//
Configuramos a linha de sincronização PD_SCL para a saída para gerar pulsos com uma duração de 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);//
}
Configuramos a linha de dados DOUT para ler o estado de prontidão do HX711, se houver um nível baixo, um handler é acionado no qual desabilitamos a interrupção e iniciamos um temporizador para gerar pulsos de clock na saída 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);
// habilitar gpiote
Depois disso, inicializamos o módulo PPI e mudamos nosso temporizador para a saída PD_SCL, para gerar pulsos com uma duração de 10 μs quando ocorre o evento de comparação, e também ligamos o módulo 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);//
Inicializamos o cronômetro zero e seu manipulador.
if(m_counter%2 != 0 && m_counter<=48){
buffer <<= 1;//
c_counter++;//
if(nrf_gpio_pin_read(DOUT))buffer++;//
}
A coisa mais interessante acontece no manipulador do cronômetro. O período de pulso é de 20 μs. Estamos interessados em pulsos ímpares (na borda de subida) e desde que seu número não seja superior a 24 e haja 48 eventos. Para cada evento ímpar, DOUT é lido
, 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 10 ( ) HX711, DOUT.
, UART (baud rate 115200, TX — 6 , RX — 8 ) sdk_config.h
Obrigado a todos pela atenção, espero que este artigo seja útil e economize um tempo valioso para desenvolvedores que procuram uma solução. Quero dizer que a abordagem técnica que a Nordic usa em suas plataformas é bastante interessante em termos de eficiência energética.
PS
O projeto ainda está em desenvolvimento, portanto, se este tópico for interessante no próximo artigo, tentarei descrever o algoritmo para calibração de sensores de peso, bem como conectar uma pilha BLE.