2020-09-17 11:12 PM
Dear community,
after solving some issues with the help of the community, I am stuck on the next problem. I really don't know why my UART, which seems to be initialized correctly, does not shift out my data for transmission.
After initializing my USART2, the TC and TXE (USART SR register) flags are immediately set, as I personally expect. But when I write data to the data register for transmission, I would expect the TXE and TC flag to be reset, and after a few more cycles (depending on my baudrate) my TXE and TC flag should be set again, after transmission is done and hence both registers are empty again. But that simply does not happen. I also do not measure anything on the corresponding pins. Here is my code:
void initIrda(void)
{
if (!isIrdaInitialized())
{
write_data_ptr = 0;
transmit_data_ptr = 0;
received_data_ptr = 0;
read_data_ptr = 0;
GPIOA->AFR[0] |= (0b0111 << GPIO_AFRL_AFSEL2_Pos); // Alternate function AF7 for PA2 and PA3
GPIOA->AFR[0] |= (0b0111 << GPIO_AFRL_AFSEL3_Pos);
startIrda();
NVIC_EnableIRQ(USART2_IRQn); // Enable USART2 interrupt (CMSIS command)
USART2->CR3 |= (1 << USART_CR3_IREN_Pos); // IrDA mode enable
USART2->CR1 //|= (1 << USART_CR1_TXEIE_Pos) // Enable TX-Interrupts
//| (1 << USART_CR1_TCIE_Pos) // Enable Transmission Complete Interrupts
|= (1 << USART_CR1_PEIE_Pos) // Enable Interrupts for parity errors
| (1 << USART_CR1_IDLEIE_Pos) // Enable Interrupt when idle line is detected
| (1 << USART_CR1_RXNEIE_Pos) // Enable RX-Interrupts
| (1 << USART_CR1_TE_Pos) // Enable Transmitter
| (1 << USART_CR1_RE_Pos); // Enable Receiver
USART2->CR1 |= (1 << USART_CR1_UE_Pos); // enable UART
USART2->CR1 &= ~(1 << USART_CR1_M_Pos); // 1 Start bit, 8 Data bits, n Stop bit
USART2->CR2 &= ~(0b11 << USART_CR2_STOP_Pos); // 1 Stop bit
USART2->BRR = 0x045; // Baudrate 115200 (see documentation how this value was calculated)
irda_status.initialized = 1;
}
}
void startIrda(void)
{
RCC->APB1ENR |= (1 << RCC_APB1ENR_USART2EN_Pos); // turn clock on for usart2 periphery
irda_status.running = 1;
}
void irda_tick(void)
{
while (transmit_data_ptr != write_data_ptr && isTXempty())
{
USART2->CR1 |= (1 << USART_CR1_TE_Pos); // send an idle frame
USART2->DR = tx_buffer[transmit_data_ptr];
transmit_data_ptr = (transmit_data_ptr + 1) & (BUFFER_SIZE - 1);
while(!((USART2->SR & USART_SR_TC_Msk) == USART_SR_TC)) {}; // wait for transmission to finish
}
}
static uint8_t isTXempty(void)
{
return (READ_BIT(USART2->SR, USART_SR_TXE) == USART_SR_TXE);
}
void irda_write(const char* arr_ptr, size_t size)
{
size_t i = 0;
for (i = 0; i < size; i++)
{
tx_buffer[write_data_ptr] = *(arr_ptr + i);
write_data_ptr = (write_data_ptr + 1) & (BUFFER_SIZE - 1);
}
}
Any help would be appreciated, I am really in desperation. Thank you.
2020-09-18 06:21 AM
> write_data_ptr = (write_data_ptr + 1) & (BUFFER_SIZE - 1);
This is odd. Maybe it'll work if BUFFER_SIZE is a power of 2. If you're trying to wrap around a circular buffer, "... % BUFFER_SIZE" would be better.
Edit: I don't see any issues in the code you posted, but you didn't include everything relevant. initIrda is never called in what you posted, as well as other functions.