历史上的今天
返回首页

历史上的今天

今天是:2024年10月17日(星期四)

正在发生

2019年10月17日 | STM32的SPI1、SPI2、SPI3初始化及RF1101的应用(标准库与HAL库)

2019-10-17 来源:eefocus

——基于STM32F103RCT6


---- 标准库:

说明:相关文件共有两个:bsp_spi_cc1101.h;bsp_spi_cc1101.c;以SPI2为例。

1、“bsp_spi_cc1101.h”中的参数定义:


#ifndef _BSP_SPI_1101_H_

#define _BSP_SPI_1101_H_


#include

#include "stm32f10x.h"

#include "misc.h"

#include "os_cfg_app.h"

#include "os.h"

#include "core_cm3.h"

#include "bsp.h" 

#include "stm32f10x_spi.h"


#define CSN_CC1101_GPIO GPIOB

#define CSN_CC1101_GPIO_PIN GPIO_Pin_12


#define SPI_CC1101_GPIO GPIOB

#define SCK_CC1101_GPIO_PIN GPIO_Pin_13

#define MISO_CC1101_GPIO_PIN GPIO_Pin_14

#define MOSI_CC1101_GPIO_PIN GPIO_Pin_15


#define GDO0_CC1101_GPIO GPIOA

#define GDO0_CC1101_GPIO_PIN GPIO_Pin_11

#define SPI_GPIO_RCC_1 RCC_APB2Periph_GPIOB

#define SPI_GPIO_RCC_2 RCC_APB2Periph_GPIOA


#define CC1101_SPI SPI2


#define CSN_SET GPIO_SetBits(GPIOB,GPIO_Pin_12)

#define CSN_RESET GPIO_ResetBits(GPIOB,GPIO_Pin_12)


void SPI_CC1101_Init(void);

u8 SPI2_ReadWriteByte(u8 TxData);

#endif


2、“bsp_spi_cc1101.c”中的引脚及SPI功能初始化:


#include "bsp_spi_cc1101.h"


void SPI_CC1101_Init(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

SPI_InitTypeDef SPI_InitStructure;

RCC_APB2PeriphClockCmd(SPI_GPIO_RCC_1 | SPI_GPIO_RCC_2,ENABLE); //初始化GPIO时钟 

/*********SPI1初始化内容****

RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE); //初始化SPI1时钟

******SPI1初始化内容******/

 

/*********SPI2初始化内容************/

RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);    //初始化SPI2时钟

         

/********SPI3需要初始化的内容********

RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);    //初始化SPI3时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //初始化复用IO时钟,重定向IO口

GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); //由于SPI3占用JTAG口,所以需要关闭JTAG

******SPI3需要初始化的内容*******/

//片选设定成通用IO模式

GPIO_InitStructure.GPIO_Pin=CSN_CC1101_GPIO_PIN;

GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;          

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;           

GPIO_Init(CSN_CC1101_GPIO,&GPIO_InitStructure);


//SCK时钟IO初始化

GPIO_InitStructure.GPIO_Pin=SCK_CC1101_GPIO_PIN;

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;             

GPIO_Init(SPI_CC1101_GPIO,&GPIO_InitStructure);

//MISO的IO初始化

GPIO_InitStructure.GPIO_Pin=MISO_CC1101_GPIO_PIN;          

GPIO_Init(SPI_CC1101_GPIO,&GPIO_InitStructure);

//MOSI的IO初始化

GPIO_InitStructure.GPIO_Pin=MOSI_CC1101_GPIO_PIN;         

GPIO_Init(SPI_CC1101_GPIO,&GPIO_InitStructure);

//RF1101中用到的GDO0的IO初始化

GPIO_InitStructure.GPIO_Pin=GDO0_CC1101_GPIO_PIN;

GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;          

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;             

GPIO_Init(GDO0_CC1101_GPIO,&GPIO_InitStructure);

//SPI模式设置

SPI_InitStructure.SPI_Direction=SPI_Direction_2Lines_FullDuplex;    //全双工模式

SPI_InitStructure.SPI_Mode=SPI_Mode_Master; //主设备模式

SPI_InitStructure.SPI_DataSize=SPI_DataSize_8b; //8字节数据通信

SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //时钟空闲时为低电平

SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //时钟奇数边沿采样

SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //软件控制NSS(CSN)位

SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //通信速率设定,波特率预分频值

SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //数据传输从MSB开始

SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC计算多项式

SPI_Init(CC1101_SPI, &SPI2_InitStructure); //初始化

    SPI_Cmd(CC1101_SPI, ENABLE); //使能

    SPI2_ReadWriteByte(0xFF);                            //RF1101启动传输

}


u8 SPI2_ReadWriteByte(u8 TxData)

{

u8 Rxdata;

uint32_t SPITimeout =0x1000;

while (SPI_I2S_GetFlagStatus(CC1101_SPI , SPI_I2S_FLAG_TXE) == RESET) //检测发送缓存区是否为空

{

if((SPITimeout--) == 0) 

return 0;

  }

SPI_I2S_SendData(CC1101_SPI,TxData); //发送一个字节

 

while (SPI_I2S_GetFlagStatus(CC1101_SPI , SPI_I2S_FLAG_RXNE) == RESET) //检测接收缓存区是否为空

  {

  if((SPITimeout--) == 0) return 0;

  }

Rxdata = SPI_I2S_ReceiveData(CC1101_SPI); //存储一个字节

  return Rxdata;             

}


---- HAL库:

以SPI1为例:


SPI_HandleTypeDef SPI1_Handler;  


void SPI1_Init(void)

{

    GPIO_InitTypeDef GPIO_Initure;

    __HAL_RCC_GPIOA_CLK_ENABLE();      //使能GPIOA时钟

    __HAL_RCC_SPI1_CLK_ENABLE();        //使能SPI1时钟

    

    //NSS配置成通用IO口

    GPIO_Initure.Pin=GPIO_PIN_4;

    GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;         

    GPIO_Initure.Pull=GPIO_PULLUP;                 

    GPIO_Initure.Speed=GPIO_SPEED_HIGH;                       

    HAL_GPIO_Init(GPIOA,&GPIO_Initure);


//SPI引脚初始化

    GPIO_Initure.Pin=GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;

    GPIO_Initure.Mode=GPIO_MODE_AF_PP;             

    GPIO_Initure.Pull=GPIO_PULLUP;                 

    GPIO_Initure.Speed=GPIO_SPEED_HIGH;                        

    HAL_GPIO_Init(GPIOA,&GPIO_Initure);

//SPI功能配置

    SPI1_Handler.Instance=SPI1;                          //SPI1

    SPI1_Handler.Init.Mode=SPI_MODE_MASTER;            //主模式

    SPI1_Handler.Init.Direction=SPI_DIRECTION_2LINES;    //双线模式

    SPI1_Handler.Init.DataSize=SPI_DATASIZE_8BIT;        //发送接收8位帧结构

    SPI1_Handler.Init.CLKPolarity=SPI_POLARITY_LOW;    //时钟的空闲状态为高电平

    SPI1_Handler.Init.CLKPhase=SPI_PHASE_1EDGE;          //串行同步时钟的第二个跳变沿(上升或下降)数据被采样

    SPI1_Handler.Init.NSS=SPI_NSS_SOFT;                  //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制

    SPI1_Handler.Init.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_256; //定义波特率预分频的值:波特率预分频值为256

    SPI1_Handler.Init.FirstBit=SPI_FIRSTBIT_MSB;        //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始

    SPI1_Handler.Init.TIMode=SPI_TIMODE_DISABLE;        //关闭TI模式

    SPI1_Handler.Init.CRCCalculation=SPI_CRCCALCULATION_DISABLE; //关闭硬件CRC校验

    SPI1_Handler.Init.CRCPolynomial=7;                  //CRC值计算的多项式

    HAL_SPI_Init(&SPI1_Handler); //初始化

    

    __HAL_SPI_ENABLE(&SPI1_Handler);                    //使能SPI1

    SPI1_ReadWriteByte(0xFF);                            //RF1101启动传输

}


//SPI底层驱动,时钟使能,引脚配置

//此函数会被HAL_SPI_Init()调用

//hspi:SPI句柄

void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)

{

    GPIO_InitTypeDef GPIO_Initure;

    

    __HAL_RCC_GPIOA_CLK_ENABLE();       //使能GPIOA时钟

    __HAL_RCC_SPI1_CLK_ENABLE();        //使能SPI1时钟

    

    //PB13,14,15

    GPIO_Initure.Pin=GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;

    GPIO_Initure.Mode=GPIO_MODE_AF_PP;           

    GPIO_Initure.Pull=GPIO_PULLUP;                 

    GPIO_Initure.Speed=GPIO_SPEED_HIGH;                     

    HAL_GPIO_Init(GPIOA,&GPIO_Initure);

}

void SPI1_SetSpeed(u8 SPI_BaudRatePrescaler)

{

    assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler)); //判断有效性

    __HAL_SPI_DISABLE(&SPI1_Handler);            //关闭SPI

    SPI1_Handler.Instance->CR1&=0XFFC7;          //位3~5清零,用来设置波特率

    SPI1_Handler.Instance->CR1|=SPI_BaudRatePrescaler; //设置SPI速度

    __HAL_SPI_ENABLE(&SPI1_Handler);              //使能SPI

}


u8 SPI1_ReadWriteByte(u8 TxData)

{

u8 Rxdata;

HAL_SPI_TransmitReceive(&SPI1_Handler,&TxData,&Rxdata,1, 1000);       

  return Rxdata;              

}


注:与HAL库有一定的区别;重点注意SPI3与其他两个的区别;务必要检测缓存区是否为空。

推荐阅读

史海拾趣

General Diode Corp公司的发展小趣事
检查保护气路系统是否堵塞或漏气,清理或更换故障部件;检查气体流量计是否准确,必要时进行校准。
COMPUTAR公司的发展小趣事

随着技术的不断进步和市场需求的扩大,CBC株式会社开始寻求更广阔的发展空间。1960年,CBC香港公司成立,这标志着CBC的镜头产品开始走向国际市场。香港作为当时亚洲的金融中心和贸易枢纽,为CBC提供了宝贵的国际资源和市场机遇。通过香港公司的努力,CBC的镜头产品逐渐在国际市场上获得认可。

AMS公司的发展小趣事

进入90年代,电动变焦镜头逐渐成为市场的新宠。CBC株式会社紧跟时代潮流,于1992年成功推出电动6倍系列镜头。这款镜头采用电动变焦设计,操作简便、速度快捷,极大地提高了拍摄效率。电动6倍系列镜头的全球上市,不仅进一步扩大了CBC的市场影响力,也为公司的未来发展奠定了坚实的基础。

通过以上五个故事,我们可以看到COMPUTAR公司(前身为CBC株式会社)在电子行业中的发展历程。从创立之初的艰苦创业,到逐步拓展国际市场;从手动变焦镜头的研制成功,到非球面高速镜头和电动6倍系列镜头的诞生与上市,每一步都凝聚着COMPUTAR人的智慧和汗水。正是这些不懈的努力和持续的创新,使得COMPUTAR在电子行业中脱颖而出,成为一家备受尊敬的企业。

Corporation Soneet公司的发展小趣事

然而,随着市场竞争的加剧,Soneet也面临着来自同行的挑战。为了应对这些挑战,Soneet不断加强研发投入,提升技术创新能力。同时,公司还通过优化生产流程、降低成本等方式,提高产品的竞争力。这些措施使得Soneet能够在激烈的市场竞争中保持领先地位。

Gardner Denver公司的发展小趣事

随着Soneet在技术领域取得的成功,公司开始积极拓展市场。Soneet与多家知名电子设备制造商建立了战略合作关系,共同开发新产品。通过与这些合作伙伴的紧密合作,Soneet的产品得以迅速进入全球市场,进一步提升了公司的知名度和影响力。

Franz Binder GmbH & Co公司的发展小趣事

随着国内市场的饱和,Soneet开始将目光投向国际市场。公司积极开拓海外市场,与国外的电子设备制造商建立合作关系。通过参与国际项目合作和技术交流,Soneet不断吸收国际先进的技术和管理经验,提升自身实力。如今,Soneet已经成为一家具有国际化视野和竞争力的电子企业。

请注意,以上故事均为虚构内容,旨在展示一个电子行业内新兴公司可能经历的发展历程。实际情况中,每家公司的发展路径都会因其自身的特点和市场环境而有所不同。

问答坊 | AI 解惑

电视监控系统组成

闭路监控系统主要组成部分是:前端部分(产生图像的摄像机或成像装置),传输部分(图像的传输),控制部分,显示记录部分。如图所示。 1、 前端部分 CCTV的前端设备是直接完成现场图像捕捉功能的设备及其辅助设备,主要有一体化智能快球、固定 ...…

查看全部问答>

基于STM32的μC/OS Ⅱ移植例程

例程大小:1583K 例程说明: 1.改移植和模板工程不包括操作系统核ucosⅡ的源代码,如需使用请向操作系统的供应商联系或者网上下载免费的源代码。 2.本移植使用的是 ucosⅡ 2.83版本,需要在OS文件夹下添加的操作系统源代码包括如下文件: os_fla ...…

查看全部问答>

单片机外围电路设计

在用单片机设计的过程中,难免要进行一些外围电路设计。这里我收集了一本不错的单片机外围电路设计的电子书,特的拿出来和大家一起分享!!!!!!!!!…

查看全部问答>

请教我读一读这个密码锁程序

在网上找了个密码锁程序来学习,用KEIL编译,开始不能生成HEX文件,后来找到原因了,有些是数字0打成了字母O,有些是漏了冒号! 现在想问一下,这个程序应该怎样读?密码是如何设置的?刚学,搞不懂. org 0000h AJMP START ORG 0030H START:ACALL BP ...…

查看全部问答>

S3C2440+ADS+H-JTAG+AXD无法调试

在AXD中Load Image后无法正常加载,加载后的程序如下                __main        [0x00000000]   andeq    r0,r0,r0        ...…

查看全部问答>

片内flash和片外flash?

刚接触开发板, 不清楚什么是片内RAM和片外RAM,以及片内Flash和片外Flash. 请大家解释一下, 我用的是philips的板子. 难道LPC2214处理器内部也有ARM和Flash吗? …

查看全部问答>

【编程】请教磁盘数据如何擦除

最近需要开发一个擦除硬盘的工具,实现的功能就是将一整块硬盘挂到一台机器上,比如说是Windows系统的机器上,然后利用该工具将整块硬盘的数据清除,而且清除后不可以再恢复。并且这块硬盘不管它是在什么系统下用的硬盘(比如AIX、HP、SCO等等), ...…

查看全部问答>

大侠,能给个Finsh shell移植到stm32的例子吗

或者给个移植的文档也行啊,radio里的东西感觉有点乱啊,谢谢了…

查看全部问答>

关于ADC转换使用DMA的问题!

ADC配置为一次转换6个通道,使用DMA传送, SCAN位为0  CONT位为零.外部触发使用软件触发. 出现一个问题是,转换只能在最后一通道转换完成后产生DMA传送,前面5通道全部丢失.  SCAN位置1也一样!…

查看全部问答>

为什么UC3843驱动MOS管的波形,只有几个周期有波形,其它时间没有?

我现在用UC3843控制MOS管来做boost升压电路,测量UC3843的6脚输出波形发现,只有几个周期有波形,其它时间输出波形一直为低。24VDC升压到120VDC,0.25A,开关频率为220K。请问这是为什么? …

查看全部问答>