éå¶ç®¡ç
ããŽã¡ã®è¡ã§äŒæãéãããå€ãã®çŸããå Žæã蚪ããã«ãããããããå€æ¹ãããŒã«ã飲ã¿ãªããUARTãèŠã€ããŸããã ããã«ãè¯ãFisher FA011ããããã©ã³ãè³Œå ¥ããŸãããããã¯USB SOUND BLASTER X-FI HDãè³Œå ¥ããªããã°ãªãããé³æ¥œãèŽããããšæã£ãŠããŸããã
以åã®èšäºã¯æåã«Geektimeã«ç§»åããããããç§ã¯ããããåãæ»ããŸãããä»ã©ãã«çœ®ãã¹ããããããããŸãã:)
ãã ãã念ã®ãããããã«ãããŸãã
STM32ãC ++ããã³FreeRTOSã æåããéçºã ããŒã1
STM32ãC ++ããã³FreeRTOSã æåããéçºã ããŒã2ããã³
STM32ãC ++ããã³FreeRTOSã æåããéçºã ããŒã3ïŒLCDããã³ç»é¢ïŒ
UART
ãã€ã¯ãã³ã³ãããŒã©ã®è©³çŽ°ãªç 究ã®åŸããã¹ãŠãã·ã³ãã«ã§ããããã«æããŸããã ããŒããžã®ãã€ãã®æ§æãšãã¹ãéä¿¡ã¯åé¡ãªãè¡ããããã¹ãŠãã¯ããã¯ã®ããã«æ©èœãããããå²ã蟌ã¿ã䜿çšããããšã«ããŸããã å²ã蟌ã¿ãã³ãã©ãŒãéçã¯ã©ã¹ã¡ãœããã«ããå¿ èŠããããŸããã ãããŠãã³ã³ãã€ã©ããã¥ã¢ã«ã®IARã¯æ¬¡ã®ããã«æžããŸããïŒ
ç¹å¥ãªé¢æ°åã¯ãéçã¡ã³ããŒé¢æ°ã«äœ¿çšã§ããŸãã ããšãã°ã
次ã®äŸã§ã¯ãé¢æ°ãã³ãã©ãŒãå²ã蟌ã¿é¢æ°ãšããŠå®£èšãããŠããŸãã
class Device { static __irq void handler(); };
ããããæ®å¿µãªãããCortex Mã®å Žåããã®æ¹æ³ã¯é©åã§ã¯ãããŸããã
ARM Cortex-Mã§ã¯ãå²ã蟌ã¿ãµãŒãã¹ã«ãŒãã³ã¯ã
éåžžã®æ©èœãç¹å¥ãªããŒã¯ãŒãã¯äžèŠã§ãã ãããã£ãŠãããŒã¯ãŒã
__irqã__ fiqãããã³__nestedã¯ãARM Cortex-Mçšã«ã³ã³ãã€ã«ããå Žåã¯äœ¿çšã§ããŸããã
ãããã®äŸå€é¢æ°åã¯ãcstartup_M.cããã³cstartup_M.sã§å®çŸ©ãããŠããŸãã
ãããã¯ãã©ã€ãã©ãªäŸå€ãã¯ãã«ã³ãŒãã«ãã£ãŠåç §ãããŸãã
NMI_Handler
HardFault_Handler
Memmanage_handler
BusFault_Handler
...
ãã¯ã¿ãŒããŒãã«ã¯é åãšããŠå®è£ ãããŸãã åžžã«ååãæã€å¿ èŠããããŸã
__vector_tableã
ãŸãã¯ãåçŽã«ãå²ã蟌ã¿ãã³ãã©ãŒã¯ãã¹ã¿ãŒãã¢ãããã¡ã€ã«ã§å®çŸ©ããããã¯ã¿ãŒããŒãã«ã«ãããã®ãšåãååãæã€å¿ èŠããããŸãã ããã¯ç¹å¥ãªããŒã¯ãŒã-匱ã__weakãªã³ã¯ïŒPUBWEAKã¢ã»ã³ãã©ãŒïŒã䜿çšããŠè¡ãããŸããã€ãŸãããã®å®çŸ©ã¯ã__ weekããŒã¯ãŒããªãã§äžèŽããã¹ãã«ãå°ãªããšã1ã€ã«ãªããŸã§äœ¿çšãããŸãã ã€ãŸãããã®ãã£ã¬ã¯ãã£ããªãã§ãŸã£ããåãååã®é¢æ°ãå®çŸ©ãããšãã³ã³ãã€ã©ãŒã¯ãã®å®çŸ©ã䜿çšããå®çŸ©ããªãå Žåã¯__weakã§ããŒã¯ãããŸãã
cUart :: USART2_IRQHandlerïŒïŒãªã©ã®éçã¡ãœããã®C ++åãstartup_stm32l1xx_md.sãŸãã¯startup_stm32l1xx_md.sãã¡ã€ã«ã«æ¿å ¥ã§ããªãããšã¯æããã§ããã¢ã»ã³ãã©ãŒã¯ãããç解ããŸããã
ããããåã«ãUSART2_IRQHandlerãã¯ãcUart :: USART2_IRQHandlerïŒïŒãã®å®çŸ©ãšäžèŽããŸããã
externâ Câ {void USART2_IRQHandlerïŒvoidïŒ{...}}ã䜿çšã§ããŸãããããã¯ãCããã®æ¿å ¥ãè¡ãããšãæå³ããŸããããã¯ãŸã£ããå¿ èŠãããŸãããéåžžããã®ãããªé¢æ°ããã¯ã©ã¹ã®å±æ§ã«ã¢ã¯ã»ã¹ããŸãããããã¡ã¯ååšãããå€ãã®ãã³ãŒãããããã¯ããå¿ èŠããããŸã:)ã
ãããã£ãŠãå¥ã®æ¹æ³ã§startup_stm32l1xx_md.cppãã¡ã€ã«ãäœæããããšã«ããŸããã ã€ã³ã¿ãŒããããæ€çŽ¢ãããšããããŸã£ããåãåé¡ãæ±ããŠãã人ãããããšãããããŸããã ããšãã°ã
äžè¬çãªèãæ¹ã¯æ¬¡ã®ãšããã§ããstartup_stm32l1xx_md.cppã¯ã©ã¹ãéçã¡ãœããïŒå²ã蟌ã¿ãã³ãã©ãŒïŒã§å®çŸ©ããããŒãã«__vector_tableãäœæããŸããåå²ã蟌ã¿ãã¯ã¿ãŒã«ã¯ãããã®éçã¡ãœãããžã®ãã€ã³ã¿ãŒããããŸãã 次ã«ãåã¡ãœããã®__weakå®çŸ©ãäœæããŸã
ãããŠä»ãã³ã³ãã€ã©ãŒã¯ãã³ãŒãå ã§void cUart1 :: handlerïŒïŒã®å®è£ ã確èªãããšãããããããšãªããããååŸããŸãã ãã¡ãããåæã«ãã¯ã©ã¹ãšã¡ãœããã¯ã startup_stm32l1xx_md.cppã§å®çŸ©ãããŠãããšããã«æ£ç¢ºã«åŒã³åºãå¿ èŠããããŸãã
FreeRtosé¢æ°vPortSVCHandler ã xPortPendSVHandler ã xPortSysTickHandlerãå¿ããŠãç®çã®å²ã蟌ã¿ãšåºæ¥äºã«çœ®ãå¿ èŠããããŸã-ãã¹ãŠãæ©èœããŸãïŒ
startup_stm32l1xx_md.cpp
#pragma language = extended #pragma segment = "CSTACK" extern "C" void __iar_program_start( void ); extern "C" void vPortSVCHandler(void); extern "C" void xPortPendSVHandler(void); extern "C" void xPortSysTickHandler(void); class cNMI { public: static void handler(void); }; class cHardFault { public: static void handler(void); }; class cMemManage { public: static void handler(void); }; class cBusFault { public: static void handler(void); }; class cUsageFault { public: static void handler(void); }; class cDebugMon { public: static void handler(void); }; class cWindowWatchdog { public: static void handler(void); }; class cPvd { public: static void handler(void); }; class cTamperTimeStamp { public: static void handler(void); }; class cRtcWakeup { public: static void handler(void); }; class cFlash { public: static void handler(void); }; class cRcc { public: static void handler(void); }; class cExti { public: static void line0Handler(void); static void line1Handler(void); static void line2Handler(void); static void line3Handler(void); static void line4Handler(void); static void line9Handler(void); static void line15_10Handler(void); }; class cDma { public: static void channellHandler(void); static void channel2Handler(void); static void channel3Handler(void); static void channel4Handler(void); static void channel5Handler(void); static void channel6Handler(void); static void channel7Handler(void); }; class cAdc { public: static void handler(void); }; class cDac { public: static void handler(void); }; class cUsb { public: static void highPriorityHandler(void); static void lowPriorityHandler(void); static void fsWakeupHandler(void); }; class cComp { public: static void handler(void); }; class cLcdDriver { public: static void handler(void); }; class cTim9 { public: static void handler(void); }; class cTim2 { public: static void handler(void); }; class cTim3 { public: static void handler(void); }; class cTim4 { public: static void handler(void); }; class cTim10 { public: static void handler(void); }; class cTim6 { public: static void handler(void); }; class cTim7 { public: static void handler(void); }; class cTim11 { public: static void handler(void); }; class cI2C1 { public: static void eventHandler(void); static void errorHandler(void); }; class cI2C2 { public: static void eventHandler(void); static void errorHandler(void); }; class cSpi1 { public: static void handler(void); }; class cSpi2 { public: static void handler(void); }; class cUart1 { public: static void handler(void); }; class cUart2 { public: static void handler(void); }; class cUart3 { public: static void handler(void); }; class cRtcAlarm { public: static void handler(void); }; typedef void( *intfunc )( void ); typedef union { intfunc __fun; void * __ptr; } intvec_elem; // The vector table is normally located at address 0. // When debugging in RAM, it can be located in RAM, aligned to at least 2^6. // If you need to define interrupt service routines, // make a copy of this file and include it in your project. // The name "__vector_table" has special meaning for C-SPY: // it is where the SP start value is found, and the NVIC vector // table register (VTOR) is initialized to this address if != 0. #pragma location = ".intvec" extern "C" const intvec_elem __vector_table[] = { { .__ptr = __sfe( "CSTACK" ) }, __iar_program_start, cNMI::handler, cHardFault::handler, cMemManage::handler, cBusFault::handler, cUsageFault::handler, 0, 0, 0, 0, vPortSVCHandler, // freeRTOS ! cDebugMon::handler, 0, xPortPendSVHandler, // freeRTOS ! xPortSysTickHandler, // freeRTOS ! //External Interrupts cWindowWatchdog::handler, //Window Watchdog cPvd::handler, //PVD through EXTI Line detect cTamperTimeStamp::handler, //Tamper and Time Stamp cRtcWakeup::handler, //RTC Wakeup cFlash::handler, //FLASH cRcc::handler, //RCC cExti::line0Handler, //EXTI Line 0 cExti::line1Handler, //EXTI Line 1 cExti::line2Handler, //EXTI Line 2 cExti::line3Handler, //EXTI Line 3 cExti::line4Handler, //EXTI Line 4 cDma::channellHandler, //DMA1 Channel 1 cDma::channel2Handler, //DMA1 Channel 2 cDma::channel3Handler, //DMA1 Channel 3 cDma::channel4Handler, //DMA1 Channel 4 cDma::channel5Handler, //DMA1 Channel 5 cDma::channel6Handler, //DMA1 Channel 6 cDma::channel7Handler, //DMA1 Channel 7 cAdc::handler, //ADC1 cUsb::highPriorityHandler, //USB High Priority cUsb::lowPriorityHandler, //USB Low Priority cDac::handler, //DAC cComp::handler, //COMP through EXTI Line cExti::line9Handler, //EXTI Line 9..5 cLcdDriver::handler, //LCD cTim9::handler, //TIM9 cTim10::handler, //TIM10 cTim11::handler, //TIM11 cTim2::handler, //TIM2 cTim3::handler, //TIM3 cTim4::handler, //TIM4 cI2C1::eventHandler, //I2C1 Event cI2C1::errorHandler, //I2C1 Error cI2C2::eventHandler, //I2C2 Event cI2C2::errorHandler, //I2C2 Error cSpi1::handler, //SPI1 cSpi2::handler, //SPI2 cUart1::handler, //USART1 cUart2::handler, //USART2 cUart3::handler, //USART3 cExti::line15_10Handler, //EXTI Line 15..10 cRtcAlarm::handler, //RTC Alarm through EXTI Line cUsb::fsWakeupHandler, //USB FS Wakeup from suspend cTim6::handler, //TIM6 cTim7::handler //TIM7 }; __weak void cNMI::handler() { while (1) {} } __weak void cHardFault::handler() { while (1) {} } __weak void cMemManage::handler() { while (1) {} } __weak void cBusFault::handler() { while (1) {} } __weak void cUsageFault::handler() { while (1) {} } __weak void cDebugMon::handler() { while (1) {} } __weak void cWindowWatchdog::handler() { while (1) {} } __weak void cPvd::handler() { while (1) {} } __weak void cTamperTimeStamp::handler() { while (1) {} } __weak void cRtcWakeup::handler() { while (1) {} } __weak void cFlash::handler() { while (1) {} } __weak void cRcc::handler() { while (1) {} } __weak void cExti::line0Handler() { while (1) {} } __weak void cExti::line1Handler() { while (1) {} } __weak void cExti::line2Handler() { while (1) {} } __weak void cExti::line3Handler() { while (1) {} } __weak void cExti::line4Handler() { while (1) {} } __weak void cExti::line9Handler() { while (1) {} } __weak void cExti::line15_10Handler() { while (1) {} } __weak void cDma::channellHandler() { while (1) {} } __weak void cDma::channel2Handler() { while (1) {} } __weak void cDma::channel3Handler() { while (1) {} } __weak void cDma::channel4Handler() { while (1) {} } __weak void cDma::channel5Handler() { while (1) {} } __weak void cDma::channel6Handler() { while (1) {} } __weak void cDma::channel7Handler() { while (1) {} } __weak void cAdc::handler() { while (1) {} } __weak void cUsb::fsWakeupHandler() { while (1) {} } __weak void cUsb::highPriorityHandler() { while (1) {} } __weak void cUsb::lowPriorityHandler() { while (1) {} } __weak void cDac::handler() { while (1) {} } __weak void cComp::handler() { while (1) {} } __weak void cLcdDriver::handler() { while (1) {} } __weak void cTim2::handler() { while (1) {} } __weak void cTim3::handler() { while (1) {} } __weak void cTim4::handler() { while (1) {} } __weak void cTim6::handler() { while (1) {} } __weak void cTim7::handler() { while (1) {} } __weak void cTim9::handler() { while (1) {} } __weak void cTim10::handler() { while (1) {} } __weak void cTim11::handler() { while (1) {} } __weak void cI2C1::errorHandler() { while (1) {} } __weak void cI2C1::eventHandler() { while (1) {} } __weak void cI2C2::errorHandler() { while (1) {} } __weak void cI2C2::eventHandler() { while (1) {} } __weak void cSpi1::handler() { while (1) {} } __weak void cSpi2::handler() { while (1) {} } __weak void cUart1::handler() { while (1) {} } __weak void cUart2::handler() { while (1) {} } __weak void cUart3::handler() { while (1) {} } __weak void cRtcAlarm::handler() { while (1) {} } extern "C" void __cmain( void ); extern "C" __weak void __iar_init_core( void ); extern "C" __weak void __iar_init_vfp( void ); #pragma required=__vector_table void __iar_program_start( void ) { __iar_init_core(); __iar_init_vfp(); __cmain(); }
DWART ã¡ãã»ãŒãžããã·ã³ã°ã®åä¿¡
ãããã£ãŠãäžæãæŽçããããšãåçŽãªãããã³ã«ã®ã¹ã¬ããã®å®è£ ãåŒãåããããšãã§ããŸãã Modbusã¯ããã«èœã¡ãŸãã-éåžžã«è€éã§ã¯ãããŸãã:)ã å§åã»ã³ãµãŒã枩床ã»ã³ãµãŒãæµéèšãªã©ã®ããã€ã¹ã®æ¥çãããã³ã«ã§ããHARTã¯çŽ æŽãããã§ãã
ãããŠãç§ãèªåã§èšå®ããã¿ã¹ã¯ã¯ããã®ãããã³ã«ãä»ããŠã PactwareãElemerovkim HARTConfigãªã©ã®ããã€ã¹ãã»ããã¢ããããããã®ããã°ã©ã ãšéä¿¡ããããšã§ãã ç§ã¯ãã¹ãŠãå€æãããšèšããªããã°ãªããªã:)
ããã«ããã€ã¯ãã³ã³ãããŒã©ãŒã®å éšæž©åºŠã»ã³ãµãŒã«ãã£ãŠæž¬å®ãããæ°æž©ã®åŸåãé€å»ããããšããã§ããŸããã
ãããŠãããã¯ç§ã®Pactwareããã€ã¹ãèŠãŸã:)
HARTããã¥ã¡ã³ãã¯ãã¡ã³ããŒã®ã¿ãå©çšã§ããŸãã ãããããã¢ãããžã§ã¯ãã«éåžžã«é©ããæççãªèª¬æãèŠã€ããããšãã§ããŸããã ãããã®ãªãœãŒã¹ã®1ã€ã®äŸã次ã«ç€ºããŸããHARTãããã³ã«ã®èª¬æãŸãã¯OSI HARTãããã³ã«ã¢ãã«
èŠããã«ãã©ã€ã³äžã«ãã¹ã¿ãŒïŒã¡ã€ã³ïŒããã€ã¹ãšã¹ã¬ãŒãïŒåŸå±ïŒããã€ã¹ããããŸãã ã¡ã€ã³ã¯ãªã¯ãšã¹ããéä¿¡ãããµããªãŒãã£ããŒãã¯æ¯ç§1200ãããã®é床ã§å¿çããŸãããã¹ãŠãã·ã³ãã«ã§ãã
åç·äžã«ã¯2ã€ã®ã¡ã€ã³ããã€ã¹ãååšããå¯èœæ§ããããŸããã1ã€ã®RS232ãã¹ã¿ãŒãšè©±ãã ãã§ãã
åãçç±ã§ããã¹ã®èª¿åãç¹ã«ç£èŠããå¿ èŠã¯ãªããããŒã¯ã³ãæã£ãŠãããšããšæã£ãŠããªããšããå€æããã®ã¯é£ãããšæããŸããç§ã®å Žåã調åå šäœã¯ããã ãã§ã-ããŒã¯ã³ããããŸãã æ¯ç§1200ãããã®é床ã§ã¯ãããã¯çŽ19ããªç§ã§ãã ã€ãŸã 19ããªç§ä»¥å ã«åä¿¡ãäžæãããªãå Žå-å°å ã¯åãå ¥ãããããšèŠãªãããããŒã¯ã³ã¯ç§ã®ãã®ã§ãããå¿çã§ããçŽ250ããªç§ä»¥å ã«å¿çãéå§ããå¿ èŠããããŸããããã§ãªãå ŽåãããŒã¯ã³ã¯åã³ãã¹ã¿ãŒã«è»¢éãããŸãã
äžè¬ã«ãç§ã¯ãã®ãããã³ã«ãDwartãšåŒã³ãŸãããããã¯ãDwarf-DwarfãDwarfãããã³HARTã®å ±çã§ãã
æåã«ãæäœãããšã³ãã£ãã£ãéžæããå¿ èŠããããŸãã
- ãªã³ã¯å±€ïŒ LinkLayer ïŒ-ã¡ãã»ãŒãžã®éåä¿¡ã ãã§ãªãããã¹ã¿ãŒããã®ãªã¯ãšã¹ãã®åä¿¡ã®çµäºã決å®ãã圹å²ãæ ããŸã
- 転éã®çµäºãå€æããããã®ã¿ã€ããŒïŒ LinkLayerTimer ïŒã¯19ããªç§ã®ã¿ã€ããŒã§ããã®åŸã¯ãã¹ã¿ãŒããã®èŠæ±ãåãå ¥ãããããšèŠãªãããŸãã ã¿ã€ããŒã¯åãã€ããåä¿¡ããåŸã«éå§ããå¿ èŠããããŸãã
- ãã¬ãŒã ïŒ ãã¬ãŒã ïŒ-ãã¬ãŒã HARTåºç»ã®åæãšåœ¢æãæ åœããŸã
- ã³ãã³ãïŒ Command ïŒ-å¥ã®ããŒã ã®å®è£ ãæ åœããŸã
- ã¡ã€ã³ã¯ã©ã¹èªäœïŒ Dwart ïŒ-圌ã¯ãã®ãã¹ãŠã®ããžãã¹ã管çããŸã
ããã±ãŒãã®ååã«æºæ ããããã«ãäžå±€ã®ã¯ã©ã¹ã¯äžã®å±€ã®ã¯ã©ã¹ãã€ãŸã ããšãã°ãã³ãã³ãã¯ãã¬ãŒã ã§ã®ã¿æ©èœãããã¬ãŒã ã¯ãªã³ã¯ã¬ã€ã€ãŒã§æ©èœããŸããããªã³ã¯ã¬ã€ã€ãŒã¯ã³ãã³ããšãã¬ãŒã ãããã³ã³ãã³ãã«é¢ãããã¬ãŒã ã«ã€ããŠã¯äœãç¥ããŸããã
ã€ãŸããæ²é»ã¿ã€ããŒãæ©èœãããŸã§ãã€ããåãå ¥ããåä¿¡ããã¡ãã»ãŒãžã®è§£æã¡ãœãããåŒã³åºããèŠæ±ã«å¿ããŠå¿ èŠãªã³ãã³ããå®è¡ããDwartã«éç¥ãããšããèãæ¹ã§ãã
äžè¬çã«ãçæ³çã«ã¯ããã¹ã¿ãŒã«ã³ãã³ã1ãèŠæ±ãããšãã«ããã®çãã次ã®ããã«ããããšããŸãã
Command1.Response.PrimaryVariable = 3.54 Command1.Send();
ãŸãããã£ãã«ã¬ãã«ãæšå®ããŸãããããã®å³ã¯ãç»åãè©°ãŸãããªãããã«ãããªãã¯ã¡ãœããã®ã¿ã瀺ããŠããŸãã
å°ã説æãããšãå²ã蟌ã¿ãã³ãã©ãŒã®ã¡ãœããã¯éçã§ããããããã®éçã¡ãœããã§ã¯ã©ã¹ã€ã³ã¹ã¿ã³ã¹ã®ã¡ãœãããšãã£ãŒã«ãã«ã¢ã¯ã»ã¹ããã«ã¯ããã£ãŒã«ããšã¡ãœãããéçã§ããããã¯ã©ã¹ã€ã³ã¹ã¿ã³ã¹ã«çŽæ¥ã¢ã¯ã»ã¹ããå¿ èŠããããŸãã ç§ã¯2çªç®ã«è¡ããŸãã-æ£ããæ¹æ³ã§ãã¯ã©ã¹ã®ç¹å®ã®ã€ã³ã¹ã¿ã³ã¹ã«åãããã³ã³ã¹ãã©ã¯ã¿ã§thisãã€ã³ã¿ã§åæåããŸãã
LinkLayerã¯ãUARTããŒããããã€ããåä¿¡ããåä¿¡ãããã¡ãŒã«æ ŒçŽããŸãã
ãã ããHARTã«ã¯ããªã¢ã³ãã«ãšåŒã°ãã0xFFã®åæãã€ããããããã®æ°ã¯20ã«éããå¯èœæ§ããããŸãïŒèªåã§æ å ±ãéã°ãããã¬ãŒã ã®å é ãã·ãŒã±ã³ã¹ããšã«å€æããã ããªã®ã§ããŸã£ããå¿ èŠãããŸããïŒ 0xFF 0xFF <éå§ãã€ã>ïŒïŒããããã¡ãŒã«20åã®ããªã¢ã³ãã«ãããããããã®ã¯ç¡é§ãªã®ã§ãå²ã蟌ã¿ã§ããããçŽæ¥ç£èŠããçµäºãããããã«ãããã¡ãŒãžã®ãã€ãã®è¿œå ãéå§ããŸãã
åãã€ããåä¿¡ããåŸã19ããªç§éã¿ã€ããŒãåèµ·åããŸããåäœããå Žåãããã±ãŒãžã¯åãå ¥ãããããšèŠãªãããŸãã
å¥ã®ã¿ã¹ã¯ã¯ãã¿ã€ããŒå²ã蟌ã¿ãããªã¬ãŒããããšããã«linklayertimerã¯ã©ã¹ããlinklayerã«éç¥ãããŠã£ã¶ãŒãããã®ãªã¯ãšã¹ãã®çµäºã瀺ãããšã§ãã ãããè¡ãããã«ãObserverãã¶ã€ã³ãã¿ãŒã³ã䜿çšããŸããããã®çµæãLinkLayerã¯LinkLayerTimerããã®ã€ãã³ããåçŽã«ãµãã¹ã¯ã©ã€ãããŸãã次ã®ããã«ãªããŸãã
linklayertimer.h
#include "susutypes.h" #include "observable.h" class cLinkLayerTimer : public iObservable { public: explicit cLinkLayerTimer(tU16 timeout); void start(void) const; private: static void irqHandler(void); static cLinkLayerTimer* instance; };
linklayertimer.cpp
#include "linklayertimer.h" #include "susuassert.h" #include <stdio.h> cLinkLayerTimer* cLinkLayerTimer::instance = NULL; /******************************************************************************* * Function: constructor * Description: TIM2 ******************************************************************************/ cLinkLayerTimer::cLinkLayerTimer(tU16 timeout) { ASSERT(instance != NULL); this->instance = this; TIM2->ARR = (uint16_t)timeout; } /******************************************************************************* * Function: start * Description: . ******************************************************************************/ void cLinkLayerTimer::start(void) const { TIM2->CNT = (uint16_t)0; TIM2->CR1 |= TIM_CR1_CEN; } /******************************************************************************* * Function: irqHandler * Description: . * , ******************************************************************************/ void cLinkLayerTimer::irqHandler(void) { ASSERT(instance != NULL); instance->notifyObservers(); TIM2->CR1 &=~ TIM_CR1_CEN; TIM2->SR &= ~TIM_SR_UIF; }
linklayer.h
#include "susutypes.h" #include "linklayertimer.h" #include "observer.h" #define PREAMBUL_SYMBOL (uint16_t) 0xFF typedef enum { LLS_none = 0, LLS_write = 1, LLS_writeComplete = 2, LLS_readComplete = 3, LLS_error = 4 } tLinkLayerStatus; class cLinkLayer : private iObserver, public iObservable { public: explicit cLinkLayer(tU8 *pRxBuf, const tU8 rxBufSize,tU8 *pTxBuf, const tU8 preambulCount); void writeData(tU8 dataSize); tLinkLayerStatus getStatus() const { return eStatus; }; virtual void eventHandle(const iObservable* pObservable); tU8* pTxBuffer; tU8* pRxBuffer; private: static void irqHandler(void); static cLinkLayer* instance; void endMessageHandler(void); void enableReceive(void) const { USART2->CR1 |= USART_CR1_RXNEIE;}; void disableReceive(void){USART2->CR1 &=~ USART_CR1_RXNEIE;}; void enableTransmit(void) const { USART2->CR1 |= USART_CR1_TCIE; }; void disableTransmit(void) const { USART2->CR1 &=~ USART_CR1_TCIE; }; tLinkLayerStatus eStatus; cLinkLayerTimer* pEndTransmitTimer; tU8 rxBufferSize; tU8 rxBufferIndex; tU8 txBufferIndex; tU8 txBufferSize; tU8 preambulsCount; tU8 preambulIndex; tBoolean readPreambuls; };
linllayer.cpp
#include <stm32l1xx.h> #include "linklayer.h" #include "susuassert.h" #include <stdio.h> #define END_MESSAGE_TIMEOUT (tU16) 19 #define GOOD_COUNT_RX_PREAMBULS (tU8) 2 cLinkLayer* cLinkLayer::instance = NULL; /******************************************************************************* * Function: constructor * Description: ******************************************************************************/ cLinkLayer::cLinkLayer(tU8 *pRxBuf, const tU8 rxBufSize,tU8 *pTxBuf, const tU8 preambulCount) { ASSERT (rxBuffer != NULL); ASSERT (txBuffer != NULL); // 3 ASSERT(preambulCount > (tU8)2); this->preambulsCount = preambulCount; this->preambulIndex = (tU8)0; this->readPreambuls = TRUE; this->pRxBuffer = pRxBuf; this->rxBufferSize = rxBufSize; this->rxBufferIndex = (tU8)0; this->pTxBuffer = pTxBuf; this->txBufferSize = (tU8)0; this->txBufferIndex = (tU8)0; this->eStatus = LLS_none; this->instance = this; this->pEndTransmitTimer = new cLinkLayerTimer(END_MESSAGE_TIMEOUT); // this->pEndTransmitTimer->addObserver(this); this->disableTransmit(); this->enableReceive(); } /******************************************************************************* * Function: writeData * Description: , ******************************************************************************/ void cLinkLayer::writeData(tU8 dataSize) { // , , // if (this->eStatus != LLS_write) { this->disableReceive(); this->txBufferSize = dataSize; this->eStatus = LLS_write; USART2->DR = PREAMBUL_SYMBOL; this->preambulIndex ++; this->enableTransmit(); } } /******************************************************************************* * Function: handler * Description: ******************************************************************************/ void cLinkLayer::irqHandler(void) { ASSERT(instance != NULL); // if (USART2->SR & USART_SR_TC) { // , 3 if (instance->preambulIndex != instance->preambulsCount) { USART2->DR = PREAMBUL_SYMBOL; instance->preambulIndex ++; } else { // - if(instance->txBufferIndex < instance->txBufferSize) { USART2->DR = (uint16_t)instance->pTxBuffer[instance->txBufferIndex++]; } else { instance->txBufferIndex = (tU8)0; instance->txBufferSize = (tU8)0; instance->disableTransmit(); instance->eStatus = LLS_writeComplete; instance->preambulIndex = (tU8)0; instance->readPreambuls = TRUE; instance->enableReceive(); } } USART2->SR &=~ USART_SR_TC; }; // if (USART2->SR & USART_SR_RXNE) { instance->pRxBuffer[instance->rxBufferIndex] = (tU8)USART2->DR; instance->pEndTransmitTimer->start(); // if (instance->readPreambuls) { if (instance->pRxBuffer[instance->rxBufferIndex] == (tU8)PREAMBUL_SYMBOL) { instance->preambulIndex++; } else { instance->readPreambuls = FALSE; instance->rxBufferIndex++; } } else { // 2 if ((instance->rxBufferIndex <= instance->rxBufferSize) && (instance->preambulIndex >= GOOD_COUNT_RX_PREAMBULS)) { instance->rxBufferIndex++; } else { instance->eStatus = LLS_error; instance->preambulIndex = (tU8)0; } } } } /******************************************************************************* * Function: endMessageHandler * Description: ******************************************************************************/ void cLinkLayer::endMessageHandler(void) { this->eStatus = LLS_readComplete; this->rxBufferIndex = (tU8) 0; this->readPreambuls = TRUE; instance->preambulIndex = (tU8)0; } /******************************************************************************* * Function: eventHandle * Description: ******************************************************************************/ void cLinkLayer::eventHandle(const iObservable* pObservable) { this->endMessageHandler(); this->notifyObservers(); }
LinkLayerèªäœãããµãã¹ã¯ã©ã€ããŒã®ãã¹ã¿ãŒããã®èŠæ±ã®åãå ¥ãã®çµäºãéç¥ããŸããããã¯åŸã§å¿ èŠã«ãªããŸã
DWART ããŒã ãã«ãã£ã³ã°
ä»ãæãèå³æ·±ãã®ã¯ããã§ã«è¿°ã¹ãããã«ããã¹ãŠãçŸããèŠããããã«ããããšããããŒã ã§ã
Command0.Response.PrimaryVariable = 3.54
åã³ãã³ãã«ã€ããŠãå¿çèŠæ±ã®æ§é å šäœãä¿åãã254åã®ã³ãã³ããããå Žåãååãªã¡ã¢ãªããªããããå¿çèŠæ±ã®æ§é ãžã®ãã€ã³ã¿ã®ã¿ãä¿åãããã®ãã€ã³ã¿ã«ããŒã¿ãžã®ãã€ã³ã¿ãå²ãåœãŠãããšã¯æããã§ãã cFrameã¯ã©ã¹ã®buildFrameBeforeDataã¡ãœããã䜿çšããŠååŸãã転éãããã¡ãŒã§ã
ãã¹ãŠã®ããŒã ã«ã€ããŠãå ±éã®ã¡ãœããã䜿çšããŠåºæ¬çãªiBaseDwartCommandã€ã³ã¿ãŒãã§ãŒã¹ãäœæããŸããé·ããšçš®é¡ãç°ãªãåããŒã ã«ãªã¯ãšã¹ããšåçããããããiDwartCommandãç¶æ¿ãããã³ãã¬ãŒãã¯ã©ã¹ãäœæããŸãã 次ã®ããã«ãªããŸãã
ã³ãã³ã0-ããã€ã¹ã«é¢ããæ å ±ã®ã¿ãè¿ããŸãã
ã³ãã³ã1-ãã©ã€ããªå€æ°ã®å€ãè¿ããŸããç§ã®å Žåã¯cVariablesã¯ã©ã¹ã«ãã£ãŠã¢ã¯ã»ã¹ãããTrimmerã䜿çšããŠãããããã³ã³ã¹ãã©ã¯ã¿ãŒã«æž¡ãå¿ èŠããããŸãã
ãã®çµæãã³ãã³ã1ããã®ããŒã¿ã®å ¥åã¯æ¬¡ã®ããã«ãªããŸãã
void cCommand1::setNewData(void) { // this->pResponse = (tCommand1Response*) this->pFrame->buildFrameBeforeData(COMMAND1, (tU8)sizeof(tCommand1Response)); this->pResponse->status1 = (tU8)0; this->pResponse->status2 = (tU8)0; this->pResponse->PrimaryVariableUnits = (tU8) pVariables->pTrimmer->getUnits(); this->pResponse->PrimaryVariableValue = std::swap<tF32>(pVariables->pTrimmer->getValue()); this->pFrame->setCheckSumm(); }
HARTã¯ããã°ãšã³ãã£ã¢ã³è¡šçŸã䜿çšããŠããããã€ã¯ãã³ã³ãããŒã©ãŒã¯ãªãã«ãšã³ãã£ã¢ã³ã§ãããããããã§ã¯cConversionã¯ã©ã¹ã¹ã¯ããã¡ãœããã䜿çšããŠãã€ããæå®ã®å Žæã«ã¹ã¯ããããŸãã ãŸããããã¯ç§ã欲ããã£ãããšãã»ãšãã©ããã£ã:)
å®è£ å šäœã¯æ¬¡ã®ããã«ãªããŸãã
basedwartcommand.h
class iBaseDwartCommand { public: virtual void send(void) = 0; virtual void setNewData(void) = 0; };
dwartcommand.h
#include "frame.h" #include "basecommand.h" #include "susuassert.h" template <class req, class resp> class iDwartCommand : public iBaseDwartCommand { public: explicit iDwartCommand(cFrame *pDwratFrame); req *pRequest; resp *pResponse; void send(void); protected: cFrame *pFrame; }; /******************************************************************************* * Function: constructor * Description: ******************************************************************************/ template <class req, class resp> iDwartCommand<req, resp>::iDwartCommand(cFrame *pDwartFrame) { ASSERT (pFrame != NULL); this->pFrame = pDwartFrame; } /******************************************************************************* * Function: send * Description: ******************************************************************************/ template <class req, class resp> void iDwartCommand<req, resp>::send(void) { this->pFrame->send(); }
command0.h
#include "command.h" #define COMMAND0 (tU8)0 #pragma pack(push, 1) typedef struct { tU8 status1; tU8 status2; tU8 expansion; tU8 manufacturer; tU8 deviceType; tU8 numberOfpreambuls; tU8 universalCommandRevision; tU8 deviceSpecificCommandRevision; tU8 softwareRevision; tU8 hardwareRevision; tU8 deviceFlags; tU8 deviceID[3]; } tCommand0Response; typedef struct { } tCommand0Request; #pragma pack(pop) class cCommand0: public iDwartCommand<tCommand0Request, tCommand0Response> { public: explicit cCommand0(cFrame *pDwartFrame); virtual void setNewData(void); };
command0.cpp
include "susuassert.h" #include "command0.h" #include "frame.h" /******************************************************************************* * Function: constructor * Description: ******************************************************************************/ cCommand0::cCommand0(cFrame *pDwartFrame): iDwartCommand(pDwartFrame) { } /******************************************************************************* * Function: setNewData * Description: ******************************************************************************/ void cCommand0::setNewData(void) { // this->pResponse = (tCommand0Response*) this->pFrame->buildFrameBeforeData(COMMAND0, (tU8)sizeof(tCommand0Response)); this->pResponse->status1 = (tU8)0; this->pResponse->status2 = (tU8)0; this->pResponse->manufacturer = (tU8)0x37; this->pResponse->deviceType = (tU8)0x04; this->pResponse->expansion = (tU8)0; this->pResponse->deviceSpecificCommandRevision = (tU8)5; this->pResponse->universalCommandRevision = (tU8)5; this->pResponse->hardwareRevision = (tU8)1; this->pResponse->softwareRevision = (tU8)201; this->pResponse->numberOfpreambuls = (tU8)5; this->pResponse->deviceID[0] = (tU8)0; this->pResponse->deviceID[1] = (tU8)0; this->pResponse->deviceID[2] = (tU8)1; this->pResponse->deviceFlags = (tU8)0; this->pFrame->setCheckSumm(); }
command1.h
#include "command.h" #include "vars.h" #define COMMAND1 (tU8)1 #pragma pack(push, 1) typedef struct { tU8 status1; tU8 status2; tU8 PrimaryVariableUnits; tF32 PrimaryVariableValue; } tCommand1Response; typedef struct { } tCommand1Request; #pragma pack(pop) class cCommand1: public iDwartCommand<tCommand1Request, tCommand1Response> { public: explicit cCommand1(cFrame *pDwartFrame,Variablesr *Vars); virtual void setNewData(void); private: Variables *pVariables; };
command1.cpp
#include "susuassert.h" #include "command1.h" #include "frame.h" /******************************************************************************* * Function: constructor * Description: ******************************************************************************/ cCommand1::cCommand1(cFrame *pDwartFrame, Variables *pVars): iDwartCommand(pDwartFrame) { ASSERT(pVars != NULL); this->pVariables = pVars; } /******************************************************************************* * Function: setNewData * Description: ******************************************************************************/ void cCommand1::setNewData(void) { // this->pResponse = (tCommand1Response*) this->pFrame->buildFrameBeforeData(COMMAND1, (tU8)sizeof(tCommand1Response)); this->pResponse->status1 = (tU8)0; this->pResponse->status2 = (tU8)0; this->pResponse->PrimaryVariableUnits = (tU8) pVariables->pTrimmer->getUnits(); this->pResponse->PrimaryVariableValue = std::swap<tF32>(pVariables->pTrimmer->getValue()); this->pFrame->setCheckSumm(); }
ä»ã®ããŒã ãåãååã«åºã¥ããŠæ§ç¯ãããŠããŸããç§ã¯å€§éã®ã¡ã¢ãªãæã£ãŠããã®ã§ããã¹ãŠã®ã³ãã³ããããã°ãããšå€æããæ倧254åã®ã³ãã³ãã1ã€ã®é åã«æããããšãã§ããŸãããããŠããªãããã䟿å©ãªã®ãã説æããŸããcCommandSetã³ã³ããã¯ã©ã¹ãäœæããŸããã
#include "command.h" #include "variables.h" #define COMMANDS_COUNT 254 class cCommandSet { public: cCommandSet(cFrame *pFrame, Variables *pVariables); iBaseDwartCommand *pCommands[COMMANDS_COUNT]; };
PactwareãšHartConfigã®2ã€ã®ããã°ã©ã ã暪河ã«é£ããŠè¡ãã«ã¯ãæå°éã®ã³ãã³ãã»ãããå®è£ ããããããã³ã³ãããŒã«å ¥ããå¿ èŠããããŸãã
commandset.cppã¯æ¬¡ã®ããã«ãªããŸãã
#include "susuassert.h" #include "commandset.h" #include "command0.h" #include "command1.h" #include "command2.h" #include "command3.h" #include "command12.h" #include "command13.h" #include "command14.h" #include "command15.h" #include "command157.h" #include "command159.h" #include "command160.h" #include "command180.h" cCommandSet::cCommandSet(cFrame *pFrame, cVariables *pVariables) { this->pCommands[COMMAND0] = new cCommand0(pFrame); this->pCommands[COMMAND1] = new cCommand1(pFrame, pVariables); this->pCommands[COMMAND2] = new cCommand2(pFrame, pVariables); this->pCommands[COMMAND3] = new cCommand3(pFrame, pVariables); this->pCommands[COMMAND13] = new cCommand13(pFrame); this->pCommands[COMMAND12] = new cCommand12(pFrame); this->pCommands[COMMAND14] = new cCommand14(pFrame); this->pCommands[COMMAND15] = new cCommand15(pFrame, pVariables); this->pCommands[COMMAND160] = new cCommand160(pFrame); this->pCommands[COMMAND157] = new cCommand157(pFrame); this->pCommands[COMMAND159] = new cCommand159(pFrame); this->pCommands[COMMAND180] = new cCommand180(pFrame); }
é åå šäœãåæåãããŠããªããããããã«ãšã©ãŒããããŸãããç§ã¯ããããã³ããŒã§å©ãã®ãé¢åã§ãã:)ãšã©ãŒãããããšãå¿ã«çããŠãããŠãã ããã
ããŒã 157ã159ãããã³160ãäœãããã®ãããããŸããïŒããšãã°ããããŒãèšç®ããããã«ãå§åå€æ°ã«åºã¥ããŠèšç®ããããŠãŒã¶ãŒå€æ°ããããšä»®å®ããŠããŸãïŒãåãã®ããã«ããããŒã¯ã«ãŒãæœåºé¢æ°ã§ãããããå·®å§ããŸãã¯å§åå·®ã«äŸåããã¬ãã«ãèšç®ããããã«èšãïŒïŒãããããç§ã¯ããããããçš®ã®ããªã€ãŒãã§æºãããã ãã§ãããã°ã©ã ã¯ããã飲ã¿èŸŒã¿ãŸããã
ã³ãã³ãã®é åãäœæãããšããäºå®ã«ãããã³ãã³ãã®åŒã³åºãã¯éåžžã«ãšã¬ã¬ã³ãã«èŠããŸã-ãã®ããã«
pCommandSet->pCommands[this->pFrame->getCurrentCommand()]->setNewData(); pCommandSet->pCommands[this->pFrame->getCurrentCommand()]->send();
ã芧ã®ãšãããã¹ã€ããã±ãŒã¹ã¯å¿ èŠãããŸãããããå°ãã®ã¡ã¢ãªããå¿ èŠã§ã:)
DWART å®äº
æ®ã£ãŠããã®ã¯ããã¹ã¿ãŒããåä¿¡ãããªã¯ãšã¹ãã解æããã¢ã¯ãã£ããªã¯ã©ã¹ãäœæããããšã ãã§ãã
åã«èšã£ãããã«ããã®ã¯ã©ã¹ã¯cLinkLayerããã®åä¿¡çµäºã®ã€ãã³ãã«ãµãã¹ã¯ã©ã€ããã
ãã®ã€ãã³ãã®ãã³ãã©ãŒã¯ã¿ã€ããŒå²ã蟌ã¿ããåŒã³åºãããããã«äœããããŠçµäºããå¿ èŠãããã®ã§ãåŠçã®ããã«ãŠã£ã¶ãŒãããã®èŠæ±ã®ããã¯ã¹ããã§ãã¯ããã ãã§ãã¢ã¯ãã£ããªã¿ã¹ã¯ã§ãã®ãã©ã°ãããŒãªã³ã°ããŸããããã§ããã°ãcFrameã䜿çšããŠã¡ãã»ãŒãžããã³ãŒããããã¹ãŠãããŸããã£ãå Žåãå¿ èŠãªã³ãã³ããåŒã³åºããŠéä¿¡ããŸãã
åãã¯ã©ã¹ãcFrameãcLinkLayerããã³CommandSetãã€ã³ã¹ã¿ã³ã¹åããcLinkLayerã«åä¿¡ããã³éä¿¡ãããã¡ãŒãžã®ãã€ã³ã¿ãŒãæž¡ããŸãããããŠãç§ã®äœæ¥ã¯èŠæ±/å¿çã¢ãŒãã§è¡ããããããéä¿¡ãšåä¿¡ã®äž¡æ¹ã«1ã€ã®ãããã¡ãŒããããåæã«ã¡ã¢ãªãŒãç¯çŽããŸãã
dwart.h
#include "susutypes.h" #include "frame.h" #include "observer.h" #include "linklayer.h" #include "variables.h" #include "commandset.h" #include "frtosWrapper.h" #define MAX_BUFFER_SIZE (tU8)255 class cDwart: private iObserver, public iActiveObject { public: cDwart(Variables *pVariables); virtual void eventHandle(const iObservable* pObservable); virtual void run(void); private: cCommandSet *pCommandSet; cLinkLayer *pLinkLayer; cFrame *pFrame; tU8 buffer[MAX_BUFFER_SIZE]; tBoolean isToken; static const tU8 deviceID[5]; };
dwart.cpp
#include "susuassert.h" #include "frame.h" #include <stddef.h> #include "dwart.h" #define SHORT_ADDR (tU8)0 #define PREAMBULS_COUNT (tU8)7 #define DWART_WAITING (tU32) (50/portTICK_PERIOD_MS) const tU8 cDwart::deviceID[5] = {(tU8)0x37,(tU8)0x04,(tU8)0x00,(tU8)0x00,(tU8)0x01}; /******************************************************************************* * Function: constructor * Description: cLinkLayer, cFrame cCommandSet * ******************************************************************************/ cDwart::cDwart(Variables *pVariables) { this->pLinkLayer = new cLinkLayer(this->buffer,MAX_BUFFER_SIZE, this->buffer, PREAMBULS_COUNT); this->pFrame = new cFrame((tU8*)deviceID, SHORT_ADDR,this->pLinkLayer); this->pCommandSet = new cCommandSet(this->pFrame, pVariables); this->pLinkLayer->addObserver(this); this->isToken = FALSE; } /******************************************************************************* * Function: eventHandle * Description: . ******************************************************************************/ void cDwart::eventHandle(const iObservable* pObservable) { ASSERT(pObservable != NULL); this->isToken = TRUE; } /******************************************************************************* * Function: run * Description: ******************************************************************************/ void cDwart::run(void) { for(;;) { if (this->isToken) { this->isToken = FALSE; if (this->pFrame->decode() == FE_good) { pCommandSet->pCommands[this->pFrame->getCurrentCommand()]->setNewData(); pCommandSet->pCommands[this->pFrame->getCurrentCommand()]->send(); } } oRTOS.taskDelay(DWART_WAITING); } }
main.cppã«æ°ããcDwartã¯ã©ã¹ã®äœæãè¿œå ããæ€èšŒã®ããã«å®è¡ããŸã
void main( void ) { const cAdcDirector* pAdcDirector = new cAdcDirector(); pAdcDirector->startConversion(); cVariables *pVariables = new cVariables(pAdcDirector); oRTOS.taskCreate(pVariablesDirector, VARIABLESDIRECTOR_STACK_SIZE, VARIABLESDIRECTOR_PRIORITY, "Var"); cDwart *pDwart = new cDwart(pVariablesDirector); oRTOS.taskCreate(pDwart, DWART_STACK_SIZE, DWART_PRIORITY, "Dwart"); ... oRTOS.startScheduler(); }
ãããŠããã§ã¯ããã¯ããŠã§ã¢ãšåŒã°ãããã€ãã®å¥è·¡ãæ¥æ¬ã®å§åã»ã³ãµãŒãèŠãŠããŸãã
ãŸããåœç€Ÿã®åœå ãœãããŠã§ã¢ãã»ã³ãµãŒãç解ããŠããŸãã
ãã¡ãããããã§ã¯å€ãã®ããšãããŸãæé©ã«è¡ãããŠããŸãããããšãã°ãã³ãã³ããžã®255ãã€ã³ã¿ãŒã®é åããããåé€ããéåžžã®ã¹ã€ããã±ãŒã¹ãä»ããŠã³ãã³ããå®è¡ã§ããŸãããŸãããã¹ãŠã®ã³ãã³ãã«å¯ŸããŠ1ã€ã®ãã¬ãŒã¹ãã«ããŒã䜿çšã§ããŸããç®çã®ã³ãã³ããäœæããŠããåé€ããŸãã
ããããç§ã®å Žåãç§ã®èšæ¶ã¯æž¬å®ãããŠããããæé©åã®åé¡ã¯ãããŸããã§ããã