在本教程中,我們將使用 STM32F103C8 的 Blue Pill 板替換一個(gè) Arduino 板,并將使用 SPI 總線與 Arduino 板進(jìn)行通信。在這個(gè)STM32 SPI 示例中,我們將使用Arduino UNO作為 Slave,STM32F103C8 作為 Master,兩個(gè)16X2 LCD 顯示器分別連接在一起。兩個(gè)電位器還與STM32(PA0)和Arduino(A0)相連,通過改變電位器來確定主機(jī)到從機(jī)和從機(jī)到主機(jī)的發(fā)送值(0到255)。
STM32F103C8中的SPI
比較 Arduino 和 STM32F103C8 Blue Pill 板中的 SPI 總線,STM32 有2 條 SPI 總線,而 Arduino Uno 有1 條 SPI 總線。Arduino Uno 有 ATMEGA328 微控制器,STM32F103C8 有 ARM Cortex-M3,比 Arudino Board 更快。
STM32 SPI 引腳 STM32F103C8
Arduino 中的 SPI 引腳
所需組件
STM32F103C8
阿杜諾
液晶 16x2 - 2
10k 電位器 – 4
面包板
連接電線
STM32 SPI教程的電路圖和連接
下表顯示了STM32 SPI與 Arduino 通信連接的引腳。
下表顯示了兩個(gè) LCD (16x2) 分別與 STM32F103C8 和 Arduino連接的引腳。
重要的:
不要忘記將 Arduino GND 和 STM32F103C8 GND 連接在一起。
STM32 SPI編程
編程類似于 Arduino 代碼。在 STM32F103C8 編程中使用了相同的《SPI.h》庫。它可以在不使用 FTDI 編程器的情況下使用 USB 端口進(jìn)行編程,要了解有關(guān) 使用 Arduino IDE 對(duì) STM32 進(jìn)行編程的更多信息,請(qǐng) 點(diǎn)擊鏈接。
Master STM32 SPI編程講解
1.首先我們需要?包含?使用SPI通信功能的SPI庫和使用LCD功能的LCD庫。還為 16x2 LCD 定義 LCD 引腳。在此處了解有關(guān)LCD 與 STM32 接口的?更多信息。
?
#include#include const int rs = PB0, en = PB1, d4 = PB10, d5 = PB11, d6 = PC13, d7 = PC14; LiquidCrystal lcd(rs,en,d4,d5,d6,d7);
?
2. 在 void setup()
以波特率 9600 開始串行通信。
?
序列號(hào).開始(9600);
?
接下來開始SPI通信
?
SPI.開始();
?
然后為 SPI 通信設(shè)置時(shí)鐘分頻器。我設(shè)置了分隔線 16。
?
SPI.setClockDivider(SPI_CLOCK_DIV16);
?
接下來將 SS 引腳設(shè)置為高電平,因?yàn)槲覀儧]有開始向從 arduino 進(jìn)行任何傳輸。
?
數(shù)字寫入(SS,HIGH);
?
3. 在void loop()
在向從機(jī)發(fā)送任何值之前,我們需要降低從機(jī)選擇值以開始從主機(jī)傳輸?shù)綇臋C(jī)。
?
數(shù)字寫入(SS,低);
?
接下來從連接到引腳 PA0 的主控 STM32F10C8 POT 讀取模擬值。
?
int pot = 模擬讀?。≒A0);
?
然后將該值轉(zhuǎn)換為一個(gè)字節(jié)(0 到 255)。
?
字節(jié) MasterSend = map(pot,0,4096,0,255);
?
這是重要的一步,在下面的語句中,我們將存儲(chǔ)在Mastersend變量中的轉(zhuǎn)換后的 POT 值發(fā)送到從 Arduino,并從從 Arduino 接收值并將其存儲(chǔ)在mastereceive變量中。
?
Mastereceive = SPI.transfer(Mastersend);
?
接下來以 500 微秒的延遲顯示從從 arduino 接收到的值,然后連續(xù)接收并顯示這些值。
?
Serial.println("從 Arduino 到主 STM32"); Serial.println(MasterReceive lcd.setCursor(0,0); lcd.print("Master: STM32"); lcd.setCursor(0,1); lcd.print("SalveVal:"); lcd.print(MasterReceive delay (500); 數(shù)字寫入(SS,高);
?
注意:我們使用 serial.println() 在 Arduino IDE 的 Serial Motor 中查看結(jié)果。
從機(jī) Arduino SPI 編程說明
1.和master一樣,首先我們需要?包含使用I2C通信功能的SPI庫?和使用LCD功能的LCD庫。還為 16x2 LCD 定義 LCD 引腳。
?
#include#include LiquidCrystal lcd(2, 3, 4, 5, 6, 7); // 定義 LCD 模塊引腳 (RS,EN,D4,D5,D6,D7)
?
2. 在 void setup()
我們以波特率 9600 開始串行通信。
?
序列號(hào).開始(9600);
?
下面的語句將 MISO 設(shè)置為 OUTPUT(必須將數(shù)據(jù)發(fā)送到 Master IN)。因此數(shù)據(jù)通過 Slave Arduino 的 MISO 發(fā)送。
?
pinMode(味噌,輸出);
?
現(xiàn)在通過使用 SPI 控制寄存器在從模式下打開 SPI
?
SPCR |= _BV(SPE);
?
然后為 SPI 通信打開中斷。如果從主機(jī)接收到數(shù)據(jù),則調(diào)用中斷服務(wù)程序并從 SPDR(SPI 數(shù)據(jù)寄存器)中獲取接收到的值
?
SPI.attachInterrupt();
?
master 的值取自 SPDR 并存儲(chǔ)在Slavereceived變量中。這發(fā)生在以下中斷例程函數(shù)中。
?
中斷服務(wù)程序(SPI_STC_vect) { 從機(jī)接收 = SPDR; 收到=真; }
?
3.next in?void loop()
從連接到引腳 A0 的 Slave Arduino POT 讀取模擬值。
?
int pot = 模擬讀取(A0);
?
將該值以一個(gè)字節(jié)為單位轉(zhuǎn)換為 0 到 255。?
?
Slavesend = map(pot,0,1023,0,255);
?
下一個(gè)重要步驟是將轉(zhuǎn)換后的值發(fā)送到主控 STM32F10C8,因此將值放入 SPDR 寄存器。SPDR 寄存器用于發(fā)送和接收值。
?
SPDR = 從發(fā)送;
?
然后以 500 微秒的延遲在 LCD 上顯示從主控 STM32F103C8 接收到的值(SlaveReceive),然后連續(xù)接收并顯示這些值。
?
lcd.setCursor(0,0); lcd.print("奴隸:阿杜諾"); lcd.setCursor(0,1); lcd.print("MasterVal:"); Serial.println("主 STM32 到從 Arduino"); Serial.println(SlaveReceived); lcd.print(SlaveReceived); 延遲(500);
?
通過 旋轉(zhuǎn)一側(cè)的電位器,您可以在另一側(cè)的 LCD 上看到不同的值:
這就是 STM32 中 SPI 通信的方式。現(xiàn)在您可以將任何 SPI 傳感器與 STM32 板連接。
//STM32F103C8的SPI Master代碼
//STM32和Arduino之間的SPI通信
#include
#define SS PA4
#include
const int rs = PB0, en = PB1, d4 = PB10, d5 = PB11, d6 = PC13, d7 = PC14; // 聲明 lcd 的管腳名稱和管腳編號(hào)
LiquidCrystal lcd(rs,en,d4,d5,d6,d7); // 設(shè)置 lcd 及其參數(shù)
無效設(shè)置(無效)
{
lcd.begin(16,2); // 設(shè)置 lcd 為 16x2 模式
lcd.setCursor(0,0); // 在第一行第一列設(shè)置光標(biāo)
lcd.print("CIRCUIT DIGEST"); // 將 CIRCUIT DIGEST 放入 LCD
延遲(3000);// 延遲 3 秒
lcd.clear(); // 清除液晶顯示器
Serial.begin(9600); // 以波特率 9600 開始串行通信
pinMode(SS,輸出);// 將 SS 作為輸出
SPI.begin(); // 開始 SPI 通信
SPI.setClockDivider(SPI_CLOCK_DIV16); // 將 SPI 通信的時(shí)鐘設(shè)置為 16 (72/16=4.5Mhz)
digitalWrite(SS,HIGH); // 將 SlaveSelect 設(shè)置為 HIGH(所以 master 不與 slave 連接)
}
無效循環(huán)(無效)
{
字節(jié)MasterSend,MasterReceive;
int pot = 模擬讀取(PA0);// 模擬讀取引腳 PA0 的輸入電位器值
MasterSend = map(pot,0,4096,0,255); // 用于將 0 到 255 的罐值從 0 轉(zhuǎn)換為 4096
digitalWrite(SS, LOW); // 開始與連接到主控的從屬通信
MasterReceive=SPI.transfer(MasterSend); // 將 mastersend 值發(fā)送到 slave 也從 slave 接收值
Serial.println("Slave Arduino to Master STM32"); // 用于串行監(jiān)視器
Serial.println(MasterReceive); // 將接收到的值放入串行監(jiān)視器
lcd.setCursor(0,0);
lcd.print("主控:STM32");
lcd.setCursor(0,1);
lcd.print("SalveVal:");
lcd.print(MasterReceive); // 將接收到的值從 slave arduino
delay(500);
數(shù)字寫入(SS,高);// 再次將 SS 線設(shè)為高電平,使其不與從屬
lcd.clear() 通信;
}
從 Arduino SPI
//Arduino的SPI從代碼
//STM32F103C8和Arduino之間的SPI通信
//電路文摘
#include
#include
LiquidCrystal lcd(2, 3, 4, 5, 6, 7); // 定義 LCD 模塊引腳 (RS,EN,D4,D5,D6,D7)
接收到的易失布爾值;
易失字節(jié)SlaveReceived,Slavesend;
無效設(shè)置()
{
lcd.begin(16,2); // 初始化 LCD 顯示
lcd.setCursor(0,0); // 在 Display 的第一行設(shè)置光標(biāo)
lcd.print("CIRCUIT DIGEST"); // 在 LCD
delay(3000) 中打印 CIRCUIT DIGEST;// 延遲 3 秒
lcd.clear(); // 清除 LCD 顯示
Serial.begin(9600); // 以波特率 9600 開始串行通信
pinMode(MISO,OUTPUT); // 將 MISO 設(shè)置為 OUTPUT(必須向 Master IN 發(fā)送數(shù)據(jù)(STM32F103C8)
SPCR |= _BV(SPE); // 在從機(jī)模式下打開 SPI
received = false;
SPI.attachInterrupt(); // 為 SPI 通信設(shè)置 Interuupt ON
}
ISR (SPI_STC_vect) // Inerrrput 例程函數(shù)
{
SlaveReceived = SPDR; // 從主控STM32F103C8接收的值存儲(chǔ)在變量slavereceived
received = true; // 設(shè)置接收為 True
}
無效循環(huán)()
{
int pot =模擬讀?。ˋ0);// 模擬從模擬引腳 A0 讀取輸入電位器值
Slavesend = map(pot,0,1023,0,255); // 將值 pot (0-1023) 轉(zhuǎn)換為 (0-255) 以發(fā)送到主控 stm32
SPDR = Slavesend; // 通過 SPDR 將 salvesend 值發(fā)送給主控 STM32F103C8
lcd.setCursor(0,0);
lcd.print("奴隸:阿杜諾");
lcd.setCursor(0,1);
lcd.print("MasterVal:");
Serial.println("主 STM32 到從 Arduino");
Serial.println(SlaveReceived);
lcd.print(SlaveReceived); // 將從主控 STM32F103C8 接收到的值置于 LCD 顯示
延遲(500)處;
lcd.clear();
}
?
?
評(píng)論
查看更多