Problem Writing to ATMEGA328P USART from MATLAB

10 views (last 30 days)
To start off, I am using an ATMEGA328P Xplained Mini board. I am writing an "echo" program on the AVR in C and in MATLAB. The MATLAB code sends a value (3) to the USART of the AVR asynchronously (via USB), and the AVR code receives the data and sends it back via USART to the MATLAB program, which stores the received value and prints it to the command window in MATLAB.
My problem is that unless I add a time-delay ( pause(1) on line 8 of the MATLAB program ) after calling the fopen() function, the AVR will not receive the data sent by MATLAB using the fwrite() function, and the MATLAB code will stay forever in the "while Bytes.Available == 0" loop. To be clear, the time delay solves the problem. However, I want to know why I need to add the delay. I have read through the datasheet of the 328P and several MATLAB documents, and I suspect that there must be some sort of time for the connection between MATLAB and the USART to stabilize. I hope that by understanding why the time delay solves the problem, that I can properly handle the issue and reduce the amount of time per transmission cycle.
Is there some pin or property that I can poll that will tell me that the AVR is ready to be sent to (similar to a CTS pin)? Or is this even the problem? I could be completely wrong with my thinking that the AVR is suspect; maybe it is MATLAB that is the problem. I appreciate any insight!
Here is the MATLAB Code:
PORT = 'COM4'; % Change as necessary
BAUD = 9600;
BITS = 8; % Number of data bits
AVR = serial(PORT, 'BaudRate', BAUD, 'DataBits', BITS);
fopen(AVR);
pause(1);
fwrite(AVR, 3, 'async');
while AVR.BytesAvailable == 0
end
% Store AVR response in variable 'response'
response = fread(AVR, AVR.BytesAvailable, 'uint8');
% Display received data on command line
disp('AVR:');
disp(response);
fclose(AVR);
delete(AVR);
clear AVR;
Here is the AVR C Code:
#define F_CPU 16000000UL
#define BAUD 9600
#define MYUBRR F_CPU/16/BAUD-1
#include <avr/io.h>
#include <util/delay.h>
void USART_Init( unsigned int );
void USART_Transmit( unsigned char );
unsigned char USART_Receive( void );
int main(void)
{
unsigned char data0;
USART_Init(MYUBRR);
while(1)
{
data0 = USART_Receive();
USART_Transmit(data0);
}
}
void USART_Init( unsigned int ubrr )
{
/* Set baud rate */
UBRR0H = (unsigned char)(ubrr>>8);
UBRR0L = (unsigned char)ubrr;
/* Enable receiver and transmitter */
UCSR0B = (1<<RXEN0)|(1<<TXEN0);
/* Set frame format: 8data, 1stop bit */
UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
}
void USART_Transmit( unsigned char data )
{
/* Wait for empty transmit buffer */
while ( !( UCSR0A & (1<<UDRE0)) )
{
}
/* Put data into buffer, sends the data */
UDR0 = data;
}
unsigned char USART_Receive( void )
{
/* Wait for data to be received */
while ( !(UCSR0A & (1<<RXC0)) )
{
}
/* Get and return received data from buffer */
return UDR0;
}

Answers (1)

Ashwini Venkatappa
Ashwini Venkatappa on 3 Aug 2016
Edited: Hans Scharler on 20 Jul 2018
In order to establish the serial communication, MATLAB takes some time(in the order of 50 milliseconds). Hence the pause command is necessary. If the pause is removed, the fwrite command is issued before the serial connection is acknowledged by the board. Hence the data is never received by the board and the program remains in the while loop waiting for data. A delay of the order of 50 msec might work but you may need to tune it to a higher/lower value.'
MATLAB has Arduino support package, which provides libraries for configuring and accessing Arduino sensors, communication interfaces etc. You could download it from the link below: http://www.mathworks.com/discovery/arduino-programming-matlab-simulink.html

Categories

Find more on MATLAB Support Package for Arduino Hardware in Help Center and File Exchange

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!