SPI 功能使用方法 SPI 功能使用方法 1 适用产品: 1.1 SM59R16A2/ SM59R08A2 1.2 SM59R16A5/ SM59R09A5/SM59R05A5/SM59R16A3/ SM59R09A3 /SM59R05A3 1.3 SM59R04A2/ SM59R04A1/ SM59R03A1/ SM59R02A1 2 SPI 使用概述: SPI 通信使用 4 个引脚,分别为: z SPI_MOSI: 做为master时数据输出;做为slave时数据输入 z SPI_MISO: 做为master时数据输入;做为slave时数据输出 z SPI_CLK: SPI的频率信号由master主控产生;数据 (输出及输入) 和频率同步 z 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 P4SPI (SPI function pin assignment)说明: SM59R16A5/SM59R16A3 P4SPI (SPI function pin assignment) ○ SM59R09A5/SM59R09A3 ○ SM59R05A5/SM59R05A3 ○ SM59R16A2 × SM59R08A2 × SM59R04A2/SM59R04A1 ○ SM59R03A1 ○ SM59R02A1 ○ Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0178 1 Ver A 2010/06 SPI 功能使用方法 ○:表示该型号可以使用 P4SPI 功能 ×:表示该型号不可使用 P4SPI 功能 Notice:所有系列的 Package type DIP-40 没有 P4,所以没有用此功能 P4SPI (SPI function pin assign)说明 Mnemonic AUX Description Direct Bit 7 Auxiliary register 91h BRS Bit 6 Bit 5 Bit 4 Serial interface 0 and 1 P4CC P4SPI P4UR1 Bit 3 Bit 2 Bit 1 Bit 0 RESET P4IIC P0KBI - DPS 00H 内建SPI,可直接经由软件设定指定其脚位至P1或P4,避免和其它特殊功能脚位重复,并提高硬件规 划的兼容性。 P4SPI: P4SPI = 0 – SPI function on P1. SS – P1.4 MOSI – P1.5 MISO – P1.6 CLK – P1.7 P4SPI = 1 – SPI function on P4. SS – P4.0 MOSI – P4.1 MISO – P4.2 CLK – P4.3 4 SPI 相关的特殊缓存器 SPI Special Function Register (SFR) SPI Direct Bit 7 Bit 6 Bit 5 SPI function Auxiliary register 91h BRS P4CC SPIC1 SPI control register 1 F1h SPIEN SPIMSS SPIC2 SPI control register 2 F2h SPIFD SPIS SPI status register F5h - SPITXD SPI transmit data buffer F3h SPITXD[7:0] 00H SPIRXD SPI receive data buffer F4h SPIRXD[7:0] 00H AUX Description Mnemonic: AUX 7 6 5 BRS P4CC P4SPI P4SPI Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 RESET P4UR 1 P4IIC P0KBI - DPS 00H SPISS SPICKP SPICKE P TBC[2:0] - SPIBR[2:0] 08H RBC[2:0] 00H SPIMLS SPIOV SPITXIF SPITDR SPIRXIF SPIRDR SPIRS 4 P4UR1 3 P4IIC 2 P0KBI 1 - Address: 91h 0 Reset DPS 00H Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0178 2 Ver A 2010/06 40H SPI 功能使用方法 P4SPI: P4SPI = 0 – SPI function on P1. P4SPI = 1 – SPI function on P4. P4SPI setting SPI_SS P1.4 0 P4.0 1 Mnemonic: SPIC1 7 6 5 SPIEN SPIMSS SPISSP SPI_MOSI P1.5 P4.1 4 SPICKP SPI_MISO P1.6 P4.2 Address: F1h 3 2 1 0 SPICKE SPIBR[2:0] SPI_CLK P1.7 P4.3 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 Fosc/256 1:1:0 Fosc/512 1:1:1 Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0178 3 Ver A 2010/06 SPI 功能使用方法 Mnemonic: SPIC2 7 6 5 SPIFD TBC[2:0] 4 3 - 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 MISO MISO MOSI MOSI SCK SCK SyncMos Master Output Shift register SPITXD Input Shift register SPIRXD SyncMos Slave 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 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 Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0178 4 Ver A 2010/06 SPI 功能使用方法 Mnemonic: SPIS 7 6 5 SPIMLS SPIOV 4 SPITXIF 3 SPITDR 2 SPIRXIF Address: F5h 0 Reset SPIRS 40h 1 SPIRDR 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 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) Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0178 5 Ver A 2010/06 SPI 功能使用方法 5 SPI 中断 5.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 *See Keil C about C51 User’s Guide about Interrupt Function description 5.2 中断相关缓存器(Interrupt SFR) Mnemonic IEN0 IEN1 IEN2 IRCON IP0 IP1 Description Interrupt Enable 0 register Interrupt Enable 1 register Interrupt Enable 2 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 RESET A8h EA - ET2 ES0 ET1 EX1 ET0 EX0 00h B8h EXEN2 - IEIIC IELVI IEKBI IEADC IESPI IEPWM 00h 9Ah - - - - - - - ES1 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 *如果需要使用中断程序,可参考以下设置: (1) SPI 中断致能设罝: IEN0 |= 0x80; IEN1 |= 0x02; //Enable interrupt All //Enable interrupt SPI Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0178 6 Ver A 2010/06 SPI 功能使用方法 (2) SPI 中断程序表示: void SPI_interrupt(void) interrupt 9 { //IRCON_SPIIF = 0; //Clear interrupt flag If(SPIS&=0x04) { SPIS &= (~0x04); //Clear TXIF bit } { SPIS &= (~0x20; //Clear RXIF bit } Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0178 7 Ver A 2010/06 SPI 功能使用方法 6 以下为两颗 MCU 分别当做 SPI master 及 slave 通讯的流程图 Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0178 8 Ver A 2010/06 SPI 功能使用方法 7 SPI master 及 slave 通讯的范例程序 7.1 Master 传资料(0xFF~0x00)至 Slave 7.2 Slave 接受后,以相同的数据回传给 Master 7.3 Master 接受 Slave 回传的数据后,做数据比较,相同则表示通讯正确,不相同则反之 Description Main program Master: //=================================================================== // // S Y N C M O S T E C H N O L O G Y // //=================================================================== #include #include #include #include "..\h\SM59R16A2.h" "..\h\SM59R16A2_extradef.h" "..\LCD\LCD16x2.h" "..\MISC\delay.h" #define Control_Byte #define SPI_SS #define SPITDR=1 0xA0 P1_0 SPIS |= 0x08 /* void SPI_interrupt(void) interrupt 9 { IRCON_SPIIF = 0; //Clear interrupt flag }*/ void SPI_Init(void) { SPIC1 = 0xD8; //SPIC1 |= 7; SPIC2 = 0x00; SPIS = 0x40; } //SPI Enable/ master/ NC/ idle hi/ rising latch //BR=(Fosc/512) //SPI full-duplex disable /8-bit communicate //MSB send first void SPI_TX( unsigned char DATA) { SPITXD = DATA; SPIS |= 0x08; while( !(SPIS&SPI_TXIF) ); SPIS &= (~SPI_TXIF); } unsigned char SPI_RX(void) { unsigned char Temp; SPIS |= 0x01; while( !(SPIS&SPI_RXIF) ); Temp = SPIRXD; SPIS |= 0x02; SPIS &= (~SPI_RXIF); return Temp; } //Load to Buffer //SPITDR //TX completed //Clear TXIF bit //Receive Start //RX completed //Load from Buffer //Receive Data Ready //Clear RXIF bit void main() { unsigned long Err =0, counter =1; unsigned char TxData, RxData,j; LCD_Init(); SPI_Init(); Delay10mSec(1); //must wait for LCD stable Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0178 9 Ver A 2010/06 SPI 功能使用方法 while(1) { for(TxData=0xFF; TxData>0; TxData--) { PrintLcdStrLX( 1, 0, "M_TX: PrintLcdStrLX( 2, 0, "M_RX: "); "); SPI_SS = 0; SPI_TX( TxData ); //for(j=0; j<0; j++); RxData = SPI_RX(); SPI_SS = 1; //CS //TX //Dealy time //RX //CS SetCursorAddr(1, 6); SetCursorAddr(2, 6); PrintLcdHex( TxData ); PrintLcdHex( RxData ); counter++; SetCursorAddr(1, 12); PrintLcdDec( counter ); if(TxData!=RxData) Err++; SetCursorAddr(2, 12); PrintLcdDec( Err ); P2=TxData; //result } } } Description Main program Slave: //=================================================================== // // S Y N C M O S T E C H N O L O G Y // //=================================================================== #include "..\h\SM59R16A2.h" #include "..\h\SM59R16A2_extradef.h" #include "..\LCD\LCD16x2.h" #include "..\MISC\delay.h" void SPI_Init(void) { SPIC1 =0x98; //SPI Enable/ slave/ Low active / NC / rising latch/ NC NC NC SPIC2 =0x00; //SPI full-duplex disable /8-bit communicate SPIS =0x40; //MSB send first } void SPI_TX( unsigned char DATA) { SPITXD = DATA; //Load to Buffer SPIS |= 0x08; //SPITDR while( !(SPIS&SPI_TXIF) ); //TX completed SPIS &= (~SPI_TXIF); //Clear TXIF bit Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0178 10 Ver A 2010/06 SPI 功能使用方法 } unsigned char SPI_RX(void) { unsigned char Temp; SPIS |= 0x01; while( !(SPIS&SPI_RXIF) ); Temp = SPIRXD; SPIS |= 0x02; SPIS &= (~SPI_RXIF); return Temp; } //Receive Start //RX completed //Load from Buffer //SPIRDR //Clear RXIF bit void main() { unsigned long Err =0, counter =1; unsigned char TxData=0, RxData=0,j; LCD_Init(); SPI_Init(); Delay10mSec(1); //must wait for LCD stable while(1) { RxData = SPI_RX(); SPI_TX( RxData ); P2 = RxData; } //RX //TX //result } 8 SPI 全双工说明,使用两颗 SM59R04A2 分别当做 SPI master 及 slave 做通讯,以下是范例程序的通 讯协议: MOSI (Master) Check Ready 0x55 Master Receive CMD DB1 DB2 DB10 Checksum High byte Checksum low byte MISO (Slave) Slave Receive ACK Ready 0x55 Slave Receive DB1 DB2 DB10 Checksum High byte Checksum low byte 9 SPI master 及 slave 全双工通讯范例程序 9.1 Master 不断送 Ready Byte(0x55),直到 Slave 同样回传 Ready Byte (0x55)做确认 Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0178 11 Ver A 2010/06 SPI 功能使用方法 9.2 待两方确认后,Master 会送 command byte(0x0A 或 0x0B) 9.3 两方数据长度定为 10-Byte 9.4 Master 送出数据固定为 0x00~0x09 9.5 Slave 送出的资料则依据收到 Master 的 command byte 有所不同 9.5.1 当command byte=0x0A,slave送出资料为0x00~0x09 9.5.2 当command byte=0x0B,slave送出资料为0x10~0x19 9.6 数据送出完成后,master 及 slave 会互传该次所接收到的数据的 checksum Description Main program Master: //========================================================================= // // S Y N C M O S T E C H N O L O G Y // //========================================================================= // SM59R04A2 SPI Master full-duplex ,8-bit communication // System clock = 22.1184 MHz //========================================================================= #include "SM59R04A2.h" #define #define #define #define #define #define #define #define #define #define #define #define SPI_RxStart SPI_RDR SPI_RXIF SPI_TDR SPI_TXIF SPI_Overflow SPI_MSB_LSB CMD_0A CMD_0B CMD_Ready finetune SPI_SS 0x01 0x02 0x04 0x08 0x10 0x20 0x40 0x0A 0x0B 0x55 15 P1_0 // for timing finetune // slave select bit SPI_Intrrupt=1; unsigned char temx; void Delay1mSec(unsigned int NTime) ; void Delay_tune(unsigned char tune); void SPI_Init(void); unsigned char SPI_RX(void); void SPI_TX( unsigned char DATA); unsigned char SPI_full_duplex(unsigned char DATA); void SPI_communication(unsigned char command); void SPI_interrupt(void) interrupt 9 { while(!((SPIS & SPI_RDR)==SPI_RDR)); while((SPIS & SPI_TDR)==SPI_TDR); SPIS &= 0xE9; // RDR set 1 by H/W // TDR clr 0 by H/W // Clear SPITXIF & SPIRXIF & SPIRDR SPI_Intrrupt = 0; } //========================================================================= //Freq = 22.1184 MHz, @ 64-pin demo board //========================================================================= void Delay1mSec(unsigned int NTime) { Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0178 12 Ver A 2010/06 SPI 功能使用方法 unsigned int i, j; for(i=0; i<NTime; i++) for(j=0; j<1300; j++); } void Delay_tune(unsigned char tune) { unsigned char i; for(i=0; i<tune; i++); } void SPI_Init(void) { SPIC1 = 0xD8; //SPI Enable/ master/ NC/ idle hi/ rising latch SPIC2 = 0x80; //SPI full-duplex ,8-bit communication only //SPIC2 = 0x00; //SPI half-duplex ,8-bit communication SPIS = 0x40; //MSB send first SPIS |= 0x01; // RX Start //SPIS &= 0xFE;// Receive Stop //SPIC1 |= 0; //SPIC1 |= 1; //SPIC1 |= 2; SPIC1 |= 3; //SPIC1 |= 4; //SPIC1 |= 5; //SPIC1 |= 6; //SPIC1 |= 7; // // } IEN0 IEN1 //BR=(Fosc/4) //BR=(Fosc/8) //BR=(Fosc/16) //BR=(Fosc/32) //BR=(Fosc/64) //BR=(Fosc/128) //BR=(Fosc/256) //BR=(Fosc/512) |= 0x80; |= 0x02; // EA=1 // IESPI=1 unsigned char SPI_RX(void) { SPI_SS = 0; SPITXD = 0xFF; // SPIS |= 0x01; // // SPI_Intrrupt = 1; // while(SPI_Intrrupt); while(!((SPIS & SPI_RDR)==SPI_RDR));// SPIS &= 0xE9; // temx = SPIRXD; SPI_SS = 1; Delay_tune(finetune); return temx; clear SPITXD, useless RX Start // send SPI CLK RDR set 1 by H/W Clear SPITXIF & SPIRXIF & SPIRDR // CS, must wait slave } void SPI_TX( unsigned char DATA) { SPI_SS = 0; SPITXD = DATA; SPIS |= SPI_TDR; // SPI_Intrrupt = 1; // while(SPI_Intrrupt); while((SPIS & SPI_TDR)==SPI_TDR); SPIS &= 0xE9; SPI_SS = 1; Delay_tune(finetune); // Load to TX Buffer // set SPITDR, TX proceed // TDR clr 0 by H/W // Clear SPITXIF & SPIRXIF & SPIRDR // CS, must wait slave } Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0178 13 Ver A 2010/06 SPI 功能使用方法 unsigned char SPI_full_duplex(unsigned char DATA) { SPI_SS = 0; SPITXD = DATA; // Load to TX Buffer SPIS |= SPI_TDR; // set SPITDR, TX proceed // SPI_Intrrupt = 1; // while(SPI_Intrrupt); while(!((SPIS & SPI_RDR)==SPI_RDR));// RDR set 1 by H/W while((SPIS & SPI_TDR)==SPI_TDR); // TDR clr 0 by H/W SPIS &= 0xE9; // Clear SPITXIF & SPIRXIF & SPIRDR temx = SPIRXD; SPI_SS = 1; Delay_tune(finetune); return temx; // CS, must wait slave } void SPI_communication(unsigned char command) { unsigned char RxData_H=0, RxData_L=0, TxData=0, loop=0, temp=0, ready=0; unsigned int checksum=0; SPI_TX(CMD_Ready); ready = SPI_RX(); // check slaver ready, send 0x55 // receive ready_byte, wait 0x55 if(ready == CMD_Ready) { SPI_TX(command); checksum=0; // send command 0x0A or 0x0B for(loop=0x00; loop<0x10; loop++) { checksum += SPI_full_duplex(loop); } RxData_H = SPI_full_duplex((unsigned char)(checksum>>8)); // send checksum high byte RxData_L = SPI_full_duplex((unsigned char)checksum); // send checksum low byte ready=0; } Delay_tune(50); // useless } void main() { Delay1mSec(100); //SPI_Intrrupt = 1; IFCON |= 0x80; SPI_Init(); Delay1mSec(1); // wait system stable // // set 1T // // must wait SPI init while(1) { SPI_communication(CMD_0A); SPI_communication(CMD_0B); } } Description Slave: //========================================================================= // // S Y N C M O S T E C H N O L O G Y Main program // //========================================================================= // SM59R04A2 SPI slave full-duplex ,8-bit communication Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0178 14 Ver A 2010/06 SPI 功能使用方法 // System clock = 22.1184 MHz //========================================================================= #include "SM59R04A2.h" #define #define #define #define #define #define #define #define #define #define SPI_RxStart SPI_RDR SPI_RXIF SPI_TDR SPI_TXIF SPI_Overflow SPI_MSB_LSB CMD_0A CMD_0B CMD_Ready unsigned unsigned unsigned unsigned 0x01 0x02 0x04 0x08 0x10 0x20 0x40 0x0A 0x0B 0x55 char TxData=0x10, RxData=0, RxBuf[5]; int loop=0, checksum=0; char RxData_H=0, RxData_L=0; char cmd=0, ready=0; void Delay1mSec(unsigned int NTime); void Delay_tune(unsigned char tune); void Init_SPI(void); void SPI_TX( unsigned char DATA); unsigned char SPI_RX(void); void Delay1mSec(unsigned int NTime) { unsigned int i, j; for(i=0; i<NTime; i++) for(j=0; j<1300; j++); } void Init_SPI(void) { SPIC1 = 0x98; //SPI Enable/ slave/ Low active / NC / rising latch SPIC2 = 0x80; //SPI full-duplex ,8-bit communication only //SPIC2 = 0x00; //SPI half-duplex ,8-bit communication SPIS = 0x40; //MSB send first SPIS |= 0x01; //Receive Start SPITXD = 0xFF; IEN0 IEN1 |= 0x80; |= 0x02; // EA=1 // IESPI=1 } void SPI_TX( unsigned char DATA) { SPITXD = DATA; // Load to TX Buffer SPIS |= SPI_TDR; // set SPITDR, TX proceed while((SPIS & SPI_TDR)==SPI_TDR); // 1:Loading ; 0: finish while(!((SPIS & SPI_TXIF)==SPI_TXIF)); // TX completed SPIS &= 0xE9; // Clear SPITXIF & SPIRXIF & SPIRDR //SPIS &= (~SPI_TXIF); // Clear TXIF bit } unsigned char SPI_RX(void) { unsigned char Temp; SPITXD = 0xFF; // clear SPITXD, useless // SPIS |= 0x01; // Receive Start while(!((SPIS & SPI_RDR)==SPI_RDR)); // RX receive while(!((SPIS & SPI_RXIF)==SPI_RXIF)); // RX completed Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0178 15 Ver A 2010/06 SPI 功能使用方法 // // // Temp = SPIRXD; SPIS &= 0xE9; SPIS &= (~SPI_RDR); SPIS &= (~SPI_RXIF); SPIS &= 0xFE; return Temp; // // // // // Load from Buffer Clear SPITXIF & SPIRXIF & SPIRDR RX Data Ready Clear RXIF bit Receive Stop } unsigned char SPI_full_duplex(unsigned char DATA) { SPITXD = DATA; // SPIS |= SPI_TDR; // while((SPIS & SPI_TDR)==SPI_TDR); // while(!((SPIS & SPI_RDR)==SPI_RDR));// SPIS &= (~SPI_RDR); // return SPIRXD; Load to TX Buffer set SPITDR, TX proceed TDR clr 0 by H/W RDR set 1 by H/W RX Data Ready } void SPI_ISR(void) interrupt 9 { while(!((SPIS & SPI_RDR)==SPI_RDR));// RDR set 1 by H/W ready = SPIRXD; // SPI cmd receive ready SPIS &= 0xE9; // Clear SPITXIF & SPIRXIF & SPIRDR if(ready==CMD_Ready) { SPI_TX(CMD_Ready); cmd = SPI_RX(); checksum = 0; switch (cmd) { case CMD_0A: // When cmd = 0x0A for(loop=0x00; loop<0x10; loop++) { checksum+= SPI_full_duplex(loop); } break; case CMD_0B: // When cmd = 0x0B for(loop=0x10; loop<0x20; loop++) { checksum+= SPI_full_duplex(loop); } break; default: // When cmd error occur for(loop=0; loop<3; loop++) { checksum+= SPI_full_duplex(0xAA); } break; } RxData_H = SPI_full_duplex((unsigned char)(checksum>>8)); RxData_L = SPI_full_duplex((unsigned char)(checksum)); } SPIS &= 0xE9; SPITXD = 0xFF; //SPIIF=0; // Clear SPITXIF & SPIRXIF & SPIRDR // clear SPITXD, useless } void main() { Delay1mSec(100); // wait system stable Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0178 16 Ver A 2010/06 SPI 功能使用方法 IFCON |= 0x80; Init_SPI(); // set 1T while(1) {} } Specifications subject to change without notice, contact your sales representatives for the most recent information. ISSFA-0178 17 Ver A 2010/06