• STM32F030 使用硬件 SPI


    前言

    以前玩过一点 STM32 单片机(主要是 STM32F103 系列),去年(2017)STM32F1 涨到不知哪里去了,今年好像降下来了。F0 系列相比 F1 系列少了一些功能,最高主频只到 48M(F1 是 72M),但是价格便宜啊,刚好最近工作需要重新接触了 STM32F030,记录一下。PS:研究了几天觉得 STM32 的各个组成部分还是很精妙的,虽然繁杂但是库函数化解了这个问题。

    步骤

    SPI 初始化

    STM32F030 默认的 SPI1 接口如下,其中 CSN 由软件控制,所以可以改为其他 IO 口

    #define SPI1_PORT       GPIOA
    #define PIN_SPI1_CSN    GPIO_Pin_4
    #define PIN_SPI1_SCK    GPIO_Pin_5
    #define PIN_SPI1_MISO   GPIO_Pin_6
    #define PIN_SPI1_MOSI   GPIO_Pin_7
    
    #define SPI1_CSN_L  (SPI1_PORT->BRR  = PIN_SPI1_CSN)
    #define SPI1_CSN_H  (SPI1_PORT->BSRR = PIN_SPI1_CSN)
    

    初始化

    void SPI1_INIT(void)
    {
    	GPIO_InitTypeDef GPIO_InitStructure;
    	SPI_InitTypeDef   SPI_InitStructure;
    
    	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
    
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;    //复用功能
    	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;    //推挽输出
    	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN;    //下拉
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;    //中速
    	GPIO_InitStructure.GPIO_Pin = PIN_SPI1_SCK | PIN_SPI1_MOSI | PIN_SPI1_MISO;
    	GPIO_Init(SPI1_PORT, &GPIO_InitStructure);
    
    	GPIO_PinAFConfig(SPI1_PORT, GPIO_PinSource5, GPIO_AF_0);
    	GPIO_PinAFConfig(SPI1_PORT, GPIO_PinSource6, GPIO_AF_0);
    	GPIO_PinAFConfig(SPI1_PORT, GPIO_PinSource7, GPIO_AF_0);
    
    	GPIO_InitStructure.GPIO_Pin = PIN_SPI1_CSN;    //配置 CSN
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    //高速
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;    //输出模式
    	GPIO_Init(SPI1_PORT, &GPIO_InitStructure);
    
    	SPI_I2S_DeInit(SPI1);    //将寄存器重设为缺省值
    	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;    //通信空闲时 SCK 为低电平
    	SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;    //第一个时钟沿捕获
    	SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;    //软件控制 NSS
    	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;    //SPI 速度 8 分频
    	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;    //数据传输从 MSB 开始
    	SPI_InitStructure.SPI_CRCPolynomial = 7;    //CRC 校验
    	SPI_Init(SPI1, &SPI_InitStructure);
    	SPI_RxFIFOThresholdConfig(SPI1, SPI_RxFIFOThreshold_QF);    //重要,把应答数据位设置为 8 位
    	SPI_Cmd(SPI1, ENABLE);
    }
    

    传输数据

    读取和发送数据需要检查标志位

    void SPI1_WriteByte(uint8_t TxData)
    {
    	while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);    //检查发送是否完成 
    	SPI_SendData8(SPI1, TxData);
    }
    
    uint8_t SPI1_ReadByte(void)
    {
    	while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);    //检查接收标志位
    	return(SPI_ReceiveData8(SPI1));
    }
    
    uint8_t SPI1_Transfer(uint8_t data)
    {
    	while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
    	SPI_SendData8(SPI1, data);
    	while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
    	return SPI_ReceiveData8(SPI1);
    }
    

    例子

    用 SPI 与 NRF24L01 模块通信

    void NRF24L01_Write_Register(uint8_t reg, uint8_t data)
    {
    	SPI1_CSN_L;
    	SPI1_Transfer(reg);
    	SPI1_Transfer(data);
    	SPI1_CSN_H;
    }
    
    uint8_t NRF24L01_Read_Register(uint8_t reg)
    {
    	uint8_t tmp;
    	SPI1_CSN_L;
    	SPI1_Transfer(reg);
    	tmp = SPI1_Transfer(0);
    	SPI1_CSN_H;
    	return tmp;
    }
    
  • 相关阅读:
    交通综合改造工程EPC总承包项目
    二三维一体化地理信息平台
    NetCore3.1升级到Net5.0序列化方法过时问题
    windows server2012部署.net core IIS,页面报503,应用程序池自动停止。。。
    NetCore使用NPOI导入Word中的图片信息
    NetCore 使用 iTextSharp 读取 PDF 中的文字信息
    NetCore 在 Docker中文件路径找不到的问题
    Vue中数组list直接push的是对象而不是追加数据的问题
    netcore3.1增加阿里云OSS云存储服务
    Centos中Docker容器中程序访问宿主机Redis和Mysql
  • 原文地址:https://www.cnblogs.com/HintLee/p/9499447.html
Copyright © 2020-2023  润新知