onewire.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. /********************************* (C) РОТЕК ***********************************
  2. * @module onewire
  3. * @file onewire.c
  4. * @version 1.0.0
  5. * @date XX.XX.XXXX
  6. * $brief DS18B20 temperature sensor driver
  7. *******************************************************************************
  8. * @history Version Author Comment
  9. * XX.XX.XXXX 1.0.0 Telenkov D.A. First release.
  10. *******************************************************************************
  11. */
  12. #include "common_config.h"
  13. #include "stm32f4xx.h"
  14. #include "stm32f4xx_dma.h"
  15. #include "usart.h"
  16. #include "gpio.h"
  17. #include "onewire.h"
  18. #ifdef PRINTF_STDLIB
  19. #include <stdio.h>
  20. #endif
  21. #ifdef PRINTF_CUSTOM
  22. #include "tinystdio.h"
  23. #endif
  24. /* Force remove debug output */
  25. #undef DBG
  26. #define DBG if(0)
  27. #ifdef DALLAS_SENSOR_ENABLE
  28. /**
  29. * @brief Размер буфера для отправки данных датчикам
  30. */
  31. #define DALLAS_BUF_SIZE 8
  32. #define DALLAS_TIME_OUT 1500000
  33. #define DALLAS_0 0x00
  34. #define DALLAS_1 0xff
  35. #define DALLAS_R_1 0xff
  36. typedef struct {
  37. gpio_t ow_pin;
  38. USART_TypeDef *uart_addr;
  39. DMA_InitTypeDef DMA_InitStructureTx;
  40. DMA_InitTypeDef DMA_InitStructureRx;
  41. uint8_t sensorBuf[DALLAS_BUF_SIZE];
  42. }ow_sensor_t;
  43. ow_sensor_t ow_sensor[MAX_T_SENSORS];
  44. #define T_SENSOR_ADD(sensor_num, ow_line, uart) \
  45. do { \
  46. ow_sensor[sensor_num].uart_addr = uart; \
  47. ow_sensor[sensor_num].ow_pin = ow_line; \
  48. } while (0);
  49. /**
  50. * @brief Настройка USART
  51. * @retval
  52. */
  53. void DALLAS_Init()
  54. {
  55. #define XTSENSOR(sensor_num, ow_line, uart) T_SENSOR_ADD(sensor_num, ow_line, uart);
  56. T_SENSOR_TABLE
  57. #undef XTSENSOR
  58. for (uint8_t i = 0; i < MAX_T_SENSORS; i ++) {
  59. uart_hw_init(ow_sensor[i].uart_addr, DALLAS_SENSOR_UART_BAUD, DALLAS_SENSOR_UART_WORD_LEN,
  60. DALLAS_SENSOR_UART_PARITY, DALLAS_SENSOR_UART_STOP_BIT);
  61. }
  62. DALLAS_DmaInit();
  63. }
  64. /**
  65. * @brief Настройка DMA
  66. * @retval
  67. */
  68. void DALLAS_DmaInit(void)
  69. {
  70. DMA_Stream_TypeDef *RxDMA_Stream = NULL;
  71. DMA_Stream_TypeDef *TxDMA_Stream = NULL;
  72. uint32_t RxDMA_Channel = 0;
  73. uint32_t TxDMA_Channel = 0;
  74. for (uint8_t i = 0; i < MAX_T_SENSORS; i ++) {
  75. if (ow_sensor[i].uart_addr == USART1) {
  76. RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
  77. RxDMA_Stream = DMA1_Stream2;
  78. TxDMA_Stream = DMA1_Stream7;
  79. RxDMA_Channel = DMA_Channel_4;
  80. TxDMA_Channel = DMA_Channel_4;
  81. } else if (ow_sensor[i].uart_addr == USART2) {
  82. RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
  83. RxDMA_Stream = DMA1_Stream5;
  84. TxDMA_Stream = DMA1_Stream6;
  85. RxDMA_Channel = DMA_Channel_4;
  86. TxDMA_Channel = DMA_Channel_4;
  87. } else if (ow_sensor[i].uart_addr == USART3) {
  88. RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
  89. RxDMA_Stream = DMA1_Stream1;
  90. TxDMA_Stream = DMA1_Stream3;
  91. RxDMA_Channel = DMA_Channel_4;
  92. TxDMA_Channel = DMA_Channel_4;
  93. } else if (ow_sensor[i].uart_addr == UART4) {
  94. RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
  95. RxDMA_Stream = DMA1_Stream2;
  96. TxDMA_Stream = DMA1_Stream4;
  97. RxDMA_Channel = DMA_Channel_4;
  98. TxDMA_Channel = DMA_Channel_4;
  99. } else if (ow_sensor[i].uart_addr == UART5) {
  100. RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
  101. RxDMA_Stream = DMA1_Stream0;
  102. TxDMA_Stream = DMA1_Stream7;
  103. RxDMA_Channel = DMA_Channel_4;
  104. TxDMA_Channel = DMA_Channel_4;
  105. } else if (ow_sensor[i].uart_addr == USART6) {
  106. RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
  107. RxDMA_Stream = DMA2_Stream1;
  108. TxDMA_Stream = DMA2_Stream6;
  109. RxDMA_Channel = DMA_Channel_5;
  110. TxDMA_Channel = DMA_Channel_5;
  111. }
  112. /* DMA на чтение */
  113. DMA_DeInit(RxDMA_Stream);
  114. ow_sensor[i].DMA_InitStructureRx.DMA_Channel = RxDMA_Channel;
  115. ow_sensor[i].DMA_InitStructureRx.DMA_PeripheralBaseAddr = (uint32_t)&ow_sensor[i].uart_addr->DR;
  116. ow_sensor[i].DMA_InitStructureRx.DMA_Memory0BaseAddr = (uint32_t)&ow_sensor[i].sensorBuf;
  117. ow_sensor[i].DMA_InitStructureRx.DMA_DIR = DMA_DIR_PeripheralToMemory;
  118. ow_sensor[i].DMA_InitStructureRx.DMA_BufferSize = DALLAS_BUF_SIZE;
  119. ow_sensor[i].DMA_InitStructureRx.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  120. ow_sensor[i].DMA_InitStructureRx.DMA_MemoryInc = DMA_MemoryInc_Enable;
  121. ow_sensor[i].DMA_InitStructureRx.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  122. ow_sensor[i].DMA_InitStructureRx.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  123. ow_sensor[i].DMA_InitStructureRx.DMA_Mode = DMA_Mode_Normal;
  124. ow_sensor[i].DMA_InitStructureRx.DMA_Priority = DMA_Priority_Medium;
  125. DMA_Init(RxDMA_Stream, &ow_sensor[i].DMA_InitStructureRx);
  126. /* DMA на запись */
  127. DMA_DeInit(TxDMA_Stream);
  128. ow_sensor[i].DMA_InitStructureTx.DMA_Channel = TxDMA_Channel;
  129. ow_sensor[i].DMA_InitStructureTx.DMA_PeripheralBaseAddr = &ow_sensor[i].uart_addr->DR;
  130. ow_sensor[i].DMA_InitStructureTx.DMA_Memory0BaseAddr = (uint32_t)&ow_sensor[i].sensorBuf;
  131. ow_sensor[i].DMA_InitStructureTx.DMA_DIR = DMA_DIR_MemoryToPeripheral;
  132. ow_sensor[i].DMA_InitStructureTx.DMA_BufferSize = DALLAS_BUF_SIZE;
  133. ow_sensor[i].DMA_InitStructureTx.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  134. ow_sensor[i].DMA_InitStructureTx.DMA_MemoryInc = DMA_MemoryInc_Enable;
  135. ow_sensor[i].DMA_InitStructureTx.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  136. ow_sensor[i].DMA_InitStructureTx.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  137. ow_sensor[i].DMA_InitStructureTx.DMA_Mode = DMA_Mode_Normal;
  138. ow_sensor[i].DMA_InitStructureTx.DMA_Priority = DMA_Priority_Medium;
  139. DMA_Init(TxDMA_Stream, &ow_sensor[i].DMA_InitStructureTx);
  140. }
  141. }
  142. /**
  143. * @brief Настроить TX пин как питающий выход
  144. * @retval
  145. */
  146. void DALLAS_OutSetAsPower(t_sensor_list_t sensor)
  147. {
  148. gpio_pindef_t *pin = &gpio_pins[ow_sensor[sensor].ow_pin];
  149. gpio_hw_config_pin(pin->port, pin->pin, (GPIO_MODE_OUT_CFG | GPIO_TYPE_PP_CFG |
  150. GPIO_SPEED_HIGH_CFG));
  151. gpio_set(ow_sensor[sensor].ow_pin, GPIO_SET);
  152. }
  153. /**
  154. * @brief Настроить TX пин как передатчик
  155. * @retval
  156. */
  157. void DALLAS_OutSetAsTX(t_sensor_list_t sensor)
  158. {
  159. gpio_pindef_t *pin = &gpio_pins[ow_sensor[sensor].ow_pin];
  160. uint8_t af_n = (uint8_t)(pin->flags >> _GPIO_AF_SHIFT);
  161. gpio_connect_af(ow_sensor[sensor].ow_pin, af_n);
  162. gpio_hw_config_pin(pin->port, pin->pin, GPIO_MODE_AF_CFG |
  163. GPIO_SPEED_HIGH_CFG);
  164. }
  165. /**
  166. * @brief Сброс и проверка наличия устройства на шине 1-wire
  167. * @retval
  168. */
  169. uint8_t DALLAS_SensorReset(t_sensor_list_t sensor)
  170. {
  171. uint8_t presence;
  172. uart_config_reinit(ow_sensor[sensor].uart_addr, DALLAS_SENSOR_RST_UART_BAUD,
  173. DALLAS_SENSOR_UART_WORD_LEN, DALLAS_SENSOR_UART_PARITY, DALLAS_SENSOR_UART_STOP_BIT);
  174. // отправляем 0xf0 на скорости 9600
  175. USART_ClearFlag(ow_sensor[sensor].uart_addr, USART_FLAG_TC);
  176. USART_SendData(ow_sensor[sensor].uart_addr, 0xf0);
  177. while (USART_GetFlagStatus(ow_sensor[sensor].uart_addr, USART_FLAG_TC) == RESET) { }
  178. presence = USART_ReceiveData(ow_sensor[sensor].uart_addr);
  179. uart_config_reinit(ow_sensor[sensor].uart_addr, DALLAS_SENSOR_UART_BAUD, DALLAS_SENSOR_UART_WORD_LEN,
  180. DALLAS_SENSOR_UART_PARITY, DALLAS_SENSOR_UART_STOP_BIT);
  181. if (presence != 0xf0) {
  182. DBG printf("DALLAS_SensorReset: DALLAS_OK\r\n");
  183. return DALLAS_OK;
  184. }
  185. DBG printf("DALLAS_SensorReset: DALLAS_NO_DEVICE\r\n");
  186. return DALLAS_NO_DEVICE;
  187. }
  188. /**
  189. * @brief Отправка и прием данных
  190. * @param sendReset посылать RESET в начале общения.
  191. * OW_SEND_RESET
  192. * OW_NO_RESET
  193. * @param *command - массив байт, отсылаемых в шину.
  194. * Если нужно чтение - отправляем OW_READ_SLOTH
  195. * @param cLen - длина буфера команд, столько байт отошлется в шину
  196. * @param *data - если требуется чтение, то ссылка на буфер для чтения
  197. * @param dLen - длина буфера для чтения. Прочитается не более этой длины
  198. * @param readStart - с какого символа передачи начинать чтение (нумеруются с 0)
  199. * можно указать OW_NO_READ, тогда можно не задавать data и dLen
  200. * @retval
  201. */
  202. uint8_t DALLAS_Send(t_sensor_list_t sensor, uint8_t sendReset, uint8_t *command,
  203. uint8_t cLen, uint8_t *data, uint8_t dLen, uint8_t readStart)
  204. {
  205. uint32_t timeOutCounter = 0;
  206. uint32_t DMA_FLAG_TCIF = 0;
  207. DMA_Stream_TypeDef *RxDMA_Stream = NULL;
  208. DMA_Stream_TypeDef *TxDMA_Stream = NULL;
  209. if (ow_sensor[sensor].uart_addr == USART1) {
  210. DMA_FLAG_TCIF = DMA_FLAG_TCIF2;
  211. RxDMA_Stream = DMA1_Stream2;
  212. TxDMA_Stream = DMA1_Stream7;
  213. } else if (ow_sensor[sensor].uart_addr == USART2) {
  214. DMA_FLAG_TCIF = DMA_FLAG_TCIF5;
  215. RxDMA_Stream = DMA1_Stream5;
  216. TxDMA_Stream = DMA1_Stream6;
  217. } else if (ow_sensor[sensor].uart_addr == USART3) {
  218. DMA_FLAG_TCIF = DMA_FLAG_TCIF1;
  219. RxDMA_Stream = DMA1_Stream1;
  220. TxDMA_Stream = DMA1_Stream3;
  221. } else if (ow_sensor[sensor].uart_addr == UART4) {
  222. DMA_FLAG_TCIF = DMA_FLAG_TCIF2;
  223. RxDMA_Stream = DMA1_Stream2;
  224. TxDMA_Stream = DMA1_Stream4;
  225. } else if (ow_sensor[sensor].uart_addr == UART5) {
  226. DMA_FLAG_TCIF = DMA_FLAG_TCIF0;
  227. RxDMA_Stream = DMA1_Stream0;
  228. TxDMA_Stream = DMA1_Stream7;
  229. } else if (ow_sensor[sensor].uart_addr == USART6) {
  230. DMA_FLAG_TCIF = DMA_FLAG_TCIF1;
  231. RxDMA_Stream = DMA2_Stream1;
  232. TxDMA_Stream = DMA2_Stream6;
  233. }
  234. /* если требуется сброс - сбрасываем и проверяем на наличие устройств */
  235. if (sendReset == DALLAS_SEND_RESET) {
  236. DBG printf("_Send: DALLAS_SEND_RESET\r\n");
  237. if (DALLAS_SensorReset(sensor) == DALLAS_NO_DEVICE) {
  238. DBG printf("_Send: DALLAS_NO_DEVICE\r\n");
  239. return DALLAS_NO_DEVICE;
  240. }
  241. }
  242. while (cLen > 0) {
  243. DALLAS_ToBits(*command, ow_sensor[sensor].sensorBuf);
  244. command++;
  245. cLen--;
  246. /* DMA на чтение */
  247. DMA_DeInit(RxDMA_Stream);
  248. DMA_Init(RxDMA_Stream, &ow_sensor[sensor].DMA_InitStructureRx);
  249. /* DMA на запись */
  250. DMA_DeInit(TxDMA_Stream);
  251. DMA_Init(TxDMA_Stream, &ow_sensor[sensor].DMA_InitStructureTx);
  252. /* старт цикла отправки */
  253. USART_ClearFlag(ow_sensor[sensor].uart_addr, USART_FLAG_RXNE | USART_FLAG_TC );
  254. USART_DMACmd(ow_sensor[sensor].uart_addr, USART_DMAReq_Tx | USART_DMAReq_Rx, ENABLE);
  255. DMA_Cmd(RxDMA_Stream, ENABLE);
  256. DMA_Cmd(TxDMA_Stream, ENABLE);
  257. while (DMA_GetFlagStatus(RxDMA_Stream, DMA_FLAG_TCIF) == RESET) {
  258. timeOutCounter++;
  259. if (timeOutCounter > DALLAS_TIME_OUT) {
  260. DBG printf("_Send: return DALLAS_ERROR\r\n");
  261. return DALLAS_ERROR;
  262. }
  263. }
  264. DBG printf("timeOutCounter: %u\r\n", (unsigned int)timeOutCounter);
  265. /* отключаем DMA */
  266. DMA_Cmd(RxDMA_Stream, DISABLE);
  267. DMA_Cmd(TxDMA_Stream, DISABLE);
  268. USART_DMACmd(ow_sensor[sensor].uart_addr, USART_DMAReq_Tx | USART_DMAReq_Rx, DISABLE);
  269. /* если прочитанные данные кому-то нужны - выкинем их в буфер */
  270. DBG printf("_Send: readStart = %d, dLen = %d\r\n", readStart, dLen);
  271. if (readStart == 0 && dLen > 0) {
  272. *data = DALLAS_ToByte(ow_sensor[sensor].sensorBuf);
  273. data++;
  274. dLen--;
  275. DBG printf("_Send: Copy\r\n");
  276. } else {
  277. if (readStart != DALLAS_NO_READ) {
  278. readStart--;
  279. DBG printf("_Send: readStart--\r\n");
  280. }
  281. DBG printf("_Send: else state\r\n");
  282. }
  283. }
  284. DBG printf("_Send: return DALLAS_OK\r\n");
  285. return DALLAS_OK;
  286. }
  287. /**
  288. * @brief Функция преобразует один байт в восемь, для передачи через USART
  289. * @param ow_byte - байт, который надо преобразовать
  290. * @param ow_bits - ссылка на буфер, размером не менее 8 байт
  291. * @retval
  292. */
  293. void DALLAS_ToBits(uint8_t ow_byte, uint8_t *ow_bits)
  294. {
  295. uint8_t i;
  296. for (i = 0; i < 8; i++) {
  297. if (ow_byte & 0x01) {
  298. *ow_bits = DALLAS_1;
  299. } else {
  300. *ow_bits = DALLAS_0;
  301. }
  302. ow_bits++;
  303. ow_byte = ow_byte >> 1;
  304. }
  305. }
  306. /**
  307. * @brief Обратное преобразование - из того, что получено через USART опять собирается байт
  308. * @param ow_bits - ссылка на буфер, размером не менее 8 байт
  309. * @param ow_byte - собранный байт данных
  310. * @retval
  311. */
  312. uint8_t DALLAS_ToByte(uint8_t *ow_bits)
  313. {
  314. uint8_t ow_byte, i;
  315. ow_byte = 0;
  316. for (i = 0; i < 8; i++) {
  317. ow_byte = ow_byte >> 1;
  318. if (*ow_bits == DALLAS_R_1) {
  319. ow_byte |= 0x80;
  320. }
  321. ow_bits++;
  322. }
  323. return ow_byte;
  324. }
  325. #endif