×
单片机 > 单片机程序设计 > 详情

STM32 软件模拟SPI时序驱动NRF24L01

发布时间:2020-08-31 发布时间:
|
其实stm32本身的硬件SPI也很好用,但是还是想用软件来模拟一下PSI的时序。
   SPI 是一种高速的,全双工,同步串行的通信总线。SPI通信方式相当于是一个环形结构,由CSN、MISO、MOSI、SCLK四线组成,主要是在SCLK时钟线的驱动下,进行数据转换。
   接下来直接上程序配置:
   使用32模拟SPI时序的IO口配置,应该注意的是MISO应该选择模拟输入方式GPIO_Mode_IN_FLOATING。
   以下是我的初始化部分:
/*用于软件模拟SPI IO口宏定义区*/#define SPI_CS_PORT     GPIOB#define SPI_CS_PIN      GPIO_Pin_11#define SPI_CS_LOW      (SPI_CS_PORT->BRR |=SPI_CS_PIN)#define SPI_CS_HIGH     (SPI_CS_PORT->BSRR |=SPI_CS_PIN)#define SPI_SCK_PORT    GPIOA#define SPI_SCK_PIN     GPIO_Pin_12#define SPI_SCK_LOW     (SPI_SCK_PORT->BRR |=SPI_SCK_PIN)#define SPI_SCK_HIGH    (SPI_SCK_PORT->BSRR|=SPI_SCK_PIN)#define SPI_MISO_PORT    GPIOA#define SPI_MISO_PIN     GPIO_Pin_8#define SPI_MISO_LOW     (SPI_MISO_PORT->BRR |=SPI_MISO_PIN)#define SPI_MISO_HIGH    (SPI_MISO_PORT->BSRR|=SPI_MISO_PIN)#define SPI_MISO_READ    (SPI_MISO_PORT->IDR &SPI_MISO_PIN)#define SPI_MOSI_PORT    GPIOA#define SPI_MOSI_PIN     GPIO_Pin_11#define SPI_MOSI_LOW     (SPI_MOSI_PORT->BRR |=SPI_MOSI_PIN)#define SPI_MOSI_HIGH    (SPI_MOSI_PORT->BSRR|=SPI_MOSI_PIN)void SPI_GPIO_Config(void)
{
    GPIO_InitTypeDef  GPIO_InitStruct;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB,ENABLE);    //CS
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
    GPIO_InitStruct.GPIO_Pin=SPI_CS_PIN;
    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(SPI_CS_PORT, &GPIO_InitStruct);    //SCK
    GPIO_InitStruct.GPIO_Pin=SPI_SCK_PIN;
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
    GPIO_Init(SPI_SCK_PORT,&GPIO_InitStruct);    //MISO
    GPIO_InitStruct.GPIO_Pin=SPI_MISO_PIN;
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;
    GPIO_Init(SPI_MISO_PORT,&GPIO_InitStruct);    //MOSI
    GPIO_InitStruct.GPIO_Pin=SPI_MOSI_PIN;
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
    GPIO_Init(SPI_MOSI_PORT,&GPIO_InitStruct);  

    SPI_CS_HIGH;
    SPI_SCK_LOW;
}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748

模拟SPI时序 

u8 SPI_RW(u8 data)
{
    u8 i;
    SPI_SCK_LOW;     //先将时钟线拉低
    for(i=0;i<8;i++)
    {   
        if((data&0x80)==0x80)  //从高位发送
        {
            SPI_MOSI_HIGH;
        }        else
        {
            SPI_MOSI_LOW;
        }

        SPI_SCK_HIGH;  //将时钟线拉高,在时钟上升沿,数据发送到从设备

        data<<=1;        if(SPI_MISO_READ)   //读取从设备发射的数据
        {            data|=0x01;     
        }
        SPI_SCK_LOW;     //在下降沿数据被读取到主机
    }    return data;         //返回读取到的数据}1234567891011121314151617181920212223242526272829

写寄存器操作:` 
u8 SPI_Moni_Write_Reg(u8 Reg,u8 data) 

u8 states;

SPI_CS_LOW;  //先将CSN拉低

states=SPI_RW(Reg);  //写入寄存器的地址,即图中的Cn位,并读取状态位

SPI_RW(data);       // 要写入的数据

SPI_CS_HIGH;

return states;

}

读寄存器操作:u8 SPI_Moni_Read_Reg(u8 Reg)
{    u8 data;

    SPI_CS_LOW;

    SPI_RW(Reg);   //先写入寄存器的地址

    data=SPI_RW(0); //通过写入无效数据0,将从设备上的数据挤出来

    SPI_CS_HIGH;    return data;
}
接下来就是写缓冲区、读缓冲区函数 了:u8 SPI_Moni_Write_Buf(u8 Reg,u8 *Buf,u8 len)
{    u8 states;

    SPI_CS_LOW;

    states=SPI_RW(Reg);    while(len>0)
    {
        SPI_RW(*Buf);
        Buf++;
        len--;
    }
    SPI_CS_HIGH;    return states;
}u8 SPI_Moni_Read_Buf(u8 Reg,u8 *Buf,u8 len)
{    u8 states;

    SPI_CS_LOW;

    states=SPI_RW(Reg);    while(len>0)
    {
        *Buf=SPI_RW(0);
        Buf++;
        len--;
    }

    SPI_CS_HIGH;    return states;
}



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
ARM 汇编的必知必会