Học lập trình STM32 với Visual Code | Bài 8: Giao tiếp SPI

 

Học lập trình STM32 với Visual Code | Bài 8: Giao tiếp SPI



SPI hoặc giao tiếp ngoại vi nối tiếp được Motorola phát triển vào những năm 1980 như một giao diện tiêu chuẩn, chi phí thấp và đáng tin cậy giữa vi điều khiển (Vi điều khiển của Motorola lúc đầu) và các IC ngoại vi của nó.

Nhờ giao diện đơn giản, linh hoạt và dễ sử dụng, SPI đã trở thành một tiêu chuẩn và các nhà sản xuất bán dẫn khác bắt đầu sử dụng giao thức này trong các chip của mình.

Trong giao thức SPI, các thiết bị được kết nối trong một mối quan hệ Master – Slave trong một giao diện đa điểm. Trong loại giao diện này, một thiết bị được coi là Master của bus (thường là một vi điều khiển) và tất cả các thiết bị khác (IC ngoại vi hoặc thậm chí các vi điều khiển khác) đều được coi là Slave.

Trong giao thức SPI, có thể chỉ có một thiết bị Master nhưng nhiều thiết bị Slave.

Bus SPI bao gồm 4 tín hiệu hoặc chân. Chúng là
  • Master – Out / Slave – In (MOSI hay SI): cổng ra của bên Master, cổng vào của bên Slave, dành cho việc truyền dữ liệu từ thiết bị Master đến thiết bị Slave .
  • Master – In / Slave – Out (MISO hay SO): cổng vào của bên Master, cổng ra của bên Slave, dành cho việc truyền dữ liệu từ thiết Slave đến thiết bị Master.
  • Serial Clock (SCK hay SCLK): xung giữ nhịp cho giao tiếp SPI
  • Chip Select (CS) hay Slave Select (SS): chọn chip


Code Master (STM32)


  #include <Arduino.h>
  #include <SPI.h>
  #include <HardwareSerial.h>
  #define SS PB12

  HardwareSerial Serial_Mon(PA10PA9);
  String buff_send = "";  // Biến nhận dữ liệu từ Serial Port
  byte buf[2];  // Mảng chứa giá trị analog của Slave gửi lên
  bool TransmitControl = false;  //Điều khiển quá trình gửi nhận dữ liệu

  void setup()
  {
    Serial_Mon.begin(9600);
    pinMode(SS, OUTPUT); 
    digitalWrite(SSHIGH);
    SPI.setSCLK(PB13);
    SPI.setMISO(PB14);
    SPI.setMOSI(PB15);
    SPI.begin(); // Mặc định - SCK: PA5  - MISO: PA6  - MOSI: PA7
    SPI.setClockDivider(SPI_CLOCK_DIV16);  // Cài đặt tốc độ truyền cho SPI

  }

  void SPI_Tranmit(String s)
  {
    digitalWrite(SS, LOW);  // lựa chọn Slave để gửi dữ liệu
    int i = 0;
    while (i < buff_send.length())
    {
      delayMicroseconds(20);
      SPI.transfer(s[i]);
      i++;
    }
    digitalWrite(SS, HIGH); // Tắt Slave
    TransmitControl = false;
  }

  int BytesToInt(byte lowerBytebyte higherbyte)
  {
    int val = (higherbyte << 8) | lowerByte;
    return val;
  }

  void SPI_Request()
  {
    digitalWrite(SS, LOW); // lựa chọn Slave để gửi dữ liệu
    delayMicroseconds(20);
    buf[0] = SPI.transfer(0);
    buf[1] = SPI.transfer(1);
    digitalWrite(SS, HIGH); // Tắt Slave
    Serial_Mon.println(BytesToInt(buf[1], buf[0]));
  }

  void loop()
  {
    while (Serial_Mon.available())
    {
      char c = (char)Serial_Mon.read();
      buff_send += c;
      if (c == '\n')
      {
        TransmitControl = true;
        SPI_Tranmit(buff_send);
        buff_send = "";
      }
    }
    if (!TransmitControl)
      SPI_Request();
  }




Code Slave (Uno)


  #include <SPI.h>
  #define LED 5
  volatile char buf;  // biến nhận dữ liệu request từ master
  volatile int ai0; // Biến giá trị analog gửi lên master
  volatile byte* buff_response; // Lưu giá trị của analog dạng bye array

  void setup()
  {
    pinMode (LED, OUTPUT);
    SPI.setClockDivider(SPI_CLOCK_DIV16); // cài đặt tốc độ của SPI
    Serial.begin (115200);
    SPCR |= _BV(SPE);  // Bật chế độ Slave
    pinMode (MISO, OUTPUT);
    SPI.attachInterrupt();  // Kích hoạt ngắt SPI
    
  }


  ISR (SPI_STC_vect)  // Hàm ngắt của SPI
  {
    buf = SPDR;  // Lưu giá trị của Master vào biến buf
    
    if(buf == '1'){
      digitalWrite(LED, LOW);
    }
    if(buf == '0'){
      digitalWrite(LED, HIGH);
    }
    
    if((int)buf== 0)
      SPDR = buff_response[0];  // Byte thấp của giá trị analog
    if((int)buf== 1)
      SPDR = buff_response[1];  // Byte cao của giá trị analog
  }

  void loop ()
  {
    ai0 = analogRead(A0);
    buff_response = IntToBytes(ai0);
  }

  byte* IntToBytes(int val){  //Hàm chuyển đổi số nguyên thành mảng byte
    static byte* arr = new byte[2];
    arr[0] = byte(val);
    arr[1] = byte(val >> 8);
    return arr;
  }



Link download file source code: Download

Video hướng dẫn



No comments:

Post a Comment