I am trying to play around with stm32 uart in polling mode. the transmission part is working properly and I read proper characters that I send from the MCU, however the reception part is not working properly.
This is a welcome message
ÿÿÿÿ
The first line is send from MCU to PC, the MCU then waits for reception. As I understand that HAL_USART_Receive is a blocking call so it should wait for user to input character from the terminal, however before i can write any characters and send them over to MCU, it moves over to the next line which is an infinite while loop. I cant understand why is it not pausing at the receive method. I debugged and checked the live expression windows, during initialization I set the receive buffer to '\0' however after passing through the HAL_Receive method the value of the buffer becomes 127. see the attached image for value stored in the buffer.
output
Can you please help me understand what am I doing wrong. My code is shown below
HAL_Init(); // Initializing HAL.
SystemClockConfig();
USART3_Init();
uint8_t tx_data[] = "This is a welcome message\r\n";
uint16_t tx_len = sizeof(tx_data);
HAL_USART_Transmit(&husart3, tx_data, tx_len, HAL_MAX_DELAY);
uint8_t rx_data[5]={0};
uint16_t rx_len = sizeof(rx_data);
HAL_USART_Receive(&husart3, rx_data, rx_len, HAL_MAX_DELAY);
while(1)
{
}
You said you are using the USART in UART mode (I assume you mean asynchronous mode) but your Handle (husart) is synchronous, and the HAL methods you are using are synchronous as well?
Your RX pin on your STM32 is held high which is why you get 0xFF (127) in your buffer when you call your receive function.
I think you have selected an incorrected setting in your code generator, are you using CubeIDE? If so, go to USART and choose "asynchronous" from the options and regenerate. You'll notice your handle change from husart to huart. The HAL functions for sending and transmitting are HAL_UART_Transmit() and HAL_UART_Receive(). Using these the same way in your current code will give the results you are looking for.
Related
I'm using the WebUSB API in Chrome. I can pair with the device, claim an interface, and begin listening to an inbound interrupt endpoint that transfers three bytes every time I press a button, and three more when the button is released (it's a vendor-specific MIDI implementation).
The USBTransferInResult.data.buffer contains all of the bytes it should, except they are not provided transfer-wise. The bytes are being transferred one byte at a time, unless I do something to generate a bunch of data at the same time, in which case, there may be as many as three or four bytes in the same USBTransferInResult.
Note: The maximum packet size for this endpoint is 8. I've tried setting it to stuff like 1 and 256 with no effect.
If I concatenated all of the result buffers, I'd have the exact data I'm expecting, but surely the API should make each transfer (seemingly) atomic.
This could be the result of something funky that the vendor (Focusrite - it's a Novation product) does with their non-compliant MIDI implementation. I just assumed that the vendor would prefer to transfer each MIDI message as an atomic interrupt transfer (not three one-byte transfers in rapid succession), as it would simplify the driver and make it more robust. I cannot see the advantage of breaking these messages up.
Note: If I enable the experimental-usb-backend, my USB device stops appearing in the dialog (when requestDevice is invoked).
This is the code I'm testing it with:
let DEVICE = undefined;
const connect = async function() {
/* Initialize the device, assign it to the global variable,
claim Interface 1, then invoke `listen`. */
const filters = [{vendorId: 0x1235, productId: 0x0018}];
DEVICE = await navigator.usb.requestDevice({filters});
await DEVICE.open();
await DEVICE.selectConfiguration(1);
await DEVICE.claimInterface(1);
listen();
};
const listen = async function() {
/* Recursively, listen for each interrupt transfer from
Endpoint 4, asking for upto 8 bytes each time, and then
logging each transfer (as a regular array of numbers). */
const result = await DEVICE.transferIn(4, 8);
const data = new Uint8Array(result.data.buffer);
console.log(Array.from(data));
listen();
};
// Note: The are a few lines of UI code here that provide a
// button for invoking the `connect` function above, and
// another button that invokes the `close` method of
// the USB device.
Given this issue is not reproducible without the USB device, I don't want to report it as a bug, unless I'm sure that it is one. I was hoping somebody here could help me.
Have I misunderstood the way the WebUSB API works?
Is it reasonable to assume that the vendor may have intended to break MIDI messages into individual bytes?
On reflection, the way this works may be intentional.
The USB MIDI spec is very complicated, as it seeks to accommodate complex MIDI setups, which can constitute entire networks in their own right. The device I'm hacking (the Novation Twitch DJ controller) has no MIDI connectivity, so it would have been much easier for the Novation engineers to just pass each MIDI message as USB interrupt transfers.
As for way it streams the MIDI bytes as soon as they're ready, I'm assuming this simplified the hardware, and is intended to be interpreted like bytecode. Each MIDI message begins with a status byte that indicates the number of data bytes that will follow it (analogous to an opcode, followed by some immediates).
Note: Status bytes also have a leading 1, while data bytes have a leading 0, so they are easy to tell apart (and SysEx messages use specific start and end bytes).
In the end, it was simple enough to use the status bytes to indicate when to instantiate a new message, and what type it should be. I then implemented a set of MIDI message classes (NoteOn, Control, SysEx etc) that each know when they have the right number of bytes (to simplify the logic for each individual message).
I am working on STM32L152VB-A controller. I am using FreeRTOS.
I used CubeMX to generate the code and I configured USART1 with global interrupts.
The non interrupt RX and TX (HAL_UART_Receive and HAL_UART_Transmit) is working.
But I am trying to make it work with interrupts.
Only after I called HAL_UART_Receive_IT, I am getting interrupt.
Since I couldn't know the receive data size, I am planning to receive characters one by one.
Since I use RTOS, I am confused about where to write HAL_UART_Receive_IT, as the message can come at any time. can anybody guide me??
PS: I tried calling the HAL_UART_Receive_IT inside ISR, but it is also not working.
I think you're confusing HAL_UART_Receive_IT with a function which actually receives anything. This is not the case. This function merely enables the UART peripheral and its receive interrupt.
If you want to stick with the HAL library you need to pass a struct of type UART_HandleTypeDef as parameter to HAL_UART_Receive_IT which contains
a uint8_t* pointer to a receive buffer
a transfer counter for the number of elements you'd like to receive
As far as I know there is no way for receiving elements indefinitely with this framework because once the transfer counter reaches zero the receive interrupt gets disabled automatically. So if you need this you're probably better of writing the ISR yourself by overwriting the weak function defined by ST (most likely called "UARTx_IRQHandler").
To finally integrate the receive interrupt in FreeRTOS you've got two options:
Receive data inside the ISR into a raw (uint8_t*) buffer like HAL does and use a critical section which temporarily disables the receive interrupt when accessing it.
Receive data inside the ISR into a FreeRTOS queue using the interrupt safe API. The official FreeRTOS book chapter 6 explains this very well.
I created the following task (consider a high priority):
void UARTReceiveTask(void const * argument)
{
/* USER CODE BEGIN UARTReceiveTask */
/* Infinite loop */
for(;;)
{
osSemaphoreWait(BinarySemaphoreUARTHandle, osWaitForever);
HAL_UART_Receive_IT(&huart3, message_received, 2);
}
/* USER CODE END UARTReceiveTask */
}
Then, if you are using HAL, you must know that HAL_UART_RxCpltCallback() is executed on the UART ISR, so I wrote:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
if (huart->Instance == USART3){
osSemaphoreRelease(BinarySemaphoreUARTHandle);
}
}
I only followed the tips on the "Mastering the FreeRTOS" document (Chapter 6) to deferr interrupts to tasks.
I haven´t dug deep into it, but I know this info is important if you are working with FreeRTOS and Arm Cortex systems.
Hope I helped!
I've got a sim connected to my microcontroller. The rst, i/o, and clck pins are wired correctly. There is a hardware UART on my board, but since it is full-duplex and not half, I've jumperd RX/TX together.
So far, I toggle RST according to ISO-7816, and my UART buffer fills up with the ATR the sim card responds with. Once I've received the ATR, I change the UART to TX mode and send it a PPS. After sending, I change the UART back to RX only mode. It follows the correct format as stated in ISO-7816, but I do not receive the confirmation bytes from the sim. The confirmation is supposed to be a repeat of the settings I sent.
I suppose your problem is of the same origin as I had with gsm modems.
Sending a command you get an acknowledgement from the device, then send the next command, get ack, etc, etc. Soon or later the device hangs up.
The key is the interpretation of the acknowledgement.
You may think the acknowledgement means the command is accepted AND executed. However - at least at ALL gsm modems I know - it means no more but the command was accepted and INTERPRETED - but not executed. In case of time consuming commands you send your next command during previous command is being executed. You do it because you may think acknowledgement means the command is done - but it is not true.
The device may or may not buffering cumulative commands, but soon or later the device runs out of resources and hangs up.
I have no experience with device you use but the phenomena seems to be the same.
While I'm not a protocol expert, the most likely cause seems to me, that you send PPS too early- "after sending" can be easily too early on modern microcontrollers. ISO 7816-3 states, that the guard time applies as usual and the waiting time is 9600 etu's.
Sending PPS too early means, that the card does not yet listen, which perfectly explains receiving no response at all. Wrong format would cause an error block, which should also be visible on the scope, which supports my assumption.
I have to send file byte-by-byte to serially connected AT89s52 from computer (VB.NET).
Every sended byte have some job to do in microcontroller what require some time.
Here is relevant part of my C code to receiving bytes:
SCON = 0x50;
TMOD = 0x20; // timer 1, mode 2, 8-bit reload
TH1 = 0xFD; // reload value for 9600 baud
TR1 = 1;
TI = 1;
again:
while(RI!=0)
{
P1=SBUF; // show data on led's
RI=0;
receivedBytes++;
}
if (key1==0)
{
goto exitreceive; // break receiving
}
show_lcd_received_bytes(receivedBytes);
// here is one more loop
// with different duration for every byte
goto again;
And here is VB.NET code for sending bytes:
For a As Integer = 1 To 10
For t As Integer = 0 To 255
SerialPort1.Write(Chr(t))
Next t
Next a
Problem is that mC have some job to do after every received byte and VB.NET don't know for that and send bytes too fast so in mC finishes just a part of all bytes (about 10%).
I can incorporate "Sleep(20)" in VB loop ant then thing will work but I have many of wasted time because every byte need different time to process and that would be unacceptable slow communication.
Now, my question is if 8051 can set some busy status on UART which VB can read before sending to decide to send byte or not.
Or how otherwise to setup such communication as described?
I also try to receive bytes with serial interrupt on mC side with same results.
Hardware is surely OK because I can send data to computer well (as expected).
Your problem is architectural. Don't try to do processing on the received data in the interrupt that handles byte Rx. Have your byte Rx interrupt only copy the received byte to a separate Rx data buffer, and have a background task that does the actual processing of the incoming data without blocking the Rx interrupt handler. If you can't keep up due to overall throughput issue, then RTS/CTS flow control is the appropriate mechanism. For example, when your Rx buffer gets 90% full, deassert the flow control signal to pause the transmit side.
As #TJD mentions hardware flow control can be used to stop the PC from sending characters while the microcomputer is processing received bytes. In the past I have implemented hardware flow by using an available port line as an output. The output needs to be connected to an TTL to RS-232 driver(if you are currently using a RS-232 you may have and extra driver available). If you are using a USB virtual serial port or RS-422/485 you will need to implement software flow control. Typically a control-S is sent to tell the PC to stop sending and a control-Q to continue. In order to take full advantage of flow control you most likely will need to also implement a fully interrupt driven FIFO to receive/send characters.
If you would like additional information concerning hardware flow control, check out http://electronics.stackexchange.com.
Blast from the past, I remember using break out boxes to serial line tracers debugging this kind of stuff.
With serial communication, if you have all the pins/wires utililzed then there is flow control via the RTS (Ready To Send) and DTR (Data Terminal Ready) that are used to signal when it is OK to send more data. Do you have control over that in the device you are coding via C? IN VB.NET, there are events used to receive these signals, or they can be queried using properties on the SerialPort object.
A lot of these answers are suggesting hardware flow control, but you also have the option of enhancing your transmission to be more robust by using software flow control. Currently, your communication is strong, but if you start running a higher baud rate or a longer distance or even just have a noisy connection, characters could be received that are incorrect, or characters could be dropped.
You could add a simple two-byte ACK sequence upon completion of whatever action is set to happen. It could look something like this:
Host sends command byte: <0x00>
Device echoes command byte: <0x00>
Device executes whatever action is needed
Device sends ACK/NAK byte (based on result):
This would allow you to see on the host side if communication is breaking down. The echoed character may mismatch what was sent which would alert you to an issue. Additionally, if a character is not received by the host within some timeout, the host can try retransmitting. Finally, the ACK/NAK gives you the option of returning a status, but most importantly it will let the host know that you've completed the operation and that it can send another command.
This can be extended to include a checksum to give the device a way to verify that the command received was valid (A simple logical inverse sent alongside the command byte would be sufficient).
The advantage to this solution is that it does not require extra lines or UART support on either end for hardware flow control.
I have a SPI for MSP430 written. If I send WRSR(01h) or RDSR(05h) to M25P64 flash.
The response I get from the Flash SPI_MISO is FFh.
So my question is "Is the response I have obtained is it right?"
How do I come to an understanding that handshaking between my SPI and Flash is correct?
Thanks
AK
Is the response I have obtained is it right?
The response is wrong. 30 seconds on Google and in the datasheet will tell you that. Things to check (since you have not provided any information):
How do I come to an understanding that handshaking between my SPI and Flash is correct?
Is this a new piece of SPI code? If so have you checked with an oscilloscope to see what you send out (clock and MOSI) is what you expect and matches what the datasheet says the device expects? It's the definitive way to be sure.
Does your SPI code work with any other devices?
Are your IO pins configured correctly on the MSP430?
Have you got the SPI module configured correctly for phase and polarity?
Did you forget to assert the chip select line?
What about HOLD?
Did you remember to send a dummy byte after the RDSR command so that the device would send the status register value?
Do you see a response from the device on an oscilloscope? Does the MSP430 read that value or a different one?
You are sometimes better first of all trying to read the device ID rather than the status register for a new piece of code. The reason for that is the device ID will never change, whereas the status register might change (although that depends on the device).