#include "system.h" #include "usart.h" static Usart * pInstance = nullptr; static constexpr unsigned HCLK = SYSTEM_CORE_CLOCK; extern "C" void USART1_IRQHandler (void) __attribute__((interrupt)); void USART1_IRQHandler (void) { if (pInstance) pInstance->irq(); }; Usart::Usart(const uint32_t _baud) noexcept : BaseLayer (), tx_ring () { pInstance = this; // 1. Clock Enable RCC.APB2PCENR.modify([](RCC_Type::APB2PCENR_DEF & r) -> auto { r.B.USART1EN = SET; r.B.IOPAEN = SET; //r.B.AFIOEN = SET; return r.R; }); // 2. GPIO Alternate Config - default TX/PA9, RX/PA10 GPIOA.CFGHR.modify([](GPIOA_Type::CFGHR_DEF & r) -> auto { r.B.MODE9 = 1u; r.B.CNF9 = 2u; // or 3u for open drain r.B.MODE10 = 0u; r.B.CNF10 = 1u; // floating input return r.R; }); RCC.APB2PRSTR.B.USART1RST = SET; RCC.APB2PRSTR.B.USART1RST = RESET; // 5. USART registry 8.bit bez parity USART1.CTLR1.modify([] (USART1_Type::CTLR1_DEF & r) -> auto { r.B.RE = SET; r.B.TE = SET; r.B.RXNEIE = SET; return r.R; }); USART1.CTLR2.modify ([](USART1_Type::CTLR2_DEF & r) -> auto { r.B.STOP = 0u; return r.R; }); const uint32_t tmp = HCLK / _baud; USART1.BRR.R = tmp; // NVIC NVIC.EnableIRQ (USART1_IRQn); USART1.CTLR1.B.UE = SET; // nakonec povolit globálně } void Usart::irq () { volatile USART1_Type::STATR_DEF status (USART1.STATR); // načti status přerušení char rdata, tdata; if (status.B.TXE) { // od vysílače if (tx_ring.Read (tdata)) { // pokud máme data USART1.DATAR.B.DR = (uint8_t) tdata; // zapíšeme do výstupu } else { // pokud ne // Předpoklad je half-duplex i.e. RS485, jinak jen zakázat TXEIE rdata = (USART1.DATAR.B.DR); // dummy read USART1.CTLR1.modify([](USART1_Type::CTLR1_DEF & r) -> auto { r.B.RE = SET; // povol prijem r.B.TXEIE = RESET; // je nutné zakázat přerušení od vysílače return r.R; }); } } if (status.B.RXNE) { // od přijímače rdata = (USART1.DATAR.B.DR); // načteme data Up (&rdata, 1u); // a pošleme dál } } uint32_t Usart::Down(const char * data, const uint32_t len) { unsigned n = 0u; for (n=0u; n auto { r.B.RE = RESET; r.B.TXEIE = SET; // po povolení přerušení okamžitě přeruší return r.R; }); return n; } void Usart::SetRS485 (const bool polarity) const { } void Usart::SetHalfDuplex (const bool on) const { }