Unrecognizable characters received over UART - stm32

I have compiled code to transmit data from an STM32 board to the Arduino Uno and print it on the serial terminal. I have previously written code, similar to this and it worked as expected.
However, when I try transmitting a string from the STM32 this time, the TX-Led of the Arduino blinks, which is strange.
I have checked the baud rate of both devices and they match. On the serial terminal of the Arduino, backward question marks are printed when I am transmitting a short string "Test".
Please could someone help me identify any potential problems with what I have done.
The code for the STM32 UART settings was generated by cubeMX:
static void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;`
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
}
The string and HAL_UART instruction to transmit the data:
char let[30] = "Test\r\n";
HAL_UART_Transmit(&huart1, (uint8_t*)let, strlen(let), 1000);
All necessary functions (MX_USART1_UART_Init()) have been called and the HAL_UART_Transmit() is in the while loop, situated in the main loop, as I have cross-checked that.
My arduino program:
void setup() {
Serial.begin(115200);
// Define the LED pin as Output
pinMode (13, OUTPUT);
Serial.println("Arduino UART Receiver");
Serial.println("-----------------------------");
}
void loop() {
digitalWrite(13, LOW);
//wait until something is received
while(! Serial.available());
digitalWrite(13, HIGH);
//read the data
char in_read=Serial.read();
//print the data
Serial.print(in_read);
}

Arduino Uno has only one USART hardware, and it's connected to a USART-USB converter chip. This bus is point-to-point and can't be shared by another device when there is an active connection between Arduino and PC.
The RX pin of the Arduino is driven by two devices: STM32 and the converter chip. Converter tries to keep that line at logic high (because the TX coming from the PC is idle) while STM32 tries to drive that line with its own TX. Anything can happen there... Arduino is probably getting junk from its RX line.
If you can somehow disconnect Arduino RX from the converter chip (cutting the trace for example) it will probably work. But then you won't be able to program Arduino again.
You may use a software serial pin instead of the hardware RX pin. I don't have much experience with Arduino but I'm sure there must be software serial libraries out there.

Related

Cant't send a data from my cell phone(android) to HM10

I am using HM10(Bluetooth module) and the NUCLEO board.
I am trying to send data (like A, B... just characters) from my android phone using "Serial Bluetooth terminal" app. I succeeded in connecting the phone and HM10, but data is not sent to HM10. I never know what is problem. Plz, give me some advice.
#include "mbed.h"
// set up the HM10 Serial connection
BufferedSerial hm10(D10,D2,9600); //TX, RX
BufferedSerial pc(CONSOLE_TX,CONSOLE_RX,9600);
DigitalOut led1(D3);
DigitalOut led2(D4);
char buf[80];
int main(){
sprintf(buf,"\r\nHello New Serial Function in mbed-os v.%.1f\r\n",6.0);
pc.write(buf, strlen(buf));
while(true) {
sprintf(buf,"waiting for data");
pc.write(buf, strlen(buf));
int num = hm10.read(buf,sizeof(buf));
led1=!led1; // for debugging
pc.write(buf,num);
//memset(buf,0,sizeof(buf));
}
}

STM32 Flash Erase fails with a "Programming Parallelism error" and "Programming Sequence error"

I have an application running on an STM32F4 which uses the STM32 HAL framework + FreeRTOS. I occasionally need to store some settings in flash during runtime and have written the following function to erase the data at my target address of 0x08060000UL (I believe this is SECTOR_6 of this particular MCU).
HAL_StatusTypeDef Flash::erase(uint32_t address)
{
HAL_StatusTypeDef status;
HAL_FLASH_Unlock(); // unlock the flash API
__disable_irq(); // disable all interrupts
vTaskSuspendAll(); // suspend all FreeRTOS tasks
FLASH_EraseInitTypeDef eraseConfig = {0};
uint32_t sectorError;
uint32_t flashError = 0;
eraseConfig.TypeErase = FLASH_TYPEERASE_SECTORS;
eraseConfig.Sector = this->getSector(address);
eraseConfig.NbSectors = 1;
eraseConfig.VoltageRange = FLASH_VOLTAGE_RANGE_3;
status = HAL_FLASHEx_Erase(&eraseConfig, &sectorError); // <---- FAILS HERE
if (status != HAL_OK)
{
flashError = HAL_FLASH_GetError();
}
status = HAL_FLASH_Lock();
xTaskResumeAll(); // resume all FreeRTOS tasks
__enable_irq(); // re-enable interrupts
return status;
}
The flashError variable ends up getting set to 6, which means the following two errors occurred during the call to HAL_FLASHEx_Erase()
#define HAL_FLASH_ERROR_PGS 0x00000002U /*!< Programming Sequence error */
#define HAL_FLASH_ERROR_PGP 0x00000004U /*!< Programming Parallelism error */
I can't be 100% sure, but I think this code worked fine prior to implementing FreeRTOS. Regardless, what kind of behavior might cause such an error? I thought disabling all ISRs as well as suspending all tasks (even though there is only one running during this operation) would cover me, but no combination of these attempts alleviates the error 🤷‍♂️.
Turns out I had to reset some peripheral flags prior to using the HAL Flash API. Why? I don't know, but clearing all the flags prior to using the API fixed my problem.
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPERR);
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_WRPERR);
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGAERR);
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGPERR);
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGSERR);

STM32 Uart Bridge

I am workin in a proyect where i need to make a bridge between to uart's. I am using the STM32F072CB Basically, all the data that I receive to the uart1 rx must be sent by uart2 tx. In the same way, what I receive in uart2 rx I must send through uart1 tx.(Both UARTs have the same baudrate). I am not aware of how much data I can receive on the rx uarts.
This is the idea
Uart1 rx --------> Uart2 tx
Uart1 tx <-------- Uart2 rx
I am using DMA with HAL_UARTEx_ReceiveToIdle_DMA to reduce cpu processing.
UART_HandleTypeDef huart1;
UART_HandleTypeDef huart2;
DMA_HandleTypeDef hdma_usart1_rx;
DMA_HandleTypeDef hdma_usart2_rx;
#define RXBuffSize 10
uint8_t RxBuff1[RxBuffSize];
uint8_t RxBuff2[RxBuffSize];
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_USART1_UART_Init();
MX_USART2_UART_Init();
HAL_UARTEx_ReceiveToIdle_DMA(&huart1,RxBuff1,RxBuffSize);
__HAL_DMA_DISABLE_IT(&hdma_usart1_rx,DMA_IT_HT);
HAL_UARTEx_ReceiveToIdle_DMA(&huart2,RxBuff2,RxBuffSize);
__HAL_DMA_DISABLE_IT(&hdma_usart2_rx,DMA_IT_HT);
while (1)
{}
}
Here is my DMA interruption callback function
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
if (huart->Instance == USART1)
{
HAL_UART_Transmit(&huart2,RxBuff1,RxBuffSize,1);
HAL_UARTEx_ReceiveToIdle_DMA(&huart1,RxBuff1,RxBuffSize);
__HAL_DMA_DISABLE_IT(&hdma_usart1_rx,DMA_IT_HT);
}
else if (huart->Instance == USART2)
{
HAL_UART_Transmit(&huart1,RxBuff2,RxBuffSize,1);
HAL_UARTEx_ReceiveToIdle_DMA(&huart2,RxBuff2,RxBuffSize);
__HAL_DMA_DISABLE_IT(&hdma_usart2_rx,DMA_IT_HT);
}
}
The code runs when the data input to rx is low. If I send too much data in the tx of the other uart I get the first bytes but lose the last ones. I also tried doing the RXBuffSize = 1 , that is to say receive a character and send it but I get the same result.
Because HAL_UART_Transmit operates in a "polling" method, it stops at the point until all strings are transmitted.
Therefore, if another string comes in while HAL_UART_Transmit is being executed, the interrupt is not executed and the entered string is lost.
After activating the TX DMA of each uart in cubemx, try applying the code as shown below.
#include <string.h>
uint8_t TxBuff1[RxBuffSize];
uint8_t TxBuff2[RxBuffSize];
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
Size = Size > RxBuffSize ? RxBuffSize : Size;
if (huart->Instance == USART1)
{
memcpy(TxBuff2, RxBuff1, Size);
HAL_UART_Transmit_DMA(&huart2, TxBuff2, Size);
HAL_UARTEx_ReceiveToIdle_DMA(&huart1, RxBuff1, RxBuffSize);
__HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);
}
else if (huart->Instance == USART2)
{
memcpy(TxBuff1, RxBuff2, Size);
HAL_UART_Transmit_DMA(&huart1, TxBuff1, Size);
HAL_UARTEx_ReceiveToIdle_DMA(&huart2, RxBuff2, RxBuffSize);
__HAL_DMA_DISABLE_IT(&hdma_usart2_rx, DMA_IT_HT);
}
}
Transmitting RxBuff directly is dangerous. When a character is received from the UART while sending, an incorrect value may be sent by the TX DMA because RX DMA changes the value in the corresponding memory.
Therefore, when RX DMA is deactivated, it is better to enable it after copying the corresponding memory value to another location.

I2C communication between two stm32 board in interrupt mode by low layer functions of STM32CUBEMX

I am working on a project which needs data communication between two stm32 (stm32f103rb and stm32f429zg).
I use stm32f103rb-nucleo examples_ll (I2C _OneBoard_Communication_IT) but it works for one byte and after that, it stops working. I want it to work repetitively.
the code structure is exactly in the way the example is written in the folder related to stm32cubemx repository.
I don't know how to make it work in a loop and by pressing the button, communication gets done every time I push the master and slave push buttons.
I have put the master completion callback function here :
void Master_Complete_Callback(void)
{
if(ubNbDataToReceive == 3)
{
/* Prepare the generation of a Non ACKnowledge condition after next received bytes */
LL_I2C_AcknowledgeNextData(I2C1, LL_I2C_NACK);
/* Read character in Receive Data register.
RXNE flag is cleared by reading data in RXDR register */
aReceiveBuffer[ubReceiveIndex++] = LL_I2C_ReceiveData8(I2C1);
ubNbDataToReceive--;
/* Disable Buffer Interrupts */
LL_I2C_DisableIT_BUF(I2C1);
}
else if(ubNbDataToReceive == 2)
{
/* Generate Stop condition */
LL_I2C_GenerateStopCondition(I2C1);
/* Read character from Receive Data register.
RXNE flag is cleared by reading data in RXDR register */
aReceiveBuffer[ubReceiveIndex++] = LL_I2C_ReceiveData8(I2C1);
ubNbDataToReceive--;
/* Read character from shift register.
RXNE flag is cleared by reading data in RXDR register */
aReceiveBuffer[ubReceiveIndex++] = LL_I2C_ReceiveData8(I2C1);
ubNbDataToReceive--;
}
else
{
if(ubNbDataToReceive > 0)
{
/* Read character from shift register.
RXNE flag is cleared by reading data in RXDR register */
aReceiveBuffer[ubReceiveIndex++] = LL_I2C_ReceiveData8(I2C2);
/* Update ubNbDataToReceive variable */
ubNbDataToReceive--;
}
}
if(ubNbDataToReceive == 0)
{
/* (1) Disable I2C1 transfer event/error interrupts:
* - Disable Events Interrupt
* - Disable Error interrupts
*/
LL_I2C_DisableIT_EVT(I2C1);
LL_I2C_DisableIT_ERR(I2C1);
LL_I2C_EnableIT_EVT(I2C1);
LL_I2C_EnableIT_ERR(I2C1);
/* Read Received character.
RXNE flag is cleared by reading of RXDR register */
if(aReceiveBuffer[ubReceiveIndex-1] == SLAVE_BYTE_TO_SEND)
{
/* Turn LED2 On:
* - Expected byte has been received
* - Master Rx sequence completed successfully
*/
//LED_On();
HAL_UART_Transmit_IT(&huart2,(uint8_t*)"#Data transfer is OK!$",strlen("#Data transfer is OK!$"));
ubNbDataToTransmit = sizeof(SLAVE_BYTE_TO_SEND);
ubNbDataToReceive = sizeof(SLAVE_BYTE_TO_SEND);
}
else
{
/* Call Error function */
Error_Callback();
}
}
}
it is easily understood that the end of the transmission process is when I add HAL_UART function to send to serial port the transmission completion.
but after this time , it works one more time and after that it stops.
I have checked the oscilloscope signal show and after the second time transmission SCL pin gets LOW .
Thanks
Did not use LL for a long time, but isnt I2C interrupt disabled after single transfer with LL_I2C_DisableIT_EVT(I2C1);?? Make sure to enable it again before next transmission.
There is such a thing that two master devices cannot communicate each other via I2C bus. Because master devices do not have DEVICE_ADDRESS. Master devices can communicate only slave devices.

How to verify whether Quectel M66 recognize my command sent via UART from STM32?

I am using STM32F103C8 board and CubeMX to create the code. I have connected the M66 to STM32 to UART2 port. I try to send some commands to Quectel M66 via STM32's UART port. It receives the command but throws some junk characters. I have set the baud rate as 9600 for all UART ports. This is my code
void M66_Check()
{
char *buffer = "ATI\r\n";
char *rec_buffer = NULL;
rec_buffer = (char*)malloc(200 * sizeof(char));
if(HAL_UART_Transmit(&huart2,buffer,strlen(buffer),200) == HAL_OK)
{
printf("AT Command sent successfully\r\n");
HAL_Delay(1000);
}
else
{
printf("Not Sent\r\n");
}
HAL_UART_Receive(&huart2,rec_buffer,50,200);
printf("About to print Response from M66 \r\n");
HAL_Delay(2000);
printf(rec_buffer);
}
This is what I am getting...Result in Putty
Any help would be greatly appreciated
There is the only way - read the answer and parse it. Then you will know if the command was executed ok.
But your response shows that your UART is running another speed (9600) than the modem. If you have not changed anything it should be 115200 as it is default modem UART speed
I have found out the problem... I needed to transmit and receive in these formats....
I missed those (uint8_t *).
To Transmit -
HAL_UART_Transmit(&huart2, (uint8_t *)buffer, strlen(buffer), 100);
To Receive -
HAL_UART_Receive(&huart2, (uint8_t *)rec_buffer,50,2000);
Now there is no problem and I am getting the response correctly.
Thanks for your help...