STM32 3个硬件SPI的使用
2016-08-11 08:51
363 查看
硬件平台:STM32F103
SPI1初始化过程static OS_EVENT *spi1_sem_event; static void SPI1SemInit(void) { spi1_sem_event = OSSemCreate(1); } extern void SPI1SemGet(void) { uint8_t err; OSSemPend(spi1_sem_event, 0, &err); } extern void SPI1SemPut(void) { OSSemPost(spi1_sem_event); } static void Spi1_Init(void) { SPI_InitTypeDef SPI_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; /* Enable SPI1 and GPIO clocks */ /*!< SPI_FLASH_SPI_CS_GPIO, SPI_FLASH_SPI_MOSI_GPIO, SPI_FLASH_SPI_MISO_GPIO, SPI_FLASH_SPI_DETECT_GPIO and SPI_FLASH_SPI_SCK_GPIO Periph clock enable */ /*!< SPI_FLASH_SPI Periph clock enable */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); /*!< AFIO Periph clock enable */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); /*!< Configure SPI_FLASH_SPI pins: SCK */ GPIO_InitStructure.GPIO_Pin = PIN_SPI1_SCLK; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(PORT_SPI1_SCLK, &GPIO_InitStructure); /*!< Configure SPI_FLASH_SPI pins: MISO */ GPIO_InitStructure.GPIO_Pin = PIN_SPI1_MISO; GPIO_Init(PORT_SPI1_MISO, &GPIO_InitStructure); /*!< Configure SPI_FLASH_SPI pins: MOSI */ GPIO_InitStructure.GPIO_Pin = PIN_SPI1_MOSI; GPIO_Init(PORT_SPI1_MOSI, &GPIO_InitStructure); /* SPI1 configuration */ // W25X16: data input on the DIO pin is sampled on the rising edge of the CLK. // Data on the DO and DIO pins are clocked out on the falling edge of CLK. SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工 SPI_InitStructure.SPI_Mode = SPI_Mode_Master;//设置SPI工作模式:设置为主SPI SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;//设置SPI的数据大小:SPI发送接收8位帧结构 #if 0 SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //串行同步时钟的空闲状态为高电平 SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //串行同步时钟的第二个跳变沿(上升或下降)数据被采样 #else SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //时钟悬空低 SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //数据捕获于第1个时钟沿 #endif SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制 SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;//定义波特率预分频的值:波特率预分频值为2 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始 SPI_InitStructure.SPI_CRCPolynomial = 7;//CRC值计算的多项式 SPI_Init(SPI1, &SPI_InitStructure); /* Enable SPI1 */ SPI_Cmd(SPI1, ENABLE); SPI1SemInit(); } extern void SPI1_SetSpeed(u8 SpeedSet) { SPI_InitTypeDef SPI_InitStructure; SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //如果速度设置输入0,则低速模式,非0则高速模式 if(SpeedSet == 1) { SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32; } else { SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; } SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPI1, &SPI_InitStructure); } extern void spi1WriteData(Uchar *buf,Uint len) { for (; len ; len--,buf++) { while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); SPI_I2S_SendData(SPI1, *buf); while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); SPI_I2S_ReceiveData(SPI1); } } extern u8 SPI1_Swap_DataMSB(u8 byte) { u8 retry=0; while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位 { retry++; if(retry>200)return 0; } SPI_I2S_SendData(SPI1, byte); //通过外设SPIx发送一个数据 retry=0; while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET) //检查指定的SPI标志位设置与否:接受缓存非空标志位 { retry++; if(retry>200)return 0; } return SPI_I2S_ReceiveData(SPI1); //返回通过SPIx最近接收的数据 }
SPI2初始化过程
static OS_EVENT *spi2_sem_event; static void SPI2SemInit(void) { spi2_sem_event = OSSemCreate(1); } extern void SPI2SemGet(void) { uint8_t err; OSSemPend(spi2_sem_event, 0, &err); } extern void SPI2SemPut(void) { OSSemPost(spi2_sem_event); } extern void Spi2_Init(void) { SPI_InitTypeDef SPI_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); /*!< AFIO Periph clock enable */ //RCC_APB2PeriphClockCmd(RCC_APB1Periph_AFIO, ENABLE); GPIO_InitStructure.GPIO_Pin = PIN_SPI2_SCLK; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(PORT_SPI2_SCLK, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = PIN_SPI2_MISO; GPIO_Init(PORT_SPI2_MISO, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = PIN_SPI2_MOSI; GPIO_Init(PORT_SPI2_MOSI, &GPIO_InitStructure); /* SPI2 configuration */ SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; #if 1 SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; #else SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //时钟悬空低 SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //数据捕获于第1个时钟沿 #endif SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; SPI_InitS 1087c tructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPI2, &SPI_InitStructure); /* Enable SPI2 */ SPI_Cmd(SPI2, ENABLE); SPI2SemInit(); } /******************************************************************************* * Function Name : SPI_SetSpeed * Description : SPI设置速度为高速 * Input : u8 SpeedSet * 如果速度设置输入0,则低速模式,非0则高速模式 * SPI_SPEED_HIGH 1 * SPI_SPEED_LOW 0 * Output : None * Return : None *******************************************************************************/ void SPI2_SetSpeed(u8 SpeedSet) { SPI_InitTypeDef SPI_InitStructure; SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //如果速度设置输入0,则低速模式,非0则高速模式 if(SpeedSet == 1) { SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32; } else { SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; } SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPI2, &SPI_InitStructure); } extern void spi2WriteData(Uchar *buf,Uint len) { for (; len ; len--,buf++) { while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET); SPI_I2S_SendData(SPI2, *buf); while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET); SPI_I2S_ReceiveData(SPI2); } } extern u8 SPI2_Swap_DataMSB(u8 byte) { /* Loop while DR register in not emplty */ while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET); /* Send byte through the SPI1 peripheral */ SPI_I2S_SendData(SPI2, byte); /* Wait to receive a byte */ while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET); /* Return the byte read from the SPI bus */ return SPI_I2S_ReceiveData(SPI2); }
SPI3初始化过程
static OS_EVENT *spi3_sem_event; static void SPI3SemInit(void) { spi3_sem_event = OSSemCreate(1); } extern void SPI3SemGet(void) { uint8_t err; OSSemPend(spi3_sem_event, 0, &err); } extern void SPI3SemPut(void) { OSSemPost(spi3_sem_event); } static void Spi3_Init(void) { SPI_InitTypeDef SPI_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; /* Enable SPI1 and GPIO clocks */ /*!< SPI_FLASH_SPI_CS_GPIO, SPI_FLASH_SPI_MOSI_GPIO, SPI_FLASH_SPI_MISO_GPIO, SPI_FLASH_SPI_DETECT_GPIO and SPI_FLASH_SPI_SCK_GPIO Periph clock enable */ /*!< SPI_FLASH_SPI Periph clock enable */ //RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE); /*!< AFIO Periph clock enable */ //RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); /*!< Configure SPI_FLASH_SPI pins: SCK */ GPIO_InitStructure.GPIO_Pin = PIN_SPI_SCLK; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(PORT_SPI_SCLK, &GPIO_InitStructure); /*!< Configure SPI_FLASH_SPI pins: MISO */ GPIO_InitStructure.GPIO_Pin = PIN_SPI_MISO; GPIO_Init(PORT_SPI_MISO, &GPIO_InitStructure); /*!< Configure SPI_FLASH_SPI pins: MOSI */ GPIO_InitStructure.GPIO_Pin = PIN_SPI_MOSI; GPIO_Init(PORT_SPI_MOSI, &GPIO_InitStructure); /* SPI1 configuration */ // W25X16: data input on the DIO pin is sampled on the rising edge of the CLK. // Data on the DO and DIO pins are clocked out on the falling edge of CLK. SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; #if 1 SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; #else SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //时钟悬空低 SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //数据捕获于第1个时钟沿 #endif SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPI3, &SPI_InitStructure); /* Enable SPI1 */ SPI_Cmd(SPI3, ENABLE); SPI3SemInit(); } /******************************************************************************* * Function Name : SPI_SetSpeed * Description : SPI设置速度为高速 * Input : u8 SpeedSet * 如果速度设置输入0,则低速模式,非0则高速模式 * SPI_SPEED_HIGH 1 * SPI_SPEED_LOW 0 * Output : None * Return : None *******************************************************************************/ void SPI3SetSpeed(u8 SpeedSet) { SPI_InitTypeDef SPI_InitStructure; SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //如果速度设置输入0,则低速模式,非0则高速模式 if(SpeedSet == 1) { SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32; } else { SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; } SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPI3, &SPI_InitStructure); } extern void spi3WriteData(Uchar *buf,Uint len) { for (; len ; len--,buf++) { while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE) == RESET); SPI_I2S_SendData(SPI3, *buf); while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_RXNE) == RESET); SPI_I2S_ReceiveData(SPI3); } } extern u8 SPI3_Swap_DataMSB(u8 byte) { /* Loop while DR register in not emplty */ while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE) == RESET); /* Send byte through the SPI1 peripheral */ SPI_I2S_SendData(SPI3, byte); /* Wait to receive a byte */ while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_RXNE) == RESET); /* Return the byte read from the SPI bus */ return SPI_I2S_ReceiveData(SPI3); }
SPI用GPIO模拟注意以下四种状态的时序,转自网络~~~
#define _CPOL 1 #define _CPHA 0 #define SCK_IO DDRA|=0X01 #define MOSI_IO DDRA|=0X02 #define MISO_IO DDRA&=0XFB #define SSEL_IO DDRA|=0X08 #define SCK_D(X) (X?(PORTA|=0X01):(PORTA&=0XFE)) #define MOSI_D(X) (X?(PORTA|=0X02):(PORTA&=0XFD)) #define SSEL_D(X) (X?(PORTA|=0X08):(PORTA&=0XF7)) #define MISO_I() (PINA&0X04) void delay() { unsigned char m,n; for(n=0;n<5;n++); for(m=0;m<100;m++); } /************************************************ 端口方向配置 与输出初始化 ************************************************/ void SPI_Init(void) { SCK_IO ; MOSI_IO ; MISO_IO ; SSEL_IO ; SSEL_D(1); MOSI_D(1); #if _CPOL==0 SCK_D(0); #else SCK_D(1); #endif } /********************************************** 模式零 写数据 ***********************************************/ #if _CPOL==0&&_CPHA==0 //MODE 0 0 void SPI_Send_Dat(unsigned char dat) { unsigned char n; for(n=0;n<8;n++) { SCK_D(0); if(dat&0x80)MOSI_D(1); else MOSI_D(0); dat<<=1; SCK_D(1); } SCK_D(0); } /********************************************* 模式零 读数据 *********************************************/ unsigned char SPI_Receiver_Dat(void) { unsigned char n ,dat,bit_t; for(n=0;n<8;n++) { SCK_D(0); dat<<=1; if(MISO_I())dat|=0x01; else dat&=0xfe; SCK_D(1); } SCK_D(0); return dat; } #endif /********************************************** 模式二 写数据 ***********************************************/ #if _CPOL==1&&_CPHA==0 //MODE 1 0 void SPI_Send_Dat(unsigned char dat) { unsigned char n; for(n=0;n<8;n++) { SCK_D(1); if(dat&0x80)MOSI_D(1); else MOSI_D(0); dat<<=1; SCK_D(0); } SCK_D(1); } /********************************************* 模式二 读数据 *********************************************/ unsigned char SPI_Receiver_Dat(void) { unsigned char n ,dat,bit_t; for(n=0;n<8;n++) { SCK_D(1); dat<<=1; if(MISO_I())dat|=0x01; else dat&=0xfe; SCK_D(0); } SCK_D(1); return dat; } #endif /********************************************* 模式一 写数据 *********************************************/ #if _CPOL==0&&_CPHA==1 //MODE 0 1 void SPI_Send_Dat(unsigned char dat) { unsigned char n; SCK_D(0); for(n=0;n<8;n++) { SCK_D(1); if(dat&0x80)MOSI_D(1); else MOSI_D(0); dat<<=1; SCK_D(0); } } /********************************************* 模式一 读数据 *********************************************/ unsigned char SPI_Receiver_Dat(void) { unsigned char n ,dat,bit_t; for(n=0;n<8;n++) { SCK_D(1); dat<<=1; if(MISO_I())dat|=0x01; else dat&=0xfe; SCK_D(0); } SCK_D(0); return dat; } #endif /////////////////////////////////////////////////////// /////////////////////////////////////////////////////// #if _CPOL==1&&_CPHA==1 //MODE 1 1 void SPI_Send_Dat(unsigned char dat) { unsigned char n; SCK_D(1); for(n=0;n<8;n++) { SCK_D(0); if(dat&0x80)MOSI_D(1); else MOSI_D(0); dat<<=1; SCK_D(1); } } /************************************ 模式三 读数据 ************************************/ unsigned char SPI_Receiver_Dat(void) { unsigned char n ,dat,bit_t; SCK_D(0); for(n=0;n<8;n++) { SCK_D(0); dat<<=1; if(MISO_I())dat|=0x01; else dat&=0xfe; SCK_D(1); } SCK_D(1); return dat; } #endif /************************************* *************************************/ void main() { SPI_Init(); DDRB = 0XFF; //#if _CPOL //SCK_D(0); //#endif while(1) { //SSEL_D(0); //SPI_Send_Dat(0x01); //SPI_Send_Dat(0x31); //SSEL_D(1); SSEL_D(0); SPI_Send_Dat(0x81); PORTB =SPI_Receiver_Dat(); SSEL_D(1); //delay(); } }
相关文章推荐
- STM32硬件SPI使用与nSS的理解
- STM32 SPI初始化和使用
- 浅谈 STM32 硬件I2C的使用 (中断方式 无DMA 无最高优先级)
- STM32F4使用硬件SPI驱动ADS8322
- STM32学习笔记之硬件SPI读写与极性设置
- STM8L151 使用硬件SPI驱动VS1003B MP3解码芯片
- 关于STM32的硬件IIC使用问题解决方案
- stm32 SPI NSS引脚的使用配置
- 基于MDK编程STM32程序无法使用,硬件仿真在汇编窗口看到停留在“0x0800XXXX BEAB BKPT 0xAB //进入调试模式”
- STM32的硬件CRC32使用
- STM32之SPI的使用
- STM32 SPI DMA 的使用
- 关于STM8S使用硬件SPI收发问题
- STM32 spi使用
- STM32 SPI DMA 的使用
- STM32 SPI DMA 的使用
- STM32未使用引脚的处理方式及推荐硬件设计规范
- STM32 SPI初始化和使用
- STM32 使用 Keil MDK 中的软件逻辑分析仪参与硬件调试
- 浅谈 STM32 硬件I2C的使用 (中断方式 无DMA 无最高优先级)