与arm微控制器的串行通信

时间:2017-01-26 18:59:53

标签: c++ c embedded codeblocks keil

我正试图通过usb将arm cortrx m4微控制器的数据发送到pc。在codeblocks ide中有一个用C ++语言编写的程序。基本上,程序使用ReadFile函数设置串行通信设置和读取数据。 问题是即使pc proogram和微控制器中的波特率相同,我也会在输出端得到垃圾值。

我该如何解决这个问题?

电脑程序如下所示。

#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");

}

此处显示在端口上连续发送char时打印的垃圾值的图像。

serial-read output

微控制器代码如下所示。

#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 个答案:

答案 0 :(得分:1)

UART_OutChar('s');
delay(10000);

此代码不正确。我怀疑你在UART有机会发送任何东西之前很久就会一遍又一遍地覆盖UART tx缓冲区。

首先,你不能写那样的延迟函数。编译器可以随意对其进行优化,因为它无法发现任何副作用。一般来说,你应该将“倦怠时间”循环视为穷人的延迟,但如果你出于某种原因必须使用它们,则必须这样写:

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

volatile关键字阻止编译器优化掉整个函数。

这样做的正确方法是,根本不使用这种钝性延迟,而是观察UART硬件的发送器忙标志。它可以在UART状态寄存器中找到,无论您为特定的微控制器调用它。

伪代码:

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

  /* can do other things here in the meantime */
}