zoukankan      html  css  js  c++  java
  • SPI

    一原理和初始化过程:

    SPI(Serial Peripheral Interface),串行外围设备接口。SPI是一种高速的、全双工、同步的通信总线。

    SPI接口一般使用4条线通信:

      MISO 主设备数据输入,从设备数据输出

      MOSI 主设备数据输出,从设备数据输入

      SCLK 时钟信号,有主设备产生

      CS 从设备片选信号,有主设备控制

      SPI模块为了和外设进行数据交换,根据外设工作要求,其输出串行同步时钟极性和相位可以进行配置。SPI_CR寄存器的CPOL(时钟极性)位,控制在没有数据传输时时钟的空闲状态电平,此位对主模式和从模式下的设备都有效。CPOL=0,串行同步时钟的空闲状态为低电平;CPOL=1,串行同步时钟的空闲状态为高电平。SPI_CR寄存器的CPHA(时钟相位)位,能配置用于选择两种不同的传输协议之一进行数据传输。CPHA=0,在串行同步时钟的第一个跳变沿(上升或下降)数据被采样;CPHA=1,在串行同步时钟的第二个跳变沿(上升或下降)数据被采样。

    1.SPI主模式配置步骤

    ①使能SPI时钟,配置PA口

      APB2外设时钟使能寄存器(RCC_APB2ENR)

      APB1外设复位寄存器 (RCC_APB1RSTR)

      Eg:RCC->APB2ENR|=1<<2; //PORTA时钟使能 

         RCC->APB2ENR|=1<<12; //SPI1时钟使能 
         //这里只针对SPI口初始化
           GPIOA->CRL&=0X000FFFFF; 
         GPIOA->CRL|=0XBBB00000;//PA5.6.7复用 
         GPIOA->ODR|=0X7<<5; //PA5.6.7上拉

    ②开全双工模式并软件管理NSS

      SPI控制寄存器1(SPI_CR1)(I2S模式下不使用)

     

      Eg:SPI1->CR1|=0<<10;//全双工模式 
         SPI1->CR1|=1<<9; //软件nss管理
         SPI1->CR1|=1<<8;

    ③设置SPI为主机并设置数据帧格式

      Eg:SPI1->CR1|=1<<2; //SPI主机
         SPI1->CR1|=0<<11;//8bit数据格式

    ④设置时钟极性和相位极性

     

       Eg:SPI1->CR1|=1<<1; //空闲模式下SCK为1 CPOL=1
          SPI1->CR1|=1<<0; //数据采样从第二个时间边沿开始,CPHA=1

    ⑤传输速率和LSBFIRST帧格式设置

      Eg:SPI1->CR1|=7<<3; //Fsck=Fcpu/256
         SPI1->CR1|=0<<7; //MSBfirst

    ⑥使能SPI

     

      Eg:SPI1->CR1|=1<<6; //SPI设备使能

    二:初始化 库函数操作

    void SPI2_Init(void)
    {
    GPIO_InitTypeDef GPIO_InitStructure;
    SPI_InitTypeDef SPI_InitStructure;

    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );//PORTBʱÖÓʹÄÜ
    RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI2, ENABLE );//SPI2ʱÖÓʹÄÜ

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //PB13/14/15¸´ÓÃÍÆÍìÊä³ö
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);//³õʼ»¯GPIOB

    GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15); 

    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master; 
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;  
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; 
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; 
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; 
    SPI_InitStructure.SPI_CRCPolynomial = 7; 
    SPI_Init(SPI2, &SPI_InitStructure); 
    SPI_Cmd(SPI2, ENABLE);
    SPI2_ReadWriteByte(0xff);

    }

    寄存器操作。。。

    void SPI1_Init(void)
     4 {     
     5     RCC->APB2ENR|=1<<2;       //PORTA时钟使能      
     6     RCC->APB2ENR|=1<<12;      //SPI1时钟使能 
     7            
     8     //这里只针对SPI口初始化
     9     GPIOA->CRL&=0X000FFFFF; 
    10     GPIOA->CRL|=0XBBB00000;//PA5.6.7复用         
    11     GPIOA->ODR|=0X7<<5;    //PA5.6.7上拉
    12         
    13     SPI1->CR1|=0<<10;//全双工模式    
    14     SPI1->CR1|=1<<9; //软件nss管理
    15     SPI1->CR1|=1<<8;  
    16 
    17     SPI1->CR1|=1<<2; //SPI主机
    18     SPI1->CR1|=0<<11;//8bit数据格式    
    19     SPI1->CR1|=1<<1; //空闲模式下SCK为1 CPOL=1
    20     SPI1->CR1|=1<<0; //数据采样从第二个时间边沿开始,CPHA=1  
    21     SPI1->CR1|=7<<3; //Fsck=Fcpu/256
    22     SPI1->CR1|=0<<7; //MSBfirst   
    23     SPI1->CR1|=1<<6; //SPI设备使能
    24     SPI1_ReadWriteByte(0xff);//启动传输(主要作用:维持MOSI为高)         
    25 }   
    26 //SPI1 速度设置函数
    27 //SpeedSet:0~7
    28 //SPI速度=fAPB2/2^(SpeedSet+1)
    29 //APB2时钟一般为72Mhz
    30 void SPI1_SetSpeed(u8 SpeedSet)
    31 {
    32     SpeedSet&=0X07;            //限制范围
    33     SPI1->CR1&=0XFFC7; 
    34     SPI1->CR1|=SpeedSet<<3;    //设置SPI1速度  
    35     SPI1->CR1|=1<<6;         //SPI设备使能 
    36 } 
    37 //SPI1 读写一个字节
    38 //TxData:要写入的字节
    39 //返回值:读取到的字节
    40 u8 SPI1_ReadWriteByte(u8 TxData)
    41 {        
    42     u16 retry=0;                 
    43     while((SPI1->SR&1<<1)==0)//等待发送区空    
    44     {
    45         retry++;
    46         if(retry>0XFFFE)return 0;
    47     }              
    48     SPI1->DR=TxData;           //发送一个byte 
    49     retry=0;
    50     while((SPI1->SR&1<<0)==0) //等待接收完一个byte  
    51     {
    52         retry++;
    53         if(retry>0XFFFE)return 0;
    54     }                                  
    55     return SPI1->DR;                        
    56 }
    四 main函数

    #include "led.h"
    #include "delay.h"
    #include "key.h"
    #include "sys.h"
    #include "usart.h"
    #include "flash.h"

    const u8 TEXT_Buffer[]={0x21,0x23};
    #define SIZE sizeof(TEXT_Buffer)
    int main(void)
    {
    u8 key;
    u16 i=0;
    u8 datatemp[SIZE];
    u32 FLASH_SIZE;

    delay_init();
    NVIC_Configuration();
    uart_init(9600);
    LED_Init();
    KEY_Init();
    SPI_Flash_Init();
    while(SPI_Flash_ReadID()!=W25Q64)
    {
    LED0=!LED0;
    }
    FLASH_SIZE=8*1024*1024;
    while(1)
    {
    datatemp[0] = 0;
    datatemp[1] = 0;
    key=KEY_Scan(0);
    if(key==KEY_UP)
    {
    SPI_Flash_Write((u8*)TEXT_Buffer,FLASH_SIZE-100,SIZE);
    printf("spi write data is= ");
    printf("data0: %x data1: %x ",datatemp[0],datatemp[1]);


    }
    if(key==KEY_DOWN)
    {
    SPI_Flash_Read(datatemp,FLASH_SIZE-100,SIZE);
    printf("spi reding data is= ");
    printf("data0: %x data1: %x ",datatemp[0],datatemp[1]);


    }
    i++;
    delay_ms(100);
    if(i==20)
    {
    LED1=!LED1;//system runing
    i=0;
    }
    }
    }

    五 实验结果

    六 扩展
    还需要发送不同的数据类型。

  • 相关阅读:
    json对象字符串互转
    git stash压栈
    Array、ArrayList和List三者的区别
    弱类型dynamic与var
    使用git初始化项目
    git本地分支关联远程分支
    mysql索引
    js中 var functionName = function() {} 和 function functionName() {} 两种函数声明的区别
    深入理解JavaScript中的this关键字
    c#读取xml文件
  • 原文地址:https://www.cnblogs.com/huangbaobaoi/p/6058325.html
Copyright © 2011-2022 走看看