stm32寄存器版学习笔记10 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设备使能

2.SPI

 1 //SPI口初始化
 2 //这里针是对SPI1的初始化
 3 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 }
spi.c
 1 // SPI总线速度设置  
 2 #define SPI_SPEED_2           0
 3 #define SPI_SPEED_4           1
 4 #define SPI_SPEED_8           2
 5 #define SPI_SPEED_16          3
 6 #define SPI_SPEED_32         4
 7 #define SPI_SPEED_64         5
 8 #define SPI_SPEED_128         6
 9 #define SPI_SPEED_256         7
10                                                                                         
11 void SPI1_Init(void);             //初始化SPI口
12 void SPI1_SetSpeed(u8 SpeedSet); //设置SPI速度   
13 u8 SPI1_ReadWriteByte(u8 TxData);//SPI总线读写一个字节
14          
15 #endif
spi.h
原文地址:https://www.cnblogs.com/kuotian/p/5672197.html