X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=ssr%2FSrc%2Fds18b20.c;h=5fa25a129f0ab4249676ea06473694dbffb7b295;hb=b0cbcd75edb4dc25236b100d2f05f9b744c2bb95;hp=0b9b49b00f8d4ebb7a30dffafca0f735a47c7d60;hpb=075b0e3ec3abb970b92ae6d033c8c41f00adffc0;p=home-hw.git diff --git a/ssr/Src/ds18b20.c b/ssr/Src/ds18b20.c index 0b9b49b..5fa25a1 100644 --- a/ssr/Src/ds18b20.c +++ b/ssr/Src/ds18b20.c @@ -12,6 +12,7 @@ static volatile u32 ds_dma_buffer; #define DS_DMA DMA1 #define DS_DMA_CHANNEL LL_DMA_CHANNEL_6 #undef DS_DEBUG +#undef DS_DEBUG2 #ifdef DS_DEBUG #define DEBUG debug_printf @@ -19,9 +20,18 @@ static volatile u32 ds_dma_buffer; #define DEBUG(xxx, ...) do { } while (0) #endif -static void ds_reset(void) +#ifdef DS_DEBUG2 +#define DEBUG2 debug_printf +#else +#define DEBUG2(xxx, ...) do { } while (0) +#endif + +// Current temperature +int ds_current_temp = DS_TEMP_UNKNOWN; + +static bool ds_reset(void) { - DEBUG("DS18B20: Reset\n"); + DEBUG2("DS18B20: Reset\n"); LL_TIM_DisableCounter(TIM3); LL_TIM_SetOnePulseMode(TIM3, LL_TIM_ONEPULSEMODE_SINGLE); @@ -66,19 +76,32 @@ static void ds_reset(void) 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)); + DEBUG2("Init DMA: %08x [%u] (%u remains)\n", ds_dma_buffer, !!(ds_dma_buffer & DS_PIN_MASK), LL_DMA_GetDataLength(DS_DMA, DS_DMA_CHANNEL)); + + // Did the device respond? + if (ds_dma_buffer & DS_PIN_MASK) + { + DEBUG("DS18B20: Initialization failed\n"); + return 0; + } + else + return 1; } static void ds_send_byte(byte b) { - DEBUG("DS write: %02x\n", b); + DEBUG2("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); + __disable_irq(); + // XXX: On STM32F1, we must configure the OC channel _after_ we enable the counter, + // otherwise OC triggers immediately. Reasons? LL_TIM_EnableCounter(TIM3); LL_TIM_OC_SetMode(TIM3, LL_TIM_CHANNEL_CH2, LL_TIM_OCMODE_INACTIVE); + __enable_irq(); while (LL_TIM_IsEnabledCounter(TIM3)) ; } @@ -98,30 +121,32 @@ static byte ds_recv_byte(void) 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); + __disable_irq(); LL_TIM_EnableCounter(TIM3); LL_TIM_OC_SetMode(TIM3, LL_TIM_CHANNEL_CH2, LL_TIM_OCMODE_INACTIVE); + __enable_irq(); while (LL_TIM_IsEnabledCounter(TIM3)) ; - DEBUG("XXX %08x\n", ds_dma_buffer); + DEBUG2("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); + DEBUG2("DS read: %02x\n", out); return out; } static byte ds_buf[10]; -static int ds_recv_block(uint n) +static bool ds_recv_block(uint n) { uint crc = 0; for (uint i=0; i>= 1; } } - // debug_printf("\n"); if (crc) { - debug_printf("WARNING: Invalid CRC %02x\n", crc); + DEBUG("DS18B20: Invalid CRC %02x\n", crc); return 0; } return 1; } -void ds_test(void) +void ds_init(void) { - uint cnt = 0; - - debug_puts("Init\n"); + DEBUG("DS18B20: Init\n"); NVIC_DisableIRQ(TIM3_IRQn); // One day, we will handle everything from interrupts... // Identify device - ds_reset(); + if (!ds_reset()) + return; ds_send_byte(0x33); ds_recv_block(8); // FIXME: Configure precision +} - for (;;) - { - LL_GPIO_ResetOutputPin(LED_GPIO_Port, LED_Pin); - // debug_printf("Tick tock: %d\n", cnt); +void ds_step(void) +{ + static byte ds_running; + static byte ds_timeout; + if (!ds_running) + { // Start measurement - ds_reset(); + if (!ds_reset()) + { + ds_current_temp = DS_TEMP_UNKNOWN; + return; + } ds_send_byte(0xcc); ds_send_byte(0x44); - while (ds_recv_byte() != 0xff) - LL_mDelay(10); + ds_running = 1; + ds_timeout = 255; + } + else + { + // Still running? + if (ds_recv_byte() != 0xff) + { + if (!ds_timeout--) + { + ds_current_temp = DS_TEMP_UNKNOWN; + ds_running = 0; + DEBUG("DS18B20: Timeout\n"); + } + return; + } + ds_running = 0; // Read scratch pad - ds_reset(); + if (!ds_reset()) + { + ds_current_temp = DS_TEMP_UNKNOWN; + return; + } ds_send_byte(0xcc); ds_send_byte(0xbe); - ds_recv_block(9); + if (!ds_recv_block(9)) + { + ds_current_temp = DS_TEMP_UNKNOWN; + return; + } 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++; + DEBUG("DS18B20: %d.%03d degC\n", t/1000, t%1000); + ds_current_temp = t; } }