STM32F103 SPI 操作

本主记录SPI 普通操作方式,主要为后续SPI设备提供基础

1、MDK工程目录(创建工程方式略),工程结构与前面 "STM32F103 DMA模式操作UART" 类式

 

2、spi 设备引脚初始在platform.c 文件下, 这里面列出SX1278 设备

platform.c 内容

/**
* @file platform.c 控制板GPIO引脚定义
*
* @author T0213-ZH
* @date 2018.06.13
*
* @note 使用STM32F103VC6 微处理器
*
* >>>> sx1278 模组接口定义 SPI1
* SPI1 引脚 PA5->CLK, PA6->MISO, PA7->MOSI PA2->CSN
* 控制引脚 PA3->RST, PA4->DIO0
*
*
* >>> 串口接口定义
* USART1 引脚 PA9->TX, PA10->RX
*
*/

#include "platform.h"

//******************************** SX1278 ******************************************************************

extern void Delayms(uint32_t ms);
void SX1278_spi_init(void){

    GPIO_InitTypeDef GPIO_InitStructure;
       
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
            
    //PA3->RST PA2->CSN
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;     
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
            
    GPIO_WriteBit(GPIOA, GPIO_Pin_3, Bit_RESET);
    GPIO_WriteBit(GPIOA, GPIO_Pin_2, Bit_SET);

    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
            
    //PA5->CLK PA6->MISO PA7->MOSI 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure); 


    //DIO0
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    GPIO_Init(GPIOA, &GPIO_InitStructure); 

    SPI_ApiStructure.init(&sx1278_ApiStructre.spi);

    Delayms(10);
    GPIO_WriteBit(GPIOA, GPIO_Pin_3, Bit_SET);
    
    Delayms(10);
}

void SX1278_spi_csn(uint8_t enable){

    GPIO_WriteBit(GPIOA, GPIO_Pin_2, (enable != 0x00) ? Bit_SET: Bit_RESET);
}

void sx1278_reset(uint8_t state){

    GPIO_WriteBit(GPIOA, GPIO_Pin_3, (state == 0) ? Bit_RESET: Bit_SET);
}

uint8_t sx1278_read_Dio_0(void){
    
    return GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_4);
}

SX1278_TypeDef sx1278_ApiStructre = {
    
    .spi.pfunc_csn = SX1278_spi_csn,
    .spi.SPIx = SPI1,
    .init = SX1278_spi_init,
    .reset = sx1278_reset,
    .rDio0 = sx1278_read_Dio_0,
};

platform.h 文件内容,主要用于包含头文件及对应设备提供接口

#ifndef __PLATFORM_H
#define __PLATFORM_H

#include "stm32f10x.h"

#include "stm32f10x\F103\driver\gpio.h"
#include "stm32f10x\F103\driver\time.h"
#include "stm32f10x\F103\driver\spi.h"
#include "stm32f10x\F103\driver\uart.h"


#include "SX1278\radio\radio.h"
#include "SX1278\radio\sx1276-Hal.h"


extern UART_TypeDef UART_TypeDef_param;
extern SX1278_TypeDef sx1278_ApiStructre;

extern volatile uint32_t TickCounter;

#endif

 

3、spi 接口源文件

spi.h 内容 

#ifndef __SPI_H
#define __SPI_H

/**
* @brief SPI 控制参数
*/
typedef struct{

    void (* pfunc_csn)(uint8_t enable); /*!< csn 控制的函数指针 */
    SPI_TypeDef *SPIx;     /*!< 对就的SPI组,如:SPI1,SPI2,SPI3 */
}SPI_CtrDef;

/**
* @brief SPI 接口函数
*/
typedef struct{
    uint8_t (* init)(SPI_CtrDef *p);           /*!< 初始化spi */
    uint8_t (* read_buf)(SPI_CtrDef *p, uint8_t reg, uint8_t *pbuf, uint8_t len);       /*!< 读多个数据 */
    uint8_t (* write_buf)(SPI_CtrDef *p, uint8_t reg, uint8_t *pbuf, uint8_t len);      /*!< 写多个数据 */
    uint8_t (* rwrite_onebyte)(SPI_CtrDef *p, uint8_t reg, uint8_t ch); /*!< 读单个数据 */
    uint8_t (* write_reg)(SPI_CtrDef *p, uint8_t reg);      /*!< 写寄存器 */ 
}SPI_ApiDef;

extern const SPI_ApiDef SPI_ApiStructure;

#endif

 spi.c 内容 

/**
* @file spi.c spi 驱动程序
*         
* @author T0213-ZH
* @date   2018.06.13 
*/

#include "platform.h"

/**
* @brief 初始化SPI 参数 
* @param p: 指向SPI设置参数指针
*
* @retval 返回初始结果 0-成功,1-失败
*/
static uint8_t SPIx_Init(SPI_CtrDef *p){
       
    SPI_InitTypeDef SPI_InitStructure;
    
    if(p->SPIx == SPI1){
        
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);                   
    }else if(p->SPIx == SPI2){   

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);        
    }else if(p->SPIx == SPI3){

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE);
    }else{
        return 1;
    }

    SPI_Cmd(p->SPIx, DISABLE);
    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_Low;                         
    SPI_InitStructure.SPI_CPHA =SPI_CPHA_1Edge;                       
    SPI_InitStructure.SPI_NSS =SPI_NSS_Soft;                          
    SPI_InitStructure.SPI_BaudRatePrescaler =SPI_BaudRatePrescaler_8; 
    SPI_InitStructure.SPI_FirstBit =SPI_FirstBit_MSB;                    
    SPI_InitStructure.SPI_CRCPolynomial =7; 
    
       SPI_Init(p->SPIx,&SPI_InitStructure);                                                              
    SPI_Cmd(p->SPIx, ENABLE);
    
    return 0;
}

/**
* @brief 读写1Bbyte数据
* @param SPIx: 指向SPI组
*        @arg SPI1 使用SPI1 组
*        @arg SPI2 使用SPI2 组
*
* @retval 8-bit 数据
*/
/*static*/ uint8_t SPI_RWbyte(SPI_TypeDef *SPIx, uint8_t ch){
    
  while( SPI_I2S_GetFlagStatus(SPIx,SPI_I2S_FLAG_TXE) == RESET);
    SPI_I2S_SendData(SPIx, ch);   
    
    while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) ==RESET);
    return SPI_I2S_ReceiveData(SPIx);    
}

/**
* @brief 读取指定寄存器中多个数据
* @param p: 指向SPI设置参数指针
* @param reg: 寄存器地址
* @param pbuf: 指向存储数据的缓存指针
* @param len: 读取长度
*
* @retval 返回结果
*/
static uint8_t SPIx_Read_buf(SPI_CtrDef *p, uint8_t reg, uint8_t *pbuf, uint8_t len){
    
    uint8_t status, i;
    
    p->pfunc_csn(0);
    
    status = SPI_RWbyte(p->SPIx, reg);
    for(i=0; i<len; i++){
        pbuf[i] = SPI_RWbyte(p->SPIx, 0xFF);
    }
    
    p->pfunc_csn(1);
    
    return status;
}

/**
* @brief 向指定寄存器中写多个数据
* @param p: 指向SPI设置参数指针
* @param reg: 寄存器地址
* @param pbuf: 指向写数据的缓存指针
* @param len: 写数据长度
*
* @retval 返回结果
*/
static uint8_t SPIx_Write_buf(SPI_CtrDef *p, uint8_t reg, uint8_t *pbuf, uint8_t len){
    
    uint8_t status, i;
    
    p->pfunc_csn(0);
    
    status = SPI_RWbyte(p->SPIx, reg);
    for(i=0; i<len; i++){
        SPI_RWbyte(p->SPIx, *pbuf++);
    }
    
    p->pfunc_csn(1);
    
    return status;
}

/**
* @brief 向指定寄存器中写读1Byte个数据
* @param p: 指向SPI设置参数指针
* @param reg: 寄存器地址
* @param ch: 需写入的数据
*
* @retval 返回结果
*/
static uint8_t SPIx_RWrite_Onebyte(SPI_CtrDef *p, uint8_t reg, uint8_t ch){
    
    uint8_t value;    
    
    p->pfunc_csn(0);
    
    SPI_RWbyte(p->SPIx, reg);
    value = SPI_RWbyte(p->SPIx, ch);
    
    p->pfunc_csn(1);
    
    return value;
}

/**
* @brief 写指定寄存器数据
* @param p: 指向SPI设置参数指针
* @param reg: 寄存器地址
*
* @retval 返回结果
*/
static uint8_t SPIx_Write_reg(SPI_CtrDef *p, uint8_t reg){
    
    uint8_t status;
    
    p->pfunc_csn(0);
    
    status = SPI_RWbyte(p->SPIx, reg);
    
    p->pfunc_csn(1);
    
    return status;
}

/**
* @brief SPI 接口函数
*/
const SPI_ApiDef SPI_ApiStructure = {
    
    .init = SPIx_Init,                     /*!< 初始化SPI */
    .read_buf = SPIx_Read_buf,             /*!< 读多个数据 */
    .write_buf = SPIx_Write_buf,           /*!< 写多个数据 */
    .rwrite_onebyte = SPIx_RWrite_Onebyte, /*!< 读写1Byte数据 */
    .write_reg = SPIx_Write_reg,           /*!< 写指定寄存器 */ 
};

 

4、具体操作在下节 SX1278 驱动

.....

 

本节文件: https://files.cnblogs.com/files/T0213-ZH/stm32f103_spi.rar

 

posted @ 2019-03-21 17:24  不在+年华  阅读(9028)  评论(0编辑  收藏  举报