《一》SPI介绍: SPI协议(Serial Peripheral Interface),即串行外围设备接口,是一种高速全双工的 通信总线,它由摩托罗拉公司提出,当前最新的为V04.01-2004 版。它被广泛地使用在ADC、LCD等设备与MCU间通讯的场合。
《二》SPI总线包含:4条总线,分别为S|S|、SCK、MOSI、MISO。它们的作用介绍如下:
(1) S|S|( Slave Select):片选信号线,当有多个SPI设备与MCU相连时,每个设备的这个片选信号线是与MCU单独的引脚相连的,而其它的SCK、MOSI、MISO线则为多个设备并联到相同的SPI总线上,“见图1”。当S|S|信号线为低电平时,片选有效,开始SPI通讯。
(2) SCK (Serial Clock):时钟信号线,由主通讯设备产生,不同的设备支持的时钟频率不一样,如 STM32
的SPI时钟频率最大为fpclk/2。
(3) MOSI (Master Output, Slave Input):主设备输出/从设备输入引脚。主机的数据从这条信号线输出,从机由这条信号线读入数据,即这条线上数据的方向为主机到从机。
(4) MISO(Master Input, Slave Output): 主设备输入 /从设备输出引脚。主机从这条信号线读入数据,从机的数据则由这条信号线输出,即在这条线上数据的方向为从机到主机。
《三》SPI 引脚及模式配置:
- void SPIM_Init(SPI_TypeDef* SPIx,unsigned short spi_baud_div)
- {
- SPI_InitTypeDef SPI_InitStructure;
- GPIO_InitTypeDef GPIO_InitStructure;
- if(SPIx==SPI1)
- {
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); //SPI1 clk enable
- SPIM_CSHigh(SPIx);
-
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; //spi1_cs pa4
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 推免复用输出
- GPIO_Init(GPIOA, &GPIO_InitStructure);
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //spi1_sck pa5
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 推免复用输出
- GPIO_Init(GPIOA, &GPIO_InitStructure);
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //spi1_mosi pa7
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 推免复用输出
- GPIO_Init(GPIOA, &GPIO_InitStructure);
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //spi1_miso pa6
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- }
- if(SPIx==SPI2)
- {
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);//SPI2 clk enable
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //spi2_cs pb12
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 推免复用输出
- GPIO_Init(GPIOB, &GPIO_InitStructure);
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; //spi2_sck pb13
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 推免复用输出
- GPIO_Init(GPIOB, &GPIO_InitStructure);
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; //spi2_mosi pb15
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 推免复用输出
- GPIO_Init(GPIOB, &GPIO_InitStructure);
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14; //spi2_miso pb14
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
- GPIO_Init(GPIOB, &GPIO_InitStructure);
- }
- SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
- SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
- SPI_InitStructure.SPI_DataWidth = SPI_DataWidth_8b;
- SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; // mode0 SPI_CPOL_Low, SPI_CPHA_1Edge;
- SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; // mode3 SPI_CPOL_High,SPI_CPHA_2Edge
- SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
- SPI_InitStructure.SPI_BaudRatePrescaler = spi_baud_div;
- SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
- SPI_Init(SPIx, &SPI_InitStructure);
-
- SPI_Cmd(SPIx, ENABLE);
- //Enables the specified SPI peripheral SPI使能、主机模式 8位数据模式 SPI 的波特率
- SPIM_TXEn(SPIx);
- SPIM_RXEn(SPIx);
- }
复制代码
《四》SPI 读取ID:
- void SPIM_ReadID(SPI_TypeDef* SPIx)
- {
- unsigned char temp;
- unsigned int i;
- SPIM_CSLow(SPIx); //Spi cs assign to this pin,select
- SPIMReadWriteByte( SPIx,RDID);
- for(i=0;i<3;i++)
- {
- temp = SPIMReadWriteByte( SPIx,0x01);
- printf("temp=0x%xrn",temp);
- }
- SPIM_CSHigh(SPIx); //Spi cs release
- }
复制代码
《五》SPI 擦除数据操作:
- /********************************************************************************************************
- **函数信息 :SPIM_SectorErase(SPI_TypeDef* SPIx)
- **功能描述 :擦除数据
- **输入参数 :SPI_TypeDef* SPIx,可选择SPI1,SPI2
- **输入参数 :unsigned long address,删除指定sector的地址 each sector = 64Kbytes
- **输出参数 :无
- ********************************************************************************************************/
- void SPIM_SectorErase(SPI_TypeDef* SPIx,unsigned long address)
- {
- unsigned char addr0,addr1,addr2;
- address = address & 0xffff0000;
- addr0 = ((unsigned char)(address>>16))&0xff;
- addr1 = ((unsigned char)(address>>8))&0xff;
- addr2 = ((unsigned char)address)&0xff;
- SPIM_WriteEnable(SPIx);
- SPIM_CSLow(SPIx); //Spi cs assign to this pin,select
- SPIMReadWriteByte(SPIx,SE);
- SPIMReadWriteByte(SPIx,addr0);
- SPIMReadWriteByte(SPIx,addr1);
- SPIMReadWriteByte(SPIx,addr2);
- SPIM_CSHigh(SPIx); //Spi cs release
-
- SPIM_checkStatus(SPIx);
- }
复制代码
《六》SPI 发送256页数据:
- /********************************************************************************************************
- **函数信息 :SPIM_PageProgram(SPI_TypeDef* SPIx,unsigned long address,unsigned char *p,unsigned int number)
- **功能描述 :发送256页数据
- **输入参数 :SPI_TypeDef* SPIx,可选择SPI1,SPI2 ; address;*p;number
- **输出参数 :无
- ********************************************************************************************************/
- void SPIM_PageProgram(SPI_TypeDef* SPIx,unsigned long address,unsigned char *p,unsigned int number)
- {
- unsigned int j;
- unsigned char addr0,addr1,addr2;
- address = address&0xffffff00; //page address
- addr0 = (unsigned char)(address>>16);
- addr1 = (unsigned char)(address>>8);
- addr2 = (unsigned char)address;
- SPIM_WriteEnable(SPIx);
- SPIM_CSLow(SPIx); //Spi cs assign to this pin,select
- SPIMReadWriteByte(SPIx,PP);
- SPIMReadWriteByte(SPIx,addr0);
- SPIMReadWriteByte(SPIx,addr1);
- SPIMReadWriteByte(SPIx,addr2);
- for(j=0;j
- {
- SPIMReadWriteByte(SPIx,*(p++));
- }
- SPIM_CSHigh(SPIx); //Spi cs release
- SPIM_checkStatus(SPIx);
- }
复制代码
《七》SPI 把写进去的一页256字节读出来:
- for(i=0;i<256;i++)
- {
- rxtmpdata[i] = 0x0;
- }
- SPIM_PageRead(SPIx,0,rxtmpdata,256); //把写进去的一页256字节读出来
- for(i=0;i<10;i++)
- {
- printf("rx[%d]=0x%xrn",i,rxtmpdata[i]);
- }
- printf("spi1 test overrn");
- }
- /********************************************************************************************************
- **函数信息 :SPIM_PageRead(SPI_TypeDef* SPIx,unsigned long address,unsigned char *p,unsigned int number)
- **功能描述 :读取256页数据
- **输入参数 :SPI_TypeDef* SPIx,可选择SPI1,SPI2 ; address ;*p ;number
- **输出参数 :无
- ********************************************************************************************************/
- void SPIM_PageRead(SPI_TypeDef* SPIx,unsigned long address,unsigned char *p,unsigned int number) //page = 256 bytes
- {
- unsigned char addr0,addr1,addr2;
- unsigned int i;
- address = address&0xffffff00; //page address
- addr0 = (unsigned char)(address>>16);
- addr1 = (unsigned char)(address>>8);
- addr2 = (unsigned char)address;
-
- SPIM_CSLow(SPIx); //Spi cs assign to this pin,select
-
- SPIMReadWriteByte( SPIx,READ);
- SPIMReadWriteByte( SPIx,addr0);
- SPIMReadWriteByte( SPIx,addr1);
- SPIMReadWriteByte( SPIx,addr2);
- for(i=0;i<256;i++)
- {
- rxtmpdata[i] = SPIMReadWriteByte(SPIx,0x00);
- }
- SPIM_CSHigh(SPIx); //Spi cs release
- }
复制代码
《八》主函数:对比发送数据与接收数据有无对错,无限循环等待发送数据:
- /********************************************************************************************************
- **函数信息 :DataCompare(unsigned char *p1, unsigned char *p2,unsigned int count)
- **功能描述 :对比发送数据与接收数据有无对错
- **输入参数 :*p1,*p2,count
- **输出参数 :无
- ********************************************************************************************************/
- void DataCompare(unsigned char *p1, unsigned char *p2,unsigned int count)
- {
- unsigned int i;
-
- for(i=0;i
- {
- if(p1[i] != p2[i])
- printf("tx[%d]=0x%x,rx[%d]=0x%xrn",i,p1[i],i,p2[i]);
- }
- }
- /********************************************************************************************************
- **函数信息 :int main (void)
- **功能描述 :开机后,串口助手打印256页数据
- **输入参数 :
- **输出参数 :
- ********************************************************************************************************/
- int main(void)
- {
- #ifdef USE_IAR
- SystemInit();//IAR系统时钟初始化
- #endif
- //spi的测试
- //注意:改变SPI1或SP2,板子上对应短路帽也应改变
- delay_init(); //延时函数初始化
- uart_init(9600); //串口初始化为9600
- SPIM_Test(SPI2); //只需修改参数
- while(1) //无限循环
- {
-
- }
- }
复制代码
结束语:刚刚开始学习SPI难免会有一些不足,希望大家相互改正,相互学习,大家加油!
另外附上在另一块 开发板上面实现SPI 数据的LCD_2.4'TFT显示屏操作(由于MiniBord 32上面资源有限)。
2
|
|
|
|