SM39R 系列 SPI 功能使用方法 SPI 功能使用方法 1 適用產品: 1.1 SM39R16A2/ SM39R12A2/ SM39R08A2 2 SPI 使用說明: 2.1 SPI 通信使用 4 個引腳,分別為: ¾ SPI_MOSI: 做為 master 時資料輸出;做為 slave 時資料輸入 ¾ SPI_MISO: 做為 master 時資料輸入;做為 slave 時資料輸出 ¾ ¾ SPI_CLK: SPI 的時脈信號由 master 主控產生;資料 (輸出及輸入) 和時脈同步 SPI_SS: 此引腳唯有做為 slave mode 時有做用;做為 master mode,此引腳當做 GPIO 使用 = 0: master致能slave = 1: master禁能slave Master MOSI MISO CLK IO IO 3 Slave 2 Slave 1 MOSI MISO CLK MOSI MISO CLK SS SS SPI 相關的特殊暫存器 SPI Special Function Register (SFR) SPI AUX SPIC1 Description Auxiliary register SPI control register 1 Direct Bit 7 Bit 6 Bit 5 Bit 4 SPI function Bit 3 Bit 2 Bit 1 Bit 0 RST 91h BRGS - P2UR P2IIC - - DPS 00H F1h SPIEN SPIMSS SPISSP SPICKP SPICKE SPIBR[2:0] 08H TBC[2:0] SPIRST RBC[2:0] 00H P2SPI SPIC2 SPI control register 2 F2h SPIFD SPIS SPI status register F5h SPIRF SPITXD SPI transmit data buffer F3h SPITXD[7:0] 00H SPIRXD SPI receive data buffer F4h SPIRXD[7:0] 00H Mnemonic: AUX 7 6 5 BRGS P2SPI SPIMLS 4 P2UR SPIOV 3 P2IIC SPITXIF 2 - SPITDR SPIRXIF SPIRDR SPIRS 1 - Address: 91h 0 Reset DPS 00H Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0239 1 Ver A 2011/09 40H SM39R 系列 SPI 功能使用方法 P2SPI: P2SPI = 0 – SPI function on P1. P2SPI = 1 – SPI function on P2. P4SPI setting SPI_SS P1.4 0 P2.4 1 Mnemonic: SPIC1 7 6 5 SPIEN SPIMSS SPISSP 4 SPICKP SPI_MOSI P1.7 P2.2 SPI_MISO P1.6 P2.3 Address: F1h 3 2 1 0 SPICKE SPIBR[2:0] SPI_CLK P0.0 P2.5 Reset 08h SPIEN: SPI 模組致能旗標: “1” – 致能 “0” – 禁能 SPIMSS: 主從模式選擇旗標(Master or Slave mode Select) “1” – MCU 做為 Master mode. “0” – MCU 做為 Slave mode. SPISSP: (SS)引腳致能狀態旗標;當 MCU 為 slave 時,可由旗標設定 Slave Select (SS)引腳致能狀態 (slave mode used only) “1” – 高準位致能 high active. “0” – 低準位致能 low active. SPICKP: 時脈閒置準位旗標(master mode used only) “1” – 時脈信號閒置時為高準位(SCK high during idle), Ex : “0” – 時脈信號閒置時為低準位(SCK high during idle), Ex : SPICKE: 時脈取樣旗標 Clock sample edge select. “1” – 正緣取樣 data latch in rising edge “0” – 負緣取樣 data latch in falling edge. * 為確保資料取樣的正確性,無論使用正緣或負緣取樣,時脈及資料同步時皆需有足夠的準備時間 (set-up time)及保持時間(hold time),時序產生如下圖: sufficient set-up time sufficient hold time SPIBR[2:0]: SPI 鮑率選擇(master mode used only), Fosc 為晶振頻率: SPIBR[2:0] Baud rate Fosc/4 0:0:0 Fosc/8 0:0:1 Fosc/16 0:1:0 Fosc/32 0:1:1 Fosc/64 1:0:0 Fosc/128 1:0:1 Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0239 2 Ver A 2011/09 SM39R 系列 SPI 功能使用方法 Fosc/256 Fosc/512 1:1:0 1:1:1 Mnemonic: SPIC2 7 6 5 SPIFD TBC[2:0] 4 3 SPIRST 2 1 RBC[2:0] Address: F2h 0 Reset 00h SPIFD: 全雙工模式致能旗標(Full-duplex mode enable) “1” : 全雙工模式致能 “0” : 全雙工模式禁能 當該旗標致能時,TBC[2:0]和RBC[2:0]會被清除並保持為零,SPI全雙工模式僅允許8位元通訊. Master透過MOSI引腳做資料輸出,slave時透過MISO回傳資料,SPI的時脈信號由master主控產 生;所有資料 (輸出及輸入) 皆和時脈同步。 Input Shift register SPIRXD Output Shift register SPITXD Clock Generator SyncMos Master MISO MISO MOSI MOSI SCK SCK Output Shift register SPITXD Input Shift register SPIRXD SyncMos Slave SPIRST: SPI Re-start (Slave mode used only) SPIRST=0: 重新啟動功能關閉,當SS動作時SPI模組傳送/接收數據。 SS 動作期間先前在 SPITXD/SPIRXD 緩衝區的數據將不會被清除(Shift counter 不會歸 零,數據是有效的) SPIRST=1: 重新啟動功能致能,當SS重新動作時SPI模組傳送/接收新的數據。 SS 動作期間先前在 SPITXD/SPIRXD 緩衝區的數據將會被清除(Shift counter 會歸 零,數據是無效的) TBC[2:0]: SPI 傳送元位計數旗標(SPI transmitter bit counter) 可設定 1~8 位元通訊,但全雙工模式僅允許 8 位元通訊。 TBC[2:0] Bit counter 8 bits output 0:0:0 1 bit output 0:0:1 2 bits output 0:1:0 3 bits output 0:1:1 4 bits output 1:0:0 5 bits output 1:0:1 6 bits output 1:1:0 7 bits output 1:1:1 Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0239 3 Ver A 2011/09 SM39R 系列 SPI 功能使用方法 RBC[2:0]: SPI 接收元位計數旗標(SPI receiver bit counter) 可設定 1~8 位元通訊,但全雙工模式僅允許 8 位元通訊。 RBC[2:0] Bit counter 8 bits input 0:0:0 1 bit input 0:0:1 2 bits input 0:1:0 3 bits input 0:1:1 4 bits input 1:0:0 5 bits input 1:0:1 6 bits input 1:1:0 1:1:1 7 bits input Mnemonic: SPIS 7 6 SPIRF SPIMLS 5 SPIOV 4 SPITXIF 3 SPITDR 2 SPIRXIF 1 SPIRDR Address: F5h 0 Reset SPIRS 40h SPIRF: SPI SS pin Release Flag.(SPI SS 釋放旗標) 當SS腳釋放(高電平)和SPIRST為”1”時,此位元被設定為1,可供Slave判斷是否已被釋放 SPIMLS: MSB or LSB output /input first “1” : 最高位元先傳送 (MSB output/input first)。 “0” : 最低位元先傳送 (LSB output/input first)。 SPIOV: 溢位旗標(Overflow flag) “1” : 當 SPIRDR 已設定(SPIRXD 原有資料未被讀取)且下一筆資料正寫入 SPIRXD 時,SPIOV 將被設定為”1”,告知 SPIRXD 資料以有損毀。 “0” : 當 SPIRDR 清為零時,SPIOV 則由硬體清除。 SPITXIF: 傳送中斷旗標(Transmit Interrupt Flag) “1” : 當 SPITXD 的資料已載入移位暫存器,由硬體設定為”1” 。 “0” : 傳送資料完成後必須由軟體清除。 SPITDR: 資料傳送位元(Transmit Data Ready) “1”: 當程序為傳送模式時,資料儲存至 SPITXD 後,由軟體設定此旗標為”1” ,告知 SPI module 允許傳出資料。 “0”: 當 SPI module 由 SPITXD 完成傳送時(或 SPITXD 被載至移位暫存器時),此旗標則由硬體自 動清除。 SPIRXIF: 接收中斷旗標(Receive Interrupt Flag) “1” : 當 SPIRXD 被載入新一筆資料後,由硬體設定為”1” 。 “0” : 接收資料完成後必須由軟體清除。 SPIRDR: 資料接收位元(Receive Data Ready) “1” : SPI module接收資料時,SPIRDR由硬體自動設定為”1”,以告知MCU完成接收並儲存至 SPIRXD;當新的一筆資料寫入SPIRXD,而SPIRDR未清除時,SPIRXD原有的資料將被覆寫,產 生overflow “0” : 由 SPIRXD 讀取資料後,必須由軟體清除此旗標。 SPIRS: 接收開始位元(Receive Start) “1” : 由軟件設為”1”,告知 SPI 模組 SPIRXD 開始接收資料(即 SPI_CLK 開始送 clock)。 “0” : 當資料接收完成,由硬體清為”0” Mnemonic: SPITXD 7 6 5 4 3 SPITXD[7:0] 2 1 0 Address: F3h Reset 00h Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0239 4 Ver A 2011/09 SM39R 系列 SPI 功能使用方法 SPITXD[7:0]: 傳送資料緩衝器(Transmit data buffer) Mnemonic: SPIRXD 7 6 5 4 3 SPIRXD[7:0] 2 1 Address: F4h 0 Reset 00h SPIRXD[7:0]: 接收資料緩衝器(Receive data buffer) 4 SPI 中斷 4.1 向量表(Interrupt vectors table) Interrupt Vector Address Interrupt Number *(use Keil C Tool) IE0 – External interrupt 0 0003h 0 TF0 – Timer 0 interrupt 000Bh 1 IE1 – External interrupt 1 0013h 2 TF1 – Timer 1 interrupt 001Bh 3 RI0/TI0 – Serial channel 0 interrupt 0023h 4 TF2/EXF2 – Timer 2 interrupt 002Bh 5 PWMIF – PWM interrupt 0043h 8 SPIIF – SPI interrupt 004Bh 9 ADCIF – A/D converter interrupt 0053h 10 KBIIF – keyboard Interface interrupt 005Bh 11 LVIIF – Low Voltage Interrupt 0063h 12 IICIF – IIC interrupt 006Bh 13 RI1/TI1 – Serial channel 1 interrupt 0083h 16 Interrupt Request Flags *請參考Keil C用戶指南中的有關中斷功能使用說明 Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0239 5 Ver A 2011/09 SM39R 系列 SPI 功能使用方法 4.2 中斷相關暫存器(Interrupt SFR) Mnemonic IEN1 IRCON IP0 IP1 Description Interrupt Enable 1 register Interrupt request register Interrupt priority level 0 Interrupt priority level 1 Direct Bit 7 Bit 6 Bit 5 Interrupt Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 RST B8h EXEN2 - IEIIC IELVI IEKBI IEADC IESPI IEPWM 00h C0H EXF2 TF2 IICIF LVIIF KBIIF ADCIF SPIIF PWMIF 00H A9h - - IP0.5 IP0.4 IP0.3 IP0.2 IP0.1 IP0.0 00h B9h - - IP1.5 IP1.4 IP1.3 IP1.2 IP1.1 IP1.0 00h Table: Priority levels IP1.x IP0.x Priority Level 0 0 1 1 0 1 0 1 Level0 (lowest) Level1 Level2 Level3 (highest) Table: Groups of priority Bit IP1.0, IP0.0 IP1.1, IP0.1 IP1.2, IP0.2 IP1.3, IP0.3 IP1.4, IP0.4 IP1.5, IP0.5 External interrupt 0 Timer 0 interrupt External interrupt 1 Timer 1 interrupt Serial channel 0 interrupt Timer 2 interrupt Group Comparator interrupt - PWM interrupt SPI interrupt ADC interrupt KBI interrupt LVI interrupt IIC interrupt Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0239 6 Ver A 2011/09 SM39R 系列 SPI 功能使用方法 5 以下為兩顆 MCU 分別當做 SPI master 及 slave 通訊的流程圖 Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0239 7 Ver A 2011/09 SM39R 系列 SPI 功能使用方法 6 SPI master 及 slave 通訊的半雙工範例程式 6.1 Master 傳資料(CMD 0x80)至 Slave 6.2 Slave 接受 CMD 後,判斷是否為正確 CMD,回傳資料給 Master 6.3 Master 接受 Slave 回傳的資料後,做資料比較,正確在 P0 輸出 0xaa,反之輸出 0x55 Description C 語言 Master: //==================================================================== // SYNCMOS TECHNOLOGY //==================================================================== #include "SM39R16A2.h" #include "SPI.h" #define SPI_VECTOR 9 #define SPIBR 7 #define SPIEN 1 #define SPIMSS 1 //#define SPISSP 0 #define SPICKP 1 #define SPICKE 0 #define SPIFD 0 #define SPIMLS 1 #define SPITXIF 0x10 #define SPIRXIF 0x04 #define SPITDR 0x08 #define SPIRDR 0x02 #define SPIRS 0x01 #define SPI_SS P1_4 #define P2SPI 0x00 #define TBC 0 #define RBC 0 //SPI Interrupt Vevtor //SPIBR[2:0] (SPI Baud Rate select 0~7) //SPI Enable //Master/Slave Select //Slave active polarity Select(Slave used only) //Clock idle polarity(Master used only) //Clock sample edge select //Full-duplex mode enable //MSB/LSB O/I First //Transmit Interrupt Flag //Receive Interrupt Flag //Transmit Data Ready //Receive Data Ready //Receive Start //SPI device select pin //SPI Function on P1(P2SPI=0) or P2(P2SPI=1) //TBC[2:0] (SPI transmitter bit counter 0~7) //RBC[2:0] (SPI receiver bit counter 0~7) unsigned char nRData; //---------------------------------------------------------------------// void SPI_Master_initialize(void) //Initialize SPI { EA = 0; //Disable All Interrupt Function AUX = AUX | (P2SPI<<5); //Set SPI Function on P1 or P2 SPI_SS = 0; IESPI = 1; //Enable SPI Interrupt Function SPIC1 = (SPIEN<<7) | (SPIMSS<<6) | (SPICKP<<4) | (SPICKE<<3) | SPIBR; SPIC2 = (SPIFD<<7) | (TBC<<4) | RBC; SPIS = (SPIMLS<<6); SPITXD = 0xFF; SPIRXD = 0xFF; EA = 1; //Enable All Interrupt } //---------------------------------------------------------------------// void SPI_MTransmit(unsigned char nTData) { if(SPIMSS) { SPITXD = nTData; SPIS = SPIS | SPITDR; //SPIMSS=1,Master mode //Load to TX Buffer //set SPITDR, TX proceed Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0239 8 Ver A 2011/09 SM39R 系列 SPI 功能使用方法 while((SPIS&SPITDR) == SPITDR) //SPITDR=(SPIS&0x08),TDR clear by H/W { ; } while((SPIS&SPITXIF) == SPITXIF) { ; } } } //---------------------------------------------------------------------// unsigned char SPI_MReceive() { if(SPIMSS) //SPIMSS=1,Master mode { unsigned char nRData; SPI_SS = 0; SPIRXD = 0xFF; // clear SPITXD, useless SPIS = SPIS | SPIRS; // RX Start and send SPI CLK //while((SPIS&SPIRDR)==SPIRDR); // SPIRDR=(SPIS&0x08),RDR set 1 by H/W while((SPIS&SPIRXIF)!=SPIRXIF) { ; } nRData = SPIRXD; return nRData; } } //---------------------------------------------------------------------// //******************Variable bit counter*******************************// /*void SPI_MVTransmit(unsigned char nTBC,unsigned char nTData) //Slave Transmit Subroutine variable bit counter { if(SPIMSS) //SPIMSS=0,Slave mode { SPIC2=SPIC2|(nTBC<<4); SPITXD=(nTData); //Load to TX Buffer SPIS=SPIS|SPITDR; //set SPITDR, TX proceed while((SPIS&SPITDR)==SPITDR); //SPITDR=(SPIS&0x08),TDR clear by H/W while((SPIS&SPITXIF)==SPITXIF); } } */ //---------------------------------------------------------------------// /*unsigned char SPI_MVReceive(unsigned char nRBC) //Slave Receive Subroutine variable bit counter { if(SPIMSS) //SPIMSS=0,Slave mode { unsigned char nRData; SPIC2=SPIC2|nRBC; SPIRXD=0xFF; SPIS=SPIS|SPIRS; // RX Start and send SPI CLK //while((SPIS&SPIRDR)==SPIRDR); // SPIRDR=(SPIS&0x08),RDR set 1 by H/W while((SPIS&SPIRXIF) != SPIRXIF); Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0239 9 Ver A 2011/09 SM39R 系列 SPI 功能使用方法 nRData=SPIRXD; return nRData; } }*/ //*********************************************************************// void SPI_Disable(void) { SPI_SS=1; SPIC1=0; //Disable SPI Function } //---------------------------------------------------------------------// void SPI_ISR(void) interrupt SPI_VECTOR //SPI Interrupt Subroutine { if((SPIS & SPIRXIF) == SPIRXIF) //SPIRDR=(SPIS&0x02) Receive Data Ready { SPIS = SPIS & 0xE1; //Clear SPITXIF & SPITDR & SPIRXIF & SPIRDR } else if((SPIS & SPITXIF) == SPITXIF) { SPIS = SPIS & 0xE1; //Clear SPITXIF & SPITDR & SPIRXIF & SPIRDR } } //---------------------------------------------------------------------// void main(void) //Main Function Start { unsigned char SACK,CMD=0x80,loop=0,CMD_PASS=0xaa,CMD_FAIL=0x55; SPI_Master_initialize(); //Call SPI Initial Subroutine while(1) { SPI_MTransmit(CMD); //Master transmit CMD to Slave SACK = SPI_MReceive(); //Call SPI Receive Subroutine if(SACK == CMD_PASS) //If Receive CMD_PASS then Master P0 show CMD_PASS { //Else Master P0 show CMD_FAIL P0 = CMD_PASS; } else { P0 = CMD_FAIL; } SPI_Disable(); while(1); } } Description C 語言 Slave: #include "SM39R16A2.h" #include "SPI.h" #define SPI_VECTOR 9 //SPI Interrupt Vevtor #define SPIBR 7 //SPIBR[2:0] (SPI Baud Rate select 0~7) #define SPIEN 1 //SPI Enable #define SPIMSS 0 //Master/Slave Select #define SPISSP 1 //Slave active polarity Select(Slave used only) Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0239 10 Ver A 2011/09 SM39R 系列 SPI 功能使用方法 //#define SPICKP 0 #define SPICKE 0 #define SPIFD 0 #define SPIMLS 1 #define SPITXIF 0x10 #define SPIRXIF 0x04 #define SPITDR 0x08 #define SPIRDR 0x02 #define SPIRS 0x01 #define P2SPI 0x00 #define TBC 0 #define RBC 0 //Clock idle polarity(Master used only) //Clock sample edge select //Full-duplex mode enable //MSB/LSB O/I First //Transmit Interrupt Flag //Receive Interrupt Flag //Transmit Data Ready //Receive Data Ready //Receive Start //SPI Function on P1(P2SPI=0) or P2(P2SPI=1) //TBC[2:0] (SPI transmitter bit counter 0~7) //RBC[2:0] (SPI receiver bit counter 0~7) unsigned char nRData; //---------------------------------------------------------------------// void SPI_Slave_initialize(void) //Initialize SPI { EA = 0; //Disable All Interrupt Function AUX = AUX | (P2SPI<<5); //Set SPI Function on P1 or P2 IESPI = 1; //Enable SPI Interrupt Function SPIC1 = (SPIEN<<7) | (SPIMSS<<6) | (SPISSP<<5) | (SPICKE<<3) | SPIBR; SPIC2 = (SPIFD<<7) | (TBC<<4) | RBC; SPIS = (SPIMLS<<6); SPITXD = 0xFF; SPIRXD = 0xFF; EA = 1; //Enable All Interrupt } //---------------------------------------------------------------------// void SPI_STransmit(unsigned char nTData) //Slave Transmit Subroutine fixed bit counter { if(~SPIMSS) //SPIMSS=0,Slave mode { SPITXD = nTData; //Load to TX Buffer SPIS = SPIS | SPITDR; //set SPITDR, TX proceed while((SPIS&SPITDR) == SPITDR) //SPITDR=(SPIS&0x08),TDR clear by H/W { ; } while((SPIS&SPITXIF) == SPITXIF) { ; } } } //---------------------------------------------------------------------// unsigned char SPI_SReceive() //Slave Receive Subroutine fixed bit counter { if(~SPIMSS) //SPIMSS=0,Slave mode { unsigned char nRData; SPIRXD = 0xFF; SPIS = SPIS | SPIRS; // RX Start and send SPI CLK //while((SPIS&SPIRDR)==SPIRDR); // SPIRDR=(SPIS&0x08),RDR set 1 by H/W while((SPIS&SPIRXIF) != SPIRXIF) { Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0239 11 Ver A 2011/09 SM39R 系列 SPI 功能使用方法 ; } nRData = SPIRXD; return nRData; } } //**********************Variable bit counter**************************************// /*void SPI_SVTransmit(unsigned char nTBC,unsigned char nTData) //Slave Transmit Subroutine variable bit counter { if(~SPIMSS) //SPIMSS=0,Slave mode { SPIC2=SPIC2|(nTBC<<4); SPITXD=(nTData); //Load to TX Buffer SPIS=SPIS|SPITDR; //set SPITDR, TX proceed while((SPIS&SPITDR)==SPITDR); //SPITDR=(SPIS&0x08),TDR clear by H/W while((SPIS&SPITXIF)==SPITXIF); } } */ //---------------------------------------------------------------------// /*unsigned char SPI_SVReceive(unsigned char nRBC) //Slave Receive Subroutine variable bit counter { if(~SPIMSS) //SPIMSS=0,Slave mode { unsigned char nRData; SPIC2=SPIC2|nRBC; SPIRXD=0xFF; SPIS=SPIS|SPIRS; // RX Start and send SPI CLK //while((SPIS&SPIRDR)==SPIRDR); // SPIRDR=(SPIS&0x08),RDR set 1 by H/W while((SPIS&SPIRXIF) != SPIRXIF); nRData=SPIRXD; return nRData; } }*/ //**************************************************************************// void SPI_ISR(void) interrupt SPI_VECTOR //SPI Interrupt Subroutine { if((SPIS&SPIRXIF) == SPIRXIF) //SPIRDR=(SPIS&0x02) Receive Data Ready { SPIS = SPIS & 0xE1; //Clear SPITXIF & SPITDR & SPIRXIF & SPIRDR } else if((SPIS&SPITXIF) == SPITXIF) { SPIS = SPIS & 0xE1; //Clear SPITXIF & SPITDR & SPIRXIF & SPIRDR } } //---------------------------------------------------------------------// void main(void) //Main Function Start { unsigned char MACK,CMD=0x80,CMD_PASS=0xaa,CMD_FAIL=0x5a; SPI_Slave_initialize(); while(1) { //Call SPI Initial Subroutine Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0239 12 Ver A 2011/09 SM39R 系列 SPI 功能使用方法 MACK = SPI_SReceive(); if(MACK == CMD) //Call SPI Receive Subroutine //If Receive CMD then Slave transmit CMD_PASS to Master { //Else transmit CMD_FAIL to Master SPI_STransmit(CMD_PASS); P0 = CMD_PASS; } else { SPI_STransmit(CMD_FAIL); P0 = SPIRXD; } while(1); } } 7 SPI master 及 slave 全雙工通訊範例程式 7.1 Master 送 CMD(0x80),同時接收 Slave 回傳(0x66)做確認 7.2 待兩方確認,Master 若確認收到 SACK(0x66)會回傳 CMD (0x80),反之回傳 CMD_FAIL(0xff) 7.3 Slave 若確認收到 CMD(0x80)會回傳 CMD_PASS(0xaa),反之回傳 CMD_FAIL(0x5a),並將接 收值顯示於 P0 7.4 Master 若確認收到 CMD_PASS(0xaa)會將 CMD_PASS 顯示於 P0,反之將 CMD_FAIL(0x55) 顯示於 P0 Description C 語言 Master: //========================================================================= // SYNCMOS TECHNOLOGY //========================================================================= #include "SM39R16A2.h" #include "SPI.h" #define SPI_VECTOR 9 #define SPIBR 7 #define SPIEN 1 #define SPIMSS 1 //#define SPISSP 0 #define SPICKP 1 #define SPICKE 0 #define SPIFD 1 #define SPIMLS 1 #define SPITXIF 0x10 #define SPIRXIF 0x04 #define SPITDR 0x08 #define SPIRDR 0x02 #define SPIRS 0x01 #define SPI_SS P1_4 #define P2SPI 0x00 //SPI Interrupt Vevtor //SPIBR[2:0] (SPI Baud Rate select 0~7) //SPI Enable //Master/Slave Select //Slave active polarity Select(Slave used only) //Clock idle polarity(Master used only) //Clock sample edge select //Full-duplex mode enable //MSB/LSB O/I First //Transmit Interrupt Flag //Receive Interrupt Flag //Transmit Data Ready //Receive Data Ready //Receive Start //SPI device select pin //SPI Function on P1(P2SPI=0) or P2(P2SPI=1) unsigned char nRData; Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0239 13 Ver A 2011/09 SM39R 系列 SPI 功能使用方法 void SPI_Master_initialize(void) //Initialize SPI { EA = 0; //Disable All Interrupt Function AUX = AUX | (P2SPI<<5); //Set SPI Function on P1 or P2 SPI_SS = 0; IESPI = 1; //Enable SPI Interrupt Function SPIC1 = (SPIEN<<7) | (SPIMSS<<6) | (SPICKP<<4) | (SPICKE<<3) | SPIBR; SPIC2 = (SPIFD<<7); SPIS = (SPIMLS<<6) | SPIRS; SPITXD = 0xFF; SPIRXD = 0xFF; EA = 1; //Enable All Interrupt } //---------------------------------------------------------------------// void SPI_MFullTransmit(unsigned char nTData) { if (SPIMSS) //SPIMSS=1,Master mode { SPIRXD = 0xFF; // clear SPITXD, useless SPITXD = (nTData); //Load to TX Buffer SPIS = SPIS | SPITDR; //set SPITDR, TX proceed while((SPIS&SPITDR) == SPITDR) //SPITDR=(SPIS&0x08),TDR clear by H/W { ; } while((SPIS&SPITXIF) == SPITXIF) { ; } } } //**********************Variable bit counter**************************************// /*void SPI_MVFullTransmit(unsigned char nTData) //Slave Transmit Subroutine variable bit counter { if(SPIMSS) //SPIMSS=0,Slave mode { SPIRXD=0xFF; // clear SPITXD, useless SPITXD=(nTData); //Load to TX Buffer SPIS=SPIS|SPITDR; //set SPITDR, TX proceed while((SPIS&SPITDR)==SPITDR); //SPITDR=(SPIS&0x08),TDR clear by H/W while((SPIS&SPITXIF)==SPITXIF); } } */ //********************************************************************************// void SPI_Disable(void) { SPI_SS = 1; SPIC1 = 0; //Disable SPI Function } //---------------------------------------------------------------------// void SPI_ISR(void) interrupt SPI_VECTOR //SPI Interrupt Subroutine Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0239 14 Ver A 2011/09 SM39R 系列 SPI 功能使用方法 { if(((SPIS&SPITXIF) == SPITXIF) & ((SPIS&SPIRXIF) == SPIRXIF)) { nRData = SPIRXD; SPIS = SPIS & 0xE1; //Clear SPITXIF & SPITDR & SPIRXIF & SPIRDR } } //---------------------------------------------------------------------// void main(void) //Main Function Start { unsigned char SACK,CMD=0x80,loop=0,CMD_PASS=0xaa,CMD_FAIL=0x55; SPI_Master_initialize(); //Call SPI Initial Subroutine while(1) { SPI_MFullTransmit(CMD); SACK = nRData; if(SACK == 0x66) { SPI_MFullTransmit(CMD); } else { SPI_MFullTransmit(0xff); } SACK = nRData; if(SACK == CMD_PASS) //If Receive CMD_PASS then Master P0 show CMD_PASS { //Else Master P0 show CMD_FAIL P0 = CMD_PASS; } else { P0 = CMD_FAIL; } SPI_Disable(); while(1) { ; } } } Description C 語言 Slave: #//========================================================================= // SYNCMOS TECHNOLOGY ///========================================================================= #include "SM39R16A2.h" #include "SPI.h" #define SPI_VECTOR 9 //SPI Interrupt Vevtor #define SPIBR 7 //SPIBR[2:0] (SPI Baud Rate select 0~7) #define SPIEN 1 //SPI Enable #define SPIMSS 0 //Master/Slave Select #define SPISSP 1 //Slave active polarity Select(Slave used only) //#define SPICKP 0 //Clock idle polarity(Master used only) Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0239 15 Ver A 2011/09 SM39R 系列 SPI 功能使用方法 #define SPICKE 0 #define SPIFD 1 #define SPIMLS 1 #define SPITXIF 0x10 #define SPIRXIF 0x04 #define SPITDR 0x08 #define SPIRDR 0x02 #define SPIRS 0x01 #define P2SPI 0x00 //Clock sample edge select //Full-duplex mode enable //MSB/LSB O/I First //Transmit Interrupt Flag //Receive Interrupt Flag //Transmit Data Ready //Receive Data Ready //Receive Start //SPI Function on P1(P2SPI=0) or P2(P2SPI=1) unsigned char nRData; void SPI_Slave_initialize(void) //Initialize SPI { EA = 0; //Disable All Interrupt Function AUX = AUX | (P2SPI<<5); //Set SPI Function on P1 or P2 IESPI = 1; //Enable SPI Interrupt Function SPIC1 = (SPIEN<<7) | (SPIMSS<<6) | (SPISSP<<5) | (SPICKE<<3) | SPIBR; SPIC2 = (SPIFD<<7); SPIS = (SPIMLS<<6) | SPIRS; SPITXD = 0xFF; SPIRXD = 0xFF; EA = 1; //Enable All Interrupt } void SPI_SFullTransmit(unsigned char nTData) { if(~SPIMSS) //SPIMSS=1,Master mode { SPIRXD = 0xFF; // clear SPITXD, useless SPITXD = (nTData); //Load to TX Buffer SPIS = SPIS | SPITDR; //set SPITDR, TX proceed while((SPIS&SPITDR)==SPITDR) //SPITDR=(SPIS&0x08),TDR clear by H/W { ; } while((SPIS&SPITXIF)==SPITXIF) { ; } } } //**********************Variable bit counter**************************************// /*void SPI_SVFullTransmit(unsigned char nTData) //Slave Transmit Subroutine variable bit counter { if(~SPIMSS) //SPIMSS=0,Slave mode { SPIRXD=0xFF; // clear SPITXD, useless SPITXD=(nTData); //Load to TX Buffer SPIS=SPIS|SPITDR; //set SPITDR, TX proceed while((SPIS&SPITDR)==SPITDR); //SPITDR=(SPIS&0x08),TDR clear by H/W while((SPIS&SPITXIF)==SPITXIF); } Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0239 16 Ver A 2011/09 SM39R 系列 SPI 功能使用方法 } */ //********************************************************************************// void SPI_ISR(void) interrupt SPI_VECTOR //SPI Interrupt Subroutine { if(((SPIS&SPITXIF) == SPITXIF) & ((SPIS&SPIRXIF) == SPIRXIF)) { nRData = SPIRXD; SPIS = SPIS & 0xE1; //Clear SPITXIF & SPITDR & SPIRXIF & SPIRDR } } void main(void) //Main Function Start { unsigned char MACK,CMD=0x80,CMD_PASS=0xaa,CMD_FAIL=0x5a; SPI_Slave_initialize(); //Call SPI Initial Subroutine while(1) { SPI_SFullTransmit(0x66); MACK = nRData; if(MACK == CMD) //If Receive CMD then Slave transmit CMD_PASS to Master { //Else transmit CMD_FAIL to Master SPI_SFullTransmit(CMD_PASS); P0 = CMD_PASS; } else { SPI_SFullTransmit(CMD_FAIL); P0 = SPIRXD; } while(1) { ; } } } 新茂國際科技希望能為客戶減少開發的時間及辛勞,故提供 “Codzard 範例程式產生器" 可於 新茂網站首頁>下載專區> 軟體下載 內下載此軟體,如有任何建議,請來信告知,謝謝! 銷售客服 電子信箱: [email protected] 技術支援 電子信箱: [email protected] Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0239 17 Ver A 2011/09