|
@@ -0,0 +1,356 @@
|
|
|
+/********************************* (C) РОТЕК ***********************************
|
|
|
+ * @module onewire
|
|
|
+ * @file onewire.c
|
|
|
+ * @version 1.0.0
|
|
|
+ * @date XX.XX.XXXX
|
|
|
+ * $brief DS18B20 temperature sensor driver
|
|
|
+ *******************************************************************************
|
|
|
+ * @history Version Author Comment
|
|
|
+ * XX.XX.XXXX 1.0.0 Telenkov D.A. First release.
|
|
|
+ *******************************************************************************
|
|
|
+ */
|
|
|
+
|
|
|
+#include "common_config.h"
|
|
|
+#include "stm32f2xx.h"
|
|
|
+#include "stm32f2xx_dma.h"
|
|
|
+#include "usart.h"
|
|
|
+#include "gpio.h"
|
|
|
+#include "onewire.h"
|
|
|
+
|
|
|
+/* Force remove debug output */
|
|
|
+#undef DBG
|
|
|
+#define DBG if(0)
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief Размер буфера для отправки данных датчикам
|
|
|
+ */
|
|
|
+#define DALLAS_BUF_SIZE 8
|
|
|
+
|
|
|
+#define DALLAS_TIME_OUT 1500000
|
|
|
+
|
|
|
+#define DALLAS_0 0x00
|
|
|
+#define DALLAS_1 0xff
|
|
|
+#define DALLAS_R_1 0xff
|
|
|
+
|
|
|
+typedef struct {
|
|
|
+ gpio_t ow_pin;
|
|
|
+ USART_TypeDef *uart_addr;
|
|
|
+ DMA_InitTypeDef DMA_InitStructureTx;
|
|
|
+ DMA_InitTypeDef DMA_InitStructureRx;
|
|
|
+ sensorBuf[DALLAS_BUF_SIZE];
|
|
|
+}ow_sensor_t;
|
|
|
+
|
|
|
+ow_sensor_t ow_sensor[MAX_T_SENSORS];
|
|
|
+
|
|
|
+#define T_SENSOR_ADD(sensor_num, ow_line, uart_addr) \
|
|
|
+ do { \
|
|
|
+ ow_sensor[sensor_num].ow_pin = ow_line; \
|
|
|
+ ow_sensor[sensor_num].uart_addr = uart_addr; \
|
|
|
+ } while (0);
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief Настройка USART
|
|
|
+ * @retval
|
|
|
+ */
|
|
|
+void DALLAS_Init()
|
|
|
+{
|
|
|
+ for (uint8_t i = 0; i < MAX_T_SENSORS; i ++) {
|
|
|
+#define XTSENSOR(sensor_num, ow_line, uart_addrm) T_SENSOR_ADD(sensor_num, ow_line, uart_addr);
|
|
|
+ T_SENSOR_TABLE
|
|
|
+#undef XTSENSOR
|
|
|
+ uart_hw_init(ow_sensor[i].uart_addr, DALLAS_SENSOR_UART_BAUD, DALLAS_SENSOR_UART_WORD_LEN,
|
|
|
+ DALLAS_SENSOR_UART_PARITY, DALLAS_SENSOR_UART_STOP_BIT);
|
|
|
+ }
|
|
|
+ DALLAS_DmaInit();
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief Настройка DMA
|
|
|
+ * @retval
|
|
|
+ */
|
|
|
+void DALLAS_DmaInit(void)
|
|
|
+{
|
|
|
+ DMA_Stream_TypeDef *RxDMA_Stream = NULL;
|
|
|
+ DMA_Stream_TypeDef *TxDMA_Stream = NULL;
|
|
|
+ uint32_t RxDMA_Channel = 0;
|
|
|
+ uint32_t TxDMA_Channel = 0;
|
|
|
+
|
|
|
+ for (uint8_t i = 0; i < MAX_T_SENSORS; i ++) {
|
|
|
+ if (ow_sensor[i].uart_addr == USART1) {
|
|
|
+ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
|
|
|
+ RxDMA_Stream = DMA1_Stream2;
|
|
|
+ TxDMA_Stream = DMA1_Stream7;
|
|
|
+ RxDMA_Channel = DMA_Channel_4;
|
|
|
+ TxDMA_Channel = DMA_Channel_4;
|
|
|
+ } else if (ow_sensor[i].uart_addr == USART2) {
|
|
|
+ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
|
|
|
+ RxDMA_Stream = DMA1_Stream5;
|
|
|
+ TxDMA_Stream = DMA1_Stream6;
|
|
|
+ RxDMA_Channel = DMA_Channel_4;
|
|
|
+ TxDMA_Channel = DMA_Channel_4;
|
|
|
+ } else if (ow_sensor[i].uart_addr == USART3) {
|
|
|
+ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
|
|
|
+ RxDMA_Stream = DMA1_Stream1;
|
|
|
+ TxDMA_Stream = DMA1_Stream3;
|
|
|
+ RxDMA_Channel = DMA_Channel_4;
|
|
|
+ TxDMA_Channel = DMA_Channel_4;
|
|
|
+ } else if (ow_sensor[i].uart_addr == UART4) {
|
|
|
+ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
|
|
|
+ RxDMA_Stream = DMA1_Stream2;
|
|
|
+ TxDMA_Stream = DMA1_Stream4;
|
|
|
+ RxDMA_Channel = DMA_Channel_4;
|
|
|
+ TxDMA_Channel = DMA_Channel_4;
|
|
|
+ } else if (ow_sensor[i].uart_addr == UART5) {
|
|
|
+ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
|
|
|
+ RxDMA_Stream = DMA1_Stream0;
|
|
|
+ TxDMA_Stream = DMA1_Stream7;
|
|
|
+ RxDMA_Channel = DMA_Channel_4;
|
|
|
+ TxDMA_Channel = DMA_Channel_4;
|
|
|
+ } else if (ow_sensor[i].uart_addr == USART6) {
|
|
|
+ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
|
|
|
+ RxDMA_Stream = DMA1_Stream1;
|
|
|
+ TxDMA_Stream = DMA1_Stream6;
|
|
|
+ RxDMA_Channel = DMA_Channel_5;
|
|
|
+ TxDMA_Channel = DMA_Channel_5;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* DMA на чтение */
|
|
|
+ DMA_DeInit(RxDMA_Stream);
|
|
|
+ ow_sensor[i].DMA_InitStructureRx.DMA_Channel = RxDMA_Stream;
|
|
|
+ ow_sensor[i].DMA_InitStructureRx.DMA_PeripheralBaseAddr = (uint32_t)&ow_sensor[i].uart_addr->DR;
|
|
|
+ ow_sensor[i].DMA_InitStructureRx.DMA_Memory0BaseAddr = (uint32_t)&ow_sensor[i].sensorBuf;
|
|
|
+ ow_sensor[i].DMA_InitStructureRx.DMA_DIR = DMA_DIR_PeripheralToMemory;
|
|
|
+ ow_sensor[i].DMA_InitStructureRx.DMA_BufferSize = DALLAS_BUF_SIZE;
|
|
|
+ ow_sensor[i].DMA_InitStructureRx.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
|
|
+ ow_sensor[i].DMA_InitStructureRx.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
|
|
+ ow_sensor[i].DMA_InitStructureRx.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
|
|
+ ow_sensor[i].DMA_InitStructureRx.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
|
|
+ ow_sensor[i].DMA_InitStructureRx.DMA_Mode = DMA_Mode_Normal;
|
|
|
+ ow_sensor[i].DMA_InitStructureRx.DMA_Priority = DMA_Priority_Medium;
|
|
|
+
|
|
|
+ DMA_Init(RxDMA_Stream, &ow_sensor[i].DMA_InitStructureRx);
|
|
|
+
|
|
|
+ /* DMA на запись */
|
|
|
+ DMA_DeInit(TxDMA_Stream);
|
|
|
+ ow_sensor[i].DMA_InitStructureTx.DMA_Channel = TxDMA_Stream;
|
|
|
+ ow_sensor[i].DMA_InitStructureTx.DMA_PeripheralBaseAddr = &ow_sensor[i].uart_addr->DR;
|
|
|
+ ow_sensor[i].DMA_InitStructureTx.DMA_Memory0BaseAddr = (uint32_t)&Dow_sensor[i].sensorBuf;
|
|
|
+ ow_sensor[i].DMA_InitStructureTx.DMA_DIR = DMA_DIR_MemoryToPeripheral;
|
|
|
+ ow_sensor[i].DMA_InitStructureTx.DMA_BufferSize = DALLAS_BUF_SIZE;
|
|
|
+ ow_sensor[i].DMA_InitStructureTx.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
|
|
+ ow_sensor[i].DMA_InitStructureTx.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
|
|
+ ow_sensor[i].DMA_InitStructureTx.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
|
|
+ ow_sensor[i].DMA_InitStructureTx.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
|
|
+ ow_sensor[i].DMA_InitStructureTx.DMA_Mode = DMA_Mode_Normal;
|
|
|
+ ow_sensor[i].DMA_InitStructureTx.DMA_Priority = DMA_Priority_Medium;
|
|
|
+
|
|
|
+ DMA_Init(TxDMA_Stream, &ow_sensor[i].DMA_InitStructureTx.);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief Настроить TX пин как питающий выход
|
|
|
+ * @retval
|
|
|
+ */
|
|
|
+void DALLAS_OutSetAsPower(t_sensor_list_t sensor)
|
|
|
+{
|
|
|
+ gpio_pindef_t *pin = &gpio_pins[ow_sensor[sensor].ow_pin];
|
|
|
+ gpio_hw_config_pin(pin->port, pin->pin, GPIO_MODE_OUT_CFG | GPIO_TYPE_PP_CFG) |
|
|
|
+ GPIO_SPEED_HIGH_CFG));
|
|
|
+ gpio_set(id, GPIO_SET);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief Настроить TX пин как передатчик
|
|
|
+ * @retval
|
|
|
+ */
|
|
|
+void DALLAS_OutSetAsTX(t_sensor_list_t sensor)
|
|
|
+{
|
|
|
+ gpio_pindef_t *pin = &gpio_pins[ow_sensor[sensor].ow_pin];
|
|
|
+ uint8_t af_n = (uint8_t)(pin->flags >> _GPIO_AF_SHIFT);
|
|
|
+ gpio_connect_af(id, af_n);
|
|
|
+ gpio_hw_config_pin(pin->port, pin->pin, GPIO_MODE_AF_CFG |
|
|
|
+ GPIO_SPEED_HIGH_CFG);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief Сброс и проверка наличия устройства на шине 1-wire
|
|
|
+ * @retval
|
|
|
+ */
|
|
|
+uint8_t DALLAS_SensorReset(t_sensor_list_t sensor)
|
|
|
+{
|
|
|
+ uint8_t presence;
|
|
|
+
|
|
|
+ uart_hw_init(ow_sensor[sensor].uart_addr, DALLAS_SENSOR_RST_UART_BAUD,
|
|
|
+ DALLAS_SENSOR_UART_WORD_LEN, DALLAS_SENSOR_UART_PARITY, DALLAS_SENSOR_UART_STOP_BIT);
|
|
|
+
|
|
|
+ // отправляем 0xf0 на скорости 9600
|
|
|
+ USART_ClearFlag(ow_sensor[sensor].uart_addr, USART_FLAG_TC);
|
|
|
+ USART_SendData(ow_sensor[sensor].uart_addr, 0xf0);
|
|
|
+
|
|
|
+ while (USART_GetFlagStatus(ow_sensor[sensor].uart_addr, USART_FLAG_TC) == RESET) { }
|
|
|
+
|
|
|
+ presence = USART_ReceiveData(ow_sensor[sensor].uart_addr);
|
|
|
+
|
|
|
+ uart_hw_init(ow_sensor[sensor].uart_addr, DALLAS_SENSOR_UART_BAUD, DALLAS_SENSOR_UART_WORD_LEN,
|
|
|
+ DALLAS_SENSOR_UART_PARITY, DALLAS_SENSOR_UART_STOP_BIT);
|
|
|
+
|
|
|
+ if (presence != 0xf0) {
|
|
|
+ DBG printf("DALLAS_SensorReset: DALLAS_OK\r\n");
|
|
|
+ return DALLAS_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ DBG printf("DALLAS_SensorReset: DALLAS_NO_DEVICE\r\n");
|
|
|
+ return DALLAS_NO_DEVICE;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief Отправка и прием данных
|
|
|
+ * @param sendReset посылать RESET в начале общения.
|
|
|
+ * OW_SEND_RESET
|
|
|
+ * OW_NO_RESET
|
|
|
+ * @param *command - массив байт, отсылаемых в шину.
|
|
|
+ * Если нужно чтение - отправляем OW_READ_SLOTH
|
|
|
+ * @param cLen - длина буфера команд, столько байт отошлется в шину
|
|
|
+ * @param *data - если требуется чтение, то ссылка на буфер для чтения
|
|
|
+ * @param dLen - длина буфера для чтения. Прочитается не более этой длины
|
|
|
+ * @param readStart - с какого символа передачи начинать чтение (нумеруются с 0)
|
|
|
+ * можно указать OW_NO_READ, тогда можно не задавать data и dLen
|
|
|
+ * @retval
|
|
|
+ */
|
|
|
+uint8_t DALLAS_Send(t_sensor_list_t sensor, uint8_t sendReset, uint8_t *command,
|
|
|
+ uint8_t cLen, uint8_t *data, uint8_t dLen, uint8_t readStart)
|
|
|
+{
|
|
|
+ uint32_t timeOutCounter = 0;
|
|
|
+ DMA_Stream_TypeDef *RxDMA_Stream = NULL;
|
|
|
+ DMA_Stream_TypeDef *TxDMA_Stream = NULL;
|
|
|
+
|
|
|
+ if (ow_sensor[sensor].uart_addr == USART1) {
|
|
|
+ RxDMA_Stream = DMA1_Stream2;
|
|
|
+ TxDMA_Stream = DMA1_Stream7;
|
|
|
+ } else if (ow_sensor[sensor].uart_addr == USART2) {
|
|
|
+ RxDMA_Stream = DMA1_Stream5;
|
|
|
+ TxDMA_Stream = DMA1_Stream6;
|
|
|
+ } else if (ow_sensor[sensor].uart_addr == USART3) {
|
|
|
+ RxDMA_Stream = DMA1_Stream1;
|
|
|
+ TxDMA_Stream = DMA1_Stream3;
|
|
|
+ } else if (ow_sensor[sensor].uart_addr == UART4) {
|
|
|
+ RxDMA_Stream = DMA1_Stream2;
|
|
|
+ TxDMA_Stream = DMA1_Stream4;
|
|
|
+ } else if (ow_sensor[sensor].uart_addr == UART5) {
|
|
|
+ RxDMA_Stream = DMA1_Stream0;
|
|
|
+ TxDMA_Stream = DMA1_Stream7;
|
|
|
+ } else if (ow_sensor[sensor].uart_addr == USART6) {
|
|
|
+ RxDMA_Stream = DMA1_Stream1;
|
|
|
+ TxDMA_Stream = DMA1_Stream6;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* если требуется сброс - сбрасываем и проверяем на наличие устройств */
|
|
|
+ if (sendReset == DALLAS_SEND_RESET) {
|
|
|
+ DBG printf("_Send: DALLAS_SEND_RESET\r\n");
|
|
|
+ if (DALLAS_SensorReset(sensor) == DALLAS_NO_DEVICE) {
|
|
|
+ DBG printf("_Send: DALLAS_NO_DEVICE\r\n");
|
|
|
+ return DALLAS_NO_DEVICE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ while (cLen > 0) {
|
|
|
+ DALLAS_ToBits(*command, ow_sensor[sensor].sensorBuf);
|
|
|
+ command++;
|
|
|
+ cLen--;
|
|
|
+
|
|
|
+ /* DMA на чтение */
|
|
|
+ DMA_DeInit(RxDMA_Stream);
|
|
|
+ DMA_Init(RxDMA_Stream, &ow_sensor[sensor].DMA_InitStructureRx);
|
|
|
+
|
|
|
+ /* DMA на запись */
|
|
|
+ DMA_DeInit(TxDMA_Stream);
|
|
|
+ DMA_Init(TxDMA_Stream, &ow_sensor[sensor].DMA_InitStructureTx);
|
|
|
+
|
|
|
+ /* старт цикла отправки */
|
|
|
+ USART_ClearFlag(ow_sensor[sensor].uart_addr, USART_FLAG_RXNE | USART_FLAG_TC );
|
|
|
+ USART_DMACmd(ow_sensor[sensor].uart_addr, USART_DMAReq_Tx | USART_DMAReq_Rx, ENABLE);
|
|
|
+ DMA_Cmd(RxDMA_Stream, ENABLE);
|
|
|
+ DMA_Cmd(TxDMA_Stream, ENABLE);
|
|
|
+
|
|
|
+
|
|
|
+ while (DMA_GetFlagStatus(RxDMA_Stream, DMA_FLAG_TCIF5) == RESET) {
|
|
|
+
|
|
|
+ timeOutCounter++;
|
|
|
+ if (timeOutCounter > DALLAS_TIME_OUT) {
|
|
|
+ DBG printf("_Send: return DALLAS_ERROR\r\n");
|
|
|
+ return DALLAS_ERROR;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ DBG printf("timeOutCounter: %u\r\n", (unsigned int)timeOutCounter);
|
|
|
+
|
|
|
+
|
|
|
+ /* отключаем DMA */
|
|
|
+ DMA_Cmd(RxDMA_Stream, DISABLE);
|
|
|
+ DMA_Cmd(TxDMA_Stream, DISABLE);
|
|
|
+ USART_DMACmd(ow_sensor[sensor].uart_addr, USART_DMAReq_Tx | USART_DMAReq_Rx, DISABLE);
|
|
|
+
|
|
|
+ /* если прочитанные данные кому-то нужны - выкинем их в буфер */
|
|
|
+ DBG printf("_Send: readStart = %d, dLen = %d\r\n", readStart, dLen);
|
|
|
+ if (readStart == 0 && dLen > 0) {
|
|
|
+ *data = DALLAS_ToByte(ow_sensor[sensor].sensorBuf);
|
|
|
+ data++;
|
|
|
+ dLen--;
|
|
|
+ DBG printf("_Send: Copy\r\n");
|
|
|
+ } else {
|
|
|
+ if (readStart != DALLAS_NO_READ) {
|
|
|
+ readStart--;
|
|
|
+ DBG printf("_Send: readStart--\r\n");
|
|
|
+ }
|
|
|
+ DBG printf("_Send: else state\r\n");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ DBG printf("_Send: return DALLAS_OK\r\n");
|
|
|
+
|
|
|
+ return DALLAS_OK;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief Функция преобразует один байт в восемь, для передачи через USART
|
|
|
+ * @param ow_byte - байт, который надо преобразовать
|
|
|
+ * @param ow_bits - ссылка на буфер, размером не менее 8 байт
|
|
|
+ * @retval
|
|
|
+ */
|
|
|
+void DALLAS_ToBits(uint8_t ow_byte, uint8_t *ow_bits)
|
|
|
+{
|
|
|
+ uint8_t i;
|
|
|
+
|
|
|
+ for (i = 0; i < 8; i++) {
|
|
|
+ if (ow_byte & 0x01) {
|
|
|
+ *ow_bits = DALLAS_1;
|
|
|
+ } else {
|
|
|
+ *ow_bits = DALLAS_0;
|
|
|
+ }
|
|
|
+
|
|
|
+ ow_bits++;
|
|
|
+ ow_byte = ow_byte >> 1;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief Обратное преобразование - из того, что получено через USART опять собирается байт
|
|
|
+ * @param ow_bits - ссылка на буфер, размером не менее 8 байт
|
|
|
+ * @param ow_byte - собранный байт данных
|
|
|
+ * @retval
|
|
|
+ */
|
|
|
+uint8_t DALLAS_ToByte(uint8_t *ow_bits)
|
|
|
+{
|
|
|
+ uint8_t ow_byte, i;
|
|
|
+ ow_byte = 0;
|
|
|
+
|
|
|
+ for (i = 0; i < 8; i++) {
|
|
|
+ ow_byte = ow_byte >> 1;
|
|
|
+ if (*ow_bits == DALLAS_R_1) {
|
|
|
+ ow_byte |= 0x80;
|
|
|
+ }
|
|
|
+
|
|
|
+ ow_bits++;
|
|
|
+ }
|
|
|
+ return ow_byte;
|
|
|
+}
|