/** @addtogroup Firmware * @{ */ /** @addtogroup Implementácia_MultiSlave * @{ */ /** @defgroup OneWire_modul * @brief Implementácia komunikácie na zbernici 1-wire * @{ */ #ifndef ONE_WIRE_LIB_H #define ONE_WIRE_LIB_H //#include "stdint.h" #include "mcu_platform.h" //#define OW_MODULE_USE_TIMER #define TRUE 0x01 // konstanty v kniznici 1-wire #define FALSE 0x00 #define OW_USE_2_WIRE FALSE #define MCU_FREQUENCY 32000 //4194 #define USE_STRONG 0 #define OW_WRITE_ZERO 60 #define OW_WRITE_ONE 6 #define OW_WRITE_ONE_DELAY 54 #define OW_WRITE_DELAY 10 #define OW_READ_PULSE 6 #define OW_READ_PRESENCE 9 #define OW_READ_DELAY 45 #define OW_RESET_MEASTER 500 #define OW_RESET_PRESENCE 80 #define OW_RESET_DELAY 400 #define OW_CONVERT_DELAY 750 #define OW_BOOSTER 25 // od 5 do 1000 usec #define OW_CMD_READ_ROM 0x33 #define OW_CMD_MATCH_ROM 0x55 #define OW_CMD_SEARCH_ROM 0xF0 #define OW_CMD_ALARM_SEARCH 0xEC #define OW_CMD_SKIP_ROM 0xCC #define OW_CMD_CONVERT_VALUE 0x44 #define OW_CMD_COPY_SCRATCHPAD 0x48 #define OW_CMD_READ_POWER_SUPPLY 0xB4 #define OW_CMD_RECALL_E2 0xB8 #define OW_CMD_READ_SCRATCHPAD 0xBE #define OW_CMD_WRITE_SCRATCHPAD 0x4E #define OW_SETTING_NORMAL 1 #define OW_SETTING_LONG 2 #define OW_SETTING_USER 3 #define OW_SET_HI (oneWirePins.port->BSRR = (uint32_t)oneWirePins.pin_ow) #define OW_SET_LO (oneWirePins.port->BRR = (uint32_t)oneWirePins.pin_ow) #define OW_UP_SET (oneWirePins.port->BSRR = oneWirePins.pin_ow_up) #define OW_UP_CLEAR (oneWirePins.port->BRR = oneWirePins.pin_ow_up) #define OW_DOWN_SET (oneWirePins.port->BSRR= oneWirePins.pin_ow_down) #define OW_DOWN_CLEAR (oneWirePins.port->BRR = oneWirePins.pin_ow_down) //#define OW_STRONG_SET (oneWirePins.port->BSRR = oneWirePins.pin_ow_strong) //#define OW_STRONG_CLEAR (oneWirePins.port->BRR = oneWirePins.pin_ow_strong) //#define OW_NO_INTERRUPTS_ONLY_SYSTICK #ifdef OW_NO_INTERRUPTS_ONLY_SYSTICK //Only systick will be disabled when calling OW_DIS_INTERRUPTS #define OW_DIS_INTERRUPTS DISABLE_sysTick_IRQ #define OW_ENA_INTERRUPTS ENABLE_sysTick_IRQ #else //All interrupts will be disabled when calling OW_DIS_INTERRUPTS #define OW_DIS_INTERRUPTS uint32_t primSpec55511 = __get_PRIMASK(); \ do{ \ __disable_irq(); \ }while(0) #define OW_ENA_INTERRUPTS do{ \ if (!primSpec55511) {__enable_irq();} \ }while(0) #endif // OW_NO_INTERRUPTS_ONLY_SYSTICK #define OW_USE_TICKS #ifdef OW_USE_TICKS /** * @brief Delay ticks helper. * @param ticks Count of ticks to wait divided by 3. * @see delay_ticks_c */ #define delay_ticks_0(ticks) { uint32_t tcks = (ticks); \ __ASM volatile( ".syntax unified;" \ "0: SUBS %[count], 1;" \ "BNE 0b;" :[count]"+r"(tcks) );} //This works only with constant numbers - ifs are evaluated at compile time /** * @brief Delays specified amount of ticks. * @param ticks Count of ticks to wait. This has to be constant value, because * this macro contains ifs, which has to be evaluated at compilation time. * @note Always disable interrupts when using this macro to achieve accurate result. */ #define delay_ticks_c(ticks) do{ \ if((ticks) > 2){delay_ticks_0((ticks)/3);} \ if((ticks) % 3 == 1) __ASM volatile( ".syntax unified; nop;"); \ else if((ticks) % 3 == 2) __ASM volatile( ".syntax unified; nop; nop;"); \ }while(0); /** * @brief Calculates number of ticks (MCU cycles) from frequency and time. * @param us Time in microseconds. * @param freq MCU frequency in kHz. */ #define OW_US_FREQ_TO_TICKS(us, freq) (((us)*(freq))/1000UL) #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));} #define delay_us(us) OW_DELAY_US((us), MCU_FREQUENCY, 0) /** * @brief Creates pulse with specified duration on selected GPIO pin. At first, new pin value is set and * after that delay is applied. * @param us Duration of pulse in microseconds. * @param hi 1 for high pulse, 0 for low pulse. * @param freq MCU frequency in kHz. * @param tick_offs Count of ticks, that are wait outside of this macro. It's value has to be at least 1, * because GPIO pin setting takes 1 tick. It can be used to fine tune pulse width, which can be affected * by instructions called after this macro. * @param GPIO_port GPIO port to be used. * @param GPIO_pin Pin on specified GPIO port. * @note Always disable interrupts when using this macro to achieve accurate result. */ #define OW_GPIO_PULSE(us, hi, freq, tick_offs, GPIO_port, GPIO_pin) do{ \ if(hi){(GPIO_port)->BSRR = (GPIO_pin);} \ else {(GPIO_port)->BRR = (GPIO_pin);} \ OW_DELAY_US((us),(freq),(tick_offs)); \ }while(0); #else #ifdef OW_MODULE_USE_TIMER void delay_us_long(uint16_t time); void delay_us(uint16_t time); #else #define delay_us_0(time) { \ __ASM volatile ( \ "mov r0, %0 \n" \ "5: \n" \ "sub r0, #1 \n" \ "bhi 5b \n": : "i"(time) :); \ } /* ------------------------------------------------------------------*/ /* ---------------------------- STM32 L0 --------------------------*/ /* ------------------------------------------------------------------*/ #ifdef STM32L0 /* ------------------------- LSI = 8000 kHz -------------------------*/ #if MCU_FREQUENCY == 8000 #define delay_us(time){ \ delay_us_0(time) \ delay_us_0(time) \ delay_us_0(time-2) \ } #define delay_us_long(time) { \ delay_us(time) \ delay_us(time) \ delay_us(time) \ delay_us(time-50) \ } #endif // MCU_FREQUENCY /* -------------------------- MSI = 4194 kHz ---------------------------*/ /** * time in code | measured time [us] * 6 | 5 * 10 | 9.5 * 20 | 20.25 * 50 | 52 */ #if MCU_FREQUENCY == 4194 #define delay_us(time){ \ delay_us_0(time-3) \ delay_us_0((time-1)/2) \ } #define delay_us_long(time) { \ delay_us(time) \ delay_us(time) \ delay_us(time) \ delay_us(time-10) \ } #endif // MCU_FREQUENCY /* --------------------------- MSI = 2097 kHz ---------------------------*/ #if MCU_FREQUENCY == 2097 #define delay_us(time){ \ delay_us_0( ((time-2)*2/3) ) \ } #define delay_us_long(time) { \ delay_us(time) \ delay_us(time-10) \ delay_us(time-10) \ delay_us(time-10) \ } #endif // MCU_FREQUENCY #endif // STM32L0 /* ------------------------------------------------------------------*/ /* ---------------------------- STM32 F0 --------------------------*/ /* ------------------------------------------------------------------*/ #ifdef STM32F0 /* --------------------------- LSI = 48 MHz ---------------------------*/ #if MCU_FREQUENCY == 48 #define delay_us(time){ \ owSetDelayUs_0(time) \ owSetDelayUs_0(time) \ owSetDelayUs_0(time) \ owSetDelayUs_0(time) \ owSetDelayUs_0(time) \ owSetDelayUs_0(time) \ owSetDelayUs_0(time) \ owSetDelayUs_0(time) \ owSetDelayUs_0(time) \ owSetDelayUs_0(time) \ owSetDelayUs_0(time) \ owSetDelayUs_0(time-1) \ } #define delay_us_long(time) { \ owSetDelayUs(time); \ owSetDelayUs(time); \ owSetDelayUs(time); \ owSetDelayUs(time); \ } #endif // FREQUENCY #endif // STM32F0 #endif // OW_MODULE_USE_TIMER #endif // OW_USE_TICKS /** * Dátová štruktúra pre komunikáciu so zbernicou 1-wire. Obsahuje: * - časové konštanty * - príznaky komunikácie * - komunikačný buffer * - inštanciu časovača knižnice STM32 HAL */ typedef struct { /** Globalne nastavenie casovania zvernice 1w */ volatile uint8_t one_wire_timing_settings; /** lokalny buffer pre ID zariadenia */ uint8_t ROM_NO[8]; /** priznak konfliktu na zbernici pri vyhladavani ID */ __IO uint32_t LastDiscrepancy; __IO uint32_t LastFamilyDiscrepancy; __IO uint32_t LastDeviceFlag; /** Priznak timeru ze aktualne je v stave cakania na udalost pri ktorej sa zmenia jeho parametre. */ __IO uint8_t flag_timer_inUse; /** Stav zbernice: OW_STATE_READY, OW_STATE_WAITING. */ __IO uint8_t ow_state; /** Priznak pripravenosti dat. Hodnoty môžu nadobúdať zo štruktúry oneWireDataReady_typeDef. */ __IO uint8_t ow_data_ready; #ifdef OW_MODULE_USE_TIMER /** Inštancia časovača knižnice HAL. Časovač je použitý pre časovanie komunikácie */ TIM_HandleTypeDef *owTimer; #endif } oneWireDriver_typeDef; /** * Definícia pinov pre ovládanie zbernice 1-wire. Aktuálne nepoužité. */ typedef struct oneWirePins_struct { /** Pin pre signál, ktorý zdvihne zbernicu na hodnotu 1 */ volatile uint16_t pin_ow_up; /** Pin pre signál, ktorý zloží zbernicu na hodnotu 0 */ volatile uint16_t pin_ow_down; /** Pin pre signál, ktorý zdvihne zbernicu na tvrdú hodnotu 1 */ volatile uint16_t pin_ow_strong; /** Pin pre vstupný signál */ volatile uint16_t pin_ow_in; /** Port, na ktorom sú piny */ GPIO_TypeDef* port; } oneWirePins_typeDef; typedef struct oneWirePin_struct { __IO uint16_t pin_ow; __IO uint16_t pin_ow_moder_bit; #if OW_USE_2_WIRE == 1 volatile uint16_t pin_ow_in; #endif // OW_USE_2_WIRE GPIO_TypeDef* port; } oneWirePin_typeDef; /** * Príznak pripravenosti dát zo senzorov zbernice 1-wire. */ typedef enum OW_DATA_enum { /** Dáta nie sú pripravené, práve sa merajú */ OW_DATA_BUSY=0, /** Dáta sú pripravené */ OW_DATA_READY=1, } oneWireDataReady_typeDef; /** * Príznak stavu zbernice v stave STRONG. */ typedef enum OW_STRONG_STATE_enum { /** Zbernica nie je v stave STRONG */ OW_STRONG_OFF = 0, /** Zbernica je v stave STRONG */ OW_STRONG_ON = 1, } oneWireStrongState_typeDef; /** * Príznak pre stav časovača. */ typedef enum { /** Časovač je spustený, prebieha meranie */ TIMER_STATE_RUN = 0, /** Časovač je vypnutý */ TIMER_STATE_IDLE = 1, } oneWireTimerState_typeDef; #ifdef OW_MODULE_USE_TIMER void oneWire_init(TIM_HandleTypeDef *timer, GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); #else #if OW_USE_2_WIRE == 1 void oneWire_init(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, uint16_t GPIO_Pin_i ); // konfiguracia portu pre 1-wire #else void oneWire_init(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin ); // konfiguracia portu pre 1-wire #endif // OW_USE_2_WIRE #endif uint8_t owReset(void); // reset zbernice a kontrola pritomnosti zariadeni uint8_t owFirst(); // nacitanie ID prveho zariadenia uint8_t owNext(); // iteracia zoznamu zariadeni uint8_t owVerify(void); // kontrola existencia ID zariadenia void owTargetSetup(uint8_t fcode); // nastavenie podmnoziny vyhladavanych zariadeni void owFamilySkipSetup(void); // zrusenie selektivneho vyhladavania void owSetRom(uint8_t *array); // nastavenie ID konkretneho zariadenia uint8_t owSearch(); uint8_t owCrc8(uint8_t); uint8_t owReadBit(void); void owWriteByte(uint8_t, uint8_t); uint8_t owReadByte(void); #ifdef OW_USE_TICKS void owWriteBit(uint8_t*); #else void owWriteBit(uint8_t); #endif void owWriteBitStrong(uint8_t); void owSetDelayMs(uint16_t time); void ow_stop_ms_timer(void); uint8_t *oneWire_getROM(); void owGetROM(uint8_t *mem_page); void owSelect_ROM(const uint8_t rom[8]); void owSelect(); void ow_ClearStrong(void); void ow_SetStrong(void); #endif //ONE_WIRE_LIB_H /** * @} */ /** * @} */ /** * @} */