implement 1-Wire APIs
This commit is contained in:
Родитель
e37b0ae050
Коммит
5625ca02a3
|
@ -0,0 +1,111 @@
|
|||
#include "jdstm.h"
|
||||
|
||||
// Implemented based on ideas from https://cnnblike.com/post/stm32-OneWire/
|
||||
// Basically, uses UART at 125kHz for signalling and at 10kHz for reset
|
||||
// UART is configured as "half-duplex", meaning the TX/RX pins are connected internally,
|
||||
// but in fact we sometimes enable both transmitter and receiver.
|
||||
// The TX pin is configured with pull-up as open-drain.
|
||||
// Unlike in the article above, no external diode is necessary, and the RX pin is not used.
|
||||
|
||||
#ifdef ONE_WIRE
|
||||
|
||||
#if USART_IDX == 1
|
||||
#define OW_UART 2
|
||||
#else
|
||||
#define OW_UART 1
|
||||
#endif
|
||||
|
||||
#if OW_UART == 1
|
||||
#define USARTx USART1
|
||||
#elif OW_UART == 2
|
||||
#define USARTx USART2
|
||||
#else
|
||||
#error "bad usart"
|
||||
#endif
|
||||
|
||||
void one_init(void) {
|
||||
#if OW_UART == 2
|
||||
#ifndef DISABLE_PLL
|
||||
#error "PLL not supported"
|
||||
#endif
|
||||
__HAL_RCC_USART2_CLK_ENABLE();
|
||||
#elif OW_UART == 1
|
||||
LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_HSI);
|
||||
__HAL_RCC_USART1_CLK_ENABLE();
|
||||
#else
|
||||
#error "bad usart"
|
||||
#endif
|
||||
|
||||
pin_setup_output_af(PIN_TX, PIN_TX_AF);
|
||||
pin_set_pull(PIN_TX, 1);
|
||||
pin_set_opendrain(PIN_TX);
|
||||
|
||||
USARTx->CR1 = LL_USART_DATAWIDTH_8B | LL_USART_PARITY_NONE | LL_USART_OVERSAMPLING_16 |
|
||||
LL_USART_DIRECTION_TX;
|
||||
|
||||
USARTx->CR2 = LL_USART_STOPBITS_1;
|
||||
USARTx->CR3 = LL_USART_HWCONTROL_NONE;
|
||||
|
||||
#ifdef LL_USART_PRESCALER_DIV1
|
||||
LL_USART_SetPrescaler(USARTx, LL_USART_PRESCALER_DIV1);
|
||||
#endif
|
||||
|
||||
LL_USART_ConfigHalfDuplexMode(USARTx);
|
||||
}
|
||||
|
||||
static void setup_xfer(int rx) {
|
||||
USARTx->BRR = rx == 2 ? HSI_MHZ * 100 : HSI_MHZ * 8; // ->10kHz or 125kHz
|
||||
if (rx)
|
||||
LL_USART_EnableDirectionRx(USARTx);
|
||||
else
|
||||
LL_USART_DisableDirectionRx(USARTx);
|
||||
LL_USART_EnableDirectionTx(USARTx);
|
||||
USARTx->ICR = USART_ISR_FE | USART_ISR_NE | USART_ISR_ORE; // clear error flags before we start
|
||||
LL_USART_Enable(USARTx);
|
||||
while (!(LL_USART_IsActiveFlag_TEACK(USARTx)))
|
||||
;
|
||||
}
|
||||
|
||||
void one_write(uint8_t b) {
|
||||
setup_xfer(0);
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
while (!LL_USART_IsActiveFlag_TXE(USARTx))
|
||||
;
|
||||
LL_USART_TransmitData8(USARTx, (b & (1 << i)) ? 0xff : 0x00);
|
||||
}
|
||||
while (!LL_USART_IsActiveFlag_TC(USARTx))
|
||||
;
|
||||
LL_USART_Disable(USARTx);
|
||||
}
|
||||
|
||||
uint8_t one_read(void) {
|
||||
setup_xfer(1);
|
||||
|
||||
uint8_t r = 0;
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
while (!LL_USART_IsActiveFlag_TXE(USARTx))
|
||||
;
|
||||
LL_USART_TransmitData8(USARTx, 0xff);
|
||||
while (!LL_USART_IsActiveFlag_RXNE(USARTx))
|
||||
;
|
||||
uint8_t v = LL_USART_ReceiveData8(USARTx);
|
||||
if (v)
|
||||
r |= (1 << 8);
|
||||
}
|
||||
LL_USART_Disable(USARTx);
|
||||
return r;
|
||||
}
|
||||
|
||||
int one_reset(void) {
|
||||
int r;
|
||||
setup_xfer(2);
|
||||
LL_USART_TransmitData8(USARTx, 0xf0);
|
||||
while (!LL_USART_IsActiveFlag_RXNE(USARTx))
|
||||
;
|
||||
uint8_t v = LL_USART_ReceiveData8(USARTx);
|
||||
r = v == 0xf0 ? -1 : 0;
|
||||
LL_USART_Disable(USARTx);
|
||||
return r;
|
||||
}
|
||||
|
||||
#endif // ONE_WIRE
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
// USART2 on lower end F0 can't be set to run from HSI
|
||||
// we're not currently setup to handle clock freq switching at that time
|
||||
#if USART_IDX != 1
|
||||
#if USART_IDX != 1 || defined(ONE_WIRE)
|
||||
#define DISABLE_PLL 1
|
||||
#endif
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
|
||||
// USART2 on lower end G0 can't be set to run from HSI
|
||||
// we're not currently setup to handle clock freq switching at that time
|
||||
#if USART_IDX != 1
|
||||
#if USART_IDX != 1 || defined(ONE_WIRE)
|
||||
#define DISABLE_PLL 1
|
||||
#endif
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче