Professional Documents
Culture Documents
Lecture 91
Lecture 91
่
ปั ญหาของการสือสารแบบ 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
MISO MISO
0 1 1 1 0 0 0 1 0 1 0 1 1 1 0 1
MSB LSB MSB LSB
PIC18F8722 ในการอ่าน
SS2
SPI Slave#1
่ น
MISO
โดยใช้ส่งสัญญาณ /SS0,
SS
นาค่าทีต
จากนั้นโมดูล 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
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