• UART Communication using PIC Microcontroller - Giao tiếp UART sử dụng Vi điều khiển PIC

QC

UART Communication using PIC Microcontroller - Giao tiếp UART sử dụng Vi điều khiển PIC

 


Trong hướng dẫn này, chúng ta học cách Bật giao tiếp UART với Vi điều khiển PIC và cách truyền dữ liệu đến và đi từ Máy tính của bạn. Cho đến nay, chúng tôi đã đề cập đến tất cả các mô-đun cơ bản như ADC, Timers, PWM và cũng đã học cách giao tiếp với màn hình LCD và màn hình 7-Segment. Bây giờ, chúng tôi sẽ tự trang bị cho mình một công cụ giao tiếp mới gọi là UART được sử dụng rộng rãi trong hầu hết các dự án Vi điều khiển. Xem tại đây Hướng dẫn sử dụng vi điều khiển PIC hoàn chỉnh của chúng tôi bằng MPLAB và XC8.


Ở đây chúng tôi đã sử dụng MCU PIC16F877A, nó có một mô-đun được gọi là “Bộ thu và phát không đồng bộ đa năng có thể định địa chỉ” được gọi ngắn gọn là USART. USART là một hệ thống giao tiếp hai dây, trong đó dữ liệu được lưu chuyển theo thứ tự. USART cũng là một giao tiếp song công, có nghĩa là bạn có thể gửi và nhận dữ liệu cùng một lúc, dữ liệu này có thể được sử dụng để giao tiếp với các thiết bị ngoại vi, chẳng hạn như thiết bị đầu cuối CRT và máy tính cá nhân.


USART có thể được định cấu hình ở các chế độ sau:


Không đồng bộ (song công)

Đồng bộ - Chính (bán song công)

Đồng bộ - Slave (bán song công)

Ngoài ra còn có hai chế độ khác nhau là chế độ 8-bit và 9-bit, trong hướng dẫn này chúng ta sẽ cấu hình mô-đun USART để hoạt động ở chế độ Không đồng bộ với hệ thống giao tiếp 8-bit, vì đây là kiểu giao tiếp được sử dụng nhiều nhất. Vì nó không đồng bộ nên không cần gửi tín hiệu đồng hồ cùng với các tín hiệu dữ liệu. UART sử dụng hai đường dữ liệu để gửi (Tx) và nhận (Rx) dữ liệu. Mặt đất của cả hai thiết bị cũng nên được làm cho chung. Loại giao tiếp này không chia sẻ đồng hồ chung do đó điểm chung là rất quan trọng để hệ thống hoạt động.



Vào cuối hướng dẫn này, bạn sẽ có thể thiết lập giao tiếp (UART) giữa máy tính và Bộ vi điều khiển PIC và bật tắt đèn LED trên bo mạch PIC từ máy tính xách tay của bạn. Trạng thái của đèn LED sẽ được gửi đến máy tính xách tay của bạn từ MCU PIC. Chúng tôi sẽ kiểm tra đầu ra bằng Hyper Terminal trên máy tính. Video chi tiết cũng được cung cấp ở cuối hướng dẫn này.

Requirements:

Hardware:

  • PIC16F877A Perf Board
  • RS232 to USB converter Module
  • Computer
  • PICkit 3 Programmer

Software:

  • MPLABX
  • HyperTerminal


Cần có bộ chuyển đổi RS232 sang USB để chuyển đổi dữ liệu nối tiếp sang dạng máy tính có thể đọc được. Có nhiều cách để thiết kế mạch của riêng bạn thay vì mua mô-đun của riêng bạn nhưng chúng không đáng tin cậy vì chúng bị nhiễu. Cái mà chúng tôi đang sử dụng được hiển thị bên dưới



Lưu ý: Mỗi bộ chuyển đổi RS232 sang USB sẽ yêu cầu cài đặt một trình điều khiển đặc biệt; hầu hết chúng sẽ được cài đặt tự động ngay khi bạn cắm thiết bị vào. Nhưng, nếu nó không thư giãn !!! Sử dụng phần bình luận và tôi sẽ giúp bạn.


Programming PIC Microcontroller for UART Communication:

Giống như tất cả các mô-đun (ADC, Timer, PWM), chúng ta cũng nên khởi tạo mô-đun USART của MCU PIC16F877A của chúng tôi và hướng dẫn nó hoạt động ở chế độ giao tiếp 8-bit UART. Hãy xác định các bit cấu hình và bắt đầu với chức năng khởi tạo UART.


Khởi tạo mô-đun UART của Vi điều khiển PIC:


Các chân Tx và Rx có mặt vật lý ở các chân RC6 và RC7. Theo biểu dữ liệu, hãy khai báo TX là đầu ra và RX là đầu vào.


    //****Setting I/O pins for UART****//
    TRISC6 = 0; // TX Pin set as output
    TRISC7 = 1; // RX Pin set as input
    //________I/O pins set __________//


Bây giờ tốc độ truyền phải được thiết lập. Tốc độ truyền là tốc độ truyền thông tin trong một kênh truyền thông. Đây có thể là một trong nhiều giá trị mặc định, nhưng trong chương trình này, chúng tôi đang sử dụng 9600 vì tốc độ truyền được sử dụng nhiều nhất.

  /**Initialize SPBRG register for required 
    baud rate and set BRGH for fast baud_rate**/
    SPBRG = ((_XTAL_FREQ/16)/Baud_rate) - 1;
    BRGH  = 1;  // for high baud_rate
    //_________End of baud_rate setting_________//

Giá trị của tốc độ truyền phải được đặt bằng cách sử dụng thanh ghi SPBRG, giá trị phụ thuộc vào giá trị của tần số tinh thể Ngoài, công thức tính tốc độ truyền được hiển thị dưới đây:

SPBRG = ( ( _XTAL_FREQ/16 ) / Baud_rate) – 1;
Bit BRGH phải được làm cao để cho phép tốc độ bit cao. Theo biểu dữ liệu (trang 13), việc kích hoạt nó luôn có lợi vì nó có thể loại bỏ lỗi trong quá trình giao tiếp.

Như đã nói trước đó, chúng tôi sẽ làm việc ở chế độ Không đồng bộ, do đó, SYNC bit phải được đặt bằng 0 và bit SPEM phải được đặt ở mức cao để kích hoạt các chân nối tiếp (TRISC6 và TRICSC5)
    //****Enable Asynchronous serial port*******//
    SYNC  = 0;    // Asynchronous
    SPEN  = 1;    // Enable serial port pins
    //_____Asynchronous serial port enabled_______//
Trong hướng dẫn này, chúng ta sẽ gửi và nhận dữ liệu giữa MCU và máy tính, do đó chúng ta phải bật cả bit TXEN và CREN.
    //**Lets prepare for transmission & reception**//
    TXEN  = 1;    // enable transmission
    CREN  = 1;    // enable reception
    //__UART module up and ready for transmission and reception__//

Các bit TX9 và RX9 phải được làm bằng 0 để chúng tôi hoạt động ở chế độ 8 bit. Nếu cần phải thiết lập độ tin cậy cao thì có thể chọn chế độ 9 bit.


    //**Select 8-bit mode**//  
    TX9   = 0;    // 8-bit reception selected
    RX9   = 0;    // 8-bit reception mode selected
    //__8-bit mode selected__//   


Với điều này, chúng tôi hoàn thành thiết lập khởi tạo của chúng tôi. Bây giờ Mô-đun được định cấu hình là UART và sẵn sàng hoạt động.


Truyền dữ liệu bằng UART:


Chức năng dưới đây có thể được sử dụng để truyền dữ liệu thông qua mô-đun UART:

//**Function to send one byte of date to UART**//
void UART_send_char(char bt)  
{
    while(!TXIF);  // hold the program till TX buffer is free
    TXREG = bt; //Load the transmitter buffer with the received value
}
//_____________End of function________________//


Khi mô-đun được khởi tạo, bất kỳ giá trị nào được tải vào thanh ghi TXREG sẽ được truyền qua UART, nhưng quá trình truyền có thể chồng chéo. Do đó, chúng ta nên luôn kiểm tra cờ Ngắt truyền TXIF. Chỉ khi bit này ở mức thấp, chúng ta có thể tiếp tục với bit tiếp theo để truyền, nếu không, chúng ta nên đợi cờ này xuống thấp.


Tuy nhiên, hàm trên chỉ có thể được sử dụng để gửi chỉ một byte dữ liệu, để gửi một chuỗi hoàn chỉnh thì nên sử dụng hàm bên dưới

//**Function to convert string to byte**//
void UART_send_string(char* st_pt)
{
    while(*st_pt) //if there is a char
        UART_send_char(*st_pt++); //process it as a byte data
}
//___________End of function______________//

Hàm này có thể hơi khó hiểu vì nó có các con trỏ, nhưng hãy tin tưởng với tôi, con trỏ rất tuyệt vời và chúng làm cho việc lập trình trở nên dễ dàng hơn và đây là một ví dụ điển hình về điều tương tự.


Như bạn có thể nhận thấy, chúng tôi đã gọi lại UART_send_char () nhưng bây giờ bên trong vòng lặp while. Chúng tôi đã chia chuỗi thành các ký tự riêng lẻ, mỗi khi hàm này được gọi, một ký tự sẽ được gửi đến TXREG và nó sẽ được truyền.


Nhận dữ liệu bằng UART:


Có thể sử dụng chức năng sau để nhận dữ liệu từ mô-đun UART:

//**Function to get one byte of date from UART**//
char UART_get_char()   
{
    if(OERR) // check for Error 
    {
        CREN = 0; //If error -> Reset 
        CREN = 1; //If error -> Reset 
    }
    
    while(!RCIF);  // hold the program till RX buffer is free
    
    return RCREG; //receive the value and send it to main function
}
//_____________End of function________________//


Khi một dữ liệu được mô-đun UART nhận, nó sẽ chọn và lưu trữ trong thanh ghi RCREG. Chúng ta có thể chỉ cần chuyển giá trị vào bất kỳ biến nào và sử dụng nó. Nhưng có thể có lỗi chồng chéo hoặc người dùng có thể gửi dữ liệu liên tục và chúng tôi chưa chuyển chúng sang một biến.


Trong trường hợp đó, bit RCIF của cờ nhận được giải cứu. Bit này sẽ xuống thấp bất cứ khi nào dữ liệu được nhận và chưa được xử lý. Do đó, chúng tôi sử dụng nó trong vòng lặp while tạo ra độ trễ để giữ chương trình cho đến khi chúng tôi xử lý giá trị đó.


Chuyển đổi đèn LED bằng cách sử dụng mô-đun UART của Vi điều khiển PIC:


Bây giờ chúng ta hãy đến với phần cuối cùng của Chương trình, chức năng void main (void), nơi chúng ta sẽ chuyển đổi một đèn LED thông qua máy tính bằng cách sử dụng giao tiếp UART giữa PIC và máy tính.


Khi chúng tôi gửi một ký tự “1” (từ máy tính), đèn LED sẽ được BẬT và thông báo trạng thái “Đèn LED ĐỎ -> BẬT” sẽ được gửi lại (từ PIC MCU) đến máy tính.


Tương tự, chúng tôi gửi một ký tự “0” (từ máy tính) đèn LED sẽ TẮT và thông báo trạng thái “Đèn LED ĐỎ -> TẮT” sẽ được gửi lại (từ PIC MCU) đến máy tính.


while(1) //Infinite loop
    {
      get_value = UART_get_char(); 
        
        if (get_value == '1') //If the user sends "1"
        {
            RB3=1; //Turn on LED
            UART_send_string("RED LED -> ON"); //Send notification to the computer 
            UART_send_char(10);//ASCII value 10 is used for carriage return (to print in new line)
        }
        
        if (get_value == '0') //If the user sends "0"
        {
           RB3=0; //Turn off LED
           UART_send_string("RED -> OFF"); //Send notification to the computer      
           UART_send_char(10);//ASCII value 10 is used for carriage return (to print in new line)
        }
    }


Simulating our program:

As usual let’s simulate our program using proteus and find out if it works as expected.



Hình ảnh trên cho thấy một thiết bị đầu cuối ảo, trong đó thiết bị đầu cuối hiển thị thông báo chào mừng và trạng thái của đèn LED. Có thể nhận thấy đèn LED Màu đỏ được kết nối với chân RB3. Hoạt động chi tiết của mô phỏng có thể được tìm thấy trong Video ở cuối.

Hardware Setup and Testing the output:

Kết nối cho mạch này thực sự đơn giản, chúng tôi sử dụng bảng PIC Perf của chúng tôi và chỉ cần kết nối ba dây với bộ chuyển đổi RS232 sang USB và kết nối mô-đun với máy tính của chúng tôi bằng cáp dữ liệu USB như hình dưới đây.



// CONFIG
#pragma config FOSC = HS       // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF       // Power-up Timer Enable bit (PWRT enabled)
#pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
// End of configuration

#include <xc.h>
#define _XTAL_FREQ 20000000
#define Baud_rate 9600

//***Initializing UART module for PIC16F877A***//
void Initialize_UART(void)
{
    //****Setting I/O pins for UART****//
    TRISC6 = 0; // TX Pin set as output
    TRISC7 = 1; // RX Pin set as input
    //________I/O pins set __________//
    
    /**Initialize SPBRG register for required 
    baud rate and set BRGH for fast baud_rate**/
    SPBRG = ((_XTAL_FREQ/16)/Baud_rate) - 1;
    BRGH  = 1;  // for high baud_rate
    //_________End of baud_rate setting_________//
    
    //****Enable Asynchronous serial port*******//
    SYNC  = 0;    // Asynchronous
    SPEN  = 1;    // Enable serial port pins
    //_____Asynchronous serial port enabled_______//

    //**Lets prepare for transmission & reception**//
    TXEN  = 1;    // enable transmission
    CREN  = 1;    // enable reception
    //__UART module up and ready for transmission and reception__//
    
    //**Select 8-bit mode**//  
    TX9   = 0;    // 8-bit reception selected
    RX9   = 0;    // 8-bit reception mode selected
    //__8-bit mode selected__//     
}
//________UART module Initialized__________//

//**Function to send one byte of date to UART**//
void UART_send_char(char bt)  
{
    while(!TXIF);  // hold the program till TX buffer is free
    TXREG = bt; //Load the transmitter buffer with the received value
}
//_____________End of function________________//

//**Function to get one byte of date from UART**//
char UART_get_char()   
{
    if(OERR) // check for Error 
    {
        CREN = 0; //If error -> Reset 
        CREN = 1; //If error -> Reset 
    }
    
    while(!RCIF);  // hold the program till RX buffer is free
    
    return RCREG; //receive the value and send it to main function
}
//_____________End of function________________//

//**Function to convert string to byte**//
void UART_send_string(char* st_pt)
{
    while(*st_pt) //if there is a char
        UART_send_char(*st_pt++); //process it as a byte data
}
//___________End of function______________//

// **********START of Main Function**************//
void main(void)
{
    int get_value;
    
    TRISB = 0x00; //Initialize PortB as output
    Initialize_UART();    //Initialize UART module                    
    
    UART_send_string("UART Module Initialized and active");    // Introductory Text
    
    while(1) //Infinite loop
    {
      get_value = UART_get_char(); 
        
        if (get_value == '1') //If the user sends "1"
        {
            RB3=1; //Turn on LED
            UART_send_string("RED LED -> ON"); //Send notification to the computer 
            UART_send_char(10);//ASCII value 10 is used for carriage return (to print in new line)
        }
        
        if (get_value == '0') //If the user sends "0"
        {
           RB3=0; //Turn off LED
           UART_send_string("RED -> OFF"); //Send notification to the computer      
           UART_send_char(10);//ASCII value 10 is used for carriage return (to print in new line)
        }
       
    }
}
// **********END of Main Function**************//











Nap Code vào PY32F003 dùng Stlink

 Nap Code vào PY32F003 dùng Stlink Bước 1: Cài đặt  KeilC v5.39 theo link sau ( chú ý 5.39 keil c mới nạp ok). https://edge07.111.ir.cdn.ir/...