serial communication with arm microcontroller

2019-09-07 03:48发布

I am trying to send data from the arm cortrx m4 microcontroller to pc through usb. There is a program written in C++ language in codeblocks ide. Basically the program sets the serial communication settings and read data using ReadFile function. The problem is I am getting garbage values at the output even if the baud rate in pc proogram and microcontroller is same.

How can I solve this problem?

The pc program is shown below.

#include <Windows.h>
#include <stdio.h>

int main(void)
{
HANDLE hComm;                          // Handle to the Serial port
char  ComPortName[] = "\\\\.\\COM51";  // Name of the Serial port to be opened,
BOOL  Status;                          // Status of the various operations
DWORD dwEventMask;                     // Event mask to trigger
char  TempChar;                        // Temperory Character
char  SerialBuffer[26];               // Buffer Containing Rxed Data
DWORD NoBytesRead;                     // Bytes read by ReadFile()
int i = 0;

printf("\n\n +==========================================+");
printf("\n |    Serial Port  Reception (Win32 API)    |");
printf("\n +==========================================+\n");
/*---------------------------------- Opening the Serial Port -----------*/

hComm = CreateFile( ComPortName,         // Name of the Port to be Opened
                    GENERIC_READ | GENERIC_WRITE, // Read/Write Access
                    0,                            // No Sharing
                    NULL,                         // No Security
                    OPEN_EXISTING,                // Open existing port only
                    0,                            // Non Overlapped I/O
                    NULL);                        // Null for Comm Devices

if (hComm == INVALID_HANDLE_VALUE)
    printf("\n    Error! - Port %s can't be opened\n", ComPortName);
else
printf("\n    Port %s Opened\n ", ComPortName);


DCB dcbSerialParams = { 0 };               // Initializing DCB structure
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);

Status = GetCommState(hComm, &dcbSerialParams);    //retreives the current settings

if (Status == FALSE)
    printf("\n    Error! in GetCommState()");

        dcbSerialParams.BaudRate = 115200;      // Setting BaudRate = 115200
        dcbSerialParams.ByteSize = 8;             // Setting ByteSize = 8
        dcbSerialParams.StopBits = ONE5STOPBITS;    // Setting StopBits = 1
        dcbSerialParams.Parity = NOPARITY;        // Setting Parity = None

Status = SetCommState(hComm, &dcbSerialParams);  //Configuring the port according to settings in DCB

        if (Status == FALSE)
            {
                printf("\n    Error! in Setting DCB Structure");
            }
        else //If Successfull display the contents of the DCB Structure
            {
                printf("\n\n    Setting DCB Structure Successfull\n");
                printf("\n       Baudrate = %ld", dcbSerialParams.BaudRate);
                printf("\n       ByteSize = %d", dcbSerialParams.ByteSize);
                printf("\n       StopBits = %d", dcbSerialParams.StopBits);
                printf("\n       Parity   = %d", dcbSerialParams.Parity);
            }

        //----------------- Setting Timeouts ----------------------------

        COMMTIMEOUTS timeouts = { 0 };
        timeouts.ReadIntervalTimeout         = 50;
        timeouts.ReadTotalTimeoutConstant    = 50;
        timeouts.ReadTotalTimeoutMultiplier  = 10;
        timeouts.WriteTotalTimeoutConstant   = 50;
        timeouts.WriteTotalTimeoutMultiplier = 10;

        if (SetCommTimeouts(hComm, &timeouts) == FALSE)
            printf("\n\n    Error! in Setting Time Outs");
        else
            printf("\n\n    Setting Serial Port Timeouts Successfull");

//-------------- Setting Receive Mask -------------------------------


if (!SetCommMask(hComm, EV_RXCHAR))
    printf("\n\n    Error! in Setting CommMask");      // Error setting communications event mask
else
    printf("\n\n    Setting CommMask successfull");


    i = 0;
    printf("\n\n    Waiting for Data Reception");

    if (WaitCommEvent(hComm, &dwEventMask, NULL))
    {
         printf("\n\n    Characters Received\n");
         do
         {
                    if (ReadFile(hComm, &TempChar, 1, &NoBytesRead, NULL))
                    {
                        // A byte has been read; process it.
                        SerialBuffer[i] = TempChar;
                        //printf("\n%c\n", TempChar);
                        if(TempChar == 's')
                            printf("\ndone\n");
                        i++;

                    }
                    else
                    {
                        // An error occurred in the ReadFile call.
                        break;
                    }
                } while (NoBytesRead);
            }

int j =0;
for (j = 0; j < i-1; j++)       // j < i-1 to remove the dupliated last character
printf("%c", SerialBuffer[j]);

CloseHandle(hComm);//Closing the Serial Port
printf("\n +==========================================+\n");

}

Here image showing the garbage value printed when the char s is continuosly sent on the port.

serial-read output

The microcontroller code goes below.

#include "PLL.h"
#include "UART.h"

#define GPIO_PORTF_DATA_R       (*((volatile unsigned long *)0x400253FC))
#define GPIO_PORTF_DIR_R        (*((volatile unsigned long *)0x40025400))
#define GPIO_PORTF_AFSEL_R      (*((volatile unsigned long *)0x40025420))
#define GPIO_PORTF_PUR_R        (*((volatile unsigned long *)0x40025510))
#define GPIO_PORTF_DEN_R        (*((volatile unsigned long *)0x4002551C))
#define GPIO_PORTF_LOCK_R       (*((volatile unsigned long *)0x40025520))
#define GPIO_PORTF_CR_R         (*((volatile unsigned long *)0x40025524))
#define GPIO_PORTF_AMSEL_R      (*((volatile unsigned long *)0x40025528))
#define GPIO_PORTF_PCTL_R       (*((volatile unsigned long *)0x4002552C))
#define SYSCTL_RCGC2_R          (*((volatile unsigned long *)0x400FE108))

unsigned long In;  // input from PF4


// time delay
void delay(int value)
{
    while(value){
    value--;}
}
//debug code
int main(void)
{
    unsigned char i;
    char string[20];          // global to assist in debugging
    unsigned long n;
    unsigned char c;
    char text[10] = "Hello!";
    unsigned long count;


    SYSCTL_RCGC2_R |= 0x00000020;     // 1) F clock
    //delay = SYSCTL_RCGC2_R;           // delay   
    GPIO_PORTF_LOCK_R = 0x4C4F434B;   // 2) unlock PortF PF0  
    GPIO_PORTF_CR_R = 0x1F;           // allow changes to PF4-0       
    GPIO_PORTF_AMSEL_R = 0x00;        // 3) disable analog function
    GPIO_PORTF_PCTL_R = 0x00000000;   // 4) GPIO clear bit PCTL  
    GPIO_PORTF_DIR_R = 0x0E;         // 5) PF4,PF0 input, PF3,PF2,PF1 output   
    GPIO_PORTF_AFSEL_R = 0x00;        // 6) no alternate function
    GPIO_PORTF_PUR_R = 0x11;          // enable pullup resistors on PF4,PF0       
    GPIO_PORTF_DEN_R = 0x1F;          // 7) enable digital pins PF4-PF0        


    PLL_Init();
    UART_Init();              // initialize UART


      n = 0;
      while(n < 10)
      {
          UART_OutChar('s');
          delay(10000);
          n++;
      }
}

1条回答
在下西门庆
2楼-- · 2019-09-07 04:41
UART_OutChar('s');
delay(10000);

This code is not correct. I suspect you keep overwriting the UART tx buffer over and over, long before the UART is given a chance to send anything at all.

First of all, you can't write the delay function like that. The compiler is free to optimize it all away, as it can't spot any side-effects. Generally, you should away "burn-away time" loops as poor man's delays, but if you for some reason must use them, they have to be written like this:

void delay(int value)
{
  for(volatile int i=0; i<value; i++)
  {}
}

The volatile keyword prevents the compiler from optimizing away the whole function.

The correct way to do this though, is not to use such blunt delays at all, but instead watch the transmitter busy flag of your UART hardware. It is found in the UART status register, whatever that one is called for your specific microcontroller.

Pseudo code:

n = 0;
while(n < 10)
{
  if((UART_SR & TX_BUSY) == 0)
  {
    UART_OutChar('s');
    n++;
  }

  /* can do other things here in the meantime */
}
查看更多
登录 后发表回答