zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    IDEA的JDBC报错解决
    java注解
    Java反射
    javaIO
    工程师的认知
    前端的一些性能提升
    ES6函数的扩展
    2020新年愿望
    高维护性的javascript
    Chrome Dev tools的几点小技巧
  • 原文地址:https://www.cnblogs.com/HintLee/p/9499447.html
Copyright © 2011-2022 走看看