spi 通信的要点 pic24f 为例

2019-04-15 13:51发布


spi 通信现实中用到的很多 使用起来有几个点容易忽略:
1. 清除各寄存器状态 2.设置spi 的模式: 16位模式 还是 8位模式,主从模式,边沿作用模式 3.片选控制:手动控制的位置
下面是 PIC24F 系列单片机的 一段例子   #include "spi.h" #define PIN_O_RFID_NSS 27 #define PIN_O_RFID_SCL 28 #define PIN_O_RFID_MOSI 29 #define PIN_I_RFID_MISO 30 #define ADDR_MODE_WRITE 0 #define ADDR_MODE_READ 1 #define SPI_SELECT_SLAVE() SetPinDigitalOut(PIN_O_RFID_NSS,0,FALSE) #define SPI_UNSELECT_SLAVE() SetPinDigitalOut(PIN_O_RFID_NSS,1,FALSE) #define IOLock() __builtin_write_OSCCONL(OSCCON | 0x40); #define IOUnlock() __builtin_write_OSCCONL( OSCCON & 0xbf); void spi_init(void) { // 切换成数字引脚 //设置管脚 IOUnlock(); RPINR20bits.SDI1R=0x1b; RPOR13bits.RP26R = 0x08; RPOR9bits.RP19R = 0x07; RPOR10bits.RP21R = 0x09; //nss IOLock(); SPI1CON1bits.MODE16 = 0; //8位模式 SPI1CON1bits.SPRE = 7; SPI1CON1bits.DISSCK = 0; //使能内部时钟 SPI1CON1bits.MSTEN = 1;//主模式 SPI1CON1bits.SSEN = 0; //不使用片选脚 SPI1CON1bits.PPRE = 1;//clk SPI1CON1bits.CKE = 1; //下降沿修改data _SPI1IE = 0; //禁止中断 _SPI1IF = 0; //中断标志 SPI1STATbits.SPIROV = 0; //清接收益出标志 SPI1STATbits.SPIRBF = 0; //接收标志 SPI1STATbits.SPITBF = 0; SPI1STATbits.SPIEN=1;//使能 } static void spi_check_error() { if(SPI1STATbits.SPIROV) { SPI1STATbits.SPIROV = 0; //sport error } } static BOOL spi_write_byte(UINT8 data,UINT8 *getdata) { spi_check_error(); _SPI1IF = 0; //clear interrupt flag since we are about to write new value SPI1BUF = data; UINT32 time = sys_timer_get(); while(sys_timer_lapse(time)<500) { if(_SPI1IF) { *getdata = (UINT8)SPI1BUF; return TRUE; } } return FALSE; } static BOOL spi_send_addr(UINT8 addr,UINT8 mode) { UINT8 byte; UINT8 getdata; //if(mode == ADDR_MODE_WRITE) byte = (addr<<1)&(~0x01);//write mode addr if (mode == ADDR_MODE_WRITE) byte = (addr<<1)&(~0x1) ; //write mode addr else if(mode == ADDR_MODE_READ) byte = (addr<<1)|0x01;//read mode addr return spi_write_byte(byte,&getdata); } BOOL spi_write_data(UINT8 addr,UINT8 data) { UINT8 getdata; SPI_SELECT_SLAVE(); if(!spi_send_addr(addr,ADDR_MODE_WRITE)) goto err; if(!spi_write_byte(data,&getdata)) goto err; SPI_UNSELECT_SLAVE(); return TRUE; err: SPI_UNSELECT_SLAVE(); return FALSE; } BOOL spi_read_byte(UINT8 addr,UINT8 *getdata) { UINT8 data; SPI_SELECT_SLAVE(); if(!spi_send_addr(addr,ADDR_MODE_READ)) goto err; if(!spi_write_byte(0x0,&data)) goto err; *getdata = data; SPI_UNSELECT_SLAVE(); return TRUE; err: SPI_UNSELECT_SLAVE(); return FALSE; }