From b0cbcd75edb4dc25236b100d2f05f9b744c2bb95 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Wed, 8 Aug 2018 16:18:02 +0200 Subject: [PATCH] SSR: Temperature measurement over USB --- ssr/Inc/app.h | 8 ++- ssr/Src/ds18b20.c | 108 ++++++++++++++++++++++++++++++----------- ssr/Src/main.c | 14 ++++-- ssr/Src/stm32f1xx_it.c | 2 +- ssr/host/test.c | 17 +++++++ 5 files changed, 113 insertions(+), 36 deletions(-) diff --git a/ssr/Inc/app.h b/ssr/Inc/app.h index f57ee6d..65b1e94 100644 --- a/ssr/Inc/app.h +++ b/ssr/Inc/app.h @@ -1,6 +1,6 @@ // main.c -extern volatile byte led_trigger; +extern volatile byte timer_ticked; // usbdev.c @@ -12,4 +12,8 @@ void tx_packet_send(void); // ds18b20.c -void ds_test(void); +extern int ds_current_temp; +#define DS_TEMP_UNKNOWN 0x7fffffff + +void ds_init(void); +void ds_step(void); 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; } } diff --git a/ssr/Src/main.c b/ssr/Src/main.c index cb54168..490bcf1 100644 --- a/ssr/Src/main.c +++ b/ssr/Src/main.c @@ -56,7 +56,7 @@ PCD_HandleTypeDef hpcd_USB_FS; /* USER CODE BEGIN PV */ /* Private variables ---------------------------------------------------------*/ struct usb usb; -volatile byte led_trigger; +volatile byte timer_ticked; /* USER CODE END PV */ @@ -109,6 +109,11 @@ static void process_packet(void) put_u32_be(tx_packet, 0); } break; + + case 2: + put_u32_be(tx_packet, 0); + put_u32_be(tx_packet+4, ds_current_temp); + break; } debug_printf(">> status %08x\n", get_u32_be(tx_packet)); @@ -170,7 +175,7 @@ int main(void) LL_TIM_EnableIT_UPDATE(TIM4); LL_TIM_GenerateEvent_UPDATE(TIM4); - ds_test(); + ds_init(); /* USER CODE END 2 */ @@ -178,15 +183,16 @@ int main(void) /* USER CODE BEGIN WHILE */ while (1) { - if (led_trigger) + if (timer_ticked) { - led_trigger = 0; + timer_ticked = 0; static byte led_state; if (led_state) LL_GPIO_SetOutputPin(LED_GPIO_Port, LED_Pin); else LL_GPIO_ResetOutputPin(LED_GPIO_Port, LED_Pin); led_state ^= 1; + ds_step(); } if (rx_packet_state == 1 && !tx_packet_state) diff --git a/ssr/Src/stm32f1xx_it.c b/ssr/Src/stm32f1xx_it.c index 2b98e27..b8a4457 100644 --- a/ssr/Src/stm32f1xx_it.c +++ b/ssr/Src/stm32f1xx_it.c @@ -257,7 +257,7 @@ void TIM4_IRQHandler(void) /* USER CODE BEGIN TIM4_IRQn 0 */ if (LL_TIM_IsActiveFlag_UPDATE(TIM4)) { - led_trigger = 1; + timer_ticked = 1; LL_TIM_ClearFlag_UPDATE(TIM4); } diff --git a/ssr/host/test.c b/ssr/host/test.c index 402db87..6e67f8e 100644 --- a/ssr/host/test.c +++ b/ssr/host/test.c @@ -94,6 +94,23 @@ int main(void) else msg(L_ERROR, "Received short packet"); + put_u32_be(req, 2); + put_u32_be(req+4, 0); + if (err = libusb_bulk_transfer(devh, 0x01, req, 8, &transferred, 2000)) + die("Transfer failed: error %d\n", err); + if (err = libusb_bulk_transfer(devh, 0x82, resp, 64, &received, 2000)) + die("Receive failed: error %d\n", err); + if (received >= 4) + { + int status = get_u32_be(resp); + if (status) + msg(L_ERROR, "Received error status %08x", status); + else + msg(L_INFO, "Temperature: %d\n", get_u32_be(resp+4)); + } + else + msg(L_ERROR, "Received short packet"); + sleep(1); } -- 2.39.2