You are on page 1of 23

SPI


ปั ญหาของการสือสารแบบ UART

• วงจรสือสารของ UART ทัง้ 2 ฝั่ง มีวงจรสร ้างสัญญาณนาฬกิ า

เป็ นของตัวเอง (Asynchronous) ซึงในบางคร ้ั ญญาณนาฬก
งสั ิ า

ของวงจรสือสารทั ง้ 2 ฝั่งอาจมีความถีต่่ างกันเล็กน้อย
ตัวอย่างเช่น
 PIC18F8722 ทีใช ่ ้ Oscillator ความถี่ 4 MHz สามารถสร ้าง BAUD
Rate เท่ากับ 9615 และ Computer ทีมี ่ BUAD Rate เท่ากับ 9600
การทีสั่ ญญาณนาฬก ่
ิ าของวงจรสือสารทั ง้ 2 ฝั่งมีความถีไม่
่ เท่ากัน
อาจทาให ้การร ับส่งข ้อมูลผิดพลาดได ้
 วิธแี ก ้ไขคือทาให ้วงจรสร ้างสัญญาณนาฬก ่
ิ าของวงจรสือสารทั ง้ 2
ฝั่งมีความถีเดี
่ ยวกัน ซึงในทางปฏิ
่ บต ั ค
ิ อ
่ นข ้างร ับประกันได ้ยากว่า

ความถีของวงจรสร ้างสัญญาณทัง้ 2 ฝั่งเท่ากัน
 หรือออกแบบให ้วงจรสือสารทั่ ง้ 2 ฝั่งได ้ร ับสัญญาณนาฬก ิ าจากวงจร
Serial Peripheral Interface (SPI)

• SPI เป็ นการสือสารอนุ กรมแบบ Synchronous ทาให ้
ร ับส่งข ้อมูลได ้ถูกต ้องแม่นยากว่า UART และสามารถ
ร ับส่งข ้อมูลได ้พร ้อมกัน (Full Duplex)
• นิ ยมใช ้ในการร ับส่งข ้อมูลระหว่าง Microcontroller กับ
อุปกรณ์ตอ ่
่ พ่วงอืนๆเช่ น Serial EEPROMs, Shift
Register, Sensor, Display Driver, A/D Converters
และ SD CARD เป็ นต ้น
องค ์ประกอบของ SPI

• SPI เป็ นการสือสารที ่ โครงสร ้างแบบ Master-
มี
Slave
• ภายในวงจรสือสารทั ่ ้ ่ ง Master และ Slave มี
งฝั
Serial Shift Register ขนาด 8 บิทสาหร ับใช้ใน
การร ับและส่งข้อมู ล
• Shift Register ของทังฝั ้ ่ ง Master และ Slave
สามารถทีจะส่่ งข้อมู ลออกไปให้อก ี ฝั่ ง พร ้อมก ับ
่ กส่งเข้ามาได้พร ้อมก ันในเวลา
SPI Master SPI Slave
MOSI MOSI

ร ับข้อมู ลทีถู
0 1 1 1 0 0 0 1 MISO MISO
0 1 0 1 1 1 0 1

เดียวก ัน ด ังนัน
MSB
้ SPI จึงเป็ นการสือสารแบบ
Master
LSB

SCLK SCLK
MSB

Full
LSB

Clock SS SS
องค ์ประกอบของ SPI
• สัญญาณของ SPI ประกอบด้วย
MOSI (Master Output Slave Input) เป็ นสัญญาณข้อมู ล
่ กส่งจาก Master ไปให้ Slave
ทีถู
MISO (Master Input Slave Output) เป็ นสัญญาณข้อมู ล
่ กส่งจาก Slave ไปให้ Master
ทีถู
SCLK (Serial Clock) เป็ นสัญญาณนาฬก ่ กส่งจาก
ิ าทีถู
Master Clock ของฝั่ ง Master ไปให้กบ
ั Serial Shift
Register ของฝั่ ง Slave
SPI Master
MOSI MOSI
SPI Slave

MISO MISO
0 1 1 1 0 0 0 1 0 1 0 1 1 1 0 1
MSB LSB MSB LSB

Master SCLK SCLK


Clock SS SS
องค ์ประกอบของ SPI
• สัญญาณของ SPI ประกอบด้วย
MOSI (Master Output Slave Input) เป็ นสัญญาณข้อมู ล
่ กส่งจาก Master ไปให้ Slave
ทีถู
MISO (Master Input Slave Output) เป็ นสัญญาณข้อมู ล
่ กส่งจาก Slave ไปให้ Master
ทีถู
SCLK (Serial Clock) เป็ นสัญญาณนาฬก ่ กส่งจาก
ิ าทีถู
Master Clock ของฝั่ ง Master ไปให้กบ
ั Serial Shift
Register ของฝั่ ง Slave
SPI Master
MOSI MOSI
SPI Slave

MISO MISO
0 1 1 1 0 0 0 1 0 1 0 1 1 1 0 1
MSB LSB MSB LSB

Master SCLK SCLK


Clock SS SS
องค ์ประกอบของ SPI
/SS (Slave Select) เป็ น
สัญญาณที่ Master ส่งไปบอก
MOSI MOSI
SPI Master SPI Slave#0

Slave ว่าต้องการร ับส่งข้อมู ล


MISO MISO TC77
Master SCLK SCLK (13-bit Temp.
ด้วย
Clock Sensor)
SS0 SS

ตัวอย่างเช่น ใช้ SPI ของ SS1


MOSI

PIC18F8722 ในการอ่าน
SS2
SPI Slave#1
่ น
MISO

อุณหภู มจิ าก LM74 ซึงเป็ SCLK SD Card

เซนเซอร ์วัดอุณหภู มข ิ นาด PIC18F8722


SS

13 bit และนาไปเก็บค่าไว้ใน MOSI

SD Card และแสดงผลใน TFT MISO


SPI Slave#2
TFT LCD
SCLK
LCD Display Module Display

โดยใช้ส่งสัญญาณ /SS0,
SS

/SS1 หรือ /SS2 ไปเลือกว่า



ต้องการทีจะติ ดต่อกับ Sensor,
Master Synchronous Serial Port
(MSSP1, MSSP2)
่ ใน
• MSSP1 และ MSSP2 เป็ นโมดู ลทีใช้

การสือสารแบบ SPI และ I2C
• SPI สามารถทางานได้ทง้ั Master หรือ MISO
Slave และ Port ต่างๆของ PIC18F8722 MOSI
่ กกาหนดให้เป็ นสัญญาณของ SPI
ทีถู
เป็ นดังนี ้ SS

RC5 (MOSI1), RD4 (MOSI2)


RC4 (MISO1), RD5 (MISO2)
RC3 (SCLK1), RD6 (SCLK2) SCLK
RF7 (/SS1), RD7 (/SS2) ใช้เฉพาะในกรณี
่ น Slave Mode
ทีเป็ MSSP Block Diagram
(SPI Mode)
Master Synchronous Serial Port
(MSSP1, MSSP2)
• จากบล็อคไดอะแกรมจะเห็นว่า
สัญญาณนาฬก ิ าของ SPI สามารถ
สร ้างได้ 2 วิธค
ี อ
ื MISO
MOSI
Timer 2 Output/2
(SSPM3:SSPM0 = 0011) SS
วงจร Oscillator ของ PIC18F8722 โดย
่ ากับ
สามารถเลือกได ้ว่าจะให ้มีความถีเท่
oFosc/4 (SSPM3:SSPM0 = 0000)
SCLK
oFosc/16 (SSPM3:SSPM0 = 0001)
oFosc/64 (SSPM3:SSPM0 = 0010)
MSSP Block Diagram
(SPI Mode)
่ ยวข้
Register ทีเกี ่ องกับ MSSP
่ ยวข้
Register ทีเกี ่ องกับ MSSP
• MSSPx Control
Register 1 (SSPxCON1)
ใช ้ในการควบคุมการ
ทางานของ MSSP
สามารถอ่านหรือเขียนได ้
ทัง้ 8 bit
<SSPM3:SSPM0> เป็ น
ตัวกาหนดว่าให ้โมดูล
MSSP เป็ น
Master Mode
<00xx>
Slave Mode <010x>
่ ยวข้
Register ทีเกี ่ องกับ MSSP
• MSSPx Status
Register (SSPxSTAT)
ใช ้แสดงสถานะของ
MSSP
บิทที่ <7:6> สามารถ
อ่านและเขียนได ้
บิทที่ <5:0> สามารถ
อ่านได ้เพียงอย่าง
เดียว
่ ยวข้
Register ทีเกี ่ องกับ MSSP
• Serial Receive/Transmit Buffer Register
(SSPxBUF) ใช ้ในการเก็บข ้อมูลทีต ่ ้องการ
ส่งออกไปหรือร ับเข ้ามา
• MSSP Shift Register (SSPxSR) เป็ น Shift
Register ทีใช่ ้ในระหว่างการร ับส่งข ้อมูล ไม่
สามารถเขียนโปรแกรมอ่านหรือเขียนข ้อมูล
กับ SSPxSR ได ้โดยตรง
PIC18F8722 SPI Master SSPM3:SSPM0 = 0b00xx PIC18F8722 SPI Slave SSPM3:SSPM0 = 0b010x
MOSI MOSI

่ ้องการส่งข ้อมูล จะต ้องเขียนโปรแกรม


• เมือต
x x x x x x x x x x x x x x x x

่ ้องการส่งไปเก็บไว ้ใน SSPxBUF


SSPxBUF SSPxBUF

นาค่าทีต
จากนั้นโมดูล MSSP จะส่งค่าทีอยู ่ ใ่ น MISO MISO
0 1 1 1 0 0 0 1 0 1 0 1 1 1 0 1


MSB SSPxSR LSB MSB SSPxSR LSB

SSPxBUF ไปเก็บไว ้ใน SSPxSR ก่อนทีจะ


Shift ข ้อมูลออกไป
Master SCLK SCLK
Clock Any Port SS

่ องการร ับข้อมู ล โมดู ล MSSP


• หรือเมือต้
จะ Shift ข้อมู ลเข้ามาเก็บไว้ใน SSPxSR
จนครบ 8 bit ก่อนทีจะส่ ่ งข้อมู ลทัง้ 8
bit ไปเก็บไว้ใน SSPxBUF
SPI Mode Waveform
(Master Mode)
• CKP
=1 Idle State = 1
=0 Idle State = 0
• CKE
=1 ข้อมู ลถู กส่งเมือ่
สัญญาณนาฬก ่
ิ าเปลียน
สถานะจาก Active ไปเป็ น
Idle
=0 ข้อมู ลถู กส่งเมือ ่
สัญญาณนาฬก ิ าเปลียน่
สถานะจาก Idle ไปเป็ น
Slave Synchronization Waveform
SPI Mode Waveform
(Slave Mode with CKE = 0)
SPI Mode Waveform
(Slave Mode with CKE = 1)
16-Bit I/O Expander with
Serial Interface
/RESET VDD
A0 MCP23S17
A1 GPA0 330
VDD
A2
PIC18F8722 GPA1 330
MOSI SI 330
RC5 GPA2
MISO SO
RC4
SCLK SCK GPA3 330
RC3
/SS /CS
RC2 330
GPA4
GPA5 330
GPA6 330
GPA7 330

15k
GPB0 1k

ตัวอย่างโปรแกรมสือสาร SPI
#include <p18f8722.h> static rom unsigned char led_patern[32] =
#include <delays.h> {0b00000001,0b00000011,0b00000110,0b00001100,0b00011001,

0b00110011,0b01100110,0b11001100,0b10011000,0b00110000,
// MCP23S17 SPI Slave Device 0b01100000,0b11000000,0b10000000,0b00000000,0b00000000,
#define SPI_SLAVE_ID 0x40
0b00000000,0b10000000,0b11000000,0b01100000,0b00110000,
#define SPI_SLAVE_ADDR 0x00 // A2=0,A1=0,A0=0
0b10011000,0b11001100,0b01100110,0b00110011,0b00011001,
#define SPI_SLAVE_WRITE 0x00
0b00001100,0b00000110,0b00000011,0b00000001,0b00000000,
#define SPI_SLAVE_READ 0x01
0b00000000,0b00000000};
// Delay in 1 ms (approximately) for 16 MHz Internal Clock
// MCP23S17 Registers Definition for BANK=0 (default)
void delay_ms(unsigned int ms)
#define IODIRA 0x00
{
#define IODIRB 0x01
do {
#define IOCONA 0x0A
Delay1KTCYx(4);
#define GPPUA 0x0C
} while(--ms);
#define GPPUB 0x0D
}
#define GPIOA 0x12
#define GPIOB 0x13

ตัวอย่างโปรแกรมสือสาร SPI unsigned char SPI_Read(unsigned char addr)
void SPI_Write(unsigned char addr,unsigned char data) {
{ // Activate the SS SPI Select pin
// Activate the SS SPI Select pin PORTCbits.RC2 = 0;
PORTCbits.RC2 = 0; // Start MCP23S17 OpCode transmission
// Start MCP23S17 OpCode transmission SSPBUF = SPI_SLAVE_ID | ((SPI_SLAVE_ADDR << 1) & 0x0E)|
SPI_SLAVE_READ;
SSPBUF = SPI_SLAVE_ID | ((SPI_SLAVE_ADDR << 1) & 0x0E)|
SPI_SLAVE_WRITE; // Wait for Data Transmit/Receipt complete
// Wait for Data Transmit/Receipt complete while(!SSPSTATbits.BF);
while(!SSPSTATbits.BF); // Start MCP23S17 Address transmission
// Start MCP23S17 Register Address transmission SSPBUF = addr;
SSPBUF = addr; // Wait for Data Transmit/Receipt complete
// Wait for Data Transmit/Receipt complete while(!SSPSTATbits.BF);
while(!SSPSTATbits.BF); // Send Dummy transmission for reading the data
// Start Data transmission SSPBUF = 0x00;
SSPBUF = data; // Wait for Data Transmit/Receipt complete
// Wait for Data Transmit/Receipt complete while(!SSPSTATbits.BF);
while(!SSPSTATbits.BF); // CS pin is not active
// CS pin is not active PORTCbits.RC2 = 1;
PORTCbits.RC2 = 1; return(SSPBUF);
} }

ตัวอย่างโปรแกรมสือสาร SPI
void main(void) SSPSTAT = 0x40; // Set SMP=0 and CKE=1. Notes: The lower 6 bit
is read only
{
SSPCON1 = 0x20; // Enable SPI Master with Fosc/4
unsigned char cnt,togbutton,inp;
PORTCbits.RC6 = 1; // Disable Chip Select
unsigned int idelay;
// Initial the MCP23S17 SPI I/O Expander
SPI_Write(IOCONA,0x28); // I/O Control Register: BANK=0,
TRISC = 0x00; // Set All on PORTC as Output SEQOP=1, HAEN=1 (Enable Addressing)
SPI_Write(IODIRA,0x00); // GPIOA As Output
/* Init the PIC18F14K22 ADC Peripheral */ SPI_Write(IODIRB,0xFF); // GPIOB As Input
ADCON0=0b00001101; // ADC port channel 3 (AN3), Enable ADC SPI_Write(GPPUB,0xFF); // Enable Pull-up Resistor on GPIOB
ADCON1=0b00000000; // Use Internal Voltage Reference (Vdd and SPI_Write(GPIOA,0x00); // Reset Output on GPIOA
Vss)
// Initial Variable Used
ADCON2=0b10101011; // Right justify result, 12 TAD, Select the
FRC for 16 MHz togbutton=0; // Toggle Button
/* Initial the PIC18F14K22 SPI Peripheral */ cnt=0;
TRISCbits.TRISC2 = 0; // RC6/SS - Output (Chip Select) idelay=100; // Default Delay;
TRISCbits.TRISC5= 0; // RC7/SDO - Output (Serial Data Out)
TRISBbits.TRISB4= 1; // RB4/SDI - Input (Serial Data In) for(;;) {
TRISBbits.TRISB2= 0; // RB6/SCK - Output (Clock) inp=SPI_Read(GPIOB); // Read from GPIOB

ตัวอย่างโปรแกรมสือสาร SPI
if (inp == 0xFE) { // Button is pressed // Write to GPIOA
delay_ms(1); SPI_Write(GPIOA,led_patern[cnt++]);
if(cnt >= 32) cnt=0;
inp=SPI_Read(GPIOB); // Read from GPIOB, for simple }
debounce
delay_ms(idelay); // Call Delay function
if (inp == 0xFE) togbutton^=0x01;
}
if (togbutton == 0x00) {
}
SPI_Write(GPIOA,0x00); // Write to MCP23S17
GPIOA
cnt=0;
}
}
if (togbutton) {
ADCON0bits.GO=1;
while (ADCON0bits.GO); // Wait conversion done
idelay=ADRESL; // Get the 8 bit LSB result
idelay += (ADRESH << 8); // Get the 2 bit MSB result

You might also like