Inverse convention STM32 - stm32

I'm new to STM32, and I use STM32L476
I programmed a UART communication using CubeIDE, and I tried to use inverse convetion so the MSB will be first, instead the default convention which is the LSB first.
I configured the UART as the following:
static void UART_Init(void)
{
/* Peripheral clock enable */
__HAL_RCC_USART1_CLK_ENABLE();
huart1.Instance = USART1;
huart1.Init.BaudRate = 9600;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.Parity = UART_PARITY_EVEN;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.AdvancedInit.MSBFirst = UART_ADVFEATURE_MSBFIRST_ENABLE;
huart1.AdvancedInit.DataInvert = UART_ADVFEATURE_DATAINV_ENABLE;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
while(1);
}
}
I using scope, and see that the data is transmitted in direct convention (LSB first).
Can someone help me, to solve this issue?
Thanks in advance.

To solve this issue, we need to add the followingl line:
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_MSBFIRST_INIT;
There is no need for the line:
huart1.AdvancedInit.DataInvert = UART_ADVFEATURE_DATAINV_ENABLE;
It works properly without it.

Related

Modify the example named UART_HyperTerminal_IT to enable UART reception interrupts on STM32F4?

I'm developing a project with STM32F4 and I need to enable the UART6 receive interrupt. I have used STM32CubeMX to enable the UART6 and in the STM32CubeMX I have enabled the NVIC USART6 global interrupt.
The example UART_HyperTerminal_IT
I have followed the example UART_HyperTerminal_IT which is installed by the package STM32Cube_FW_F4_V1.27.0.
The code is more recent but not so different from this example code.
I would like to modify the example to send back every character received from UART6 on the same UART6 (echo). So I have removed all the code of the example that sends data by the UART and wait data from the UART.
I have initialized the UART6 by the following code:
UartHandle.Instance = USART6;
UartHandle.Init.BaudRate = 115200;
UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
UartHandle.Init.StopBits = UART_STOPBITS_1;
UartHandle.Init.Parity = UART_PARITY_NONE;
UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
UartHandle.Init.Mode = UART_MODE_TX_RX;
UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;
if(HAL_UART_Init(&UartHandle) != HAL_OK) {
/* Initialization Error */
Error_Handler();
}
The previous code is very similar to the example code (I have changed only baud rate and the parity).
My interrupt routine
I have defined the function USART6_IRQHandler in the file stm32f4xx_it.c as in the code below:
void USART6_IRQHandler(void) {
unsigned char ch;
uint32_t isrflags = READ_REG(huart6.Instance->SR);
uint32_t cr1its = READ_REG(huart6.Instance->CR1);
if (((isrflags & USART_CR1_RXNEIE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET)){
huart6.Instance->SR;
ch = huart6.Instance->DR;
HAL_UART_Transmit(&huart6, &ch, 1, 1000);
}
HAL_UART_IRQHandler(&huart6);
}
In the readme file of the example I have found this sentence:
This example shows how to ensure UART Data buffer transmission and reception with
Interrupt.
The sentence says that in the example the Interrupt is enabled, but if I try to send data to the UART6 the interrupt routine USART6_IRQHandler() is not called.
I think that the UART6 Receive Interrupt is not enabled, but how can I enable it? Is there a specific bit in some register that must be set?
Thanks
This post on SO speak about this topic but I think is too old for my STM32F4.
This other post is old too.
Thanks to #pmacfarlane's comment I solved the problem of the lack of reception interrupts in the example UART_HyperTerminal_IT.
So I confirm that the only modification needed to obtain the echo of the characters receives from UART6 is the addition of the instruction huart6.Instance->CR1 |= USART_CR1_RXNEIE;.
Initialization of UART6 with reception interrupts enabled
So the initialization code for the UART6 becomes:
huart6.Instance = USART6;
huart6.Init.BaudRate = 115200;
huart6.Init.WordLength = UART_WORDLENGTH_8B;
huart6.Init.StopBits = UART_STOPBITS_1;
huart6.Init.Parity = UART_PARITY_NONE;
huart6.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart6.Init.Mode = UART_MODE_TX_RX;
huart6.Init.OverSampling = UART_OVERSAMPLING_16;
if(HAL_UART_Init(&huart6) != HAL_OK) {
/* Initialization Error */
Error_Handler();
}
// ---> enable reception interruptions
huart6.Instance->CR1 |= USART_CR1_RXNEIE;
Note. In the previous code I have substituted the variable UART_HandleTypeDef UartHandle used in the UART_HyperTerminal_IT example with the variable:
UART_HandleTypeDef huart6;
Interrupt routine implements echo
The code of the interrupt routine presented in the question remains exactly the same:
void USART6_IRQHandler(void) {
unsigned char ch;
uint32_t isrflags = READ_REG(huart6.Instance->SR);
uint32_t cr1its = READ_REG(huart6.Instance->CR1);
if (((isrflags & USART_CR1_RXNEIE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET)){
huart6.Instance->SR;
ch = huart6.Instance->DR;
HAL_UART_Transmit(&huart6, &ch, 1, 1000);
}
HAL_UART_IRQHandler(&huart6);
}
The USART6_IRQHandler() function retrieves the received char and sends it immediately back implementing the echo of every char received.
While loop empty
That's all, the while(1) loop is completly empty:
while(1) {
// empty loop
}

Stm32f407 Uart Dma Multiple Array Tx

I tried to send Buffer from stm32f407 to terminal.Type is uint8_t and array is 15000. My code is works. but when i try to send 2 buffer like 5000 array, there is problem for second buffer. I use normal mode.What i should do to sending succesfully?
/* USART3 DMA Init */
/* USART3_TX Init */
hdma_usart3_tx.Instance = DMA1_Stream3;
hdma_usart3_tx.Init.Channel = DMA_CHANNEL_4;
hdma_usart3_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_usart3_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart3_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart3_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart3_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart3_tx.Init.Mode = DMA_NORMAL;
hdma_usart3_tx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
hdma_usart3_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_usart3_tx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(huart,hdmatx,hdma_usart3_tx);
/* USART3 interrupt Init */
HAL_NVIC_SetPriority(USART3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART3_IRQn);
/* USER CODE BEGIN USART3_MspInit 1 */
/* USER CODE END USART3_MspInit 1 */
void Send_Dataa(void)
{
HAL_UART_Transmit_DMA(wifi_uart, buf1, 5000);
HAL_UART_Transmit_DMA(wifi_uart, buf2, 5000);
}
If you check the return code from HAL_UART_Transmit_DMA(), you'll probably see it is returning HAL_BUSY. (Note you should always be checking the return codes from HAL functions.)
You'll need to wait until the first transmit is complete before starting the second transmit. You can use HAL_UART_GetState() to monitor the state of the UART.
The HAL does not chain together multiple DMA requests.

STM32F1 problem receiving duplicated first byte on USART

I have a problem with an STM23F103 I'm using UART to transmit and receive data.the data is sent and another board replies. I can see the communication with a Logic Analyzer which looks fine on it.but the received data on STM32 have the first byte either from the first byte of the packet send or from last byte of the last received packet.I don't know what's wrong with my code but I can't figure out how to solve the issue
Here is the code in the main
uint8_t b[5] = {0xAA,0xBB,0xCC,0xDD,0xEE};
HAL_UART_Transmit(&huart3,b, sizeof(b), 100);
uint8_t r[5]={0,0,0,0,0};
HAL_UART_Receive(&huart3, r, sizeof(r), 100);
HAL_Delay(100);
uint8_t d[5] = {0x11,0x22,0x33,0x44,0x55};
HAL_UART_Transmit(&huart3,d, sizeof(d), 100);
uint8_t r2[5]={0,0,0,0,0};
HAL_UART_Receive(&huart3, r2, sizeof(r2), 100);
HAL_Delay(100);
and here the Init
static void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 10400;
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 packet that appears on the logic analyzer is 0xA1,B2,C3,D4,E5 but on the STM32 it receives AA,A1,B2,C3,D4 the first byte is always the same as the packet that I sent.but only on the first packet.
On the other packets are received like this 0xE5,66,77,88,99 while it should be 66,77,88,99,AA but I get E5 from the last received packet. I thought that that packet has not being received so I thought by increasing the size of r and r2 from 5 to 6 it would solve the issue but it doesn't. I receive AA,A1,B2,C3,D4,E5 for r and 0xE5,66,77,88,99,AA for r2.
I hope its detailed enough to see the issue.
I'm using STM32CubeIDE
Sounds like this may be a settings issue as your code looks fine.
I would start by double checking the UART properties in your UART_Init(). Make sure they're the same for both the sender and receiver (baud rate, parity etc).
Your logic analyser will also need to know the correct UART properties.
Post a link to your code and I may be able to help you further.

STM32 SPI slave mode doesn't transmit properly

I am using an STM32G030C8T6 as an SPI (Slave device) which receives characters from a Raspberry pi (Master device), receiving works perfectly! no problems there, however when i try to send data from STM32 to Pi, it seems that the STM32 gets stuck for a while and Pi rx buffer is filled with only one bit in repeat e.g., if i send char buf[6] = {0,1,2,3,4,5}; Pi receives (111111) or (333333) depending on how many characters i am sending.
What do i actually want to do?
I want to transmit ADC data from STM32(slave mode) to Pi(master mode), so far it only receives one bit i repeat.
Can someone please help me achieve this?
Here's my SPI config:
void MX_SPI1_Init(void)
{
/* USER CODE BEGIN SPI1_Init 0 */
/* USER CODE END SPI1_Init 0 */
/* USER CODE BEGIN SPI1_Init 1 */
/* USER CODE END SPI1_Init 1 */
/* SPI1 parameter configuration*/
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_SLAVE;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;
hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI1_Init 2 */
/* USER CODE END SPI1_Init 2 */
}
then the functions to read characters, send data and string
char SPI_read(void)
{
// SPI1->SR is the STATUS REGISTER on SPI1 Bus
// SPI1->DR is the DATA REGISTER on SPI1 Bus
char data;
while(!(SPI1->SR & SPI_SR_RXNE));
while(SPI1->SR & SPI_SR_BSY);
data = SPI1->DR;
printmsg("%c",data);
return data;
}
void spi_Send(char caracSend)
{
while(!(SPI1->SR & SPI_SR_TXE));
SPI1->DR = caracSend;
}
void spi_send_string(char* stringSend)
{
int i=0;
unsigned int sizeChar = 0;
sizeChar = strlen(stringSend);
__NOP();
for(i=0;i<sizeChar;i++)
{
spi_Send(stringSend[i]);
}
}
Here's my function to receive data from Pi which i call in the main while loop.
void SPI_Receive_Commands(void)
{
while(HAL_GPIO_ReadPin(SPI_SS_GPIO_Port, SPI_SS_Pin) == GPIO_PIN_RESET);
{
HAL_SPI_Receive(&hspi1, (uint8_t *)spi_buf, 10, 100);
if(spi_buf[0] == 'v')
{
memset(spi_buf,'*',10);
printmsg("Character V received\r\n");
Battery_Voltage();
spi_send_string(batteryVoltage);
spi_Send('v');
printmsg("Sending battery voltage\r\n");
}
}
}
Thank you so much for helping me out in advance.
Initialisation. You need set the RX FIFO threshold to 1/4 as you read and write bytes. I do not know how to do it in HAL. Register level simply set FRXTH bit in the CR2 register
DR register has to be accessed in 8 bits operations.
You do not need to use BSY bit in polling mode unless you want to disable the SPI peripheral.
void spi_Send(char caracSend)
{
while(!(SPI1->SR & SPI_SR_TXE));
*(volatile uint8_t *)&SPI1->DR = caracSend;
}
void spi_send_string(char* str)
{
if(str) while(*str) spi_Send(*str++);
}
char SPI_read(void)
{
char data;
while(!(SPI1->SR & SPI_SR_RXNE));
data = *(volatile uint8_t *)&SPI1->DR;
return data;
}
Remember that raspberry pi HAS TO send dummy data to allow slave to send information. Slave does not generate the clock signal and clock has to be supplied by the Master

PGSERR and PGPERR Bit Clear

I have a problem with PGSERR and PGPERR bits being set after reset operation
I am using stm32f4 board than I am using CANBUS and FW update process.
When I use serial debug print in MX_CAN1_Init function. I faced with flash erasing error. Then I analyse that error I found PGSERR and PGPERR bits set.
These bits have to be "0" .
I wanted to analyze this problem so I did these test in my initlize states:
MX_CAN1_Init();
Serialdebugprint("Read PGAERR FLAG %d\n",__HAL_FLASH_GET_FLAG((FLASH_FLAG_PGPERR)));
Serialdebugprint("Read PGSERR FLAG %d\n",__HAL_FLASH_GET_FLAG((FLASH_FLAG_PGSERR)));
I get this value:
Read PGAERR FLAG 64
Read PGSERR FLAG 128
I get this value:
Read PGAERR FLAG 64
Read PGSERR FLAG 128
But these flag has to be 0. After the reset.
If I removed the MX_CAN1_Init these flag equals to "0".
When I changed some parameter in the CAN_Init function for example communication speed to 83.3kps to 1Mbs I get this flag as 0 and 128 . By the way when I remove the serialdebug I get the 0 and 128 again.
If I put the MX_CAN1_Init function after a few function than this flag returns "0" .
What is the reason?
/**
* #brief CAN1 Init function
* #retval null
*/
static void MX_CAN1_Init(void)
{
CAN_FilterTypeDef sFilterConfig;
hcan1.Instance = CAN1;
hcan1.Init.Prescaler = 28; //3
hcan1.Init.Mode = CAN_MODE_NORMAL;
hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan1.Init.TimeSeg1 = CAN_BS1_15TQ; //11
hcan1.Init.TimeSeg2 = CAN_BS2_2TQ; //2
hcan1.Init.TimeTriggeredMode = DISABLE;
hcan1.Init.AutoBusOff = ENABLE;
hcan1.Init.AutoWakeUp = DISABLE;
hcan1.Init.AutoRetransmission = ENABLE;
hcan1.Init.ReceiveFifoLocked = DISABLE;
hcan1.Init.TransmitFifoPriority = DISABLE;
if (HAL_CAN_Init(&hcan1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/*##-2- Configure the CAN Filter ###########################################*/
sFilterConfig.FilterBank = 0;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
sFilterConfig.FilterIdHigh = 0x0000;
sFilterConfig.FilterIdLow = 0x0000;
sFilterConfig.FilterMaskIdHigh = 0x0000;
sFilterConfig.FilterMaskIdLow = 0x0000;
sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;
sFilterConfig.FilterActivation = ENABLE;
sFilterConfig.SlaveStartFilterBank = 0;
if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)
{
/* Filter configuration Error */
// SerialPrint("FILTER ERROR !!");
Error_Handler();
}
/*##-3- Start the CAN peripheral ###########################################*/
if (HAL_CAN_Start(&hcan1) != HAL_OK)
{
// SerialPrint("CAN START ERROR !!");
/* Start Error */
Error_Handler();
}
/*##-4- Activate CAN RX notification #######################################*/
if(HAL_CAN_ActivateNotification(&hcan1,CAN_IT_TX_MAILBOX_EMPTY | CAN_IT_RX_FIFO0_MSG_PENDING |CAN_IT_BUSOFF) != HAL_OK)
{
Error_Handler();
}
Serialdebugprint("Success CAN Init \n");
}
Serialdebugprint function:
void Serialdebugprint(const char *serial_data, ...)
{
char uartbuffer[1024]="";
va_list arg;
va_start(arg, serial_data);
uint16_t len = vsnprintf(uartbuffer, 1024, serial_data, arg);
va_end(arg);
HAL_UART_Transmit(&huart2, (uint8_t *)uartbuffer, len, 100);
}
I think problem start HAL_UART_Transmit(&huart2, (uint8_t *)uartbuffer, len, 100) after this line. What is the reason for ?
Stumbled over this thread when I debugged a related Problem. At some point in my firmware I needed to erase 1 page in the flash of an STM32L496. All I got from the STM HAL was an HAL_ERROR. Further investigations showed that PGSERR Flag was set from a previous flash write process. In the end I found out that the error flag was set because a memset operation to address 0x00.
meaning the PGSERR Flag can be set if you have code like this:
uint8_t* pointer;
memset(pointer, 0x00, 10);
btw. there in my case there was no Hartfault when running that code.
char uartbuffer[1024]=""; means "please give me a stack overflow asap". Don't declare huge buffers like that on the stack, move them to file scope and/or declare as static.
The stack overflow destroys your call stack and pretty much everything else too, after which your code starts to run or access addresses in la-la-land, leading to PGSERR.
To fix this problem, you need to add __HAL_FLASH_CLEAR_FLAG(0xFF); before HAL_FLASH_Unlock();