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

 

转载于:https://www.cnblogs.com/T0213-ZH/articles/10573067.html

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值