医保局网站建设中标公告,高端网站建设公司哪家公司好,程序员公司,在线推广网站的方法有哪些1.SPI通信简介SCK#xff1a;串行时钟线MOSI#xff1a;主机输出、从机输入#xff08;主机向从机发送数据#xff09;MISO#xff1a;主机输入、从机输出#xff08;主机从从机接收数据#xff09;SS#xff1a;从机选择#xff08;从机寻址#xff09;2.SPI硬件电路…1.SPI通信简介SCK串行时钟线MOSI主机输出、从机输入主机向从机发送数据MISO主机输入、从机输出主机从从机接收数据SS从机选择从机寻址2.SPI硬件电路SS线都是低电平有效的同一时间只有一条SS线能被置低电平即同一时间只能选中一个从机当从机被选中时即SS线被置低电平时MISO才会是推挽输出否则会被设置成高阻态被断开3.SPI时序基本单元1.起始和发送就是起始就是选择从机结束从机选中状态2.收发数据时序模式功能都一样1.模式0MISO初始时为高阻态结束时要重新配置为高阻态数据提前移出和移入MOSI在第0个边沿移出在第1个边沿移入原因数据要先移出才能移入2.模式1MISO初始时为高阻态结束时要重新配置为高阻态3.模式2MISO初始时为高阻态结束时要重新配置为高阻态4.模式3MISO初始时为高阻态结束时要重新配置为高阻态3.收发SPI时序格式以芯片W25Q64作为参考基本格式起始指令码读写等功能数据将被写入的地址数据4.基本配置格式手动实现时序//从机选择写SS的引脚 void MySPI_W_SS(uint8_t BitValue) { GPIO_WriteBit(GPIOA, GPIO_Pin_4, (BitAction)BitValue); } //时钟线 void MySPI_W_SCK(uint8_t BitValue) { GPIO_WriteBit(GPIOA, GPIO_Pin_5, (BitAction)BitValue); } //主机将数据写入从机发送 void MySPI_W_MOSI(uint8_t BitValue) { GPIO_WriteBit(GPIOA, GPIO_Pin_7, (BitAction)BitValue); } //主机接收从机数据接收 uint8_t MySPI_R_MISO(void) { return GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6); } //初始化 void MySPI_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //将SCK、MOSI、SS配置成推挽输出 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); //将主机输入、从机输出的MISO配置成上拉输入 GPIO_InitStructure.GPIO_Mode GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin GPIO_Pin_6; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); //置默认电平 MySPI_W_SS(1); MySPI_W_SCK(0); } //起始时序 void MySPI_Start(void) { MySPI_W_SS(0); } //终止时序 void MySPI_Stop(void) { MySPI_W_SS(1); } //交换一个字节模式0收发数据 //注意从机的操作是从机自动进行的软件代码只需管主机 //方法一使用掩码取出每一位数据进行操作 uint8_t MySPI_SwapByte(uint8_t ByteSend) { uint8_t i, ByteReceive 0x00; for (i 0; i 8; i ) { MySPI_W_MOSI(!!(ByteSend (0x80 i))); MySPI_W_SCK(1); if (MySPI_R_MISO()){ByteReceive | (0x80 i);} MySPI_W_SCK(0); } return ByteReceive; } //方法二将数据本身进行移位相当于将主机数据一位一位移出再一位一位移入从机数据 //uint8_t MySPI_SwapByte(uint8_t ByteSend) //{ // uint8_t i; // // for (i 0; i 8; i ) // { // MySPI_W_MOSI(!!(ByteSend 0x80); // ByteSend1; // MySPI_W_SCK(1); // if (MySPI_R_MISO()){ByteSend | 0x01;} // MySPI_W_SCK(0); // } // // return ByteSend; //}4.硬件实现SPI通信STM32内部的SPI外设1.SPI外设简介注意SPI1挂载在APB2PCLK是72MHz而SPI2挂载在APB1PCLK是36MHz2.STM32中SPI外设的内部结构图LSBFIRST帧格式可以选择数据是低位先行还是高位先行给0先发送MSB即高位先行给1先发送LSB即低位先行TXE发送寄存器空RXNE接受寄存器非空NSS从机选择低电平有效 当SSOE置1时NSS配置成输出即成为主机当SSOE清0后NSS变为输入即成为从机3.SPI基本结构图4.硬件SPI的操作流程1.主模式全双工连续传输效率高示例为模式三发送数据解释开始时TXE1表示发送寄存器空TXE为0时数据进入发送寄存器TXE再次为1时数据由发送寄存器进入移位寄存器同时下一个数据紧接着进入发送寄存器接收数据解释开始时RXNE0表示接受寄存器空RXNE为1时数据由移位寄存器进入接受寄存器完成后清除RXNE即直接置0这种数据传输模式是交叉的并不是发送一个数据后马上接收此数据2.非连续传输基本逻辑发送一个数据然后等待此数据被接收最后发送下一个字节。注意相较主模式全双工连续传输传输速度明显更慢3.硬件SPI的实战代码1.部分函数功能//写DR数据寄存器 void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data); //读DR数据寄存器 uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx);2.配置思路1.RCC开启时钟把SPI外设和对应的GPIO口的时钟打开2.配置GPIOSCK、MOSI配置成复用推挽输出模式。MISO配置成上拉输入模式SS配置成通用推挽输出3.配置SPI外设4.开启SPI使能)3.基本配置格式使用库函数实现时序//从机选择 void MySPI_W_SS(uint8_t BitValue) { GPIO_WriteBit(GPIOA, GPIO_Pin_4, (BitAction)BitValue); } //初始化 void MySPI_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //SPI1是APB2上的外设 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); //开启SS从机选择时钟 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin GPIO_Pin_4; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); //SCK和MOSI复用推挽输出 GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Pin GPIO_Pin_5 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); //MISO上拉输入模式 GPIO_InitStructure.GPIO_Mode GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin GPIO_Pin_6; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); //SPI初始化 SPI_InitTypeDef SPI_InitStructure; SPI_InitStructure.SPI_Mode SPI_Mode_Master;//SPI模式决定SPI是主机还是从机 SPI_InitStructure.SPI_Direction SPI_Direction_2Lines_FullDuplex;//数据传输模式此处为双线全双工 SPI_InitStructure.SPI_DataSize SPI_DataSize_8b;//8位数据帧 SPI_InitStructure.SPI_FirstBit SPI_FirstBit_MSB;//高位先行 SPI_InitStructure.SPI_BaudRatePrescaler SPI_BaudRatePrescaler_128;//128分频SPI1外设72/128 //配置模式模式0、1、2、3 SPI_InitStructure.SPI_CPOL SPI_CPOL_Low; SPI_InitStructure.SPI_CPHA SPI_CPHA_1Edge; SPI_InitStructure.SPI_NSS SPI_NSS_Soft;//选择NSS模式硬件NSS或软件NSS此处为软件NSS SPI_InitStructure.SPI_CRCPolynomial 7; SPI_Init(SPI1, SPI_InitStructure); SPI_Cmd(SPI1, ENABLE); MySPI_W_SS(1); } //起始时序 void MySPI_Start(void) { MySPI_W_SS(0); } //终止时序 void MySPI_Stop(void) { MySPI_W_SS(1); } //交换一个字节 uint8_t MySPI_SwapByte(uint8_t ByteSend) { while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) ! SET);//等待TXE SPI_I2S_SendData(SPI1, ByteSend);//将数据写入DR while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) ! SET);//等待RNXE return SPI_I2S_ReceiveData(SPI1);//将DR中的数据读出 }