2015-09-27 03:19 AM
Hi,
I began by creating some code polling the com port of the g-eval board in a transactional way - easily send a command at will, then in a non-blocking loop check to see if it has received command, compare command to take action. This I can expand and control easily.I know I haven't handled buffer overrun or buffer resets yet - but that is easy.Where I am stumped is in the conversion of this code from a while loop to uart interrupt fired IRQ handlers. In the code below, I have tried to move the code for receiving data only (not sending data) from the while loop into a UART interrupt handler, but it does not fire. If any flaw jumps out, I would be grateful if you could let me know as after two days, I can't seem to get it. I also discovered a bug in keil i think. If I switch into debugger mode, and click reset before the first run of the code, I somehow loose visibility of my debug variables for the rest of that session. I lost a lot of time before I relaised that. Anyone know the cause? #include ''stm32f2xx.h''#include ''stm322xg_eval.h''// #include <stdio.h>#include <stdint.h>#include <string.h> void USART_Config(void);void USART_PutString(char *s);uint16_t USART_GetChar(void);void NVIC_Configuration(void);int myflag = 0x00;int rxi=0;char str[] = ''Hello, World!\n'';char cmd[20];char ctest[20] = ''brk'';; int main(void){ NVIC_Configuration(); // Call USART1 configuration USART_Config(); // Send ''Hello, World!'' to PC USART_PutString(str); while (1) { } }void USART_Config(void){ GPIO_InitTypeDef GPIO_InitStruct; USART_InitTypeDef USART_InitStruct; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_USART3); GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_USART3); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOC, &GPIO_InitStruct); USART_InitStruct.USART_BaudRate = 9600; USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_InitStruct.USART_Parity = USART_Parity_No; USART_InitStruct.USART_StopBits = USART_StopBits_1; USART_InitStruct.USART_WordLength = USART_WordLength_8b; USART_Init(USART3, &USART_InitStruct); USART_Cmd(USART3, ENABLE); USART_ITConfig(USART3, USART_IT_RXNE | USART_IT_TXE, ENABLE);}void USART_PutChar(char c){ // Wait until transmit data register is empty while (!USART_GetFlagStatus(USART3, USART_FLAG_TXE)); // Send a char using USART1 USART_SendData(USART3, c);}void USART_PutString(char *s){ // Send a string while (*s) { USART_PutChar(*s++); }}uint16_t USART_GetChar(void){ // Wait until data is received while (!USART_GetFlagStatus(USART3, USART_FLAG_RXNE)); // Read received char return USART_ReceiveData(USART3);}void USART3_IRQHandler(void){if (USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) // Received characters modify string { uint16_t data = USART_GetChar(); if (data != 0x0D) { cmd[rxi]=data; rxi++; // If received char is 'H' then turn on orange LED if(strcmp(cmd, ctest) == 0) { myflag=0xfe; } } } } void NVIC_Configuration(void){ NVIC_InitTypeDef NVIC_InitStructure; /* Configure the NVIC Preemption Priority Bits */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); /* Enable the USART3 Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);}2015-09-27 08:35 AM
Don't enable the TXE interrupt, and make sure strings are NUL terminated when using the strxxx() functions.
2015-09-27 09:06 AM
Clive,
Thanks - that got rx interrupts working - although I don't understand why having Tx interrupts enabled stopped it from working...could you please explain? Another major thing i don't get is - why don't these types of ISR have to clear the bit like other examples such as TIMx bits- does the hardware do that automatically as a consequence of being read? The other thing I don't understand about Tx intterupts is what triggers the first one? Rx interrupts are, I assume, triggered by the hardware when it receives a character, right? But what gets the first Tx interrupt going in, for example, the code you posted at the following link? Thanks again2015-09-27 10:00 AM
The TXE/RXNE interrupt bits are a direct reflection of those bits in the status register, they set/clear based on your interaction with the data register. On the TIM peripheral you have to explicitly clear the source, because there's not the same one-to-one relationship between the buffers, and flags reflecting the state of the buffers.
TXE is set whenever the USART doesn't have new data to send, enabling the interrupt will thus immediately result in an interrupt occurring. If you can't service the interrupt by giving the USART data, then it's going to keep asserting that it needs data, and you endlessly enter the interrupt and never run foreground code. If you don't have any data to supply, you must turn OFF the interrupt, until you do.