与臂微控制器的串行通信 [英] serial communication with arm microcontroller

查看:287
本文介绍了与臂微控制器的串行通信的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过usb从arm cortrx m4微控制器发送数据。有一个用C ++语言编写的代码块中的程序。基本上该程序设置串行通信设置并使用ReadFile功能读取数据。
问题是,即使pc程序和微控制器中的波特率相同,我也会在输出中获取垃圾值。

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?

pc程序如下所示。

#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为连续发送在港口。

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

< img src =https://i.stack.imgur.com/X8wtf.jpgalt =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++;
      }
}


推荐答案

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

此代码不正确。我怀疑你一直在覆盖UART tx缓冲区,很久以前UART才有机会发送任何东西。

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++)
  {}
}

volatile关键字可防止编译器优化整个功能。

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

正确的方法是,不要使用这样的钝器延迟,而是观察UART硬件的发送器忙标志。在UART状态寄存器中找到,无论是为特定的微控制器调用哪一个。

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.

伪代码:

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

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

这篇关于与臂微控制器的串行通信的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆