stm32 hal rfm95
1.0.0
RFM95 Lorawan 모듈 용 STM32 HAL 드라이버.
CMAKE 기반 프로젝트의 경우 (예 : Clion과 함께 STM32CUBEMX 프로젝트를 사용할 때) 예를 들어 드라이버를 하위 모듈로 설정하고 링크 할 수 있습니다.
add_subdirectory ( "<directory-to-driver>/rfm95" )
target_link_libraries (< target - name > stm32-hal-rfm95)RFM95 모듈을 SPI를 통해 마이크로 컨트롤러에 연결하고 큐브를 사용하여 버스를 초기화 한 후이 라이브러리를 사용하여 다음 예제와 같이 RFM95 모듈과 상호 작용할 수 있습니다. DIO0, 1 및 5 인터럽트를 처리해야합니다.
int main () {
// Create the handle for the RFM95 module.
rfm95_handle_t rfm95_handle = {
. spi_handle = & hspi1 ,
. nss_port = RFM95_NSS_GPIO_Port ,
. nss_pin = RFM95_NSS_Pin ,
. nrst_port = RFM95_NRST_GPIO_Port ,
. nrst_pin = RFM95_NRST_Pin ,
. device_address = {
0x00 , 0x00 , 0x00 , 0x00
},
. application_session_key = {
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00
},
. network_session_key = {
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00
},
. receive_mode = RFM95_RECEIVE_MODE_NONE
};
// Initialise RFM95 module.
if (! rfm95_init ( & rfm95_handle )) {
printf ( "RFM95 init failednr" );
}
uint8_t [] data_packet = {
0x01 , 0x02 , 0x03 , 0x4
};
if (! rfm95_send_receive_cycle ( & rfm95_handle , data_packet , sizeof ( data_packet ))) {
printf ( "RFM95 send failednr" );
} else {
printf ( "RFM95 send successnr" );
}
}
void HAL_GPIO_EXTI_Callback ( uint16_t GPIO_Pin )
{
if ( GPIO_Pin == RFM95_DIO0_Pin ) {
rfm95_on_interrupt ( & rfm95_handle , RFM95_INTERRUPT_DIO0 );
} else if ( GPIO_Pin == RFM95_DIO1_Pin ) {
rfm95_on_interrupt ( & rfm95_handle , RFM95_INTERRUPT_DIO1 );
} else if ( GPIO_Pin == RFM95_DIO5_Pin ) {
rfm95_on_interrupt ( & rfm95_handle , RFM95_INTERRUPT_DIO5 );
}
} reload_config 및 save_config 함수를 사용하여 RX 및 TX 프레임 카운터뿐만 아니라 비 휘발성 메모리의 다른 구성을 저장하고 검색 할 수 있습니다. 예를 들어, 내 eeprom 라이브러리 (https://github.com/henriheimann/stm32-hal-eprom)를 사용하여 프레임 카운터를 저장할 때 예제 구현은 다음과 같습니다.
// Forward declaration of the frame counter functions.
static bool reload_config ( rfm95_eeprom_config_t * config );
static void save_config ( const rfm95_eeprom_config_t * config );
// Create the handle for the RFM95 module.
rfm95_handle_t rfm95_handle = {
// ... see example above
. reload_config = reload_config ,
. save_config = save_config ,
};
// Create the EEPROM handle.
eeprom_handle_t eeprom_handle = {
. i2c_handle = & hi2c1 ,
. device_address = EEPROM_24LC32A_ADDRESS ,
. max_address = EEPROM_24LC32A_MAX_ADDRESS ,
. page_size = EEPROM_24LC32A_PAGE_SIZE
};
static bool reload_config ( rfm95_eeprom_config_t * config )
{
return eeprom_read_bytes ( & eeprom_handle , 0x0000 , ( uint8_t * ) config , sizeof ( rfm95_eeprom_config_t ));
}
static void save_config ( const rfm95_eeprom_config_t * config )
{
eeprom_write_bytes ( & eeprom_handle , 0x0000 , ( uint8_t * ) config , sizeof ( rfm95_eeprom_config_t ));
}최종 장치를 구성 할 수있는 Mac 명령으로 다운 링크 메시지를 수신하는 라이브러리의 기능을 사용하려면 정밀 클록 및 지연 기능 및 기타 기능을 제공해야합니다. STM32L4의 LPTIM1을 사용한 예제 구현은 다음과 같습니다.
// Forward declaration of the functions.
static uint32_t get_precision_tick ();
static void precision_sleep_until ( uint32_t target_ticks );
static uint8_t random_int ( uint8_t max );
static uint8_t get_battery_level ();
// Create the handle for the RFM95 module.
rfm95_handle_t rfm95_handle = {
// ... see example above
. precision_tick_frequency = 32768 ,
. precision_tick_drift_ns_per_s = 5000 ,
. receive_mode = RFM95_RECEIVE_MODE_RX12 ,
. get_precision_tick = get_precision_tick ,
. precision_sleep_until = precision_sleep_until ,
. random_int = random_int ,
. get_battery_level = get_battery_level
};
volatile uint32_t lptim_tick_msb = 0 ;
static uint32_t get_precision_tick ()
{
__disable_irq ();
uint32_t precision_tick = lptim_tick_msb | HAL_LPTIM_ReadCounter ( & hlptim1 );
__enable_irq ();
return precision_tick ;
}
void HAL_LPTIM_AutoReloadMatchCallback ( LPTIM_HandleTypeDef * hlptim )
{
lptim_tick_msb += 0x10000 ;
}
static void precision_sleep_until ( uint32_t target_ticks )
{
while (true) {
uint32_t start_ticks = get_precision_tick ();
if ( start_ticks > target_ticks ) {
break ;
}
uint32_t ticks_to_sleep = target_ticks - start_ticks ;
// Only use sleep for at least 10 ticks.
if ( ticks_to_sleep >= 10 ) {
// Calculate required value of compare register for the sleep minus a small buffer time to compensate
// for any ticks that occur while we perform this calculation.
uint32_t compare = ( start_ticks & 0xffff ) + ticks_to_sleep - 2 ;
// If the counter auto-reloads we will be woken up anyway.
if ( compare > 0xffff ) {
HAL_SuspendTick ();
HAL_PWREx_EnterSTOP2Mode ( PWR_STOPENTRY_WFI );
HAL_ResumeTick ();
// Otherwise, set compare register and use the compare match interrupt to wake up in time.
} else {
__HAL_LPTIM_COMPARE_SET ( & hlptim1 , compare );
while (! __HAL_LPTIM_GET_FLAG ( & hlptim1 , LPTIM_FLAG_CMPOK ));
__HAL_LPTIM_CLEAR_FLAG ( & hlptim1 , LPTIM_FLAG_CMPM );
__HAL_LPTIM_ENABLE_IT ( & hlptim1 , LPTIM_IT_CMPM );
HAL_SuspendTick ();
HAL_PWREx_EnterSTOP2Mode ( PWR_STOPENTRY_WFI );
HAL_ResumeTick ();
__HAL_LPTIM_DISABLE_IT ( & hlptim1 , LPTIM_IT_CMPM );
}
} else {
break ;
}
// Busy wait until we have reached the target.
while ( get_precision_tick () < target_ticks );
}
static uint8_t random_int ( uint8_t max )
{
return 0 ; // Use ADC other means of obtaining a random number.
}
static uint8_t get_battery_level ()
{
return 0xff ; // 0xff = Unknown battery level.
} STM32L0, STM32L4 및 STM32F4 마이크로 컨트롤러가 지원됩니다. HAL 헤더는 다른 마이크로 컨트롤러를 포함하여 rfm95.h 에 추가 될 수 있습니다.