spi 通信的要点 pic24f 为例


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


 

 


 





 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值