[PIC®/AVR®/dsPIC®产品]

求助,写SPI通讯,发送不出去,下面是我的代码,用的pic16lf1503,

[复制链接]
1414|3
手机看帖
扫描二维码
随时随地手机跟帖
林ze|  楼主 | 2018-3-21 15:12 | 显示全部楼层 |阅读模式
#include "main.h"

__CONFIG(FOSC_INTOSC&WDTE_OFF&PWRTE_OFF&MCLRE_ON&CP_OFF&BOREN_OFF&CLKOUTEN_OFF);
__CONFIG(WRT_OFF&STVREN_OFF&BORV_HI&LPBOR_OFF&LVP_OFF);


const unsigned char TX_ADDRESS[12][TX_ADR_WIDTH]={{0x34,0x43,0x10},{0xc2,0xc2,0xc2},
                                                                                                                                        {0xc3,0xc2,0xc2},{0xc4,0xc2,0xc2},
                                                                                                                                        {0xc5,0xc2,0xc2},{0xc6,0xc2,0xc2},
                                                                                                                                        {0xc2,0xc2,0xc2},{0xc3,0xc2,0xc2},
                                                                                                                                        {0xc4,0xc2,0xc2},{0xc5,0xc2,0xc2},
                                                                                                                                        {0xc6,0xc2,0xc2},{0x34,0x43,0x10},}; //发送地址

//const unsigned char RX_ADDRESS[RX_ADR_WIDTH]={0x34,0x43,0x10}; //接收地址
unsigned char txBuf[16] = {0};
unsigned char measureCh;               //测量通道



void delay(unsigned char x)
{
    unsigned int i,j;
    for(i=x;i>0;i--)
        for(j=110;j>0;j--);
}
void led()
{
        RA5=1;
        __delay_ms(500);
        RA5=0;
        __delay_ms(500);
}

void InitNRF24L01()
{
        TRISC5 = 0;                //CE 输出
        TRISC4 = 0;                //CSN 输出
        TRISA2 = 1;                //IRQ 输入
       
        //延时10.3ms
       
        //设置PWM_UP位为1,并且等待1.5ms,进入待机模式1
       
        //SPI 端口设置
        TRISC0 = 0;//spi时钟
        TRISC1 = 1;//spi数据输入,实际上由模块自动控制
        TRISC2 = 0;//spi数据输出口
        //TRISA5 = 1;//原来是spi从机选择,主控下,没用,作为输入口

        CKP = 0;//时钟空闲为低
        CKE = 1;//第一边沿采样数据
        SSPM0 = SSPM1 = SSPM2 = SSPM3 = 0;//spi主控模式,1/4时钟周期
        SSP1IF = 0;//清除中断位
        SSPEN = 1;//使能SSP       
}

void Reset24L01_SPI_CTRL()
{
        CKP = 0;//时钟空闲为低
        CKE = 1;//第一边沿采样数据
        SSPM0 = SSPM1 = SSPM2 = SSPM3 = 0;//spi主控模式,1/4时钟周期
        SSP1IF = 0;//清除中断位
        SSPEN = 1;//使能SSP       
}       


/********SPI端口收发字节,并返回从机字节*************/
/********无片选控制***********************************/
unsigned char SPI_SendByte(unsigned char byte)
{
        unsigned char rtData;
                                               
        SSPBUF = byte;
        led();
        while(SSP1IF == 0)        //等待发送完毕
        ;
        led();
        rtData = SSPBUF;
        SSP1IF = 0;       
       
        return rtData;
}


/*********************************************/
/* 函数功能:给24L01的寄存器写值(一个字节) */
/* 入口参数:reg   要写的寄存器地址          */
/*           value 给寄存器写的值            */
/* 出口参数:status 状态值                   */
/*********************************************/
unsigned char NRF24L01_Write_Reg(unsigned char reg,unsigned char value)
{
        unsigned char status;

        CSN = 0;  
          status = SPI_SendByte(reg);//发送寄存器地址,并读取状态值
        SPI_SendByte(value);
        CSN = 1;

        return status;
}


/*************************************************/
/* 函数功能:读24L01的寄存器值 (一个字节)      */
/* 入口参数:reg  要读的寄存器地址               */
/* 出口参数:value 读出寄存器的值                */
/*************************************************/
unsigned char NRF24L01_Read_Reg(unsigned char reg)
{
        unsigned char value;

        CSN = 0;  
          SPI_SendByte(reg);//发送寄存器值(位置),并读取状态值
        value = SPI_SendByte(0);
        CSN = 1;

        return value;
}

/**********************************************/
/* 函数功能:给24L01的寄存器写值(多个字节)  */
/* 入口参数:reg  要写的寄存器地址            */
/*           *pBuf 值的存放数组               */
/*           len   数组字节长度               */
/**********************************************/
unsigned char NRF24L01_Write_Buf(unsigned char reg, unsigned char *pBuf, unsigned char len)
{
        unsigned char status,u8_ctr;
        CSN = 0;            
       
          status = SPI_SendByte(reg);//发送寄存器值(位置),并读取状态值
       
          for(u8_ctr=0; u8_ctr<len; u8_ctr++)
        SPI_SendByte(*pBuf++); //写入数据
        CSN = 1;         
          return status;          //返回读到的状态值
}
/*********************************************/
/* 函数功能:读24L01的寄存器值(多个字节)   */
/* 入口参数:reg   寄存器地址                */
/*           *pBuf 读出寄存器值的存放数组    */
/*           len   数组字节长度              */
/* 出口参数:status 状态值                   */
/*********************************************/
unsigned char NRF24L01_Read_Buf(unsigned char reg,unsigned char *pBuf,unsigned char len)
{
        unsigned char status,u8_ctr;
        CSN = 0;      
          status=SPI_SendByte(reg);//发送寄存器地址,并读取状态值             
        for(u8_ctr=0;u8_ctr<len;u8_ctr++)
        pBuf[u8_ctr]=SPI_SendByte(0);//读出数据
        CSN = 1;
          return status;        //返回读到的状态值
}
/********************************************/
/* 函数功能:检测24L01是否存在              */
/* 返回值;  0  存在                        */
/*           1  不存在                      */
/********************************************/       
unsigned char NRF24L01_Check(void)
{
        unsigned char check_in_buf[5]={0x11,0x22,0x33,0x44,0x55};
        unsigned char check_out_buf[5]={0x00};

        NRF24L01_Write_Buf(WRITE_REG+TX_ADDR, check_in_buf, 5);

        NRF24L01_Read_Buf(READ_REG+TX_ADDR, check_out_buf, 5);

        if((check_out_buf[0] == 0x11)&&\
           (check_out_buf[1] == 0x22)&&\
           (check_out_buf[2] == 0x33)&&\
           (check_out_buf[3] == 0x44)&&\
           (check_out_buf[4] == 0x55))
           return 0;
        else
                return 1;
}

/*********************************************/
/* 函数功能:设置24L01为发送模式             */
/*********************************************/
void NRF24L01_TX_Mode(void)
{
        CE = 0;        //CE拉低,使能24L01配置       
       
          NRF24L01_Write_Buf(WRITE_REG+TX_ADDR,(unsigned char*)&TX_ADDRESS[measureCh][0],TX_ADR_WIDTH);//写TX节点地址
         
          NRF24L01_Write_Reg(WRITE_REG+SETUP_AW,0x01);        //3字节 地址宽度
          //NRF24L01_Write_Buf(WRITE_REG+RX_ADDR_P0,(unsigned char*)RX_ADDRESS,RX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK
          NRF24L01_Write_Reg(WRITE_REG+SETUP_RETR,0x00);          
          NRF24L01_Write_Reg(WRITE_REG+EN_AA,0x00);     ////禁止通道0的自动应答   
          NRF24L01_Write_Reg(WRITE_REG+EN_RXADDR,0x00); ////禁止通道0的接收地址  
          //NRF24L01_Write_Reg(WRITE_REG+SETUP_RETR,0x1a);//设置自动重发间隔时间:500us + 86us;最大自动重发次数:10次
          NRF24L01_Write_Reg(WRITE_REG+RF_CH,RFCHANNAL);       //设置RF通道为40
          NRF24L01_Write_Reg(WRITE_REG+RF_SETUP,0x26);  ////设置TX发射参数,0db增益,250kbps   
          NRF24L01_Write_Reg(WRITE_REG+CONFIG,0x0C);    //配置基本工作模式的参数;PWR_DOWN,EN_CRC,16BIT_CRC,接收模式,开启所有中断,进入掉电模式
       
        //CE 当前为低,为待机模式1
        //CE = 1;        //CE置高,使能发送
}


/**********************************************/
/* 函数功能:设置24L01为发送模式              */
/* 入口参数:txbuf  发送数据数组              */
/* 返回值; 0x10    达到最大重发次数,发送失败*/
/*          0x20    成功发送完成              */
/*          0xff    发送失败                  */
/**********************************************/
unsigned char NRF24L01_TxPacket(unsigned char *txbuf)
{
        unsigned char state;
   
        CE = 0;;        //CE拉低,使能24L01配置
          NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);//写数据到TX BUF  2个字节
        CE = 1;        //CE置高,使能发送          
        while(IRQ == 1);//等待发送完成
        state=NRF24L01_Read_Reg(STATUS);  //读取状态寄存器的值          
        NRF24L01_Write_Reg(WRITE_REG+STATUS,state); //清除TX_DS或MAX_RT中断标志
        /*if(state&MAX_TX)//达到最大重发次数
        {
                NRF24L01_Write_Reg(FLUSH_TX,0xff);//清除TX FIFO寄存器
                return MAX_TX;
        }
        if(state&TX_OK)//发送完成
        {
                return TX_OK;
        }*/
        return 0xff;//发送失败
}                               
//发送温度数据
        void SendT()
        {
                CE = 0;
                __delay_ms(2);
                NRF24L01_Write_Reg(WRITE_REG+CONFIG,0x0e);   //上电 //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式,开启所有中断
                __delay_ms(2);
                //CE = 1;
                __delay_ms(50);
                NRF24L01_TxPacket(txBuf);
                __delay_ms(2);
                CE = 0;
                __delay_ms(2);
                NRF24L01_Write_Reg(WRITE_REG+CONFIG,0x0c);  //掉电休眠  //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式,开启所有中断
                __delay_ms(2);
                //CE = 1;       
        }
       
        void SendFirst()
        {
                txBuf[1] = 0^(CHANNAL+0xc8);

                RC3 = 1;        //打开发射模块电源开关
                __delay_ms(50);
                //发射前重新初始化
                Reset24L01_SPI_CTRL(); //InitNRF24L01();
                __delay_ms(2);
                NRF24L01_TX_Mode();
                __delay_ms(2);
                 ///////////////////////////////
                SendT();
                __delay_ms(50);
        RC3 = 0;
        }               

void Init(void)
{
        INTCON = 0;//关闭总中断,禁止外设,timer0,外部,电平中断,清除timer0,外部,电平中断标志
       
        ANSELC=0;
        ANSELA=0X10;
       
        //RBPU = 0; //使能RB口线 上拉
       
        InitNRF24L01();
        NRF24L01_TX_Mode();
       
        PEIE = 1;//开外设中断
        //GIE = 1;//开总中断
}
void main()
{       
        TRISA5=0;
        RA5=0;       
        OSCCON |= 0x72;                                //8M内部振荡器
        while(HFIOFS  == 0)                        //等待稳定
                        ;
       
        //测量通道号,0-11对应1-12路测量通道
        measureCh = CHANNAL;
        txBuf[0] = measureCh;        //地址标识
        /////////////////////////////////
        TRISA0 = 0;
        TRISA1 = 0;
        RA0 = RA1 = 0;
       
    TRISC3 = 0;//发射模块电源控制开关
        RC3 = 0;
        __delay_ms(1000);
        Init();
        SendFirst();
       
        while(1)
        {
                led();
        }

}
林ze|  楼主 | 2018-3-21 15:14 | 显示全部楼层
通过验证卡在 while(SSP1IF == 0)        //等待发送完毕; 这一句了

使用特权

评论回复
michaellengleng| | 2018-3-26 11:39 | 显示全部楼层

使用特权

评论回复
zhizaibide| | 2019-7-17 08:35 | 显示全部楼层
林ze 发表于 2018-3-21 15:14
通过验证卡在 while(SSP1IF == 0)        //等待发送完毕; 这一句了

楼主解决了吗?
我调试的时候也遇到同样的问题,在SPI读写数据时,一直在while(!BF)死循环。
但是,如果不单步调试,将断电设在这个语句之后可以跑过去。
SPI读写数据模块:
UINT8 __reentrant SPI_RW(UINT8 byte)
{
    SSP1BUF = byte;
    while (!BF);        //发送一个byte,接受一个无用的byte,缓冲标志位置1
    SSP1IF = 0;     //清除中断标志位
    return(SSP1BUF)
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

4

帖子

0

粉丝