Hi,
I am currently testing the USART on my STM32F103C8 Blue Pill, which I should be able to send text to and it will echo back anything typed and respond to various commands.
I'm finding something a little odd, though. It prints the start up messages fine and goes into the main loop to wait for characters from the USART, which it echoes back to the terminal. The problem is it ignores the first 10 chars every time it restarts. Every time.
Here's the basic code:
/* Initialize all configured peripherals */ MX_GPIO_Init(); MX_TIM2_Init(CLKSPD); MX_TIM3_Init(); MX_USART2_UART_Init(); // Clear the terminal window HAL_UART_Transmit(&huart2, (uint8_t *)12, 1, HAL_MAX_DELAY); // Start progress logging HAL_UART_Transmit(&huart2, (uint8_t *)"GPIO, Timers and UART set up.\r\n", 32, HAL_MAX_DELAY); /* USER CODE BEGIN 2 */ HAL_TIM_Base_Start(&htim2); HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1); HAL_TIM_Base_Start(&htim3); HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1); HAL_UART_Transmit(&huart2, (uint8_t *)"Clock outputs enabled.\r\n", 26, HAL_MAX_DELAY); //__HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE); HAL_UART_Receive_IT(&huart2, (uint8_t *)aRxBuffer, RXBUFFERSIZE); HAL_UART_Transmit(&huart2, (uint8_t *)"aRxBuffer set up.\r\n", 21, HAL_MAX_DELAY); // USART INTERRUPTS NVIC_SetPriority(USART2_IRQn, 0); NVIC_EnableIRQ(USART2_IRQn); /* USER CODE END 2 */ HAL_UART_Transmit(&huart2, (uint8_t *)"USART Interrupts enabled.\r\n", 28, HAL_MAX_DELAY); /* Infinite loop */ /* USER CODE BEGIN WHILE */ uint8_t buffer[40] = ""; int bufferRxPtr = 0; uint8_t CR[4] = "\r\n"; HAL_UART_Transmit(&huart2, (uint8_t *)"Entering main loop...\r\n", 24, HAL_MAX_DELAY); while (1) { HAL_UART_Receive(&huart2, &buffer[bufferRxPtr], 1, HAL_MAX_DELAY); if (buffer[bufferRxPtr] == 13) { // CR & LF HAL_UART_Transmit(&huart2, CR, sizeof(CR), HAL_MAX_DELAY); bufferRxPtr = 0; } else if (buffer[bufferRxPtr] == 35) { // End of Line char '#' detected - interpret command buffer[bufferRxPtr] = '\0'; bufferRxPtr = 0; HAL_UART_Transmit(&huart2, CR, sizeof(CR), HAL_MAX_DELAY); // Check for command char at the start of the buffer if (buffer[0] == 37) { // Now get the command switch (buffer[1]) { case 67: // Uppercase C case 99: // Lowercase c ToggleClkSpeed(true, buffer[2]); break; case 82: // Uppercase R case 114: // Lowercase r HAL_UART_Transmit(&huart2, (uint8_t *)"Resetting...\r\n", 14, HAL_MAX_DELAY); SystemReset(); break; case 83: // Uppercase S case 115: // Lowercase s HAL_UART_Transmit(&huart2, (uint8_t *)"%S", 2, HAL_MAX_DELAY); HAL_UART_Transmit(&huart2, &CLKSPD, 1, HAL_MAX_DELAY); HAL_UART_Transmit(&huart2, (uint8_t *)"#", 1, HAL_MAX_DELAY); break; case 88: // Uppercase X case 120: // Lowercase x ToggleClkSpeed(false, buffer[2]); break; default: HAL_UART_Transmit(&huart2, (uint8_t *)"Unrecognised command: ", 22, HAL_MAX_DELAY); HAL_UART_Transmit(&huart2, buffer, strlen((char*)buffer), HAL_MAX_DELAY); HAL_UART_Transmit(&huart2, CR, sizeof(CR), HAL_MAX_DELAY); break; } } } else { HAL_UART_Transmit(&huart2, &buffer[bufferRxPtr], 1, HAL_MAX_DELAY); // Check for potential buffer overflow if (bufferRxPtr > sizeof(buffer) - 2) { bufferRxPtr = 0; } else { bufferRxPtr += 1; } }
Now, I know it's not interrupt driven, I'm just trying to get the basics working first. In the terminal window, on reset, I'm seeing everything up to "Entering main loop..." - I then have to tap a key 11 times - on the 11th time, I see the char echoed back in the terminal window.
Any ideas why it's ignoring me for 10 chars?
Yeah, I'm not entirely sure how to do that effectively. I'm very new to the STM-series, literally having just received the Blue Pill in the post this week.
I'm using ST32CubeMX and Keil as my tool chain, with one of those cheap ST-LINK V2 devices you can get on eBay (so not the full debugger one you get from STM.) I've tried simulating the device in the debugger in Keil but that hasn't really gotten me very far - there were a load of errors to do with memory read/writes which I seem to have to fix using the Debug/Memory Map to enable read/write to certain parts of memory every time I reset the CPU, but after that it runs but doesn't really do much of anything. Setting break points doesn't seem to work either. :/
I was hoping that someone with more experience could scan the code above and spot the problem, but I'm realising that's probably a bit unrealistic. ;)
>>with one of those cheap ST-LINK V2 devices you can get on eBay (so not the full debugger one you get from STM.)
Ok, so why wouldn't that debug in exactly the same way as any other external, or on-board, ST-LINK? Keil doesn't know the difference.
Most probable reason for data loss is that HAL_UART_Transmit() blocks for dozens of character times, and you're not concurrently receiving data.
You should manage data reception in an interrupt, with reasonably deep buffering.
"I'm not entirely sure how to do that effectively"
That really is a basic skill that you need to learn right from the beginning!
Don't bother with the simulator - just use the debugger.
Why not start with a Nucleo board, which has the ST-Link built in - probably cheaper than the cost of a separate board + even an eBay ST-Link rip-off.
(a real ST-Link is only ~£20)
Take a look in the Support section for tutorials, app notes, etc.
ST also have load of training materials, videos, etc ...
... is that HAL_UART_Transmit() blocks for dozens of character times
I don't think that's the case here.
OP speaks of "tapping keys", so sounds like the input data is being provided manually - so unlikely to be overrunning ?
www2.keil.com/.../learn
there is a section specifically on using the debugger
Yes, I know. I was hoping that the STM32 would be as easy to set up as the Arduino Nano, so I dived straight into the code not expecting to need to use a debugger. Best laid plans, and all that...
Righto. So there's some extra connections I need to make between the ST-Link and the Blue Pill, I gather. Will get on that ASAP.
Because I'm a hobbyist rather than a professional and I'm just trying to evaluate the STM32F103 as a possible replacement for the ATmega328 I've got doing the job currently. I need more IO pins than the '328 offers as I'd like the micro-controller to have full access to the address and data bus of the SBC it supervises for DMA.
If it's Arduino you want, see:
community.st.com/.../stm32-cores-enabled-in-arduino-ide
(although the site is broken at the moment)
I don't see why being a hobbyist prevents you using a Nucleo board?
eg, uk.farnell.com/.../2394226
under a tenner with an ST-Link built in!
>>Righto. So there's some extra connections I need to make between the ST-Link and the Blue Pill, I gather. Will get on that ASAP.
SWDIO, SWCLK, NRST, GND - Same pins to program as debug. Basic requirements of a SWD attached debug pod.
For a real external ST-LINK the VTarget voltage will also need connecting to power the buffers.
* I don't see why being a hobbyist prevents you using a Nucleo board? *
No reason other than I'm trying to minimise cost on something I may not actually end up using.
* eg, uk.farnell.com/.../2394226 under a tenner with an ST-Link built in! *
I obviously misread your post - under a tenner isn't bad at all!