From: Martin Mares Date: Wed, 8 Aug 2018 09:15:54 +0000 (+0200) Subject: SSR: DS18B20 X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=d06351fae4e82caf11a1439649f9dc276f28f668;p=home-hw.git SSR: DS18B20 --- diff --git a/ssr/Inc/app.h b/ssr/Inc/app.h index 980422d..f57ee6d 100644 --- a/ssr/Inc/app.h +++ b/ssr/Inc/app.h @@ -9,3 +9,7 @@ extern byte tx_packet[64]; extern volatile byte rx_packet_state, tx_packet_state; void tx_packet_send(void); + +// ds18b20.c + +void ds_test(void); diff --git a/ssr/Inc/util.h b/ssr/Inc/util.h index 3a29fd6..7e37313 100644 --- a/ssr/Inc/util.h +++ b/ssr/Inc/util.h @@ -62,8 +62,7 @@ static inline void put_u32_le(byte *p, u32 x) // debug.c #undef DEBUG_SEMIHOSTING -// #define DEBUG_USART USART1 -#undef DEBUG_USART +#define DEBUG_USART USART1 void debug_printf(const char *fmt, ...); void debug_puts(const char *s); diff --git a/ssr/Makefile b/ssr/Makefile index c5f919a..53278af 100644 --- a/ssr/Makefile +++ b/ssr/Makefile @@ -56,6 +56,7 @@ Src/main.c \ Src/debug.c \ Src/usb.c \ Src/usbdev.c \ +Src/ds18b20.c \ /aux/misc/stm/F1-package/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_rcc.c \ /Src/system_stm32f1xx.c \ Src/stm32f1xx_it.c \ diff --git a/ssr/Src/ds18b20.c b/ssr/Src/ds18b20.c new file mode 100644 index 0000000..d44524d --- /dev/null +++ b/ssr/Src/ds18b20.c @@ -0,0 +1,185 @@ +// DS18B20 Temperature Sensor + +#include "main.h" +#include "util.h" +#include "app.h" + +static volatile u32 ds_dma_buffer; + +#define DS_PORT THERMO_GPIO_Port +#define DS_PIN THERMO_GPIO_Pin +#define DS_PIN_MASK (1U << 7) // Unfortunately, this cannot be inferred from the Pin constant +#define DS_DMA DMA1 +#define DS_DMA_CHANNEL LL_DMA_CHANNEL_6 +#define DS_DEBUG + +#ifdef DS_DEBUG +#define DEBUG debug_printf +#else +#define DEBUG(xxx, ...) do { } while (0) +#endif + +static void ds_reset(void) +{ + DEBUG("DS18B20: Reset\n"); + LL_TIM_DisableCounter(TIM3); + LL_TIM_SetOnePulseMode(TIM3, LL_TIM_ONEPULSEMODE_SINGLE); + + // DMA for reading pin state + ds_dma_buffer = 0xdeadbeef; + LL_DMA_SetMemoryAddress(DS_DMA, DS_DMA_CHANNEL, (u32) &ds_dma_buffer); + LL_DMA_SetPeriphAddress(DS_DMA, DS_DMA_CHANNEL, (u32) &DS_PORT->IDR); + LL_DMA_SetDataLength(DS_DMA, DS_DMA_CHANNEL, 1); + LL_DMA_EnableChannel(DS_DMA, DS_DMA_CHANNEL); + + LL_TIM_OC_InitTypeDef oc; + + // CC1 is used to drive the DMA (read line state at specified time) + LL_TIM_OC_StructInit(&oc); + oc.OCMode = LL_TIM_OCMODE_FROZEN; + oc.CompareValue = 560; + LL_TIM_OC_Init(TIM3, LL_TIM_CHANNEL_CH1, &oc); + LL_TIM_EnableDMAReq_CC1(TIM3); + LL_TIM_CC_SetDMAReqTrigger(TIM3, LL_TIM_CCDMAREQUEST_CC); + + // CC2 is used to generate pulses (return line to idle state at specified time) + LL_TIM_OC_StructInit(&oc); + oc.OCMode = LL_TIM_OCMODE_FORCED_ACTIVE; + oc.OCState = LL_TIM_OCSTATE_ENABLE; + oc.CompareValue = 480; + oc.OCPolarity = LL_TIM_OCPOLARITY_LOW; + LL_TIM_OC_Init(TIM3, LL_TIM_CHANNEL_CH2, &oc); + + // Set timer period to the length of the whole transaction + LL_TIM_SetAutoReload(TIM3, 999); + + // Pull line down and start timer + LL_TIM_OC_SetMode(TIM3, LL_TIM_CHANNEL_CH2, LL_TIM_OCMODE_INACTIVE); + LL_TIM_EnableCounter(TIM3); + + // Wait until the timer expires + while (LL_TIM_IsEnabledCounter(TIM3)) + ; + // Counter is automatically disabled at the end of cycle + + // Disable DMA + LL_TIM_DisableDMAReq_CC1(TIM3); + LL_DMA_DisableChannel(DS_DMA, DS_DMA_CHANNEL); + + DEBUG("Init DMA: %08x [%u] (%u remains)\n", ds_dma_buffer, !!(ds_dma_buffer & DS_PIN_MASK), LL_DMA_GetDataLength(DS_DMA, DS_DMA_CHANNEL)); +} + +static void ds_send_byte(byte b) +{ + DEBUG("DS write: %02x\n", b); + LL_TIM_SetAutoReload(TIM3, 99); // Each write slot takes 100μs + for (uint m=1; m < 0x100; m <<= 1) + { + LL_TIM_OC_SetCompareCH2(TIM3, ((b & m) ? 1 : 89)); // 1: 1μs pulse, 0: 89μs pulse + LL_TIM_OC_SetMode(TIM3, LL_TIM_CHANNEL_CH2, LL_TIM_OCMODE_FORCED_ACTIVE); + LL_TIM_OC_SetMode(TIM3, LL_TIM_CHANNEL_CH2, LL_TIM_OCMODE_INACTIVE); + LL_TIM_EnableCounter(TIM3); + while (LL_TIM_IsEnabledCounter(TIM3)) + ; + } +} + +static byte ds_recv_byte(void) +{ + LL_TIM_SetAutoReload(TIM3, 79); // Each read slot takes 80μs + LL_TIM_OC_SetCompareCH2(TIM3, 1); // Generate 1μs pulse to start read slot + LL_TIM_OC_SetCompareCH1(TIM3, 8); // Sample data 8μs after start of slot + LL_TIM_EnableDMAReq_CC1(TIM3); + + uint out = 0; + for (uint m=1; m < 0x100; m <<= 1) + { + ds_dma_buffer = 0xdeadbeef; + LL_DMA_SetDataLength(DS_DMA, DS_DMA_CHANNEL, 1); + LL_DMA_EnableChannel(DS_DMA, DS_DMA_CHANNEL); + LL_TIM_OC_SetMode(TIM3, LL_TIM_CHANNEL_CH2, LL_TIM_OCMODE_FORCED_ACTIVE); + LL_TIM_OC_SetMode(TIM3, LL_TIM_CHANNEL_CH2, LL_TIM_OCMODE_INACTIVE); + LL_TIM_EnableCounter(TIM3); + while (LL_TIM_IsEnabledCounter(TIM3)) + ; + debug_printf("XXX %08x\n", ds_dma_buffer); + if (ds_dma_buffer & DS_PIN_MASK) + out |= m; + LL_DMA_DisableChannel(DS_DMA, DS_DMA_CHANNEL); + } + + LL_TIM_DisableDMAReq_CC1(TIM3); + DEBUG("DS read: %02x\n", out); + return out; +} + +static byte ds_buf[10]; + +static int ds_recv_block(uint n) +{ + uint crc = 0; + for (uint i=0; i> 7); + crc = (crc << 1) & 0xff; + if (k) + crc ^= 0x31; + b >>= 1; + } + } + + if (crc) + { + debug_printf("WARNING: Invalid CRC %02x\n", crc); + return 0; + } + return 1; +} + +void ds_test(void) +{ + uint cnt = 0; + + debug_puts("Init\n"); + NVIC_DisableIRQ(TIM3_IRQn); // One day, we will handle everything from interrupts... + + // Identify device + ds_reset(); + ds_send_byte(0x33); + ds_recv_block(8); + + for(;;); + + // FIXME: Configure precision + + for (;;) + { + LL_GPIO_ResetOutputPin(LED_GPIO_Port, LED_Pin); + // debug_printf("Tick tock: %d\n", cnt); + + // Start measurement + ds_reset(); + ds_send_byte(0xcc); + ds_send_byte(0x44); + while (ds_recv_byte() != 0xff) + LL_mDelay(10); + + // Read scratch pad + ds_reset(); + ds_send_byte(0xcc); + ds_send_byte(0xbe); + ds_recv_block(9); + int t = (int16_t)(ds_buf[0] | (ds_buf[1] << 8)); + t = t*1000/16; + + LL_GPIO_SetOutputPin(LED_GPIO_Port, LED_Pin); + debug_printf("Temp: %d.%03d degC\n", t/1000, t%1000); + + LL_mDelay(1000); + cnt++; + } +} diff --git a/ssr/Src/main.c b/ssr/Src/main.c index d10eb43..419f049 100644 --- a/ssr/Src/main.c +++ b/ssr/Src/main.c @@ -170,6 +170,8 @@ int main(void) LL_TIM_EnableIT_UPDATE(TIM4); LL_TIM_GenerateEvent_UPDATE(TIM4); + ds_test(); + /* USER CODE END 2 */ /* Infinite loop */ @@ -337,7 +339,7 @@ static void MX_TIM3_Init(void) GPIO_InitStruct.Pin = THERMO_Pin; GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH; - GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN; LL_GPIO_Init(THERMO_GPIO_Port, &GPIO_InitStruct); }