one_wire.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. /** @addtogroup Firmware
  2. * @{
  3. */
  4. /** @addtogroup Implementácia_MultiSlave
  5. * @{
  6. */
  7. /** @defgroup OneWire_modul
  8. * @brief Implementácia komunikácie na zbernici 1-wire
  9. * @{
  10. */
  11. #ifndef ONE_WIRE_LIB_H
  12. #define ONE_WIRE_LIB_H
  13. //#include "stdint.h"
  14. #include "mcu_platform.h"
  15. //#define OW_MODULE_USE_TIMER
  16. #define TRUE 0x01 // konstanty v kniznici 1-wire
  17. #define FALSE 0x00
  18. #define OW_USE_2_WIRE FALSE
  19. #define MCU_FREQUENCY 32000 //4194
  20. #define USE_STRONG 0
  21. #define OW_WRITE_ZERO 60
  22. #define OW_WRITE_ONE 6
  23. #define OW_WRITE_ONE_DELAY 54
  24. #define OW_WRITE_DELAY 10
  25. #define OW_READ_PULSE 6
  26. #define OW_READ_PRESENCE 9
  27. #define OW_READ_DELAY 45
  28. #define OW_RESET_MEASTER 500
  29. #define OW_RESET_PRESENCE 80
  30. #define OW_RESET_DELAY 400
  31. #define OW_CONVERT_DELAY 750
  32. #define OW_BOOSTER 25 // od 5 do 1000 usec
  33. #define OW_CMD_READ_ROM 0x33
  34. #define OW_CMD_MATCH_ROM 0x55
  35. #define OW_CMD_SEARCH_ROM 0xF0
  36. #define OW_CMD_ALARM_SEARCH 0xEC
  37. #define OW_CMD_SKIP_ROM 0xCC
  38. #define OW_CMD_CONVERT_VALUE 0x44
  39. #define OW_CMD_COPY_SCRATCHPAD 0x48
  40. #define OW_CMD_READ_POWER_SUPPLY 0xB4
  41. #define OW_CMD_RECALL_E2 0xB8
  42. #define OW_CMD_READ_SCRATCHPAD 0xBE
  43. #define OW_CMD_WRITE_SCRATCHPAD 0x4E
  44. #define OW_SETTING_NORMAL 1
  45. #define OW_SETTING_LONG 2
  46. #define OW_SETTING_USER 3
  47. #define OW_SET_HI (oneWirePins.port->BSRR = (uint32_t)oneWirePins.pin_ow)
  48. #define OW_SET_LO (oneWirePins.port->BRR = (uint32_t)oneWirePins.pin_ow)
  49. #define OW_UP_SET (oneWirePins.port->BSRR = oneWirePins.pin_ow_up)
  50. #define OW_UP_CLEAR (oneWirePins.port->BRR = oneWirePins.pin_ow_up)
  51. #define OW_DOWN_SET (oneWirePins.port->BSRR= oneWirePins.pin_ow_down)
  52. #define OW_DOWN_CLEAR (oneWirePins.port->BRR = oneWirePins.pin_ow_down)
  53. //#define OW_STRONG_SET (oneWirePins.port->BSRR = oneWirePins.pin_ow_strong)
  54. //#define OW_STRONG_CLEAR (oneWirePins.port->BRR = oneWirePins.pin_ow_strong)
  55. //#define OW_NO_INTERRUPTS_ONLY_SYSTICK
  56. #ifdef OW_NO_INTERRUPTS_ONLY_SYSTICK
  57. //Only systick will be disabled when calling OW_DIS_INTERRUPTS
  58. #define OW_DIS_INTERRUPTS DISABLE_sysTick_IRQ
  59. #define OW_ENA_INTERRUPTS ENABLE_sysTick_IRQ
  60. #else
  61. //All interrupts will be disabled when calling OW_DIS_INTERRUPTS
  62. #define OW_DIS_INTERRUPTS uint32_t primSpec55511 = __get_PRIMASK(); \
  63. do{ \
  64. __disable_irq(); \
  65. }while(0)
  66. #define OW_ENA_INTERRUPTS do{ \
  67. if (!primSpec55511) {__enable_irq();} \
  68. }while(0)
  69. #endif // OW_NO_INTERRUPTS_ONLY_SYSTICK
  70. #define OW_USE_TICKS
  71. #ifdef OW_USE_TICKS
  72. /**
  73. * @brief Delay ticks helper.
  74. * @param ticks Count of ticks to wait divided by 3.
  75. * @see delay_ticks_c
  76. */
  77. #define delay_ticks_0(ticks) { uint32_t tcks = (ticks); \
  78. __ASM volatile( ".syntax unified;" \
  79. "0: SUBS %[count], 1;" \
  80. "BNE 0b;" :[count]"+r"(tcks) );}
  81. //This works only with constant numbers - ifs are evaluated at compile time
  82. /**
  83. * @brief Delays specified amount of ticks.
  84. * @param ticks Count of ticks to wait. This has to be constant value, because
  85. * this macro contains ifs, which has to be evaluated at compilation time.
  86. * @note Always disable interrupts when using this macro to achieve accurate result.
  87. */
  88. #define delay_ticks_c(ticks) do{ \
  89. if((ticks) > 2){delay_ticks_0((ticks)/3);} \
  90. if((ticks) % 3 == 1) __ASM volatile( ".syntax unified; nop;"); \
  91. else if((ticks) % 3 == 2) __ASM volatile( ".syntax unified; nop; nop;"); \
  92. }while(0);
  93. /**
  94. * @brief Calculates number of ticks (MCU cycles) from frequency and time.
  95. * @param us Time in microseconds.
  96. * @param freq MCU frequency in kHz.
  97. */
  98. #define OW_US_FREQ_TO_TICKS(us, freq) (((us)*(freq))/1000UL)
  99. #define OW_DELAY_US(us, freq, tick_offs) if(OW_US_FREQ_TO_TICKS((us), (freq)) >= (tick_offs)) {delay_ticks_c(OW_US_FREQ_TO_TICKS((us), (freq)) - (tick_offs));}
  100. #define delay_us(us) OW_DELAY_US((us), MCU_FREQUENCY, 0)
  101. /**
  102. * @brief Creates pulse with specified duration on selected GPIO pin. At first, new pin value is set and
  103. * after that delay is applied.
  104. * @param us Duration of pulse in microseconds.
  105. * @param hi 1 for high pulse, 0 for low pulse.
  106. * @param freq MCU frequency in kHz.
  107. * @param tick_offs Count of ticks, that are wait outside of this macro. It's value has to be at least 1,
  108. * because GPIO pin setting takes 1 tick. It can be used to fine tune pulse width, which can be affected
  109. * by instructions called after this macro.
  110. * @param GPIO_port GPIO port to be used.
  111. * @param GPIO_pin Pin on specified GPIO port.
  112. * @note Always disable interrupts when using this macro to achieve accurate result.
  113. */
  114. #define OW_GPIO_PULSE(us, hi, freq, tick_offs, GPIO_port, GPIO_pin) do{ \
  115. if(hi){(GPIO_port)->BSRR = (GPIO_pin);} \
  116. else {(GPIO_port)->BRR = (GPIO_pin);} \
  117. OW_DELAY_US((us),(freq),(tick_offs)); \
  118. }while(0);
  119. #else
  120. #ifdef OW_MODULE_USE_TIMER
  121. void delay_us_long(uint16_t time);
  122. void delay_us(uint16_t time);
  123. #else
  124. #define delay_us_0(time) { \
  125. __ASM volatile ( \
  126. "mov r0, %0 \n" \
  127. "5: \n" \
  128. "sub r0, #1 \n" \
  129. "bhi 5b \n": : "i"(time) :); \
  130. }
  131. /* ------------------------------------------------------------------*/
  132. /* ---------------------------- STM32 L0 --------------------------*/
  133. /* ------------------------------------------------------------------*/
  134. #ifdef STM32L0
  135. /* ------------------------- LSI = 8000 kHz -------------------------*/
  136. #if MCU_FREQUENCY == 8000
  137. #define delay_us(time){ \
  138. delay_us_0(time) \
  139. delay_us_0(time) \
  140. delay_us_0(time-2) \
  141. }
  142. #define delay_us_long(time) { \
  143. delay_us(time) \
  144. delay_us(time) \
  145. delay_us(time) \
  146. delay_us(time-50) \
  147. }
  148. #endif // MCU_FREQUENCY
  149. /* -------------------------- MSI = 4194 kHz ---------------------------*/
  150. /**
  151. * time in code | measured time [us]
  152. * 6 | 5
  153. * 10 | 9.5
  154. * 20 | 20.25
  155. * 50 | 52
  156. */
  157. #if MCU_FREQUENCY == 4194
  158. #define delay_us(time){ \
  159. delay_us_0(time-3) \
  160. delay_us_0((time-1)/2) \
  161. }
  162. #define delay_us_long(time) { \
  163. delay_us(time) \
  164. delay_us(time) \
  165. delay_us(time) \
  166. delay_us(time-10) \
  167. }
  168. #endif // MCU_FREQUENCY
  169. /* --------------------------- MSI = 2097 kHz ---------------------------*/
  170. #if MCU_FREQUENCY == 2097
  171. #define delay_us(time){ \
  172. delay_us_0( ((time-2)*2/3) ) \
  173. }
  174. #define delay_us_long(time) { \
  175. delay_us(time) \
  176. delay_us(time-10) \
  177. delay_us(time-10) \
  178. delay_us(time-10) \
  179. }
  180. #endif // MCU_FREQUENCY
  181. #endif // STM32L0
  182. /* ------------------------------------------------------------------*/
  183. /* ---------------------------- STM32 F0 --------------------------*/
  184. /* ------------------------------------------------------------------*/
  185. #ifdef STM32F0
  186. /* --------------------------- LSI = 48 MHz ---------------------------*/
  187. #if MCU_FREQUENCY == 48
  188. #define delay_us(time){ \
  189. owSetDelayUs_0(time) \
  190. owSetDelayUs_0(time) \
  191. owSetDelayUs_0(time) \
  192. owSetDelayUs_0(time) \
  193. owSetDelayUs_0(time) \
  194. owSetDelayUs_0(time) \
  195. owSetDelayUs_0(time) \
  196. owSetDelayUs_0(time) \
  197. owSetDelayUs_0(time) \
  198. owSetDelayUs_0(time) \
  199. owSetDelayUs_0(time) \
  200. owSetDelayUs_0(time-1) \
  201. }
  202. #define delay_us_long(time) { \
  203. owSetDelayUs(time); \
  204. owSetDelayUs(time); \
  205. owSetDelayUs(time); \
  206. owSetDelayUs(time); \
  207. }
  208. #endif // FREQUENCY
  209. #endif // STM32F0
  210. #endif // OW_MODULE_USE_TIMER
  211. #endif // OW_USE_TICKS
  212. /**
  213. * Dátová štruktúra pre komunikáciu so zbernicou 1-wire. Obsahuje:
  214. * - časové konštanty
  215. * - príznaky komunikácie
  216. * - komunikačný buffer
  217. * - inštanciu časovača knižnice STM32 HAL
  218. */
  219. typedef struct {
  220. /** Globalne nastavenie casovania zvernice 1w */
  221. volatile uint8_t one_wire_timing_settings;
  222. /** lokalny buffer pre ID zariadenia */
  223. uint8_t ROM_NO[8];
  224. /** priznak konfliktu na zbernici pri vyhladavani ID */
  225. __IO uint32_t LastDiscrepancy;
  226. __IO uint32_t LastFamilyDiscrepancy;
  227. __IO uint32_t LastDeviceFlag;
  228. /** Priznak timeru ze aktualne je v stave cakania na udalost pri ktorej sa zmenia jeho parametre. */
  229. __IO uint8_t flag_timer_inUse;
  230. /** Stav zbernice: OW_STATE_READY, OW_STATE_WAITING. */
  231. __IO uint8_t ow_state;
  232. /** Priznak pripravenosti dat. Hodnoty môžu nadobúdať zo štruktúry oneWireDataReady_typeDef. */
  233. __IO uint8_t ow_data_ready;
  234. #ifdef OW_MODULE_USE_TIMER
  235. /** Inštancia časovača knižnice HAL. Časovač je použitý pre časovanie komunikácie */
  236. TIM_HandleTypeDef *owTimer;
  237. #endif
  238. } oneWireDriver_typeDef;
  239. /**
  240. * Definícia pinov pre ovládanie zbernice 1-wire. Aktuálne nepoužité.
  241. */
  242. typedef struct oneWirePins_struct {
  243. /** Pin pre signál, ktorý zdvihne zbernicu na hodnotu 1 */
  244. volatile uint16_t pin_ow_up;
  245. /** Pin pre signál, ktorý zloží zbernicu na hodnotu 0 */
  246. volatile uint16_t pin_ow_down;
  247. /** Pin pre signál, ktorý zdvihne zbernicu na tvrdú hodnotu 1 */
  248. volatile uint16_t pin_ow_strong;
  249. /** Pin pre vstupný signál */
  250. volatile uint16_t pin_ow_in;
  251. /** Port, na ktorom sú piny */
  252. GPIO_TypeDef* port;
  253. } oneWirePins_typeDef;
  254. typedef struct oneWirePin_struct {
  255. __IO uint16_t pin_ow;
  256. __IO uint16_t pin_ow_moder_bit;
  257. #if OW_USE_2_WIRE == 1
  258. volatile uint16_t pin_ow_in;
  259. #endif // OW_USE_2_WIRE
  260. GPIO_TypeDef* port;
  261. } oneWirePin_typeDef;
  262. /**
  263. * Príznak pripravenosti dát zo senzorov zbernice 1-wire.
  264. */
  265. typedef enum OW_DATA_enum {
  266. /** Dáta nie sú pripravené, práve sa merajú */
  267. OW_DATA_BUSY=0,
  268. /** Dáta sú pripravené */
  269. OW_DATA_READY=1,
  270. } oneWireDataReady_typeDef;
  271. /**
  272. * Príznak stavu zbernice v stave STRONG.
  273. */
  274. typedef enum OW_STRONG_STATE_enum {
  275. /** Zbernica nie je v stave STRONG */
  276. OW_STRONG_OFF = 0,
  277. /** Zbernica je v stave STRONG */
  278. OW_STRONG_ON = 1,
  279. } oneWireStrongState_typeDef;
  280. /**
  281. * Príznak pre stav časovača.
  282. */
  283. typedef enum {
  284. /** Časovač je spustený, prebieha meranie */
  285. TIMER_STATE_RUN = 0,
  286. /** Časovač je vypnutý */
  287. TIMER_STATE_IDLE = 1,
  288. } oneWireTimerState_typeDef;
  289. #ifdef OW_MODULE_USE_TIMER
  290. void oneWire_init(TIM_HandleTypeDef *timer, GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
  291. #else
  292. #if OW_USE_2_WIRE == 1
  293. void oneWire_init(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, uint16_t GPIO_Pin_i ); // konfiguracia portu pre 1-wire
  294. #else
  295. void oneWire_init(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin ); // konfiguracia portu pre 1-wire
  296. #endif // OW_USE_2_WIRE
  297. #endif
  298. uint8_t owReset(void); // reset zbernice a kontrola pritomnosti zariadeni
  299. uint8_t owFirst(); // nacitanie ID prveho zariadenia
  300. uint8_t owNext(); // iteracia zoznamu zariadeni
  301. uint8_t owVerify(void); // kontrola existencia ID zariadenia
  302. void owTargetSetup(uint8_t fcode); // nastavenie podmnoziny vyhladavanych zariadeni
  303. void owFamilySkipSetup(void); // zrusenie selektivneho vyhladavania
  304. void owSetRom(uint8_t *array); // nastavenie ID konkretneho zariadenia
  305. uint8_t owSearch();
  306. uint8_t owCrc8(uint8_t);
  307. uint8_t owReadBit(void);
  308. void owWriteByte(uint8_t, uint8_t);
  309. uint8_t owReadByte(void);
  310. #ifdef OW_USE_TICKS
  311. void owWriteBit(uint8_t*);
  312. #else
  313. void owWriteBit(uint8_t);
  314. #endif
  315. void owWriteBitStrong(uint8_t);
  316. void owSetDelayMs(uint16_t time);
  317. void ow_stop_ms_timer(void);
  318. uint8_t *oneWire_getROM();
  319. void owGetROM(uint8_t *mem_page);
  320. void owSelect_ROM(const uint8_t rom[8]);
  321. void owSelect();
  322. void ow_ClearStrong(void);
  323. void ow_SetStrong(void);
  324. #endif //ONE_WIRE_LIB_H
  325. /**
  326. * @}
  327. */
  328. /**
  329. * @}
  330. */
  331. /**
  332. * @}
  333. */