#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);