æè¡ã®çŸä»£ã®ãã¬ã³ãã¯ãããé«åºŠãªçµ±åã®éãæ©ãã§ããŸããé²æ©ã«ãããé»åããã€ã¹ã®éçºããã»ã¹ãèšèšè ã®çµã¿ç«ãŠã«ãŸããŸãè¿ã¥ããããšãã§ããŸãã æãé¡èãªäŸã®1ã€ã¯ããããããããããªã³ã·ã¹ãã ãã®èšå€§ãªæ°ã§ã-SoCãã»ãšãã©ãããã奜ã¿ã®ãã€ã¯ãã³ã³ãããŒã©ãŒãšåšèŸºæ©åšã®æã ä»æ¥ã¯ããããã®ã·ã¹ãã ã®1ã€ã§ããNordic SemiconductorãããNRF51822ã«æ³šç®ããŸããããã¯ãBluetooth 4.0æšæºã«å«ãŸããBLEãã¯ãããžãŒãšé£æºããããã«é©åãããã·ã¹ãã ã®ãœãªã¥ãŒã·ã§ã³ã§ãã
ãŸããé»åããã€ã¹ã¯ãŸããŸãçµ±åã®ã¬ãã«ãé«ããŠããã®ã§ãããã°ã©ãã³ã°ã§ããé«ãã¬ãã«ã®æœè±¡åã«ãŸã§èžã¿èŸŒãã§ããªã¢ã«ã¿ã€ã ãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã§ããRTOSãå®è¡ããBluetoothã¢ããªã±ãŒã·ã§ã³ãäœæããŠã¿ãŸãããã
ãã®èšäºã®ç®æšã¯ãRTOS Keil-RTXãå®è¡ããNRF51822ã®ç°¡åãªçµã¿èŸŒã¿ã¢ããªã±ãŒã·ã§ã³ãäœæãã1ç§ã«1åADCãã¯ãšãªããåä¿¡ããå€ãBLEç¹æ§ã«æžã蟌ãããšã§ãã ãã®ãããã¯ã«èå³ãããå Žå-catãžããããã
RTOSãšBLEã«ã€ããŠç°¡åã«
RTOSã«ã€ããŠå€ãã®ããšãèšãããŠããã®ã§ãç¹°ãè¿ããªãããã«ã ãããšããã§ããã«ã€ããŠèªãããšããå§ãããŸãã RTOSã䜿çšããããšã®éèŠãªæ©èœã®ãã¡ãã³ãŒãã«æ··ä¹±ãå ããããšãªãããã°ã©ã ã®æ©èœãéåžžã«ç°¡åã«åäžã§ããããšã ãã«æ³šæããããšæããŸãã ããã¯ãããã°ã©ã ã®åã ã®ã»ã¯ã·ã§ã³ãäºãã«å¹²æžããããšãªãæ¡ä»¶ä»ãã§åæã«åäœããåé¢ããããããã¯ãšããŠå®è¡ã§ããããã«å¯èœã§ãã ãããŠãå€ããå®è¡æã«èŠæ±ãããå€æ°ã®ç°ãªãã¿ã¹ã¯ãå®è¡ããããšãä¿èšŒãããŠãããã·ã¹ãã ãªã³ããããçšã®ã¢ããªã±ãŒã·ã§ã³ãäœæããå ŽåãRTOSã䜿çšããããšã§ç掻ãå€§å¹ ã«ç°¡çŽ åãããŸãã
BLEã®æŠèŠãšãã®ä»çµã¿ã«ã€ããŠã¯ã äžé£ã®ãã°ãããèšäºãããããšããããããã€ãã®ããšãç解ããã®ã«åœ¹ç«ã¡ãŸããã ãŸã èªãã§ããªãå Žåã¯ãå¿ ããã§ãã¯ããŠãã ããã ãã®èšäºã®ãã¬ãŒã ã¯ãŒã¯ã§ã¯ããã®ãã¯ãããžãŒã䜿çšããå®çšçãªãã¥ã¢ã³ã¹ã«èå³ãæã£ãŠããŸãã
äžè¬çã«èšã£ãŠããç§ãã¡ã¯BLEãšRTOSã®åéã§ãããšæžããã®ã§ãããæå³ã§ãããã2ã€ã®æŠå¿µã¯åå ããªããŠãéåžžã«ããŸãããã®ã§ãç§ã¯å°ãcã«ãªããŸããã äºå®ãã³ã³ãããŒã©ãŒã§BLEèŠæ Œã䜿çšããããã«äœ¿çšããBluetoothã¹ã¿ãã¯ã¯ãããèªäœãäžçš®ã®RTOSã§ãããã¿ã¹ã¯ããããã®ã¿ã¹ã¯ã®ãã£ã¹ãããã£ãŒãã¿ã€ããŒãå»ã ãšéããã€ãã³ããçºçãããšããäºå®ã§ãã ãããã£ãŠãç§ã®å人çãªæèŠã§ã¯ãBLEã¢ããªã±ãŒã·ã§ã³ã§ã®RTOSã®äœ¿çšã¯ãã¢ããªã±ãŒã·ã§ã³å šäœãæœè±¡åã®1ã€ã®ã¬ãã«ã«å°ãã®ã§ãè¯ã圢ã«ãªãã§ãããã
å¿ èŠãªããŒã«
NRF51ã®èµ·åã«é¢ããåºæ¬çãªåé¡ã«è§Šããªãããã«ããããã«ãComrade Foxekã®èšäºã«äŸåãããããåãããŒã«ãå¿ èŠã«ãªããŸãã
â¢ãããã°ããŒãNRF51
â¢OC Androidãå®è¡ããŠããã¹ããŒããã©ã³
â¢nRF Connect Androidã¢ããª
â¢MKD ARM Keil uVision
RTOSã»ããã¢ãã
å€å žçãªæ¹æ³ã§éå§ããŸã-Pack Installerã䜿çšããŠble_app_templateãã³ãã¬ãŒããããžã§ã¯ããããŒããïŒãã®æé ã®è©³çŽ°ã«ã€ããŠã¯ã nRF51822ïŒã¯ã€ãã¯ã¹ã¿ãŒãã®èšäºãåç §ïŒãRun-Time EnvironmentãããŒãžã£ãŒã䜿çšããŠå¿ èŠãªäŸåé¢ä¿ãè¿œå ããŸãã
ããã§ããããžã§ã¯ãã«RTOSãè¿œå ããŸããã ããŠãéãšçžäºäœçšã§ããããã«ããã¥ãŒãã³ã°ãè¡ãå¿ èŠããããŸãã CMSIS-RTOSã¯ãCortex-Mã³ã¢ã«åºã¥ããããã»ããµã§ã®åäœã«ããé©åããŠãããååãšããŠãSysTickã·ã¹ãã ã¿ã€ããŒã䜿çšããŠOSã®æéãéååããŸãã ãã ããNRF51ã³ã³ãããŒã©ãŒã«ã¯ããŒãäžã«Cortex-M0ã³ã¢ããããSysTickã¿ã€ããŒããªããããã¡ãŒã«ãŒã¯RTOSã¯ãããã³ã°ã«RTC1ãªã¢ã«ã¿ã€ã ã¯ããã¯ã䜿çšããããšããå§ãããŸãã äžæ¹ã§ã¯ãRTC1ã¯ã³ã³ãããŒã©ãŒã®ã¹ãªãŒãã¢ãŒãã§ãªãã«ãªããªãããããã®ãœãªã¥ãŒã·ã§ã³ã¯ãã©ã¹ã§ããã€ãŸããRTOSã§éåžžã«äœãæ¶è²»ã§ã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ã§ããããšãæå³ããŸãã äžæ¹ãRTCãããã¯ã¯32768 Hzã®åšæ³¢æ°ã§ã¯ããã¯ãããŸããããã¯ãã·ã¹ãã æéã®ã¯ã©ã³ã¿ã ã®ãµã€ãºãååã«å°ããã§ããªãããšãæå³ããŸãã
UPDã ã©ã³ã¿ã€ã ç°å¢ãããŒãžã£ãŒã®app_timerã¢ãžã¥ãŒã«ã®[nRF_Libraries]ã¿ãã§ã[Rtx]ãªãã·ã§ã³ãéžæããŸãã ããããªããšãå²ã蟌ã¿ãã³ãã©RTC1ã®è€æ°ã®å®çŸ©ãšç«¶åããŸãã
OSã§åäœããã¿ã€ããŒãç解ãããããã«ãããã€ãã®é¢æ°ãè¿œå ããå¿ èŠããããŸããã¿ã€ããŒãšãããã€ãã®ã€ãã³ããã³ãã©ãŒãšã¿ã€ããŒå²ã蟌ã¿ãåæåããŸãã ãããè¡ãã«ã¯ãCMSISã¿ãããRTX_Conf_CM.cãã¡ã€ã«ãéãã
ããããŒãã¡ã€ã«nrf.hãè¿œå ããã°ããŒãã«é¢æ°ã»ã¯ã·ã§ã³ãèŠã€ããŠããã®äžã®é¢æ°ã®å 容ã次ã®ãã®ã«çœ®ãæããŸãã
ãœãŒã¹ã³ãŒã
/*---------------------------------------------------------------------------- * Global Functions *---------------------------------------------------------------------------*/ /*--------------------------- os_idle_demon ---------------------------------*/ #define TIMER_MASK 0xFFFFFF volatile unsigned int rtos_suspend; /// \brief The idle demon is running when no other thread is ready to run void os_idle_demon (void) { unsigned int expected_time; unsigned int prev_time; NVIC_SetPriority(PendSV_IRQn, NVIC_GetPriority(RTC1_IRQn)); for (;; ) { rtos_suspend = 1; expected_time = os_suspend(); expected_time &= TIMER_MASK; if (expected_time > 2) { prev_time = NRF_RTC1->COUNTER; expected_time += prev_time; NRF_RTC1->CC[0] = (expected_time > TIMER_MASK) ? expected_time - TIMER_MASK : expected_time; NRF_RTC1->INTENCLR = RTC_INTENSET_TICK_Msk; NVIC_EnableIRQ(RTC1_IRQn); __disable_irq(); if (rtos_suspend) { NRF_RTC1->INTENSET = RTC_INTENSET_COMPARE0_Msk; __WFI(); NRF_RTC1->EVENTS_COMPARE[0] = 0; NRF_RTC1->INTENCLR = RTC_INTENSET_COMPARE0_Msk; } __enable_irq(); NRF_RTC1->INTENSET = RTC_INTENSET_TICK_Msk; expected_time = NRF_RTC1->COUNTER; expected_time = (expected_time >= prev_time) ? expected_time - prev_time : TIMER_MASK - prev_time + expected_time; } os_resume(expected_time); } } #if (OS_SYSTICK == 0) // Functions for alternative timer as RTX kernel timer /*--------------------------- os_tick_init ----------------------------------*/ /// \brief Initializes an alternative hardware timer as RTX kernel timer /// \return IRQ number of the alternative hardware timer int os_tick_init (void) { NRF_CLOCK->LFCLKSRC = (CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos); NRF_CLOCK->EVENTS_LFCLKSTARTED = 0; NRF_CLOCK->TASKS_LFCLKSTART = 1; while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0) { // Do nothing. } NRF_RTC1->PRESCALER = 32;//OS_TRV; NRF_RTC1->INTENSET = RTC_INTENSET_TICK_Msk; NRF_RTC1->TASKS_START = 1; return (RTC1_IRQn); /* Return IRQ number of timer (0..239) */ } /*--------------------------- os_tick_val -----------------------------------*/ /// \brief Get alternative hardware timer's current value (0 .. OS_TRV) /// \return Current value of the alternative hardware timer uint32_t os_tick_val (void) { return NRF_RTC1->COUNTER; } /*--------------------------- os_tick_ovf -----------------------------------*/ /// \brief Get alternative hardware timer's overflow flag /// \return Overflow flag\n /// - 1 : overflow /// - 0 : no overflow uint32_t os_tick_ovf (void) { return NRF_RTC1->EVENTS_OVRFLW; } /*--------------------------- os_tick_irqack --------------------------------*/ /// \brief Acknowledge alternative hardware timer interrupt void os_tick_irqack (void) { if ((NRF_RTC1->EVENTS_TICK != 0) && ((NRF_RTC1->INTENSET & RTC_INTENSET_TICK_Msk) != 0)) { NRF_RTC1->EVENTS_TICK = 0; } } #if defined (__CC_ARM) /* ARM Compiler */ __asm __declspec(noreturn) void RTC1_IRQHandler(void) { EXTERN OS_Tick_Handler BL OS_Tick_Handler } #else #error "Unknown compiler! Don't know how to create SVC function." #endif #endif // (OS_SYSTICK == 0)
os_idle_demonïŒïŒé¢æ°ã¯ãçãšãã¢ãŒãã䜿çšãããšãã®ã·ã¹ãã ã®åäœãæ£ç¢ºã«æ åœããŸããã¢ããªã±ãŒã·ã§ã³ãã¿ã¹ã¯ã§ããžãŒã§ãªãå Žåãã·ã¹ãã èªäœãã³ã³ãããŒã©ãŒãã¹ãªãŒãç¶æ ã«ããŸãã
次ã«ãã·ã¹ãã ã«SysTickã䜿çšããªãããšãäŒããŸããããã«ã¯ããã¹ãŠã®æ©èœãæ¢ã«åãã£ãŠãããããåæã«ãã¯ããã¯ãåäœããåšæ³¢æ°ãšã·ã¹ãã æéãéååããæ¹æ³ãæå®ããããã§ãã ãããè¡ãã«ã¯ãåããã¡ã€ã«RTX_Conf_CM.cã§æ§æãŠãŒãã£ãªãã£ãéããé©åãªã·ã¹ãã ãã©ã¡ãŒã¿ãŒãèšå®ããŸãã
10 msã®ã·ã¹ãã èªã¿åãééã¯å¶ç¶éžæãããŸããã§ããïŒ32768 Hzã®ã¯ããã¯åšæ³¢æ°ã§327ã¹ããªãã¿ãŒã䜿çšãããšãã¿ã€ããŒåšæ³¢æ°ã¯99.9 Hzã«ãªããå°ãªããšãããçšåºŠã®åŠ¥åœãªç²ŸåºŠã§ã·ã¹ãã ã¿ã€ãã³ã°ãæäŸããŸãã ãã®ééã«äœãå€ã䜿çšããå¿ èŠãããå Žåã¯ã蚱容å¯èœãªç²ŸåºŠãäžããå€ãéžæã§ããŸãïŒããšãã°ãé€æ°31ããã³ééé·977ÎŒsïŒãããããã¯éå圢ã®æ°å€ã«ãªããã³ãŒãã«æ··ä¹±ããããããŸãã ãŸããéæšæºã®ã¹ã¿ãã¯ãµã€ãºã§ã¹ããªãŒã ãäœæãããããã®ã¹ããªãŒã ã«ã¡ã¢ãªãå²ãåœãŠãã¹ã¿ãã¯ã®éãããå»ãããšãã§ããŸããããã«ããããããã°ãããèŠèŠçã«ãªããŸãã
ãã®æ®µéã§ãããã°ã©ã ãçµã¿ç«ãŠãŠã³ã³ãããŒã©ãŒã«ããŠã³ããŒãããããšãã§ããŸãã ãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ãèµ·åããã¡ã€ã³é¢æ°ãå¯äžã®ã¹ã¬ãããšããŠå®è¡ãå§ããŸãã ãã ããRTOSã®æå³ã¯ãããŸããŸãªã¿ã¹ã¯ãããŸããŸãªã¹ã¬ããã§ã¹ãã³ããããšãªã®ã§ãBLEã¹ã¿ãã¯çšã«ç¬èªã®ã¹ã¬ãããäœæããŸãã
// ble_stack_thread osPoolDef(ble_evt_pool, 8, ble_evt_t); // osPoolId ble_evt_pool; // osMessageQDef(ble_stack_msg_box, 8, ble_evt_t); // osMessageQId ble_stack_msg_box; // osThreadId ble_stack_thread_id; // void ble_stack_thread(void const * arg); // osThreadDef (ble_stack_thread, osPriorityAboveNormal, 1, 400);
ããã§ãã¹ã¿ãã¯ã䜿çšããã¡ã¢ãªããŒã«ãã¹ã¿ãã¯ãã·ã¹ãã ããã¡ãã»ãŒãžãåä¿¡ããã¡ãŒã«ããã¯ã¹ãããã³ã¹ããªãŒã èªäœã決å®ãããã®çªå·ãšå®è¡ãããé¢æ°ã宣èšããŸããã ã¹ã¬ãããäœããããã決å®ããã ãã§ãªããã·ã¹ãã ããã³ã¹ã¿ãã¯ã€ãã³ããã³ãã©ãŒã§ãã®äœæé¢æ°ã宣èšããŸãã
ãœãŒã¹ã³ãŒã
// BLE void ble_stack_thread(void const * arg) { uint32_t err_code; osEvent evt; ble_evt_t * p_ble_evt; UNUSED_PARAMETER(arg); while (1) { evt = osMessageGet(ble_stack_msg_box, osWaitForever); // wait for message if (evt.status == osEventMessage) { p_ble_evt = evt.value.p; switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: err_code = bsp_indication_set(BSP_INDICATE_CONNECTED); APP_ERROR_CHECK(err_code); m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; break; case BLE_GAP_EVT_DISCONNECTED: m_conn_handle = BLE_CONN_HANDLE_INVALID; break; default: // No implementation needed. break; } (void)osPoolFree(ble_evt_pool, p_ble_evt); } } } // BLE void ble_create_thread (void) { ble_evt_pool = osPoolCreate(osPool(ble_evt_pool)); ble_stack_msg_box = osMessageCreate(osMessageQ(ble_stack_msg_box), NULL); ble_stack_thread_id = osThreadCreate(osThread(ble_stack_thread), NULL); }
ã芧ã®ãšãããon_ble_evtã€ãã³ããã³ãã©ãŒã®æšæºé¢æ°ã¯ãã¹ããªãŒã ãžã®åçŽãªã¡ãã»ãŒãžè»¢éã«çœ®ãæããããŠããŸãããã®å éšã§ã¯ããã³ãã©ãŒãå®è¡ã«äœ¿çšããããžãã¯ãæ¢ã«æ§æãããŠããŸãã
ã·ã¹ãã ã«ã¹ããªãŒã ãç»é²ããã«ã¯ãã¡ã¢ãªããŒã«ãšã¡ãŒã«ããã¯ã¹ãäœæããé¢æ°ãäœæããŸãããã®åŸãã¹ããªãŒã ãäœæããå°ãåã«å®£èšããèå¥åã§ç»é²ããŸãã ããããã¹ãŠmainã«è¿œå ããŠå®è¡ããã ãã§ãã
ãœãŒã¹ã³ãŒã
int main(void) { uint32_t err_code; bool erase_bonds; static osStatus status; // status = osKernelInitialize(); // timers_init(); ble_stack_init(); device_manager_init(erase_bonds); gap_params_init(); advertising_init(); services_init(); conn_params_init(); // err_code = ble_advertising_start(BLE_ADV_MODE_FAST); APP_ERROR_CHECK(err_code); ble_create_thread(); // status = osKernelStart(); }
é¢æ°osKernelInitializeïŒïŒããã³osKernelStartïŒïŒã«æ³šæããŠãã ãã-mainã¯ãã§ã«ã¹ããªãŒã ã§ãããããå ¥åããããŸã§ã«RTOSã¯ãã§ã«å®è¡ãããŠããŸãã ãã ããã¹ã¬ãããäœæããåæ¢ããOSã§åšèŸºå šäœãæ§æããæ¹ããããããæåã®æ©èœãäžæåæ¢ãã2çªç®ã®æ©èœãåéããŠåäœãããŸãã
ããã«ãbsp_bleã«é¢é£ãããã®ã¯ãã¹ãŠããããžã§ã¯ãããåé€ããŸããããã®ã©ã€ãã©ãªã¯RTOSããã€ãã¹ããã¹ã¿ãã¯ã«å¹²æžããããšããŠããããã§ãã ã¡ã€ã³ã¯ã¹ããªãŒã ã§ãããããã¡ã€ã³ã«ãŒãèªäœãã¡ã€ã³ããåé€ããŸããããã¹ãŠã®åæåã®åŸãã¡ã¢ãªãäºçŽãããŸãŸã«ããå¿ èŠã¯ãããŸããã ãããã£ãŠãäž»ãªç®çãããã³ã·ã¹ãã ãåäœãç¶ããããããã¯å¥è·¡ã§ãã
ããã§ãããã°ã©ã ããã«ãããã³ã³ãããŒã©ãŒã«ããŠã³ããŒãããŠãnRF Connectããã°ã©ã ã䜿çšããŠããã€ã¹ã«æ¥ç¶ã§ããŸãã
ã芧ã®ãšããããŸã åäžã®ãµãŒãã¹ã¯ãããŸããã®ã§ãä¿®æ£ããæãæ¥ãŸããã ãåç¥ã®ããã«ãADCããããŒã¿ãèªã¿åãããµãŒãã¹ã®ç¹æ§ã«æžã蟌ã¿ãŸãã ç¹°ãè¿ããŠèªåã®èªè»¢è»ãæ§ç¯ããªãããã«ããããããµãŒãã¹ãšæ©èœãäœæããããã®ãã³ãã¬ãŒãã䜿çšããŸã ã
ãœãŒã¹ã³ãŒã
// void services_init(void) { ble_uuid_t ble_uuid; /* 128 - UUID */ ble_uuid128_t base_uuid = ADC_BASE_UUID; uint8_t uuid_type; ble_uuid.type = BLE_UUID_TYPE_VENDOR_BEGIN; ble_uuid.uuid = ADC_SERVICE_UUID; sd_ble_uuid_vs_add(&base_uuid, &ble_uuid.type); sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &adc_handles); } /* * UUID - * handles - ( ) * n_bytes - * iswrite, isnotf, isread - , , */ uint32_t char_add(uint16_t UUID, ble_gatts_char_handles_t * handles, uint8_t n_bytes, bool iswrite, bool isnotf, bool isread) { ble_gatts_char_md_t char_md; ble_gatts_attr_md_t cccd_md; ble_gatts_attr_t attr_char_value; ble_uuid_t char_uuid; ble_gatts_attr_md_t attr_md; memset(&cccd_md, 0, sizeof(cccd_md)); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm); cccd_md.vloc = BLE_GATTS_VLOC_STACK; memset(&char_md, 0, sizeof(char_md)); char_md.char_props.notify = isnotf; // ; char_md.char_props.write = iswrite; // ; char_md.char_props.read = isread; // ; char_md.p_char_user_desc = NULL; char_md.p_char_pf = NULL; char_md.p_user_desc_md = NULL; char_md.p_cccd_md = &cccd_md; char_md.p_sccd_md = NULL; /* UUID - 128 - */ char_uuid.type = BLE_UUID_TYPE_VENDOR_BEGIN; char_uuid.uuid = UUID; memset(&attr_md, 0, sizeof(attr_md)); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm); attr_md.vloc = BLE_GATTS_VLOC_STACK; attr_md.rd_auth = 0; attr_md.wr_auth = 0; attr_md.vlen = 0; attr_char_value.p_uuid = &char_uuid; attr_char_value.p_attr_md = &attr_md; attr_char_value.init_len = n_bytes; attr_char_value.init_offs = 0; attr_char_value.max_len = n_bytes; // ; attr_char_value.p_value = NULL; // ; /* */ sd_ble_gatts_characteristic_add(adc_handles, &char_md, &attr_char_value, handles); return 0; }
ããã§ãADC_BASE_UUIDãšADC_SERVICE_UUIDã¯ã次ã®åœ¢åŒã§å®çŸ©ãããè€åãµãŒãã¹èå¥åã§ãã
/* UUID ( UUID ) */ #define ADC_BASE_UUID {0x66, 0x9A, 0x0C, 0x20, 0x00, 0x08, 0x1A, 0x8F, 0xE7, 0x11, 0x61, 0xBE, 0x00, 0x00, 0x00, 0x00} /* UUID ( UUID ) */ #define ADC_SERVICE_UUID 0x1533 #define ADC_CHAR_UUID 0x1534
ããã§ã1ãã€ãã®ããŒã¿ãå«ã1ã€ã®ç¹æ§ãæã€ãµãŒãã¹ãã§ããŸããã ãã®ãã€ããæçšãªæ å ±ã§åããã ãã§ããããã èšäºãåç §ããŠADCãåæåããŸããADCã¯1ç§éã«1åå€æãå®è¡ããç¹æ§ã®å 容ãæŽæ°ããé¢æ°ãè¿œå ããŸãã
ãœãŒã¹ã³ãŒã
// void ADC_init (void) { // 2 8 NRF_ADC->CONFIG = 0x00; NRF_ADC->CONFIG |= (ADC_CONFIG_RES_8bit << ADC_CONFIG_RES_Pos)| (ADC_CONFIG_INPSEL_AnalogInputOneThirdPrescaling << ADC_CONFIG_INPSEL_Pos)| (ADC_CONFIG_PSEL_AnalogInput2 << ADC_CONFIG_PSEL_Pos); NRF_ADC->INTENSET |= ADC_INTENSET_END_Enabled << ADC_INTENSET_END_Pos; NRF_ADC->ENABLE |= ADC_ENABLE_ENABLE_Enabled << ADC_ENABLE_ENABLE_Pos; // NVIC_SetPriority(ADC_IRQn, 1); NVIC_EnableIRQ(ADC_IRQn); // NRF_TIMER1->POWER = 1; NRF_TIMER1->MODE = TIMER_MODE_MODE_Timer << TIMER_MODE_MODE_Pos; NRF_TIMER1->PRESCALER = 10; // 16 MHz / 2^10 = 15625 Hz NRF_TIMER1->CC[0] = 15625; // 15625 Hz / 15625 = 1 Hz NRF_TIMER1->INTENSET = (TIMER_INTENSET_COMPARE1_Enabled << TIMER_INTENSET_COMPARE1_Pos); NRF_TIMER1->SHORTS |= (TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos); // PPI NRF_PPI->CH[0].EEP = (uint32_t) &NRF_TIMER1->EVENTS_COMPARE[0]; NRF_PPI->CH[0].TEP = (uint32_t) &NRF_ADC->TASKS_START; NRF_PPI->CHEN |= PPI_CHEN_CH0_Enabled; NRF_PPI->CHENSET |= PPI_CHENSET_CH0_Enabled; NRF_PPI->TASKS_CHG[0].EN = 1; NRF_TIMER1->TASKS_START = 1; } // void ADC_IRQHandler(void) { rtos_suspend = 0; NRF_ADC->EVENTS_END = 0; if (NRF_ADC->CONFIG >> ADC_CONFIG_PSEL_Pos == ADC_CONFIG_PSEL_AnalogInput2) { NRF_TIMER1->EVENTS_COMPARE[0] = 0; adc_val = NRF_ADC->RESULT; osSignalSet(char_update_thread_id, 1<<CharUpdateSignal); } }
å²ã蟌ã¿ãã³ãã©ã«ã¯æ¬¡ã®ãããªæ§é ãããããšã«æ³šæããŠãã ãã
rtos_suspend = 0;
rtos_suspendå€æ°èªäœã¯RTOSæ§æãã¡ã€ã«ã§å®çŸ©ãããmain.sã«ãšã¯ã¹ããŒããããŸãã ãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã¯å²ã蟌ã¿ãå¶åŸ¡ããªãããããã®å€æ°ã¯ãã·ã¹ãã ãçŸæç¹ã§ã¢ã€ãã«ç¶æ ã§ã¯ãªãå²ã蟌ã¿ãã³ãã©ãŒã«ããããšãããã°ã©ã ãç解ããããã«å¿ èŠã§ããã€ãŸããçãšãæ©èœãä»ããã¢ã¯ãã£ãã«ããªãã§ãã ããã ãã以å€ã®å Žåãã·ã¹ãã ã®åäœã¯äºæž¬ã§ããªããŸãŸãªã®ã§ãåå²ã蟌ã¿ãã³ãã©ãŒããã®å€æ°ããŒãã«ããããšã匷ããå§ãããŸãã
å²ã蟌ã¿ãã³ãã©ãŒããã¹ã¿ãã¯ã§ã¢ã¯ã·ã§ã³ãå®è¡ããããšã¯äžå¯èœãªã®ã§ïŒãã®å Žåãç¹æ§ãæŽæ°ããŸãïŒããããè¡ãã¹ã¬ãããäœæã§ããŸãã å²ã蟌ã¿ããã®ãããŒãšå¯Ÿè©±ããããã«ãä¿¡å·ãªã©ã®ããŒã«ããããŸãã æ¬è³ªçã«ãã·ã°ãã«ïŒãããã¯èšå®ããã³ãªã»ããã§ãããã©ã°å€æ°ã®åãªããããã§ãïŒã¯ãå²ã蟌ã¿ã«éåžžã«äŒŒãŠããŸãã ç¹æ§ãšãã®ã¢ã©ãŒãä¿¡å·ãèšé²ããããã®ã¹ããªãŒã ãäœæããã¡ã€ã³ã«è¿œå ããŸãã
糞
// void char_update_thread (void const* arg); // osThreadId char_update_thread_id; // osThreadDef(char_update_thread, osPriorityNormal, 1, 0); // int32_t CharUpdateSignal = 0x01; // void char_update_thread (void const* arg) { while(1) { osSignalWait(1<<CharUpdateSignal,osWaitForever); ble_char_update(&adc_val,1,adc_char_handles.value_handle); } }
ã¡ã€ã³
int main(void) { uint32_t err_code; bool erase_bonds; static osStatus status; // status = osKernelInitialize(); // timers_init(); ble_stack_init(); device_manager_init(erase_bonds); gap_params_init(); advertising_init(); services_init(); char_add(ADC_CHAR_UUID,&adc_char_handles, 1, false, false, true); conn_params_init(); // err_code = ble_advertising_start(BLE_ADV_MODE_FAST); APP_ERROR_CHECK(err_code); // ADC_init(); // ble_create_thread(); char_update_thread_id = osThreadCreate(osThread(char_update_thread),NULL); // status = osKernelStart(); }
ããã§æºåå®äºã§ãã ããã°ã©ã ãã³ã³ãããŒã©ãŒã«ããŒãããŠãååŸãããã®ã確èªã§ããŸãã
ã芧ã®ãšããã1ãã€ãã®å€ãæ ŒçŽãã1ã€ã®ç¹æ§ãæã€ãµãŒãã¹ããããŸãã ãããèªã¿åã£ãŠãADCã®å ¥åã§ã®é»å§å€åã«å¿ããŠå€ãå€åããããšã確èªã§ããŸãã ãã®ç¹æ§ãéç¥ããããšãå¯èœã§ãããã€ã¹ã®ç¹æ§ã®ããŒã¿ãå€æŽãããå Žåãã¹ããŒããã©ã³ã§èªåçã«æŽæ°ãããŸãã
ãããã«
çµè«ãšããŠãäžèŠRTOSã¯ãããžã§ã¯ãã«äžå¿ èŠãªè€éãããããããŠããããã«èŠããŸãããããã¯å®å šã«çå®ã§ã¯ãããŸããã å®éãäœæããã¢ããªã±ãŒã·ã§ã³ã¯ããã¹ãŠã®ã¿ã¹ã¯çšã®ã¡ã¢ãªããªããªããŸã§ç°¡åã«ã¹ã±ãŒãªã³ã°ã§ããŸãã æ°ããã¢ãžã¥ãŒã«ããšã«ãäœããã®æ°åŠçãªæäœã§ããããšåšèŸºæ©åšãšé£æºããå Žåã§ããããšãç¬èªã®ã¹ã¬ãããäœæããã ãã§ååã§ããããã°ã©ããŒãèããå¿ èŠãããã®ã¯ãã¿ã¹ã¯ã®åªå é äœä»ãæ¹æ³ã§ããã»ããã©ãšã©ããã䜿çšããŠåæãæ§ç¯ããããã®åããªãœãŒã¹ã
åç §è³æ
RTOS BLEãããžã§ã¯ã
Keil-RTX WebããŒãž
nRF51822ã®æŠèŠïŒã¯ã€ãã¯ã¹ã¿ãŒã
nRF51822ã®æŠèŠïŒçãšãã«ã®ãŒãšäžéšã®åšèŸºæ©åš
NRF51822補åããŒãž