其实stm32本身的硬件SPI也很好用,但是还是想用软件来模拟一下PSI的时序。 SPI 是一种高速的,全双工,同步串行的通信总线。SPI通信方式相当于是一个环形结构,由CSN、MISO、MOSI、SCLK四线组成,主要是在SCLK时钟线的驱动下,进行数据转换。 接下来直接上程序配置: 使用32模拟SPI时序的IO口配置,应该注意的是MISO应该选择模拟输入方式GPIO_Mode_IN_FLOATING。 以下是我的初始化部分:
/*用于软件模拟SPI IO口宏定义区*/#define SPI_CS_PORT GPIOB#define SPI_CS_PIN GPIO_Pin_11#define SPI_CS_LOW (SPI_CS_PORT->BRR |=SPI_CS_PIN)#define SPI_CS_HIGH (SPI_CS_PORT->BSRR |=SPI_CS_PIN)#define SPI_SCK_PORT GPIOA#define SPI_SCK_PIN GPIO_Pin_12#define SPI_SCK_LOW (SPI_SCK_PORT->BRR |=SPI_SCK_PIN)#define SPI_SCK_HIGH (SPI_SCK_PORT->BSRR|=SPI_SCK_PIN)#define SPI_MISO_PORT GPIOA#define SPI_MISO_PIN GPIO_Pin_8#define SPI_MISO_LOW (SPI_MISO_PORT->BRR |=SPI_MISO_PIN)#define SPI_MISO_HIGH (SPI_MISO_PORT->BSRR|=SPI_MISO_PIN)#define SPI_MISO_READ (SPI_MISO_PORT->IDR &SPI_MISO_PIN)#define SPI_MOSI_PORT GPIOA#define SPI_MOSI_PIN GPIO_Pin_11#define SPI_MOSI_LOW (SPI_MOSI_PORT->BRR |=SPI_MOSI_PIN)#define SPI_MOSI_HIGH (SPI_MOSI_PORT->BSRR|=SPI_MOSI_PIN)void SPI_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB,ENABLE); //CS GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP; GPIO_InitStruct.GPIO_Pin=SPI_CS_PIN; GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(SPI_CS_PORT, &GPIO_InitStruct); //SCK GPIO_InitStruct.GPIO_Pin=SPI_SCK_PIN; GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP; GPIO_Init(SPI_SCK_PORT,&GPIO_InitStruct); //MISO GPIO_InitStruct.GPIO_Pin=SPI_MISO_PIN; GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING; GPIO_Init(SPI_MISO_PORT,&GPIO_InitStruct); //MOSI GPIO_InitStruct.GPIO_Pin=SPI_MOSI_PIN; GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP; GPIO_Init(SPI_MOSI_PORT,&GPIO_InitStruct); SPI_CS_HIGH; SPI_SCK_LOW; }123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
模拟SPI时序
u8 SPI_RW(u8 data) { u8 i; SPI_SCK_LOW; //先将时钟线拉低 for(i=0;i<8;i++) { if((data&0x80)==0x80) //从高位发送 { SPI_MOSI_HIGH; } else { SPI_MOSI_LOW; } SPI_SCK_HIGH; //将时钟线拉高,在时钟上升沿,数据发送到从设备 data<<=1; if(SPI_MISO_READ) //读取从设备发射的数据 { data|=0x01; } SPI_SCK_LOW; //在下降沿数据被读取到主机 } return data; //返回读取到的数据}1234567891011121314151617181920212223242526272829
写寄存器操作:`
u8 SPI_Moni_Write_Reg(u8 Reg,u8 data)
{
u8 states;
SPI_CS_LOW; //先将CSN拉低 states=SPI_RW(Reg); //写入寄存器的地址,即图中的Cn位,并读取状态位 SPI_RW(data); // 要写入的数据 SPI_CS_HIGH; return states;
}
读寄存器操作:u8 SPI_Moni_Read_Reg(u8 Reg) { u8 data; SPI_CS_LOW; SPI_RW(Reg); //先写入寄存器的地址 data=SPI_RW(0); //通过写入无效数据0,将从设备上的数据挤出来 SPI_CS_HIGH; return data; } 接下来就是写缓冲区、读缓冲区函数 了:u8 SPI_Moni_Write_Buf(u8 Reg,u8 *Buf,u8 len) { u8 states; SPI_CS_LOW; states=SPI_RW(Reg); while(len>0) { SPI_RW(*Buf); Buf++; len--; } SPI_CS_HIGH; return states; }u8 SPI_Moni_Read_Buf(u8 Reg,u8 *Buf,u8 len) { u8 states; SPI_CS_LOW; states=SPI_RW(Reg); while(len>0) { *Buf=SPI_RW(0); Buf++; len--; } SPI_CS_HIGH; return states; }
上一篇:STM32中使用MMA7660重力加速度传感器
下一篇:ARM9 2440硬件SPI驱动程序-NRF24L01
推荐阅读最新更新时间:2024-03-16 15:38