RSS订阅信息安全技术跟踪与研究:技术、平台、会议、论文、产业
你现在的位置:首页 / 技术积累 / 正文

PC与MSP430G2553通过UART通信编程实践

0 技术积累 | 2016年6月15日
转载申明:本站原创,欢迎转载。但转载时请保留原文地址。
原文地址:http://www.vonwei.com/post/PCUartWithMSP430.html

         Windows PC主机上通过串口COM**与微控制器进行通信,Windows主机的程序通过Visual Studio编译,微控制器为MSP430G2553通过CCS编译和下载。

         通过USB线连接MSP430 LaunchPad后,Windows主机端的设备管理中多个了端口如下:

1. Windows串口编程基本操作

         打开串口需要使用CreateFile()函数,Windows通过句柄Handles控制所有资源,打开成功后CreateFile函数会返回一个有效句柄,最后关闭串口连接时调用CloseHandle()函数关闭该句柄即可。

         这些Win32 API函数都包含在Windows.h中,因此需要#include该头文件,CreateFile函数有7个参数,典型的串口打开方式如下:

         hComm = CreateFile(“\\\\.\\COM10”,                //port name

                      GENERIC_READ | GENERIC_WRITE, //Read/Write

                      0,                            // No Sharing

                      NULL,                         // No Security

                      OPEN_EXISTING,// Open existing port only

                      0,            // Non Overlapped I/O

                      NULL);        // Null for Comm Devices

        

         Windows系统中,设置串口的波特率、比特位、数据格式通过DCB数据结构进行,GetCommState()函数可以获得串口的当前设置,SetCommState()函数可以使用新的DCB结构值设置串口,典型的设置过程如下:

         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 = CBR_9600;      // Setting BaudRate = 9600,波特率

         dcbSerialParams.ByteSize = 8;             // Setting ByteSize = 8,字节大小

         dcbSerialParams.StopBits = ONESTOPBIT;    // 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");

         }

 

         超时设置(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   Error! in Setting Time Outs");

         else

                   printf("\n\n   Setting Serial Port Timeouts Successfull");

 

         向串口写数据,通过WriteFile()函数即可,典型的写操作如下(写一个字符A):

         char lpBuffer[] = "A";

         DWORD dNoOFBytestoWrite;         // No. of bytes to write into the port

         DWORD dNoOfBytesWritten = 0;     // No. of bytes written to the port

         dNoOFBytestoWrite = sizeof(lpBuffer);

 

         Status = WriteFile(hComm,        // Handle to the Serial port,打开的串口句柄

                   lpBuffer,     // Data to be written to the port,要写的数据缓冲区

                   dNoOFBytestoWrite,  //No. of bytes to write,想要写的字节数

                   &dNoOfBytesWritten, //Bytes written,实际写的字节数

                   NULL);

 

         类似写,从串口读数据是使用ReadFile函数,接受数据有两种方式:方法一是不断的轮询串口,看是否能读到数据,这样比较耗资源;方法二是设置一个事件机制,等到有数据时让Windows系统通知我们接受。下面介绍基于事件机制的读数据过程:

         //SetCommMash函数用来设置事件,对串口设备进行监视,参数hComm是打开的串口句柄,EV_RXCHAR是字符接收事件

         Status = SetCommMask(hComm, EV_RXCHAR); //Configure Windows to Monitor the serial device for Character Reception

         if (Status == FALSE)

                   printf("\n\n    Error! in Setting CommMask");

         else

                   printf("\n\n    Setting CommMask successfull");

        

         //函数WaitCommEvent等待设置的世界发生,该函数返回时就可以调用ReadFile读数据了

         Status = WaitCommEvent(hComm, &dwEventMask, NULL); //Wait for the character to be received

         if (Status == FALSE)

         {

                   printf("\n    Error! in Setting WaitCommEvent()");

         }

         else //If  WaitCommEvent()==True Read the RXed data using ReadFile();

         {

                   printf("\n\n    Characters Received");

                   do

                   {

                            Status = ReadFile(hComm, &TempChar, sizeof(TempChar), &NoBytesRead, NULL);

                            SerialBuffer[i] = TempChar;

                            i++;

                   }while (NoBytesRead > 0);

         }//end else       

 

2. PCMSP430UART通信:PC写,MSP430

PC端代码:

void writetoUART()

{

    HANDLE hComm;                          // Handle to the Serial port

    char   ComPortName[] = "\\\\.\\COM10"; // Name of the Serial port(May Change) to be opened,

    BOOL   Status;

       

    printf("\n\n +==========================================+");

    printf("\n |  Serial Transmission (Win32 API)         |");

    printf("\n +==========================================+\n");

/*----------------------------------- Opening the Serial Port --------------------------------------------*/

 

    hComm = CreateFileA( ComPortName,                       // Name of the Port to be Opened

                        GENERIC_READ | GENERIC_WRITE,      // Read/Write Access

                        0,                                 // No Sharing, ports cant be shared

                        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", ComPortName);

    else

        printf("\n   Port %s Opened\n ", ComPortName);

 

       

/*------------------------------- Setting the Parameters for the SerialPort ------------------------------*/

 

    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 = CBR_9600;      // Setting BaudRate = 9600

    dcbSerialParams.ByteSize = 8;             // Setting ByteSize = 8

    dcbSerialParams.StopBits = ONESTOPBIT;    // 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

    {

        printf("\n   Setting DCB Structure Successfull\n");

        printf("\n       Baudrate = %d", 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   Error! in Setting Time Outs");

    else

        printf("\n\n   Setting Serial Port Timeouts Successfull");

 

       

/*----------------------------- Writing a Character to Serial Port----------------------------------------*/

    char   lpBuffer[] = "A";               // lpBuffer should be  char or byte array, otherwise write wil fail

    DWORD  dNoOFBytestoWrite;              // No of bytes to write into the port

    DWORD  dNoOfBytesWritten = 0;          // No of bytes written to the port

       

    dNoOFBytestoWrite = sizeof(lpBuffer); // Calculating the no of bytes to write into the port

 

    Status = WriteFile(hComm,               // Handle to the Serialport

                           lpBuffer,            // Data to be written to the port

                           dNoOFBytestoWrite,   // No of bytes to write into the port

                           &dNoOfBytesWritten,  // No of bytes written to the port

                           NULL);

       

    if (Status == TRUE)

        printf("\n\n    %s - Written to %s", lpBuffer, ComPortName);

    else

        printf("\n\n   Error %d in Writing to Serial Port",GetLastError());

 

    CloseHandle(hComm);//Closing the Serial Port

    printf("\n ==========================================\n");

    //getchar();

}

 

MSP430G2553端代码:

#include <msp430.h>

 

/*

 * main.c

 */

int main(void) {

    WDTCTL = WDTPW | WDTHOLD;    // Stop watchdog timer

 

    //Configure the Clocks, DCO@1MHz,SMCLK@1MHz

    if(CALBC1_1MHZ == 0xFF)

     while(1);  //if calibration constant erased, do not load, trap CPU!

    DCOCTL = 0;

    BCSCTL1 = CALBC1_1MHZ;

    DCOCTL = CALDCO_1MHZ;

 

    //Configure the Ports: Setting the UART function for P1.1&P1.2, Setting the direction for P1.0 and P1.6

    P1SEL  |=  BIT1 + BIT2;  // P1.1 UCA0RXD input

    P1SEL2 |=  BIT1 + BIT2;  // P1.2 UCA0TXD output

 

    P1DIR  |=  BIT0 + BIT6;  // P1.0 and P1.6 output

    P1OUT  &= ~BIT0 + BIT6;  // clear,P1.0 and P1.6 = 0

 

    //Configure USCI_A0 in UART mode

    UCA0CTL1 |=  UCSSEL_2 + UCSWRST;  // USCI Clock = SMCLK,USCI_A0 disabled

    UCA0BR0   =  104;                 // 104 From datasheet table-

    UCA0BR1   =  0;                   // -selects baudrate =9600,clk = SMCLK

    UCA0MCTL  =  UCBRS_6;             // Modulation value = 6 from datasheet ------UCBRS_6

    UCA0CTL1 &= ~UCSWRST;             // Clear UCSWRST to enable USCI_A0

 

    //Configure USCI_A0 interrupts

    IE2 |= UCA0RXIE;                  // Enable the Receive  interrupt

    _BIS_SR(LPM0_bits + GIE);         // Going to LPM0 while enable the global interrupt

   

    return 0;

}

 

//USCI_A0 Receive ISR

#pragma vector = USCIAB0RX_VECTOR

  __interrupt void ReceiveInterrupt(void)

{

   IFG2 &= ~UCA0RXIFG; // Clear RX flag

   switch(UCA0RXBUF)

   {

   case 'A': //Blinking LED1 to signal,连续闪烁两次

       P1OUT ^= BIT0; //LED1 on

       __delay_cycles(250000);

       P1OUT ^= BIT0; //LED1 off

       __delay_cycles(250000);

       P1OUT ^= BIT0; //LED1 on

       __delay_cycles(250000);

       P1OUT ^= BIT0; //LED1 off

       break;

   case 'B'://Blinking LED2,闪烁一次

       P1OUT ^= BIT6;

       __delay_cycles(250000);

       P1OUT ^= BIT6;

       break;

   }

}

 

测试结果:

         PC端发送A时,MSP430设备上的LED1红灯会连续闪烁两次;

         修改PC端代码发送B时,MSP430设备上的LED2绿灯会闪一下。

 

3. PCMSP430UART通信:PC读,MSP430

PC端代码:

void readfromUART()

{

    HANDLE hComm;                          // Handle to the Serial port

    char  ComPortName[] = "\\\\.\\COM10"// Name of the Serial port(May Change) to be opened,

    BOOL  Status;                          // Status of the various operations

    DWORD dwEventMask;                     // Event mask to trigger

    char  TempChar;                        // Temperory Character

    char  SerialBuffer[256];               // 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 = CreateFileA( ComPortName,                  // Name of the Port to be Opened

                        GENERIC_READ | GENERIC_WRITE, // Read/Write Access

                        0,                            // No Sharing, ports cant be shared

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

 

/*------------------------------- Setting the Parameters for the SerialPort ------------------------------*/

           

    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 = CBR_9600;      // Setting BaudRate = 9600

    dcbSerialParams.ByteSize = 8;             // Setting ByteSize = 8

    dcbSerialParams.StopBits = ONESTOPBIT;    // 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 = %d", 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 ----------------------------------------------*/

           

    Status = SetCommMask(hComm, EV_RXCHAR); //Configure Windows to Monitor the serial device for Character Reception

   

    if (Status == FALSE)

        printf("\n\n    Error! in Setting CommMask");

    else

        printf("\n\n    Setting CommMask successfull");

 

           

/*------------------------------------ Setting WaitComm() Event   ----------------------------------------*/

           

    printf("\n\n    Waiting for Data Reception");

 

    Status = WaitCommEvent(hComm, &dwEventMask, NULL); //Wait for the character to be received

   

/*-------------------------- Program will Wait here till a Character is received ------------------------*/             

 

    if (Status == FALSE)

    {

        printf("\n    Error! in Setting WaitCommEvent()");

    }

    else //If  WaitCommEvent()==True Read the RXed data using ReadFile();

    {

        printf("\n\n    Characters Received");

        do

        {

            Status = ReadFile(hComm, &TempChar, sizeof(TempChar), &NoBytesRead, NULL);

            SerialBuffer[i] = TempChar;

            i++;

        }while (NoBytesRead > 0);

 

                   

 

/*------------Printing the RXed String to Console----------------------*/

 

        printf("\n\n    ");

        int j =0;

        for (j = 0; j < i-1; j++)       // j < i-1 to remove the dupliated last character

            printf("%c", SerialBuffer[j]);

       

    }//end else

       

    CloseHandle(hComm);//Closing the Serial Port

    printf("\n +==========================================+\n");

    //getchar();

}

 

MSP430端代码:

#include <msp430.h>

 

/*

 * main.c

 */

int main(void) {

    WDTCTL = WDTPW | WDTHOLD;    // Stop watchdog timer

 

    //Configure the Clocks, DCO@1MHz,SMCLK@1MHz

    if(CALBC1_1MHZ == 0xFF)

     while(1);  //if calibration constant erased, do not load, trap CPU!

    DCOCTL = 0;

    BCSCTL1 = CALBC1_1MHZ;

    DCOCTL = CALDCO_1MHZ;

 

    //Configure the Ports: Setting the UART function for P1.1&P1.2, Setting the direction for P1.0 and P1.6

    P1SEL  |=  BIT1 + BIT2;  // P1.1 UCA0RXD input

    P1SEL2 |=  BIT1 + BIT2;  // P1.2 UCA0TXD output

 

    P1DIR  |=  BIT0 + BIT6;  // P1.0 and P1.6 output

    P1OUT  &= ~BIT0 + BIT6;  // clear,P1.0 and P1.6 = 0

    //Enabling MAX485 in Transmit mode

    //P2DIR |= BIT0 + BIT1;   // P2.0 -> DE,P2.1 -> ~RE Output

    //P2OUT  |= BIT0; //P2.0 -> DE (high)

    //P2OUT  |= BIT1; //P2.1 -> ~RE (high) RE is active Low

 

    //Configure USCI_A0 in UART mode

    UCA0CTL1 |=  UCSSEL_2 + UCSWRST;  // USCI Clock = SMCLK,USCI_A0 disabled

    UCA0BR0   =  104;                 // 104 From datasheet table-

    UCA0BR1   =  0;                   // -selects baudrate =9600,clk = SMCLK

    UCA0MCTL  =  UCBRS_0;             // Modulation value = 6 from datasheet ------UCBRS_6

    UCA0CTL1 &= ~UCSWRST;             // Clear UCSWRST to enable USCI_A0

 

    //Send Message through UART---UCA0TXBUF

    //UCA0TXBUF = 'C';

    char TextMessage[50] = "MSP430 Say Hello to Host! \n";

    char Count = 0;

    while(TextMessage[Count] != '\0')

    {

     while(!(UCA0TXIFG & IFG2));// USCI_A0 TX buffer ready?

     UCA0TXBUF = TextMessage[Count];

     Count++;

    }

 

    _BIS_SR(LPM0_bits + GIE);         // Going to LPM0 while enable the global interrupt

   

    return 0;

}

 

测试结果PC端成功接收到设备端发送的字符串,如下


 

说明:

         上述代码,PC端在VS2010下编译成功,MSP430CCS 版本6.1.2.00015下编译成功。代码本身与IDE工具没有关系,使用其它IDE应该不算难事。

         MSP430端代码的理解,可以参考前一篇博文。

研究UART串口通信的目的,主要是为了修改MSP430boot过程,使得能对MSP430进行镜像更新,PC主机可以将生成的最新应用镜像通过UART发送给MSP430boot代码,boot代码替换对应的镜像,即可完成最终镜像更新过程。最终目的是要设计安全更新协议,保护整个更新过程的安全。UART通信跑通是第一步。

 

 参考:

http://xanthium.in/Serial-Port-Programming-using-Win32-API

https://github.com/xanthium-enterprises/Serial-Programming-Win32API-C




  • ------------------分隔线----------------

  • 如果感兴趣,欢迎关注本站微信号,跟踪最新博文信息,手机微信扫一扫下面的二维码,即可关注!
  • 微月信公众号
  • 推荐您阅读更多有关于“ 嵌入式设备  UART  串口通信   ”的文章

    请填写你的在线分享代码
    上一篇:MSP430的UART串口通信详解下一篇:操作系统概念理解与答疑

    猜你喜欢

    评论列表:

    发表评论

    必填

    选填

    选填

    必填,不填不让过哦,嘻嘻。

    记住我,下次回复时不用重新输入个人信息

    本站介绍
    最近发表
    本年最热文章
    本月最热文章
    网站分类
    文章归档