2020-11-20 10:25 AM
I am working on a system where I send HEX commands through the USART3 of the STM32F407VG to the COM machine with its corresponding PC.
The particularity of this communication is that in each sending of frames, the first byte of the frame must be sent with the wake up bit activated. (9 bits - 9n1), the rest of the bytes must be sent with the wake up deactivated (8 bits - 8N1)
I have used this code in the CUBE ID but it doesn't work
void EnviarComando(uint8_t cmdEnTx[], int lenEnTx)
{
int InterByte = 5; // Tiempo Interbyte
int i = 1;
/*Envío del primer byte (address) en 9 bits */
huart3.Init.WordLength = UART_WORDLENGTH_9B;
HAL_UART_Transmit(&huart3, cmdEnTx, 1, InterByte);
/*Envío del resto de bytes en 8 bits */
huart3.Init.WordLength = UART_WORDLENGTH_8B;
while (i< lenEnTx)
{
HAL_UART_Transmit(&huart3, &cmdEnTx[i], 1, InterByte);
i++;
}
}
The initial configuration of the USART 3 is this:
static void MX_USART3_UART_Init(void)
{
huart3.Instance = USART3;
huart3.Init.BaudRate = 19200;
huart3.Init.WordLength = UART_WORDLENGTH_8B;
huart3.Init.StopBits = UART_STOPBITS_1;
huart3.Init.Parity = UART_PARITY_NONE;
huart3.Init.Mode = UART_MODE_TX_RX;
huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart3.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart3) != HAL_OK)
{
Error_Handler();
}
}
The same I did with Arduino Mega and it works perfectly acting on the bits of the UART register.
This is the code I used for the Mega 2560
void sendCommand(byte temp[], int len) //Envío de trama a EGM
{
UCSR1B = 0b10011101; //9 bits on
serEgm.write(temp[0]); //envía primer byte( address máquina )
delay(5); //Default 1
UCSR1B = 0b10011100; //9 bits off
for (int i=1; i<len;i++)
{
serEgm.write(temp[i]); //envía el resto de bytes de la trama
delay(5);//Default 1
}
}
I am blocked with this matter, so I appreciate in advance any ideas or contributions that allow me to solve this problem
Regards
2020-11-20 11:27 AM
As in the Arduino code you write directly to the mcu's UART peripheral registers (UCSR1B), here, you need to write to the UART registers. Writing to the init struct members does nothing, it's just a variable in memory.
First, read the USART chapter in RM. The number of bits per frame in 'F4 is governed by USART_CR1.M bit, but you must be sure all transfers are finished if you want to modify it. Then, you do
USART3->CR1 &= ~USART_CR1_M; // set to 8-bit
or
USART3->CR1 |= USART_CR1_M; // set to 9-bit
JW
2020-11-20 01:09 PM
Calling HAL_UART_Init after you change the value in huart3.Init.WordLength will probably also work.
Switching between 9 bits and 8 bits is an abnormal setup. Are you sure that's what is required?
2020-11-20 01:20 PM
Yes, this is indicated in the specifications of this protocol
Watch
In wakeup mode, the host sets the 9th (wakeup) bit each time it sends the first byte of a message to the gaming machine. For all additional bytes in the message, this bit is cleared. Gaming machines use the wakeup bit to determine whether the received byte is the first byte of a new message or an additional byte of the current message. Gaming machines clear the wakeup bit for all bytes when responding to the host, except when reporting a loop break condition (refer to 4.2 Loop Break Indication on page 4-1). Note: For UARTs / DUARTs that do not directly support wakeup mode, the parity bit can be used in place of the wakeup bit.
2020-11-20 01:52 PM
That's permanently 9-bit protocol, it's just the 9th bit's value which is supposed to change.
Read the venerable Intel 8051's manual, this is called Multiprocessor Communication there.
JW
PS. TDK, well spotted.
PS2. And this is also exactly what UCRSnB does in AVR:
2020-11-20 02:05 PM
Yup. There's still a stop bit after the wakeup bit.
2020-11-20 02:15 PM
Except for the initial example that I have shown you in Arduino (it is not my code, it was a contribution that was suggested to me in a forum), I have never worked with 9 bits, but I think the specifications do not establish it as you say, they are always 8 data bits, the ninth bit is only set to identify the first byte of the sent frame.
Communication between the host and gaming machines occurs through a serial data link operating at 19.2 KBaud in a "wakeup" mode. The 11-bit data packet consists of one start bit, eight data bits, a ninth ‘wakeup’ bit, and one stop bit.
2020-11-20 02:23 PM
2020-11-20 02:38 PM
Are you suggesting that the USART3 should be set to 9 bit and only disable the ninth bit for sending after the first byte?
I have tested the statements waclawek.jan has sent me
USART3-> CR1 & = ~ USART_CR1_M; // set to 8-bit and USART3-> CR1 | = USART_CR1_M; // set to 9-bit
It has not worked, perhaps because in that test the USART was set to 8 bits.
I will try again setting the USART to 9 bit
2020-11-20 03:08 PM
As I've said, this mode of usage originates in 8051. The standard you quoted from originates at a company which indeed used 8051s in their products.
In STM32, you need to set USART to 9-bit mode, and write 16-bit words to USART->DR, with 9th bit set as the protocol requires. I don't know if Cube is suitable for this, I don't use Cube.
JW