ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

51单片机实战教程(21 同步串行外围通信接口SPI)

2021-12-26 09:05:50  阅读:164  来源: 互联网

标签:i8 21 void 器件 SPI BOOL str 通信接口


        SPI是Sysnchronous Serial Peripheral Interface 的缩写。SPI是一种全双工、高速、同步的通信总线,有两种操作模式:主模式和从模式。所谓全双工是指SPI主器件在向从器件发送数据的同时,也读取(或者接收从器件)的数据,从器件接收主器件数据的同时也向主器件发送数据。STC15W系列部分单片机内部集成了SPI总线接口。SPI总线在嵌入式系统中非常重要,如多片单片机间通信,SPI flash存储芯片的数据读写等。SPI总线由4条线组成,分别为:MOSI、MISO、SCLK、SS。下面分别对这4条线做下说明。

        MOSI(Master Out Slave In)主器件输出从器件输入,用于主器件到从器件的串行数据传输。当SPI器件做主器件时是信号输出线,当SPI器件做从器件时是信号输入线。在时钟的前半周期,主机将数据放在MOSI信号线上,从机在该边界处获取数据。

        MISO(Master In Slave Out):主器件的输入,从器件的输出,用于实现从器件到主器件的数据传输。当SPI器件做主器件时是信号输入线,当SPI器件做从器件时是信号输出入线。SPI规范中一个主机可以连接多个从机,主机的MISO线会连接到多个从机上,当主机与其中一个从机通信时,因将其他从机MISO脚驱动置为高阻状态(将SS脚拉高)。

        SCLK(SPI Clock):串行时钟信号,用于同步主器件和从器件之间在MOSI及MISO线上的数据传输。当主器件启动一次数据传输时,自动产生8个SCLK时钟周期信号给从机。在SCLK的每个跳变处(上升沿或下降沿)移处一位数据。因此,一次数据传输可以传输一个字节的数据。

        SS(Slave Select):从机选择信号(线),可以说是片选(CS)信号,从机选择信号是一个输入信号,低电平有效,故STC15单片机说明书中,在SS上加了一横线。当器件的SS脚未必设置成忽略时,当SPI器件的SS脚被拉低时,该机就被设置成从器件。

       STC15系列单片机SPI的功能框图如下:

    STC15系列单片机的SPI相关特殊功能寄存器如下:

 有了对SPI寄存器的了解,就可以来编写SPI的库函数。建两个文件分别以stcspior.h, stcspi.c存入C51 Template文件夹下Library文件夹中。完成后的头文件如下:

/*stcspi.h
  Designed by Bill Liu
  Version 0.0 
  Modified last by Bill Liu on 12/26/2021
*/

#ifndef __STCSPI_H__
#define __STCSPI_H__

#include "mtype.h"
#include "stc15w4k.h"
#include "stcint.h"
#include "delay.h"

extern FSYSCLOCK FSCLK; //FSCLK was defined in mian.h, FSYSCLOCK was defined in mtype.h

//***********************************************************
typedef enum
{

	SPI_PG1 = 0, //P1.2/SS,P1.3/MOSI,/P1.4/MISO,P1.5SCLK
	SPI_PG2,     //P2.4/SS_2,P2.3/MOSI_2,P2.2/MISO_2,P2.1/SCLK_2
	SPI_PG3      //5.4/SS_3,P4.0/MOSI_3,P4.1/MISO_3,P4.3/SCLK_3
}SPI_PINGROUP; 

//***********************************************************
typedef enum
{
	SPI_FCLK0 = 0, //cpu fclk/4
	SPI_FCLK1, //cpu fclk/8
	SPI_FCLK2, //cpu fclk/16
	SPI_FCLK3, //cpu fclk/32
}SPI_FCLK; //frequency of SPI clk

/***********************************************************
Function: SPI_PinSel(SPI_PINGROUP mSel);
Return value: void
Discription: configure SPI pins
Example:
	SPI_PinSel(SPI_PG1); //P1.2/SS,P1.3/MOSI,/P1.4/MISO,P1.5SCLK
***********************************************************************/
void SPI_PinSel(SPI_PINGROUP mSel);

/***********************************************************
Function: SPI_ClkSel(SPI_FCLK mSel);
Return value: void
Discription: configure SPI clock
Example:
	SPI_PinSel(SPI_FCLK0); //cpu fclk/4
***********************************************************************/
void SPI_ClkSel(SPI_FCLK mSel);

/***********************************************************
Function: SPI_SSPin(BOOL mEnable);
Return value: void
Discription: configure SPI SS pin enable/disable
Example:
	SPI_SSPin(0); //SPI SS pin is ignored
***********************************************************************/
void SPI_SSPin(BOOL mEnable);

/***********************************************************
Function: SPI_Enable(BOOL mEnable);
Return value: void
Discription: configure SPI enable/disable
Example:
  SPI_Enable(1); //SPI enable
	SPI_Enable(0); //SPI disable
***********************************************************************/
void SPI_Enable(BOOL mEnable);

/***********************************************************
Function: SPI_DataOrder(BOOL fLSB);
Return value: void
Discription: configure transmit data order for SPI transmitting 
Example:
  SPI_DataOrder(1); //begin from LSB 
***********************************************************************/
void SPI_DataOrder(BOOL fLSB);

/***********************************************************
Function: SPI_MasterEnable(BOOL bMaster);
Return value: void
Discription: configure SPI device master/slave 
Example:
  SPI_MasterEnable(1); //set this device as master
***********************************************************************/
void SPI_MasterEnable(BOOL bMaster);

/***********************************************************
Function: SPI_IdleClkPol(BOOL bHigh);
Return value: void
Discription: configure SPI idle clk voltage level
Example:
	SPI_IdleClkPol(1); //SPI idle clk voltage level: high
***********************************************************************/
void SPI_IdleClkPol(BOOL bHigh);

/***********************************************************
Function: SPI_ClkPhase(BOOL bSOT); // SOT:sampling on the trailing edge
Return value: void
Discription: configure SPI  clk phase, sampling on the trailing edge/sampling on the leading edge
Example:
	SPI_ClkPhase(1); //sampling on the trailing edge
***********************************************************************/
void SPI_ClkPhase(BOOL bSOT);

/***********************************************************
Function: SPI_Init(BOOL mSSable,SPI_PINGROUP mSel, SPI_FCLK mSelClk, BOOL bMaster); 
Return value: void
Discription: configure SPI  device
Example:
	SPI_Init(1, SPI_PG1, SPI_FCLK0, 1);//SS pin enable, SPI pin select group 0, SPI clock, mcu clock/4, master device
***********************************************************************/
void SPI_Init(BOOL mSSable,SPI_PINGROUP mSel, SPI_FCLK mSelClk, BOOL bMaster); 

/***********************************************************
Function: SPI_SendChar(i8 mdata); 
Return value: void
Discription: master SPI device send  char
Example:
	SPI_SendChar(123); 
***********************************************************************/
void SPI_SendChar(i8 mdata); 

/***********************************************************
Function: SPI_SendStringAndEof(i8* str); 
Return value: void
Discription: master SPI device transmit string and end of flag
Example:
	SPI_SendStringAndEof("Hello world!"); 
***********************************************************************/
void SPI_SendStringAndEof(i8* str); 

/***********************************************************
Function: SPI_RecChar(i8* mdata); 
Return value: char
Discription: SPI slave device receive  char
Example:
	char tem;
	SPI_RecChar(&tem); 
***********************************************************************/
char SPI_RecChar(i8* mdata); 

/***********************************************************
Function: SPI_SendAndRecChar(i8 mdata);
Return value: void
Discription: master SPI device transmit char and receive char
Example:
	char tem = SPI_SendAndRecChar(i8 mdata); 
***********************************************************************/
char SPI_SendAndRecChar(i8 mdata);

/***********************************************************
Function: SPI_RecStringTillEof(i8* str); 
Return value: void
Discription: SPI slave device receive  string till end of flag
Example:
	char str[20];
	SPI_RecStringTillEof(str); 
***********************************************************************/
void SPI_RecStringTillEof(i8* str); 



#endif

       在写源代码时需要特别注意的是要清除SPSTAT中的SPIF及WCOL需写入1,有点类似STM32部分寄存器的操作,前面在写中断库函数时,就没注意到这点,现已修改过来。完成后的源代码如下:

/*stcspi.c
  Designed by Bill Liu
  Version 0.0 
  Modified last by Bill Liu on 12/26/2021
*/

#include "stcspi.h"

//***********************************************************
void SPI_PinSel(SPI_PINGROUP mSel)
{
	ui8 tem = P_SW1;
	SetBits(&tem,3,2,mSel);
	P_SW1 = tem;
}
//End of SPI_PinSel(SPI_PINGROUP mSel)

//***********************************************************
void SPI_ClkSel(SPI_FCLK mSel)
{
  ui8 tem = SPCTL;
	SetBits(&tem,1,0,mSel);
	SPCTL = tem; 
}
//End of SPI_ClkSel(SPI_FCLK mSel)

//***********************************************************
void SPI_SSPin(BOOL mEnable)
{
   if(mEnable)
		 SPCTL &= 0x7F;
	 else
		 SPCTL |= 0x80;
}
//End of SPI_SSPin(BOOL mEnable)

//***********************************************************
void SPI_Enable(BOOL mEnable)
{
  if(mEnable)
		SPCTL |= 0x40;
	else
		SPCTL &= 0xBF;
}
//End of SPI_Enable(BOOL mEnable)

//***********************************************************
void SPI_DataOrder(BOOL fLSB)
{
	if(fLSB)
		SPCTL |= 0x20;
	else
		SPCTL &= 0xDF;
}
//End of SPI_DataOrder(BOOL fMSB)

//***********************************************************
void SPI_MasterEnable(BOOL bMaster)
{
	if(bMaster)
		SPCTL |= 0x10;
	else
		SPCTL &= 0xEF;
}
//End of SPI_MasterEnable(BOOL bMaster)

//***********************************************************
void SPI_IdleClkPol(BOOL bHigh)
{
	if(bHigh)
		SPCTL |= 0x08;
	else
		SPCTL &= 0xF7;
}
//End of SPI_IdleClkPol(BOOL bHigh)

//***********************************************************
void SPI_ClkPhase(BOOL bSOT)
{
  if(bSOT) //sampling on the trailing edge
		SPCTL |= 0x04;
	else
		SPCTL &= 0xFB;
}
//End of SPI_ClkPhase(BOOL bSOT)

//***********************************************************
void SPI_Init(BOOL mSSable,SPI_PINGROUP mSel, SPI_FCLK mSelClk, BOOL bMaster)
{
		SPI_SSPin(mSSable);
		SPI_PinSel(mSel);
		SPI_ClkSel(mSelClk);
	  SPI_MasterEnable(bMaster);
}
//End of SPI_Init(BOOL mSSable,SPI_PINGROUP mSel, SPI_FCLK mSelClk, BOOL bMaster)

//***********************************************************
void SPI_SendChar(i8 mdata)
{
	SPI_Enable(1);
  STC_ClearSPIFlag();//clear flag
	SPDAT = mdata;
	while(!(SPSTAT & 0x80));
	SPSTAT = 0xFF; //clear flag
}	
//End of SPI_SendChar(i8 mdata)

//***********************************************************
void SPI_SendStringAndEof(i8* str)
{ ui8 i = 0;
	while(str[i] != 0)
	{
		SPI_SendChar(str[i]);
		Delayxus(2,FSCLK);
		i++;
	}
  SPI_SendChar(0xFF);
}
//End of SPI_SendStringAndEof(i8* str)

//***********************************************************
char SPI_RecChar(i8* mdata)
{ 
	SPI_Enable(1);
  STC_ClearSPIFlag();//clear flag
	while(!(SPSTAT & 0x80));
	STC_ClearSPIFlag();//clear flag
	*mdata = SPDAT;
	return *mdata;
}
//End of SPI_RecChar(i8* mdata)

//***********************************************************
char SPI_SendAndRecChar(i8 mdata)
{
	i8 tem;
	SPI_Enable(1);
  STC_ClearSPIFlag();//clear flag
	SPDAT = mdata;
	while(!(SPSTAT & 0x80));
	STC_ClearSPIFlag();//clear flag
	tem = SPDAT;
	return tem;
}
//End of SPI_SendAndRecChar(i8 mdata)

//***********************************************************
void SPI_RecStringTillEof(i8* str)
{
  ui8 i = 0;
  memset(str, 0, strlen(str));
  SPI_Enable(1);
  STC_ClearSPIFlag();//clear flag
  while(str[i] != 0xFF)
  {
    STC_ClearSPIFlag();//clear flag
    while(!(SPSTAT & 0x80));
    STC_ClearSPIFlag();//clear flag
    str[i] = SPDAT;
    i++;
  }
  str[i] = 0;
}
//SPI_RecStringTillEof(i8* str)

此处不做验证示例,以后在项目实战中再做说明。本文代码及相关库文件已打包上传到CSDN,如需离线查看,可去下载,文件名为STC15 SPI Library Source Code.rar。

标签:i8,21,void,器件,SPI,BOOL,str,通信接口
来源: https://blog.csdn.net/billliu66/article/details/122148180

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有