Thứ Tư, 28 tháng 11, 2018

Bài 13. PIC 18F450 Giao Tiếp UART

Giới thiệu 

Một số thiết bị như GPS, GSM, RFID, cảm biến, vv cần phải giao tiếp với vi điều khiển PIC để truyền hoặc nhận thông tin. Để giao tiếp với vi điều khiển PIC, một số giao thức truyền thông được sử dụng như RS232, SPI, I2C, CAN vv Về cơ bản, một giao thức là một tập hợp các quy tắc được cả người gửi và người nhận đồng ý,
  • Dữ liệu được đóng gói như thế nào?
  • Có bao nhiêu bit cấu thành một nhân vật?
  • Khi dữ liệu bắt đầu và kết thúc?
PIC18F4550 có một mô-đun USART được tích hợp sẵn, rất hữu ích cho giao tiếp nối tiếp. Với sự giúp đỡ của USART, chúng tôi có thể gửi / nhận dữ liệu đến máy tính hoặc các thiết bị khác. USART cũng được sử dụng trong giao tiếp PIC với các mô-đun khác nhau như Wi-Fi (ESP8266), Bluetooth, GPS, GSM, v.v.
Chúng ta sẽ thấy cách giao tiếp được thiết lập giữa vi điều khiển PIC và PC thông qua USART bằng giao thức RS232. Chúng tôi cũng sẽ xem làm thế nào để giao tiếp với máy tính xách tay, mà không có cổng RS232 DB9 và thay vào đó sử dụng cổng USB.
Chúng ta hãy bắt đầu với giao tiếp nối tiếp sử dụng PIC18F4550.
Truyền thông không đồng bộ: PIC18F4550 có bộ thu phát không đồng bộ tích hợp. Không đồng bộ nghĩa là mỗi ký tự (byte dữ liệu) được đặt ở giữa các bit bắt đầu và dừng. Bit bắt đầu luôn luôn là 0 (thấp) và bit dừng luôn luôn là 1 (cao).

Tốc độ bit và tốc độ truyền: Tốc độ truyền dữ liệu trong giao tiếp dữ liệu nối tiếp được biểu thị bằng bps (bit trên giây). Một thuật ngữ được sử dụng rộng rãi khác cho bps là tốc độ truyền; có nghĩa là, số lần thay đổi tín hiệu mỗi giây. Ở đây tín hiệu ở dạng bit, do đó tốc độ bit = tốc độ truyền.
Giao diện : Mặc dù có nhiều chân trong đầu nối DB9, chúng tôi không cần tất cả. Chúng tôi chỉ sử dụng các chân RX, TX và GND.

Chuyển đổi cấp độ

Chuyển đổi mức PIC18F TTL thành mức RS232 và ngược lại
PC có mức RS232 trong khi vi điều khiển PIC có mức TTL. RS232 có mức điện áp khác nhau cho logic 0 và 1. Để làm cho nó tương thích với các mức điện áp PIC TTL, chúng ta phải sử dụng MAX232 IC.
PIC18F TTL để chuyển đổi mức RS232

Baud Rate tính toán

Làm thế nào để tính toán tốc độ Baud trong PIC18F4550?
Mong muốn \, Baud \, Tỷ lệ = \ frac {Fosc} {64 \ ast (X + 1)}
một giá trị sẽ được nạp vào thanh ghi SPBRG (16-bit) của PIC18F4550 để đạt được tốc độ truyền mong muốn. Giá trị của SPBRG cho tốc độ truyền mong muốn được tính như,
                                              SPBRG = \ frac {Fosc} {64 \ ast Mong muốn \, Baud \, Tỷ lệ} -1
Ví dụ
Giả sử, Fosc = 8 MHz và Tốc độ Baud = 9600 bps
Sau đó, SPBRG = ((8 MHz) / (64 × 9600)) - 1 
SPBRG = (8 MHz / 64 × 9600) - 1                                 
Do đó, SPBRG = 12
Công thức trên phụ thuộc vào bit BRGH trong thanh ghi TXSTA .
Hãy xem thanh ghi TXSTA, được sử dụng để cài đặt truyền dẫn, cụ thể như sau

TXSTA: Trạng thái truyền và đăng ký điều khiển
Đăng ký TXSTA
TXEN : Truyền cho phép Bit
          1 = Bật truyền
          0 = Vô hiệu hóa việc truyền
BRGH : Tốc độ truyền cao chọn bit
           0 = Tốc độ thấp
                   SPBRG = \ frac {Fosc} {64 \ ast Mong muốn \, Baud \, Tỷ lệ} -1
           1 = Tốc độ cao
                  SPBRG = \ frac {Fosc} {16 \ ast Mong muốn \, Baud \, Tỷ lệ} -1
Tải giá trị được tính trực tiếp vào thanh ghi SPBRG.
Bit CSRC không được sử dụng cho giao tiếp không đồng bộ.

TX9 : Truyền tải thứ 9 cho phép Bit
          0 = Chọn truyền 8 bit
          1 = Chọn truyền 9 bit
SYNC : Chế độ USART Chọn Bit
          0 = Chế độ không đồng bộ
          1 = Chế độ đồng bộ
SENDB: Gửi bit ký tự ngắt
          1 = Gửi đồng bộ ngắt trên lần truyền tiếp theo (xóa theo phần cứng sau khi hoàn thành)
          0 = Hoàn thành quá trình truyền đồng bộ
TRMT : Truyền trạng thái đăng ký thay đổi bit
          0 = TSR đầy đủ
          1 = TSR trống

TX9D : bit bit truyền dữ liệu thứ 9
Có thể là bit Địa chỉ / Dữ liệu hoặc bit chẵn lẻ.
Trong PIC18F4550, đăng ký RCSTA được sử dụng cho cài đặt nhận dữ liệu nối tiếp.
RCSTA: Nhận đăng ký kiểm soát và trạng thái
Đăng ký RCSTA

SPEN : Kích hoạt cổng nối tiếp
          1 = Kích hoạt cổng nối tiếp để liên lạc
          0 = Vô hiệu hóa cổng nối tiếp để liên lạc

RX9 : bit nhận bit 9 bit
          1 = Bật tiếp nhận 9 bit
          0 = Bật tiếp nhận 8 bit
Nói chung, chúng tôi sử dụng tiếp nhận 8 bit

SREN : bit nhận đơn
Không được sử dụng

CREN : Nhận liên tục Bật bit
1 = Cho phép nhận để tiếp nhận byte dữ liệu liên tục
0 = Vô hiệu hóa bộ thu
ADDEN: Địa chỉ phát hiện Kích hoạt bit

Chế độ không đồng bộ 9 bit (RX9 = 1)
1 = Bật phát hiện địa chỉ, cho phép ngắt và tải bộ đệm nhận khi bit RSR được thiết lập.
0 = Vô hiệu hóa phát hiện địa chỉ, tất cả các byte được nhận và bit thứ chín có thể được sử dụng như bit chẵn lẻ.

Chế độ không đồng bộ 9 bit (RX9 = 0)
 Không quan tâm (bất kỳ 0 hoặc 1)

FERR: Lỗi bit khung
1 = Lỗi khung (có thể được cập nhật bằng cách đọc đăng ký RCREG và nhận byte hợp lệ tiếp theo)
0 = Không có lỗi khung

OERR: Lỗi lỗi quá mức
1 = Lỗi tràn có thể được xóa bằng cách xóa bit CREN.
0 = Không có lỗi quá tải

RX9D: bit thứ 9 của dữ liệu nhận
Đây có thể là bit địa chỉ / dữ liệu hoặc bit chẵn lẻ và phải được tính bằng phần mềm người dùng.

Đệm dữ liệu và cờ ngắt cho giao tiếp nối tiếp
Để truyền dữ liệu và nhận dữ liệu TXREG và các thanh ghi dữ liệu 8 bit của RCREG được phân bổ tương ứng với PIC18F4550.
Truyền đăng ký

Nhận đăng ký

  • Khi chúng tôi phải truyền dữ liệu, chúng tôi sẽ trực tiếp sao chép dữ liệu đó vào thanh ghi TXREG. Sau khi hoàn thành việc truyền dữ liệu 8 bit, cờ ngắt TXIF được tạo ra.
  • Đây TXIF (truyền ngắt cờ) nằm ở PIR1 đăng ký. Cờ TXIF được thiết lập khi dữ liệu 8 bit được truyền đi. Sau đó, bộ đệm sẵn sàng nhận dữ liệu khác để truyền.
  • Ngoài ra, RCIF (nhận cờ ngắt) được đặt trong thanh ghi PIR1 . Khi cờ này được thiết lập, nó chỉ ra rằng byte dữ liệu đầy đủ được nhận bởi thanh ghi RCREG . Đọc ngay thanh ghi RCREG . Bây giờ, thanh ghi RCREG đã sẵn sàng để nhận dữ liệu khác.
  • Khi cờ RCIF không được thiết lập, vi điều khiển PIC phải đợi cho việc tiếp nhận byte dữ liệu hoàn chỉnh.

Các bước lập trình US18F4550 USART 

Khởi tạo
1. Khởi tạo Baud Rate bằng cách tải một giá trị vào thanh ghi SPBRG.
2. Sau đó đặt bit SPEN trong RCSTA để bật Serial Port.
3. Sau đó đặt BRGH bit trong TXSTA cho tốc độ thấp hoặc cao.
4. Cũng rõ ràng SYNC bit trong thanh ghi TXSTA để liên lạc không đồng bộ.
5. Đặt bit TXEN trong thanh ghi TXSTA để cho phép truyền.
6. Đặt bit CREN trong thanh ghi RCSTA để cho phép nhận.
#define F_CPU 8000000/64

void USART_Init(long baud_rate)
{
    float temp;
    TRISC6=0;  /* Make Tx pin as output*/
    TRISC7=1;    /* Make Rx pin as input*/

    /* Baud rate=9600, SPBRG = (F_CPU /(64*9600))-1*/
    temp= (( (float) (F_CPU) / (float) baud_rate ) - 1);     
    SPBRG = (int) temp; 

    TXSTA = 0x20;   /* Enable Transmit(TX) */ 
    RCSTA = 0x90;   /* Enable Receive(RX) & Serial */
}

Chế độ truyền
1. Sao chép dữ liệu mà chúng tôi muốn truyền vào thanh ghi TXREG.
2. Giám sát cờ TXIF được đặt khi quá trình truyền hoàn tất.
Char USART_TransmitChar (char out)
{
   while (TXIF == 0); /* Wait for transmit interrupt flag*/
   TXREG = out;   /* Write char data to transmit register */    
}

Chế độ nhận
1. Giám sát cờ RCIF cho đến khi nó được đặt thành 1, cho biết hoàn thành 1 byte được nhận trong thanh ghi RCREG.
2. Ngoài ra, hãy kiểm tra bit OERR. Nếu nó được thiết lập sau đó vô hiệu hóa và kích hoạt CREN.
3. Sau đó, đọc ngay thanh ghi RCREG để tránh tràn.
Char USART_ReceiveChar()
{
    while(RCIF==0);      /*wait for receive interrupt flag*/
    if(RCSTAbits.OERR)
    {           
        CREN = 0;
        NOP();
        CREN=1;
    }
    return(RCREG);       /*received in RCREG register and return to main program */
}

Ứng dụng

Hãy tạo một ứng dụng đơn giản, trong đó chúng ta sẽ tạo ra một tiếng vang của các nhân vật nơi các ký tự sẽ được truyền tuần tự từ PC sang PIC18F4550 và trả về từ PIC18F4550 cho PC.
#include <pic18f4550.h>
#include "Configuration_Header_File.h"
#include "LCD_16x2_8-bit_Header_File.h"

void USART_Init(long);
void USART_TxChar(char);
char USART_RxChar();

#define F_CPU 8000000/64

#define Baud_value (((float)(F_CPU)/(float)baud_rate)-1)

/************************CODE FOR ECHO GENERATION USING USART*****************/
void main()
{
    OSCCON=0x72;    
    char data_in;
    LCD_Init();               /*Initialize 16x2 LCD */
    USART_Init(9600);         /*initialize USART operation with 9600 baud rate*/ 
    MSdelay(50);
    while(1)
    {
        data_in=USART_RxChar();
        LCD_Char(data_in);
        USART_TxChar(data_in);
    }
    
}

/*****************************USART Initialization*******************************/
void USART_Init(long baud_rate)
{
    float temp;
    TRISC6=0;                       /*Make Tx pin as output*/
    TRISC7=1;                       /*Make Rx pin as input*/
    temp=Baud_value;     
    SPBRG=(int)temp;                /*baud rate=9600, SPBRG = (F_CPU /(64*9600))-1*/
    TXSTA=0x20;                     /*Transmit Enable(TX) enable*/ 
    RCSTA=0x90;                     /*Receive Enable(RX) enable and serial port enable */
}
/******************TRANSMIT FUNCTION*****************************************/ 
void USART_TxChar(char out)
{        
        while(TXIF==0);            /*wait for transmit interrupt flag*/
        TXREG=out;                 /*transmit data via TXREG register*/    
}
/*******************RECEIVE FUNCTION*****************************************/
char USART_RxChar()
{

while(RCIF==0);       /*wait for receive interrupt flag*/
    if(RCSTAbits.OERR)
    {           
        CREN = 0;
        NOP();
        CREN=1;
    }
    return(RCREG);   /*receive data is stored in RCREG register and return */
}

 Đầu ra

Giao tiếp USART bằng cách sử dụng thường xuyên dịch vụ ngắt (ISR)

  • Giao tiếp trên USART được thực hiện bằng cách bỏ phiếu liên tục cờ ngắt.
  • Tuy nhiên, việc bỏ phiếu cờ ngắt làm tăng mức tiêu thụ điện năng trong bộ vi điều khiển và cũng không thể thực hiện các tác vụ khác vì việc bỏ phiếu gián đoạn đang thực thi liên tục.
  • Interrupt Service Routine (ISR) thực hiện mã ứng dụng bất cứ khi nào có gián đoạn xảy ra.
  • Và nếu ngắt không xảy ra, bộ điều khiển vi điều khiển có thể thực thi tác vụ khác.
Để sử dụng USART ISR trong PIC18F4550, GIE (Global Interrupt Enable), PEIE (Peripheral Interrupt Enable) cần được kích hoạt cùng với RCIE (Receive Interrupt Enable) và TXIE (Transmit Interrupt Enable).

Các bước để lập trình PIC18F4550 USART bằng cách sử dụng ngắt 

Khởi tạo
  1. Khởi tạo Baud Rate bằng cách tải một giá trị vào thanh ghi SPBRG.
  2. Sau đó thiết lập bit SPEN trong RCSTA cho Serial Port cho phép.
  3. Sau đó đặt BRGH bit trong TXSTA cho tốc độ thấp hoặc cao.
  4. Ngoài ra, SYNC bit rõ ràng trong thanh ghi TXSTA để liên lạc không đồng bộ.
  5. Đặt bit TXEN trong thanh ghi TXSTA để cho phép truyền.
  6. Đặt bit CREN trong thanh ghi RCSTA để cho phép nhận.
Kích hoạt GIE, PEIE, RCIE và TXIE cho ISR.
#define F_CPU 8000000/64

void USART_Init(long baud_rate)
{   
    float temp;
    TRISC6=0;  /* Make Tx pin as output*/
    TRISC7=1;  /* Make Rx pin as input*/
    temp=(( (float) (F_CPU) / (float) baud_rate) - 1);     
    SPBRG = (int) temp; /* Baud rate=9600 SPBRG=(F_CPU /(64*9600))-1*/
    TXSTA = 0x20; /* TX enable; */
    RCSTA = 0x90; /* RX enable and serial port enable*/
    INTCONbits.GIE = 1; /* Enable Global Interrupt */
    INTCONbits.PEIE = 1;/* Enable Peripheral Interrupt */
    PIE1bits.RCIE = 1; /* Enable Receive Interrupt*/
    PIE1bits.TXIE = 1; /* Enable Transmit Interrupt*/
}

Mã ứng dụng cho ECHO sử dụng ISR

#include <pic18f4550.h>
#include "Configuration_Header_File.h"
#include "LCD_16x2_8-bit_Header_File.h"

void USART_Init(long);

#define F_CPU 8000000/64
char out;

void main()
{
    OSCCON=0x72;
    LCD_Init();
    USART_Init(9600);    
    LCD_String_xy(1,0,"Receive");
    LCD_Command(0xC0);
    while(1);
}

void USART_Init(long baud_rate)
{   
    float temp;
    TRISC6=0;  /* Make Tx pin as output */
    TRISC7=1;  /* Make Rx pin as input */
    temp=(( (float) (F_CPU) / (float) baud_rate) - 1);     
    SPBRG=(int)temp; /* Baud rate=9600 SPBRG=(F_CPU /(64*9600))-1 */
    TXSTA=0x20;  /* TX enable; */
    RCSTA=0x90;  /* RX enable and serial port enable */
    INTCONbits.GIE=1; /* Enable Global Interrupt */
    INTCONbits.PEIE=1; /* Enable Peripheral Interrupt */
    PIE1bits.RCIE=1; /* Enable Receive Interrupt */
    PIE1bits.TXIE=1; /* Enable Transmit Interrupt */
}


void interrupt ISR()
{
      while(RCIF==0);
      out=RCREG; /* Copy received data from RCREG register */
      LCD_Char(out);
      while(TXIF==0);
      TXREG=out; /* Transmit received(ECHO) to TXREG register */
}

Code mô phỏng

Không có nhận xét nào:

Đăng nhận xét