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;
}