SPISPI

ops/2025/2/12 2:40:48/

#include "stm32f10x.h"

void MySPI_W_SS(uint8_t BitValue)    //写SS的引脚
{
    GPIO_WriteBit(GPIOA,GPIO_Pin_4,(BitAction)BitValue);//BitAction表示非0即1
}


void MySPI_Init(void)
{    //开启SPI和GPIO的时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE);//SPI1是挂载在APB2的外设
    
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_4;//SS引脚计划软件模拟 所以配置通用推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    
    GPIO_Init(GPIOA,&GPIO_InitStructure);
    
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;    
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_5 | GPIO_Pin_7;//SCK、MOSI外设控制的输出 配置为复用推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    
    GPIO_Init(GPIOA,&GPIO_InitStructure);
    
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPU;        
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_6;//MISO配置为上拉输入
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    
    GPIO_Init(GPIOA,&GPIO_InitStructure);    

    SPI_InitTypeDef SPI_InitStructure;
    //SCK时钟频率=PCLK频率/分频系数,分频系数越大 SCK时钟频率越小,传输越慢 目前72M/128=500KHz
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //CPHA=0 第一个边沿开始采样
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;//计划使用SPI0,空闲默认低电平
    SPI_InitStructure.SPI_CRCPolynomial = 7;//用不上 填默认值即可 
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;  //8位数据帧
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //双线全双工
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;//高位先行
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;//计划使用软件模拟
    SPI_Init(SPI1,&SPI_InitStructure);
    
    SPI_Cmd(SPI1,ENABLE);
    
    MySPI_W_SS(1);//默认不选中从机
}

//SPI的起始时序
void MySPI_Start(void)
{
    //根据PPT中的起始条件:将SS从高电平切换成低电平
    MySPI_W_SS(0);
}
//SPI的终止时序
void MySPI_Stop(void)
{
    //根据PPT中的终止条件:将SS从低电平切换成高电平
    MySPI_W_SS(1);
}

//SPI交换一个字节 使用模式0
uint8_t MySPI_SwapByte(uint8_t ByteSend)    
{    //硬件SPI必须是发送同时接收,要想接收必须先发送,只有给TDR写东西才会触发时序的生成,
    //如果不发送只调用接收函数,时序不会动
    while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE) != SET);
    //写入DR的时候 会顺便执行清除TXE的操作 而下一句代码恰好是写入DR 
    SPI_I2S_SendData(SPI1,ByteSend);//传入ByteSend写入到TDR,自动写入到移位寄存器,时序波形自动产生,无需再调用函数

    while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE) != SET);//发送和接收是同步的,接收完成代表发送完成
    //接收完成会收到一个字节数据,置标志位RXNE

    return SPI_I2S_ReceiveData(SPI1);//直接将置换得到的数据通过返回值返回出去

}

void SPI_I2S_DeInit(SPI_TypeDef* SPIx);    //恢复缺省配置
void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct);    //初始化
void SPI_StructInit(SPI_InitTypeDef* SPI_InitStruct);    //结构体变量初始化
void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState);    //外设使能
void SPI_I2S_ITConfig(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT, FunctionalState NewState);//中断使能
void SPI_I2S_DMACmd(SPI_TypeDef* SPIx, uint16_t SPI_I2S_DMAReq, FunctionalState NewState);//DMA使能
void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data);    //写DR数据寄存器
uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx);    //读DR数据寄存器
//NSS引脚配置
void SPI_NSSInternalSoftwareConfig(SPI_TypeDef* SPIx, uint16_t SPI_NSSInternalSoft);
void SPI_SSOutputCmd(SPI_TypeDef* SPIx, FunctionalState NewState);

void SPI_DataSizeConfig(SPI_TypeDef* SPIx, uint16_t SPI_DataSize);//8位或16位数据帧的配置

//CRC校验的配置
void SPI_TransmitCRC(SPI_TypeDef* SPIx);    
void SPI_CalculateCRC(SPI_TypeDef* SPIx, FunctionalState NewState);
uint16_t SPI_GetCRC(SPI_TypeDef* SPIx, uint8_t SPI_CRC);
uint16_t SPI_GetCRCPolynomial(SPI_TypeDef* SPIx);

void SPI_BiDirectionalLineConfig(SPI_TypeDef* SPIx, uint16_t SPI_Direction);//半双工时双向线方向的配置

//常见函数
FlagStatus SPI_I2S_GetFlagStatus(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG);//获取和清除标志位
void SPI_I2S_ClearFlag(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG);
ITStatus SPI_I2S_GetITStatus(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT);
void SPI_I2S_ClearITPendingBit(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT);


http://www.ppmy.cn/ops/7487.html

相关文章

sql篇-如何重启MySQL,正确启动MySQL

Windows启动mysql 1.点击“开始”->“运行”(快捷键WinR)(以管理员身份运行) 2.启动:输入 net stop mysql 3.停止:输入 net start mysql Linux启动MySQL 1、通过rpm包安装的MySQL service mysqld restart 2、从源码包安装的MyS…

【GPTs分享】GPTs分享之 AskYourPDF Research Assistant​

一、简介 AskYourPDF Research Assistant 是一款高级人工智能研究助手,专门设计用于帮助用户高效从PDF文件和文章中提取信息。它结合了深度学习技术和自然语言处理能力,以便用户能够快速地查询、总结及处理文档内容,并能够生成与文章内容相关…

Linux安装和使用Android Debug Bridge(ADB)

目录 1、开发环境和工具 2、ADB是什么? 3、安装ADB 3.1、使用包管理器安装 ADB 3.2、手动安装 ADB 4、使用ADB 4.1、连接设备 4.2、执行shell命令 4.3、安装应用程序 4.4、截取屏幕截图 4.5、模拟按键和手势 4.6、上传文件到Android设备 4.7、从Android设备下载文件…

40.Vue 应用

Vue 应用 应用实例 每个 Vue 应用都是通过 createApp函数创建一个新的 应用实例 import { createApp } from vueconst app createApp({/* 根组件选项 */ })根组件 我们传入 createApp 的对象实际上是一个组件,每个应用都需要一个“根组件”,其他组件…

Python数据挖掘项目开发实战:使用朴素贝叶斯进行社会媒体挖掘

注意:本文的下载教程,与以下文章的思路有相同点,也有不同点,最终目标只是让读者从多维度去熟练掌握本知识点。 下载教程: Python数据挖掘项目开发实战_使用朴素贝叶斯进行社会媒体挖掘_编程案例实例课程教程.pdf Pytho…

CSS 伪元素和伪类的用法和区别

伪元素 伪元素则基于元素的位置来添加内容或样式 在内容元素的前后插入额外的元素或样式,但是这些元素实际上并不在文档中生成。它们只在外部显示可见,但不会在文档的源代码中找到它们,因此,称为“伪”元素。 伪元素通常用双冒…

9.列表渲染

列表渲染 我们可以使用 v-for 指令基于一个数组来渲染一个列表。v-for 指令的值需要使用 item in items 形式的特殊语法&#xff0c;其中 items 是源数据的数组&#xff0c;而 item 是迭代项的别名 <template><div><p v-for"item in names">{{ it…

Chrome 侧边栏开发示例

前言 最近做项目&#xff0c;需要开发浏览器扩展&#xff0c;但是考虑页面布局兼容性问题&#xff0c;使用了Chrome114开始的侧边栏&#xff0c;浏览器自带的能力毕竟不会出现兼容性问题&#xff0c;不过Chrome123开始&#xff0c;侧边栏居然又可以选择固定右侧扩展栏了&#…