#include "STM32F0x1.h" #include "CortexM0.h" // NVIC_EnableIRQ #include "gpio.h" #include "usart.h" extern "C" uint32_t SystemCoreClock; static Usart * Instance = nullptr; void Usart::irq (void) { volatile USART1_Type::ISR_DEF status (USART1.ISR); // načti status přerušení char tdata; volatile char rdata; if (status.B.TC) { // od vysílače if (tx_ring.Read (tdata)) { // pokud máme data USART1.TDR.R = (uint32_t) tdata & 0xFFu;// zapíšeme do výstupu } else { // pokud ne //USART1.CR1.B.RE = SET; // povol prijem USART1.CR1.B.TCIE = RESET; // je nutné zakázat přerušení od vysílače } } if (status.B.RXNE) { // od přijímače rdata = (USART1.RDR.R) & 0xFFu; // načteme data (void) rdata; // zahodime } } /// Voláno z čistého C - startup.c extern "C" void USART1_IRQHandler (void) { if (Instance) Instance->irq(); }; //! [MembersConstructorExample] Usart::Usart(const uint32_t baud) noexcept : BaseLayer(), tx_ring() { //! [MembersConstructorExample] if (Instance) return; // Chyba - jedina instance Instance = this; // 1. Clock Enable RCC.APB2ENR.B.USART1EN = SET; // 2. GPIO Alternate Config GpioClass txp (GpioPortA, 9, GPIO_Mode_AF); GpioClass rxp (GpioPortA, 10, GPIO_Mode_AF); txp.setAF (1); rxp.setAF (1); // 4. NVIC NVIC_EnableIRQ (USART1_IRQn); uint32_t tmp = 0; // 5. USART registry 8.bit bez parity USART1.CR1.modify([] (USART1_Type::CR1_DEF & r) -> uint32_t { // pro ilustraci, co by bylo auto r.B.TE = SET; //r.B.RE = SET; // příjem je zde zbytečný //r.B.RXNEIE = SET; return r.R; }); USART1.CR2.R = 0; USART1.CR3.B.OVRDIS = SET; // Tuhle část už vezmeme přímo z knihovny, jen ty hodiny zjednodušíme na SystemCoreClock uint32_t apbclock = SystemCoreClock; uint32_t integerdivider, fractionaldivider; /* Determine the integer part */ if (USART1.CR1.B.OVER8 != RESET) { /* Integer part computing in case Oversampling mode is 8 Samples */ integerdivider = ((25u * apbclock) / (2u * (baud))); } else { /* Integer part computing in case Oversampling mode is 16 Samples */ integerdivider = ((25u * apbclock) / (4u * (baud))); } tmp = (integerdivider / 100u) << 4; /* Determine the fractional part */ fractionaldivider = integerdivider - (100u * (tmp >> 4)); /* Implement the fractional part in the register */ if (USART1.CR1.B.OVER8 != RESET) { tmp |= ((((fractionaldivider * 8u ) + 50u) / 100u)) & ((uint8_t)0x07u); } else { tmp |= ((((fractionaldivider * 16u) + 50u) / 100u)) & ((uint8_t)0x0Fu); } /* Write to USART BRR */ USART1.BRR.R = (uint16_t)tmp; USART1.CR1.B.UE = SET; // nakonec povolit globálně } //! [VirtualMethodBottom] uint32_t Usart::Down (const char * data, const uint32_t len) { uint32_t res; // výsledek, musí žít i po ukončení smyčky for (res=0; res auto { r.B.DEAT = 1u; // doba vybavení před start bitem - 16 ~= 1 bit, 0..31 r.B.DEDT = 1u; // doba vybavení po stop bitu - 16 ~= 1 bit, 0..31 return r.R; }); //! [LambdaExampleUsage] USART1.CR1.B.UE = SET; } extern "C" { int terminate () { return 0; } };