你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM8S SPI单线通信中断程序

[复制链接]
磊元lystudio 发布时间:2015-10-6 21:47
/*
************************************************************************************************************
版权所有 (C),2010-2012,磊元科技有限公司
--------------------------------------------------------------------------------------------------
头文件名:        CommSpi.h
头文件名称:        串行外设接口(SPI接口)的头文件
程序版本:        1.0
文件功能:
    本文件是对串行外设接口(SPI接口)的源程序文件的编译控制声明、字符化常数和输入/输出引脚定义、
  全局常量声明、全局数据结构类型定义、全局变量声明和函数原型声明的头文件。
文件说明:
    1.本文件中的所有标识符定义前缀字母表示意义如下:
      c  ---------- 常量
      v  ---------- 变量
      g  ---------- 全局变量(Global)
      l  ---------- 局部变量(Local)
      uc ---------- 数据类型(Unsigned Char)
      ui ---------- 数据类型(Unsigned Word)
      p  ---------- 指针
      st ---------- 数据体
      pt ---------- 指向数据体的指针
            Pre --------- 条件编译预定义
            MFH --------- 宏定义硬件操作函数
            MFS --------- 宏定义软件操作和条件编译函数
            MFO --------- 宏定义其他函数
    2.注意:使用源程序的SPI接口接收和发送数据的函数之前,必须使能全局中断。
    3.注意:本文件仅实现1条时钟线(SCK)和1条双向数据线(MOSI)的单工通信方式。
主要函数列表:   
    ▲.在主函数中运行的函数:
      1.void UsartsInit(void)(USARTs端口和查询式串行通讯协议的初始化)
      2.void Rs422UsartsAskManage(void)(查询式RS422的通讯协议处理)
    ▲.中断请求服务函数:
      1.void usart1_txc_isr(void)(发送结束中断方式发送数据的中断服务程序)
      2.void usart1_rxc_isr(void)(接收结束中断方式接收数据的中断服务程序)
编译工具软件:      IAR Embedded Workbench for Atmel AVR 版本:5.20A 以上
链接文件:          1.SysCfg.h ------------ 系统运行结构定义配置的头文件。
编作者:            磊元
编制日期:          2009年4月8日
--------------------------------------------------------------------------------------------------
头文件版本历史:
2006年07月26日  〖磊元〗 -------- 版本 1.0 :原始版本(AVR)
2015年09月20日  〖磊元〗 -------- 版本 2.0 :扩增版本(STM8S)
************************************************************************************************************
*/
#ifndef _COMMSPI_H_                                       // “_COMMSPI_H_”条件编译开始
#define _COMMSPI_H_

/*==========================================================================================================
                     本头文件包括的其他头文件
建议:包含本项目的文件使用 #include "文件名.扩展名" ,
   包含系统库的文件使用 #include <文件名.扩展名> 。
==========================================================================================================*/
#include "SysCfg.h"                                       // 系统运行结构定义配置的头文件

#ifdef __cplusplus
extern "C" {                                              // 声明接在下面的指令为C程序编译系统
#endif

/*==========================================================================================================
                       条件编译控制声明
==========================================================================================================*/
//#ifndef PreGlobalCompilerHardware                         // 非“全局统一的条件编译控制和硬件定义”条件编译
#if defined(PreGlobalWithRedundantCode)
/*------------------------------------------------------------------------------------------------
声明程序指令使用冗余代码的条件定义:
------------------------------------------------------------------------------------------------*/
#define PreCommSpiWithRedundantCode                       // “使用冗余程序代码”条件定义
#endif
/*------------------------------------------------------------------------------------------------
声明串行外设接口(SPI接口)工作于哪种方式的条件定义:
注意:只能使用下面几个条件定义中的1个条件定义,不允许使用2个以上条件定义!!!
警告:此处的声明定义对于本源程序文件和其他源程序文件的编译有决定性作用,应慎重!
------------------------------------------------------------------------------------------------*/
#define PreCommSpiUseSingleMasterMode                          // “SPI接口工作于单主机方式”条件定义
//#define PreCommSpiUseSingleSlaveMode                      // “SPI接口工作于单从机方式”条件定义
//#define PreCommSpiUseMultiSlaveMode                            // “SPI接口工作于多从机方式”条件定义
#if   (   (defined(PreCommSpiUseSingleMasterMode) || defined(PreCommSpiUseSingleSlaveMode)) \
       && (defined(PreCommSpiUseSingleMasterMode) || defined(PreCommSpiUseMultiSlaveMode )) \
       && (defined(PreCommSpiUseSingleSlaveMode ) || defined(PreCommSpiUseMultiSlaveMode )) )
#error 错误:<声明串行外设接口(SPI接口)工作于哪种方式的条件定义>不允许使用2个以上条件定义!!!
#endif
/*------------------------------------------------------------------------------------------------
声明在应用中对于具有多个SPI接口的目标器件芯片,具体指定使用哪一个SPI端口的条件定义:
------------------------------------------------------------------------------------------------*/
#define PreCommSpiMultipleSpiEnable0                      // 使用SPI0接口的声明定义
//#endif                                                    // “PreGlobalCompilerHardware”

/*==========================================================================================================
               各类字符化常数和硬件设计相关的输入/输出引脚定义
==========================================================================================================*/
//#ifndef PreGlobalCompilerHardware                         // 非“全局统一的条件编译控制和硬件定义”条件编译
/*------------------------------------------------------------------------------------------------
SPI接口接口的输入/输出引脚定义:
注:下列这些定义与硬件设计相关,如需改变控制的输入/输出引脚仅在此重新定义即可。
0--A,1--B,2--C,3--D,4--E,5--F,6--G,7--H,8--I,9--J。
------------------------------------------------------------------------------------------------*/
#if   (defined(PreMcuIs__AtMega64)  || defined(PreMcuIs__AtMega64A)  || \
       defined(PreMcuIs__AtMega128) || defined(PreMcuIs__AtMega128A) || \
       defined(PreMcuIs__AtMega162) || defined(PreMcuIs__AtMega162A)    )
#elif (defined(PreMcuIs__STM8S207R6) || defined(PreMcuIs__STM8S208R6)  || \
       defined(PreMcuIs__STM8S207R8) || defined(PreMcuIs__STM8S208R8)  || \
       defined(PreMcuIs__STM8S207RB) || defined(PreMcuIs__STM8S208RB)     )
#ifdef _USE_STM8_FWLIB_                                   // “使用 STM8 FWLib 的库文件”条件编译开始
#define cSpi0Gpio             GPIOE
#define cSpi0SclPinBit        GPIO_PIN_1
#define cSpi0SdaPinBit        GPIO_PIN_2
#else                                                     // “_USE_STM8_FWLIB_”
#define cDdrSpi0Mosi         P2DDR                       // SPI0主出/ 从入引脚的数据方向寄存器
#define cOdrSpi0Mosi         P2ODR                       // SPI0主出/ 从入引脚的输出数据寄存器
#define cIdrSpi0Mosi         P2IDR                       // SPI0主出/ 从入引脚的输入数据寄存器
#define cPurSpi0Mosi         P2PUR                       // SPI0主出/ 从入引脚的上拉电阻寄存器(控制寄存器1)
#define cCirSpi0Mosi         P2CIR                       // SPI0主出/ 从入引脚的控制中断寄存器(控制寄存器2)
#define cPidSpi0Mosi         PI26                        // SPI0主出/ 从入引脚的引脚输入
#define cPodSpi0Mosi         PO26                        // SPI0主出/ 从入引脚的引脚输出
#define cBitSpi0Mosi         BIT6                        // SPI0主出/ 从入引脚的引脚数字索引
#define cDdrSpi0Miso         P2DDR                       // SPI0主入/ 从出引脚的数据方向寄存器
#define cOdrSpi0Miso         P2ODR                       // SPI0主入/ 从出引脚的输出数据寄存器
#define cIdrSpi0Miso         P2IDR                       // SPI0主入/ 从出引脚的输入数据寄存器
#define cPurSpi0Miso         P2PUR                       // SPI0主入/ 从出引脚的上拉电阻寄存器(控制寄存器1)
#define cCirSpi0Miso         P2CIR                       // SPI0主入/ 从出引脚的控制中断寄存器(控制寄存器2)
#define cPidSpi0Miso         PI27                        // SPI0主入/ 从出引脚的引脚输入
#define cPodSpi0Miso         PO27                        // SPI0主入/ 从出引脚的引脚输出
#define cBitSpi0Miso         BIT7                        // SPI0主入/ 从出引脚的引脚数字索引
#define cDdrSpi0Sclk         P2DDR                       // SPI0串行时钟引脚的数据方向寄存器
#define cOdrSpi0Sclk         P2ODR                       // SPI0串行时钟引脚的输出数据寄存器
#define cIdrSpi0Sclk         P2IDR                       // SPI0串行时钟引脚的输入数据寄存器
#define cPurSpi0Sclk         P2PUR                       // SPI0串行时钟引脚的上拉电阻寄存器(控制寄存器1)
#define cCirSpi0Sclk         P2CIR                       // SPI0串行时钟引脚的控制中断寄存器(控制寄存器2)
#define cPidSpi0Sclk         PI25                        // SPI0串行时钟引脚的引脚输入
#define cPodSpi0Sclk         PO25                        // SPI0串行时钟引脚的引脚输出
#define cBitSpi0Sclk         BIT5                        // SPI0串行时钟引脚的引脚数字索引
#define cDdrHt1381Cs         P3DDR                       // SPI0 HT1381 片选引脚的数据方向寄存器
#define cOdrHt1381Cs         P3ODR                       // SPI0 HT1381 片选引脚的输出数据寄存器
#define cIdrHt1381Cs         P3IDR                       // SPI0 HT1381 片选引脚的输入数据寄存器
#define cPurHt1381Cs         P3PUR                       // SPI0 HT1381 片选引脚的上拉电阻寄存器(控制寄存器1)
#define cCirHt1381Cs         P3CIR                       // SPI0 HT1381 片选引脚的控制中断寄存器(控制寄存器2)
#define cPidHt1381Cs         PI32                        // SPI0 HT1381 片选引脚的引脚输入
#define cPodHt1381Cs         PO32                        // SPI0 HT1381 片选引脚的引脚输出
#define cBitHt1381Cs         BIT2                        // SPI0 HT1381 片选引脚的引脚数字索引
#endif                                                    // “_USE_STM8_FWLIB_”
#else
#error 错误:没有定义SPI接口接口的输入引脚端口!!!
#endif                                                    // “PreMcuIs__......”
/*------------------------------------------------------------------------------------------------
SPI接口收发数据缓冲区大小字符化定义:
------------------------------------------------------------------------------------------------*/
#define cSpi0BufSize          0x12                        // SPI接口接收和发送数据缓冲区大小
//#endif                                                    // “PreGlobalCompilerHardware”
#ifdef PreCommSpiUseMultiSlaveMode                        // “SPI接口工作于多从机方式”条件编译结束
#define cSpi0RxBufSize        (cSpi0BufSize + 1)          // SPI接口接收数据缓冲区大小
#define cSpi0TxBufSize        (cSpi0BufSize + 2)          // SPI接口发送数据缓冲区大小
#else
#define cSpi0RxBufSize        (cSpi0BufSize + 0)          // SPI接口接收数据缓冲区大小
#define cSpi0TxBufSize        (cSpi0BufSize + 1)          // SPI接口发送数据缓冲区大小
#endif
//#ifndef PreGlobalCompilerHardware                         // 非“全局统一的条件编译控制和硬件定义”条件编译
#define cSpiErrorMax          0x10                        // SPI接口通讯收发作业最大发生错误次数值
#define cSpiOverSec           0x08                        // 通讯任务超时时间的最大秒数值(8s)
#define cSpiOverSpiOk         0x3A                        // 占用SPI接口超时时间的最大秒数值(58s)
//#endif                                                    // “PreGlobalCompilerHardware”
#if   (defined(_IAR_EW_AVR_))
/*--------------------------------------------------------------------------------------
SPI工作时的数据发送次序、时钟极性、时钟相位、SCK时钟速率配置定义:
“DORD” ----- 数据发送次序,置位=数据的LSB首先发送;清位=数据的MSB首先发送。
“CPOL” ----- 时钟极性,置位=空闲时SCK为高电平;清位=空闲时SCK为低电平。
“CPHA” ----- 时钟相位,置位=在SCK的结束沿采样;清位=在SCK的起始沿采样。
“SPR1、SPR0” ----- SCK时钟速率,00=1/4系统时钟频率;
                                     01=1/16系统时钟频率;
                                     10=1/64系统时钟频率;
                                     11=1/128系统时钟频率。
--------------------------------------------------------------------------------------*/
// SPI配置寄存器的位屏蔽值
#define cSpiSpicrCfgMask      ((1<<DORD)|            \
                               (1<<CPOL)|(1<<CPHA)|  \
                               (1<<SPR1)|(1<<SPR0))
#define cSpiSpicrConfig       ((1<<DORD)|            \
                               (0<<CPOL)|(0<<CPHA)|  \
                               (0<<SPR1)|(1<<SPR0))
#elif ((defined(_IAR_EW_MCS51_)) || (defined(_KEIL_UV_MCS51_)))
#elif (   defined(_IAR_EW_STM8_) \
       || defined(_COSMIC_STM8_) )                        // “......_STM8 编译器”条件编译开始
#ifdef _USE_STM8_FWLIB_                                   // “使用 STM8 FWLib 的库文件”条件编译开始
#else                                                     // “_USE_STM8_FWLIB_”
/*------------------------------------------------------------------------------------------------
SPI工作时的数据发送次序、时钟极性、时钟相位、SCK时钟速率配置定义:
“spiCPHA ” ----- 【DF】时钟相位控制位,0:数据锁存在第1个时钟沿,1:数据锁存在第2个时钟沿
“spiCPOL ” ----- 【LH】时钟空闲极性(仅主机模式有效),0:空闲时SCK为低电平,1:空闲时SCK为高电平。
“spiDORD ” ----- 【ML】发送数据次序,0:MSB首先发送,1:LSB首先发送
“spiCS2、spiCS1、spiCS0” ----- SCK时钟速率,000~11=1/2~1/256系统时钟频率。
------------------------------------------------------------------------------------------------*/
// SPI配置寄存器的位屏蔽值
#define cSpiSpicrCfgMask      ((u8)( ((1<<spiCPHA )|                             \
                                      (1<<spiCPOL )|                             \
                                      (1<<spiCS0  )|(1<<spiCS1  )|(1<<spiCS2  )| \
                                      (1<<spiDORD )                              )))
// SPI配置=数据锁存在第1个时钟沿、空闲时SCK为低电平、LSB首先发送
#define cSpiSpicrCfgDLL256    ((0<<spiCPHA )|                             \
                               (0<<spiCPOL )|                             \
                               (1<<spiCS0  )|(1<<spiCS1  )|(1<<spiCS2  )| \
                               (1<<spiDORD )                              )
#define cSpiSpicrCfgDLL016    ((0<<spiCPHA )|                             \
                               (0<<spiCPOL )|                             \
                               (1<<spiCS0  )|(1<<spiCS1  )|(0<<spiCS2  )| \
                               (1<<spiDORD )                              )
#define cSpiSpicrCfgDLL032    ((0<<spiCPHA )|                             \
                               (0<<spiCPOL )|                             \
                               (0<<spiCS0  )|(0<<spiCS1  )|(1<<spiCS2  )| \
                               (1<<spiDORD )                              )
// SPI配置=数据锁存在第2个时钟沿、空闲时SCK为低电平、LSB首先发送
#define cSpiSpicrCfgFLL256    ((1<<spiCPHA )|                             \
                               (0<<spiCPOL )|                             \
                               (1<<spiCS0  )|(1<<spiCS1  )|(1<<spiCS2  )| \
                               (1<<spiDORD )                              )
// SPI配置=数据数据锁存在第1个时钟沿、空闲时SCK为高电平、LSB首先发送
#define cSpiSpicrCfgDHL256    ((0<<spiCPHA )|                             \
                               (1<<spiCPOL )|                             \
                               (1<<spiCS0  )|(1<<spiCS1  )|(1<<spiCS2  )| \
                               (1<<spiDORD )                              )
// SPI配置=数据数据锁存在第2个时钟沿、空闲时SCK为高电平、LSB首先发送
#define cSpiSpicrCfgFHL032    ((1<<spiCPHA )|                             \
                               (1<<spiCPOL )|                             \
                               (0<<spiCS0  )|(0<<spiCS1  )|(1<<spiCS2  )| \
                               (1<<spiDORD )                              )
#endif                                                    // “_USE_STM8_FWLIB_”
#else
#error 错误:
#endif                                                    // “PreMcuIs__......”
/*------------------------------------------------------------------------------------------------
SPI接口CRC除数多项式值定义:
------------------------------------------------------------------------------------------------*/
#define cSpiCrcPolynomial     ((u8)( 0x8C))               // SPI的CRC除数多项式值


收藏 1 评论18 发布时间:2015-10-6 21:47

举报

18个回答
磊元lystudio 回答时间:2015-10-6 21:47:57

/*==========================================================================================================
                     全局变量数据结构类型定义
==========================================================================================================*/
/*------------------------------------------------------------------------------------------------
SPI接口通讯处理消息任务标志的全局数据结构类型定义:
------------------------------------------------------------------------------------------------*/
#define CommSpi0FlagDefaults                              \
                           {  CLEAR                      ,\
                              CLEAR                      ,\
                              CLEAR                      ,\
                              CLEAR                      ,\
                              CLEAR                      ,\
                              CLEAR                      ,\
                              CLEAR                      ,\
                              0  }                        // SPI接口0消息任务标志变量的默认初始化值
typedef struct
{
  unsigned char Busy        : 1;                          // SPI接口〖忙〗
  unsigned char RxOk        : 1;                          // 接收数据缓冲区己更新
  unsigned char RxOvf       : 1;                          // 接收数据缓冲区溢出
  unsigned char Error       : 1;                          // 通讯收发作业发生错误
  unsigned char Txd         : 1;                          // 正在进行发送数据作业
  unsigned char TxRdy       : 1;                          // 发送数据作业准备结束标志
  unsigned char OverS       : 1;                          // 通讯任务时间超时
  unsigned char SpiOk       : 1;                          // 占用SPI接口(其他程序使用)
} CommSpi0FlagBits;

/*------------------------------------------------------------------------------------------------
SPI接口通讯收发数据处理的全局数据结构类型定义:
------------------------------------------------------------------------------------------------*/
typedef struct
{
  unsigned char             TxSize                      ; // 每次发送数据个数大小
  unsigned char             TxCnt                       ; // 每次发送数据个数计数器
  unsigned char             TxBuf[cSpi0RxBufSize]       ; // 每次发送数据缓冲区

  unsigned char             RxSize                      ; // 每次接收数据个数大小
  unsigned char             RxCnt                       ; // 每次接收数据个数计数器
  unsigned char             RxBuf[cSpi0TxBufSize]       ; // 每次接收数据缓冲区

  unsigned char             OverS                       ; // 通讯任务时间超时的计时秒变量
  unsigned char             Cycle                       ; // 重新启动通讯收发作业圈数
  unsigned char             OverSpi                     ; // 占用SPI接口超时的计时秒变量(其他程序使用)
  unsigned char             StepSpi                     ; // SPI接口操作步骤(其他程序使用)
} CommSpi0DataStru;



/*==========================================================================================================
                        全局常量声明
==========================================================================================================*/



/*==========================================================================================================
                        全局变量声明
==========================================================================================================*/
/*------------------------------------------------------------------------------------------------
SPI接口通讯处理消息任务标志的全局变量声明:
------------------------------------------------------------------------------------------------*/
extern bdata CommSpi0FlagBits      gbitSpi0;

/*------------------------------------------------------------------------------------------------
SPI接口通讯收发数据处理的全局变量声明:
------------------------------------------------------------------------------------------------*/
extern xdata CommSpi0DataStru      gstvSpi0;



/*==========================================================================================================
                     源程序文件中的函数原型声明
==========================================================================================================*/
/*------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------*/
void CommSpiInit(void);

/*------------------------------------------------------------------------------------------------
函数名称:  查询SPI接口通讯发送数据作业工作状态
函数功能:  本函数用于检查SPI接口通讯发送数据作业工作状态的函数。
函数入口参数:没有
函数返回值: SPI接口收发器的工作状态,0(空闲状态)。
调用函数:  1.
备注:        1.
------------------------------------------------------------------------------------------------*/
unsigned char CommSpiBusBusy(void);

/*------------------------------------------------------------------------------------------------
函数名称:  设置SPI接口为标准/快速模式和占空比
函数功能:  本函数用于设置SPI接口为标准/快速模式和占空比操作的函数。
函数入口参数:Model ----------------- 标准/快速模式和占空比, ON(快速模式)/ OFF(标准模式)。
函数返回值: 没有
调用函数:  1.
备注:        1.
------------------------------------------------------------------------------------------------*/
void CommSpiBusModeDfLhMl(unsigned char Model);

#ifdef PreCommSpiUseSingleMasterMode                      // “SPI接口工作于单主机方式”的条件编译
/*------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------*/
#if cSpiTxBufSize < 256
void CommSpiTxWithData(unsigned char *pData, unsigned char Length);
#else
void CommSpiTxWithData(unsigned char *pData, unsigned int  Length);
#endif

/*------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------------*/
#if cSpiRxBufSize < 256
void CommSpiRxWithData(unsigned char Length);
#else
void CommSpiRxWithData(unsigned int  Length);
#endif

/*------------------------------------------------------------------------------------------------
函数名称:  SPI接口工作于单主机方式,使用中断进行接收和发送数据的中断服务程序。
函数功能:  本函数用于SPI接口工作于单主机方式,使用中断进行接收和发送数据的中断服务程序。
函数入口参数:gbitSpi.Rxd ------------- “正在进行接收数据作业”标志。
       gstvSpi.TxSize ---------- 每次发送数据个数大小变量。
       gstvSpi.TxCnt ----------- 每次发送数据个数计数器变量。
       gstvSpi.TxBuf[] --------- 每次发送数据缓冲区数组变量。
              gstvSpi.RxSize ---------- 每次接收数据个数大小变量。
函数返回值: 没有
函数出口参数:gbitSpi.Busy ------------ SPI接口〖忙〗,出口值=清位(可能)。
              gbitSpi.Error ----------- 通讯收发作业发生错误,出口值=置位(可能)。
              gucvSpiEvent ------------ SPI接口的状态码变量,出口值= 不确定。
       gstvSpi.TxCnt ----------- 每次发送数据个数计数器变量,出口值=gstvSpi.TxCnt。
       gstvSpi.ErrNum ---------- 通讯收发作业发生错误次数,出口值=不确定。
              gstvSpi.RxCnt ----------- 每次接收数据个数计数器变量,出口值=gstvSpi.RxSize。
              gstvSpi.RxBuf[] --------- 每次接收数据缓冲区变量,出口值=从SPI接口上接收到的数据。
调用函数:  1.
备注:        1.注意:本函数需在SPI接口中断请求的中断向量函数中调用。
                     在调用之前需对该中断向量进行初始化,使能该中断。
       2.全部完成通讯收发作业后,本函数将禁止SPI接口中断。
------------------------------------------------------------------------------------------------*/
#if   (   defined(_IAR_EW_AVR_)   \
       || defined(_IAR_EW_MCS51_) \
       || defined(_IAR_EW_STM8_)  )
#pragma vector = int_SPI_vector
INTERRUPT_KEY void CommSpi_isr(void);
#elif (defined(_KEIL_UV_MCS51_) )

#elif (   defined(_COSMIC_STM8_)  )
INTERRUPT_KEY void CommSpi_isr(void);
#else
void CommSpiIsr(void);
#endif                                                    // “_IAR_EW_......”
#endif                                                    // “SPI接口工作于单主机方式”条件编译结束

#if defined(PreCommSpiUseSingleSlaveMode) || defined(PreCommSpiUseMultiSlaveMode)
                                                          // “SPI接口工作于从机方式”的条件编译

#endif                                                    // “SPI接口工作于从机方式”条件编译结束


/*------------------------------------------------------------------------------------------------
函数名称:  设置“占用SPI接口”标志
函数功能:  本函数用于设置“占用SPI接口”标志的函数。
函数入口参数:没有
函数返回值: 没有
调用函数:  1.
备注:        1.
------------------------------------------------------------------------------------------------*/
void CommSpiSetSpiOk(void);

/*------------------------------------------------------------------------------------------------
函数名称:  清除“占用SPI接口”标志
函数功能:  本函数用于清除“占用SPI接口”标志的函数。
函数入口参数:没有
函数返回值: 没有
调用函数:  1.
备注:        1.
------------------------------------------------------------------------------------------------*/
void CommSpiClrSpiOk(void);

/*------------------------------------------------------------------------------------------------
函数功能:    本函数是SPI接口通信接收和发送作业不间断循环调用运行函数。
备注:        ▲.注意:本函数为消息任务队列函数,要在主函数中不间断循环调用运行。
              ▲.当SPI接口工作于从机方式时,SPI接口中断总是处于使能状态,以便
                  SPI接口处于随时接收数据状态。
------------------------------------------------------------------------------------------------*/
void CommSpiCircleFunc(void);



#ifdef __cplusplus
}                                                         // extern "C" 链接指示符作用域结束
#endif

#endif                                                    // “_COMMSPI_H_”条件编译结束


/*
************************************************************************************************************
                       本头文件到此结束
************************************************************************************************************
*/



磊元lystudio 回答时间:2015-10-6 21:48:27


/*
************************************************************************************************************
版权所有 (C),2010-2012,磊元科技有限公司
--------------------------------------------------------------------------------------------------
源程序文件名:   CommSpi.c
源程序名称:    串行外设接口(SPI接口)的源程序文件
程序版本:        1.0
程序功能:
    本文件是串行外设接口(SPI接口)使用中断方式接收和发送数据通信的源程序文件。
程序说明:
    1.注意:使用源程序的SPI接口接收和发送数据的函数之前,必须使能全局中断。
    2.注意:本文件仅实现1条时钟线(SCK)和1条双向数据线(MOSI)的单工通信方式。

主要函数列表:   
    ▲.在主函数中运行的函数:
      1.void Drv74595Init(void)
                (串行输出端口初始化)
    ▲.芯片74HC595输出驱动函数:
      1.void Drv74595Drive(const unsigned char *pParallel)
                (串入并出芯片74HC595输出驱动)
      2.void Drv74595Single(unsigned char Parallel, unsigned char Series)
                (串入并出芯片74HC595单个驱动)

链接子程序文件:  
    1.

编译工具软件:      IAR Embedded Workbench for Atmel AVR 版本:5.20A 以上

编作者:            磊元
编制日期:          2009年4月8日
--------------------------------------------------------------------------------------------------
适用器件芯片类型:  ATmega 系列( Atmel 公司生产的 8 位 RISC 单片机)
器件芯片时钟频率:  任意
存储器模式:        大存储器模式
外部扩展存储器大小:0【字节】
调用堆栈大小:      6 【字节】
数据堆栈大小:      4 【字节】
--------------------------------------------------------------------------------------------------
源程序版本历史:
2006年07月26日  〖磊元〗 -------- 版本 1.0 :原始版本(AVR)
2015年09月20日  〖磊元〗 -------- 版本 2.0 :扩增版本(STM8S)
************************************************************************************************************
*/

/*==========================================================================================================
                        调试开关声明
==========================================================================================================*/
//#define DEBUG


/*==========================================================================================================
                      本源程序包括的头文件
建议:包含本项目的文件使用 #include "文件名.扩展名" ,
   包含系统库的文件使用 #include <文件名.扩展名> 。
==========================================================================================================*/
#include "CommSpi.h"                                      // 本源程序的头文件
#include "DataMath.h"                                     // 算术运算及数制转换等数学算法的头文件
#include "RtcTimer.h"                                     // 应用内部定时器计时的实时时钟的头文件

#ifdef __cplusplus
extern "C" {                                              // 声明接在下面的指令为C程序编译系统
#endif



/*==========================================================================================================
                        全局常量定义
==========================================================================================================*/
#if   (defined(_IAR_EW_AVR_))

#elif ((defined(_IAR_EW_MCS51_)) || (defined(_KEIL_UV_MCS51_)))

#elif (   defined(_IAR_EW_STM8_) \
       || defined(_COSMIC_STM8_) )                        // “......_STM8 编译器”条件编译开始
#ifdef _USE_STM8_FWLIB_                                   // “使用 STM8 FWLib 的库文件”条件编译开始

#else                                                     // “_USE_STM8_FWLIB_”

#endif                                                    // “_USE_STM8_FWLIB_”
#else
#error 错误:
#endif                                                    // “PreMcuIs__......”


/*==========================================================================================================
                        全局变量定义
==========================================================================================================*/
/*------------------------------------------------------------------------------------------------
SPI接口通讯处理消息任务标志的全局变量定义:
------------------------------------------------------------------------------------------------*/
bdata CommSpi0FlagBits      gbitSpi0;

/*------------------------------------------------------------------------------------------------
SPI接口通讯收发数据处理的全局变量定义:
------------------------------------------------------------------------------------------------*/
xdata CommSpi0DataStru      gstvSpi0;



/*==========================================================================================================
                  本源程序文件内部使用的字符化常数定义
==========================================================================================================*/
#if   defined(PreCommSpiMultipleSpiEnable0)               // “使用SPI接口0”条件编译开始
#define cDdrSpiMosi           cDdrSpi0Mosi
#define cPurSpiMosi           cPurSpi0Mosi
#define cCirSpiMosi           cCirSpi0Mosi
#define cOdrSpiMosi           cOdrSpi0Mosi
#define cIdrSpiMosi           cIdrSpi0Mosi
#define cPidSpiMosi           cPidSpi0Mosi
#define cPodSpiMosi           cPodSpi0Mosi
#define cBitSpiMosi           cBitSpi0Mosi
#define cDdrSpiMiso           cDdrSpi0Miso
#define cPurSpiMiso           cPurSpi0Miso
#define cCirSpiMiso           cCirSpi0Miso
#define cOdrSpiMiso           cOdrSpi0Miso
#define cIdrSpiMiso           cIdrSpi0Miso
#define cPidSpiMiso           cPidSpi0Miso
#define cPodSpiMiso           cPodSpi0Miso
#define cBitSpiMiso           cBitSpi0Miso
#define cDdrSpiSclk           cDdrSpi0Sclk
#define cPurSpiSclk           cPurSpi0Sclk
#define cCirSpiSclk           cCirSpi0Sclk
#define cOdrSpiSclk           cOdrSpi0Sclk
#define cIdrSpiSclk           cIdrSpi0Sclk
#define cPidSpiSclk           cPidSpi0Sclk
#define cPodSpiSclk           cPodSpi0Sclk
#define cBitSpiSclk           cBitSpi0Sclk
#define cSpiRxBufSize         cSpi0RxBufSize
#define cSpiTxBufSize         cSpi0TxBufSize
#define CommSpiDataStru       CommSpi0DataStru
#define cSpiAddrNum           cSpi0AddrNum
#define gbitSpi               gbitSpi0
#define gstvSpi               gstvSpi0
#define gucvSpiEvent          gucvSpi0Event
#elif defined(PreCommSpiMultipleSpiEnableS)               // “使用SPI接口s”条件编译开始

#endif                                                    // “使用SPI接口......”



/*==========================================================================================================
                  本源程序文件内部使用的数据结构类型定义
==========================================================================================================*/



/*==========================================================================================================
                   本源程序文件内部使用的局部常量定义
==========================================================================================================*/



/*==========================================================================================================
                   本源程序文件内部使用的局部变量定义
==========================================================================================================*/



/*==========================================================================================================
                   本源程序文件内部使用的函数原型声明
==========================================================================================================*/
static void CommSpiBusAgain(void);



/*==========================================================================================================
                 本源程序文件内部使用的一些操作指令的宏定义
==========================================================================================================*/
/*------------------------------------------------------------------------------------------------
输入/输出端口和引脚宏定义:(注:下列这些定义用以简化宏函数参数字符。)
------------------------------------------------------------------------------------------------*/
#define MFH_PIN_CFG_INPU_SpiMosi                          MFH_PIN_CFG_INPU(cDdrSpiMosi, cPurSpiMosi, cCirSpiMosi, cOdrSpiMosi, cIdrSpiMosi, cBitSpiMosi)
#define MFH_PIN_CFG_INHZ_SpiMosi                          MFH_PIN_CFG_INHZ(cDdrSpiMosi, cPurSpiMosi, cCirSpiMosi, cOdrSpiMosi, cIdrSpiMosi, cBitSpiMosi)
#define MFH_PIN_CFG_OOUT_SpiMosi                          MFH_PIN_CFG_OOUT(cDdrSpiMosi, cPurSpiMosi, cCirSpiMosi, cOdrSpiMosi, cIdrSpiMosi, cBitSpiMosi)
#define MFH_PIN_CFG_OUTH_SpiMosi                          MFH_PIN_CFG_OUTH(cDdrSpiMosi, cPurSpiMosi, cCirSpiMosi, cOdrSpiMosi, cIdrSpiMosi, cBitSpiMosi)
#define MFH_PIN_CFG_OUTL_SpiMosi                          MFH_PIN_CFG_OUTL(cDdrSpiMosi, cPurSpiMosi, cCirSpiMosi, cOdrSpiMosi, cIdrSpiMosi, cBitSpiMosi)
#define MFH_PIN_OUT_SETH_SpiMosi                          MFH_PIN_OUT_SETH(cDdrSpiMosi, cPurSpiMosi, cCirSpiMosi, cOdrSpiMosi, cIdrSpiMosi, cBitSpiMosi)
#define MFH_PIN_OUT_CLRL_SpiMosi                          MFH_PIN_OUT_CLRL(cDdrSpiMosi, cPurSpiMosi, cCirSpiMosi, cOdrSpiMosi, cIdrSpiMosi, cBitSpiMosi)
#define MFH_PIN_IN_STATE_SpiMosi                          MFH_PIN_IN_STATE(cDdrSpiMosi, cPurSpiMosi, cCirSpiMosi, cOdrSpiMosi, cIdrSpiMosi, cBitSpiMosi)

#define MFH_PIN_CFG_INPU_SpiMiso                          MFH_PIN_CFG_INPU(cDdrSpiMiso, cPurSpiMiso, cCirSpiMiso, cOdrSpiMiso, cIdrSpiMiso, cBitSpiMiso)
#define MFH_PIN_CFG_INHZ_SpiMiso                          MFH_PIN_CFG_INHZ(cDdrSpiMiso, cPurSpiMiso, cCirSpiMiso, cOdrSpiMiso, cIdrSpiMiso, cBitSpiMiso)
#define MFH_PIN_CFG_OOUT_SpiMiso                          MFH_PIN_CFG_OOUT(cDdrSpiMiso, cPurSpiMiso, cCirSpiMiso, cOdrSpiMiso, cIdrSpiMiso, cBitSpiMiso)
#define MFH_PIN_CFG_OUTH_SpiMiso                          MFH_PIN_CFG_OUTH(cDdrSpiMiso, cPurSpiMiso, cCirSpiMiso, cOdrSpiMiso, cIdrSpiMiso, cBitSpiMiso)
#define MFH_PIN_CFG_OUTL_SpiMiso                          MFH_PIN_CFG_OUTL(cDdrSpiMiso, cPurSpiMiso, cCirSpiMiso, cOdrSpiMiso, cIdrSpiMiso, cBitSpiMiso)
#define MFH_PIN_OUT_SETH_SpiMiso                          MFH_PIN_OUT_SETH(cDdrSpiMiso, cPurSpiMiso, cCirSpiMiso, cOdrSpiMiso, cIdrSpiMiso, cBitSpiMiso)
#define MFH_PIN_OUT_CLRL_SpiMiso                          MFH_PIN_OUT_CLRL(cDdrSpiMiso, cPurSpiMiso, cCirSpiMiso, cOdrSpiMiso, cIdrSpiMiso, cBitSpiMiso)
#define MFH_PIN_IN_STATE_SpiMiso                          MFH_PIN_IN_STATE(cDdrSpiMiso, cPurSpiMiso, cCirSpiMiso, cOdrSpiMiso, cIdrSpiMiso, cBitSpiMiso)

#define MFH_PIN_CFG_INPU_SpiSclk                          MFH_PIN_CFG_INPU(cDdrSpiSclk, cPurSpiSclk, cCirSpiSclk, cOdrSpiSclk, cIdrSpiSclk, cBitSpiSclk)
#define MFH_PIN_CFG_INHZ_SpiSclk                          MFH_PIN_CFG_INHZ(cDdrSpiSclk, cPurSpiSclk, cCirSpiSclk, cOdrSpiSclk, cIdrSpiSclk, cBitSpiSclk)
#define MFH_PIN_CFG_OOUT_SpiSclk                          MFH_PIN_CFG_OOUT(cDdrSpiSclk, cPurSpiSclk, cCirSpiSclk, cOdrSpiSclk, cIdrSpiSclk, cBitSpiSclk)
#define MFH_PIN_CFG_OUTH_SpiSclk                          MFH_PIN_CFG_OUTH(cDdrSpiSclk, cPurSpiSclk, cCirSpiSclk, cOdrSpiSclk, cIdrSpiSclk, cBitSpiSclk)
#define MFH_PIN_CFG_OUTL_SpiSclk                          MFH_PIN_CFG_OUTL(cDdrSpiSclk, cPurSpiSclk, cCirSpiSclk, cOdrSpiSclk, cIdrSpiSclk, cBitSpiSclk)
#define MFH_PIN_OUT_SETH_SpiSclk                          MFH_PIN_OUT_SETH(cDdrSpiSclk, cPurSpiSclk, cCirSpiSclk, cOdrSpiSclk, cIdrSpiSclk, cBitSpiSclk)
#define MFH_PIN_OUT_CLRL_SpiSclk                          MFH_PIN_OUT_CLRL(cDdrSpiSclk, cPurSpiSclk, cCirSpiSclk, cOdrSpiSclk, cIdrSpiSclk, cBitSpiSclk)
#define MFH_PIN_IN_STATE_SpiSclk                          MFH_PIN_IN_STATE(cDdrSpiSclk, cPurSpiSclk, cCirSpiSclk, cOdrSpiSclk, cIdrSpiSclk, cBitSpiSclk)

#define MFH_PIN_CFG_INPU_Ht1381Cs                         MFH_PIN_CFG_INPU(cDdrHt1381Cs, cPurHt1381Cs, cCirHt1381Cs, cOdrHt1381Cs, cIdrHt1381Cs, cBitHt1381Cs)
#define MFH_PIN_CFG_INHZ_Ht1381Cs                         MFH_PIN_CFG_INHZ(cDdrHt1381Cs, cPurHt1381Cs, cCirHt1381Cs, cOdrHt1381Cs, cIdrHt1381Cs, cBitHt1381Cs)
#define MFH_PIN_CFG_OOUT_Ht1381Cs                         MFH_PIN_CFG_OOUT(cDdrHt1381Cs, cPurHt1381Cs, cCirHt1381Cs, cOdrHt1381Cs, cIdrHt1381Cs, cBitHt1381Cs)
#define MFH_PIN_CFG_OUTH_Ht1381Cs                         MFH_PIN_CFG_OUTH(cDdrHt1381Cs, cPurHt1381Cs, cCirHt1381Cs, cOdrHt1381Cs, cIdrHt1381Cs, cBitHt1381Cs)
#define MFH_PIN_CFG_OUTL_Ht1381Cs                         MFH_PIN_CFG_OUTL(cDdrHt1381Cs, cPurHt1381Cs, cCirHt1381Cs, cOdrHt1381Cs, cIdrHt1381Cs, cBitHt1381Cs)
#define MFH_PIN_OUT_SETH_Ht1381Cs                         MFH_PIN_OUT_SETH(cDdrHt1381Cs, cPurHt1381Cs, cCirHt1381Cs, cOdrHt1381Cs, cIdrHt1381Cs, cBitHt1381Cs)
#define MFH_PIN_OUT_CLRL_Ht1381Cs                         MFH_PIN_OUT_CLRL(cDdrHt1381Cs, cPurHt1381Cs, cCirHt1381Cs, cOdrHt1381Cs, cIdrHt1381Cs, cBitHt1381Cs)
#define MFH_PIN_IN_STATE_Ht1381Cs                         MFH_PIN_IN_STATE(cDdrHt1381Cs, cPurHt1381Cs, cCirHt1381Cs, cOdrHt1381Cs, cIdrHt1381Cs, cBitHt1381Cs)
磊元lystudio 回答时间:2015-10-6 21:48:46

/*------------------------------------------------------------------------------------------------
MFHSpiModSpiOnn( ) --------- 使能SPI接口模块
MFHSpiModSpiOff( ) --------- 禁止SPI接口模块
MFHSpiModClkOnn( ) --------- 使能SPI接口模块外设时钟
MFHSpiModClkOff( ) --------- 禁止SPI接口模块外设时钟
MFHSpiFlgAllClr( ) --------- 清0SPI接口全部中断标志位
MFHSpiIntAllClr( ) --------- 进入中断后,在中断句柄中,清0SPI接口全部中断标志位(在中断服务程序中)
MFHSpiIntErrChk( ) --------- 检查SPI接口错误中断状态值
MFHSpiIntWufChk( ) --------- 检查SPI接口唤醒中断状态值
MFHSpiIntAllOnn( ) --------- 使能SPI接口事件全部中断
MFHSpiIntTxdOnn( ) --------- 使能SPI接口发送中断、错误中断
MFHSpiIntRxdOnn( ) --------- 使能SPI接口接收中断、错误中断
MFHSpiIntAllOff( ) --------- 禁止SPI接口事件全部中断
------------------------------------------------------------------------------------------------*/
#if   (defined(_IAR_EW_AVR_))

#elif ((defined(_IAR_EW_MCS51_)) || (defined(_KEIL_UV_MCS51_)))

#elif (   defined(_IAR_EW_STM8_) \
       || defined(_COSMIC_STM8_) )                        // “......_STM8 编译器”条件编译开始
#ifdef _USE_STM8_FWLIB_                                   // “使用 STM8 FWLib 的库文件”条件编译开始

#else                                                     // “_USE_STM8_FWLIB_”
#define MFHSpiModSpiOnn( )            SPICR1                       |= (u8)( ((1<<spiEN   )))            ;
// 因为SPI接口模块被停止,无法控制SCK引脚电平
#define MFHSpiModSpiOff( )            SPICR1                       &= (u8)(~((1<<spiEN   )))            ; \
                                      if (SPICR1 & (u8)( ((1<<spiCPOL ))))                                \
                                      {                                                                   \
                                        MFH_PIN_OUT_SETH_SpiSclk;                                         \
                                      }                                                                   \
                                      else                                                                \
                                      {                                                                   \
                                        MFH_PIN_OUT_CLRL_SpiSclk;                                         \
                                      }
#define MFHSpiModClkOnn( )            CLKPECR1                     |= (u8)( ((1<<clkSPI  )))            ;
#define MFHSpiModClkOff( )            CLKPECR1                     &= (u8)(~((1<<clkSPI  )))            ;
#define MFHSpiFlgAllClr( )            SPISR                         = (u8)( ((0<<spiRXNE )|               \
                                                                             (0<<spiDRE  )|               \
                                                                             (0<<spiWUF  )|(0<<spiCRCEF)| \
                                                                             (0<<spiMODF )|(0<<spiOVF  )| \
                                                                             (0<<spiBSY  ) ));
#define MFHSpiIntAllClr( )            SPISR                         = (u8)( ((0<<spiRXNE )|               \
                                                                             (0<<spiDRE  )|               \
                                                                             (0<<spiWUF  )|(0<<spiCRCEF)| \
                                                                             (0<<spiMODF )|(0<<spiOVF  )| \
                                                                             (0<<spiBSY  ) ));
#define MFHSpiIntErrChk( )            SPISR & (u8)( ((1<<spiCRCEF)|               \
                                                     (1<<spiMODF )|(1<<spiOVF  )) )
#define MFHSpiIntWufChk( )            SPISR & (u8)( ((1<<spiWUF  )               ) )
#define MFHSpiIntAllOnn( )            SPIICR                        = (u8)( ((1<<spiWUIE )|(1<<spiERRIE)| \
                                                                             (1<<spiRXIE )|               \
                                                                             (1<<spiTXIE ) )              );
#define MFHSpiIntTxdOnn( )            SPIICR                        = (u8)( ((0<<spiWUIE )|(1<<spiERRIE)| \
                                                                             (0<<spiRXIE )|               \
                                                                             (1<<spiTXIE ) )              );
#define MFHSpiIntRxdOnn( )            SPIICR                        = (u8)( ((0<<spiWUIE )|(1<<spiERRIE)| \
                                                                             (1<<spiRXIE )|               \
                                                                             (0<<spiTXIE ) )              );
#define MFHSpiIntAllOff( )            SPIICR                        = (u8)( ((0<<spiWUIE )|(0<<spiERRIE)| \
                                                                             (0<<spiRXIE )|               \
                                                                             (0<<spiTXIE ) )              );
#endif                                                    // “_USE_STM8_FWLIB_”
#else
#error 错误:
#endif                                                    // “PreMcuIs__......”




/*
************************************************************************************************************
                       程序指令代码清单
************************************************************************************************************
*/
/*==========================================================================================================
函数名称:  串行外设接口(SPI接口),使用中断方式接收和发送数据通信的初始化
函数功能:  本函数用于串行外设接口(SPI接口),使用中断方式接收和发送数据通信的初始化操作。
函数入口参数:没有
函数返回值: 没有
调用函数:  1.
备注:        1.本函数仅在主函数中调用一次即可。
==========================================================================================================*/
void  CommSpiInit (void)
{
  CommSpiDataStru           *pSpi;                        // 指向SPI接口通讯收发数据处理变量的指针

  pSpi                      = &gstvSpi;                   // 取SPI接口通讯收发数据处理变量的首个地址
#ifdef PreCommSpiUseSingleMasterMode                      // “SPI接口工作于单主机方式”的条件编译
/*------------------------------------------------------------------------------------------------
“SPI接口工作于主机方式”的初始化操作。
------------------------------------------------------------------------------------------------*/
  MFH_PIN_CFG_OUTL_SpiMosi;                               // 设置SPI主出/ 从入引脚为输出引脚,并为L电平
  MFH_PIN_CFG_INPU_SpiMiso;                               // 设置SPI主入/ 从出引脚为输入引脚,并使能上拉电阻
  MFH_PIN_CFG_OUTL_SpiSclk;                               // 设置SPI串行时钟引脚为输出引脚,并确保为L电平(没有操作时)
  MFH_PIN_CFG_OUTL_Ht1381Cs;                              // 设置SPI HT1381 片选引脚为输出引脚,并为L电平(禁止)
#if   (defined(_IAR_EW_AVR_))
  SPCR = (0<<SPIE)|(1<<SPE)|                              // 禁止SPI中断、SPI使能、
         (1<<MSTR)|                                       // 主机模式、
         + cSpiSpicrConfig;                               // 数据次序、时钟极性、时钟相位、SCK速率。
  SPSR = 0x00;                                            // 清除SPI速度加倍
  temp = SPSR;                                            // 通过先读 SPSR,紧接着访问 SPDR 来清零SPI
  temp = SPDR;                                            // 中断标志和写冲突标志,使SPI空闲
  SFIOR &= ~(1<<PUD) ;                                    // 使能所有I/O端口的上拉电阻
#elif ((defined(_IAR_EW_MCS51_)) || (defined(_KEIL_UV_MCS51_)))

#elif (   defined(_IAR_EW_STM8_) \
       || defined(_COSMIC_STM8_) )                        // “......_STM8 编译器”条件编译开始
#ifdef _USE_STM8_FWLIB_                                   // “使用 STM8 FWLib 的库文件”条件编译开始
  I2C_Cmd(ENABLE);
  I2C_Init(cSpi0BaudRate, cSpiOwnAddr, I2C_DUTYCYCLE_2, I2C_ACK_CURR, I2C_ADDMODE_7BIT, (cSysCpuClk / 1000000UL));
  I2C_ITConfig((I2C_IT_ERR | I2C_IT_EVT | I2C_IT_BUF), ENABLE);
#else                                                     // “_USE_STM8_FWLIB_”
//  SpiDeInit( );
  SPICR1          = (u8)( ((1<<spiMSTR )|                 // 主/从机模式=主机,
                           (0<<spiEN   )|                 // 禁止SPI接口模块,
                           cSpiSpicrCfgDLL256));          // SPI配置=数据锁存在第1个时钟沿、空闲时SCK为低电平、LSB首先发送
  SPICR2          = (u8)( ((1<<spiSSI  )|(1<<spiSSM  )|   // 内部从设备=主模式,使能软件从机设备管理
                           (0<<spiRXTX )|                 // 只接收,0:全双工(同时发送和接收),1:输出禁止(只接收)
                           (0<<spiCRCTX)|(0<<spiCRCEN)|   // 下一个发送的数据来自Tx缓冲区,禁止硬件CRC计算
                           (0<<spiBDOE )|(1<<spiBDM  ) ));// 禁止双向模式下输出,使能单线双向数据模式
  SPICRCPR        = (u8)( cSpiCrcPolynomial);             // 置SPICRC多项式寄存器的数值
  SPIICR          = (u8)( ((0<<spiWUIE )|(0<<spiERRIE)|   // 禁止唤醒中断,禁止错误中断
                           (0<<spiRXIE )|                 // 禁止接收中断
                           (0<<spiTXIE) ));               // 禁止发送中断
#endif                                                    // “_USE_STM8_FWLIB_”
#else
#error 错误:
#endif                                                    // “PreMcuIs__......”
#endif                                                    // “PreCommSpiUseSingleMasterMode”
#if defined(PreCommSpiUseSingleSlaveMode) || defined(PreCommSpiUseMultiSlaveMode)
                                                          // “SPI接口工作于从机方式”的条件编译
/*------------------------------------------------------------------------------------------------
“SPI接口工作于从机方式”的初始化操作。
------------------------------------------------------------------------------------------------*/
  MFH_PIN_CFG_INHZ_SpiMosi;                               // 设置SPI主出/ 从入引脚为输入引脚,并为高阻输入态
  MFH_PIN_CFG_OUTL_SpiMiso;                               // 设置SPI主入/ 从出引脚为输出引脚,并为L电平
  MFH_PIN_CFG_INHZ_SpiSclk;                               // 设置SPI串行时钟引脚为输入引脚,并使能上拉电阻
  MFH_PIN_CFG_INPU_Ht1381Cs;                              // 设置SPI HT1381 片选引脚为输入引脚,并使能上拉电阻
#if   (defined(_IAR_EW_AVR_))
  SPCR = (1<<SPIE)|(1<<SPE)|                              // SPI中断使能、SPI使能、
         (0<<MSTR)|                                       // 从机模式、
         + cSpiSpicrConfig;                               // 数据次序、时钟极性、时钟相位、SCK速率。
  SPSR = 0x00;                                            // 清除SPI速度加倍
  temp = SPSR;                                            // 通过先读 SPSR,紧接着访问 SPDR 来清零SPI
  temp = SPDR;                                            // 中断标志和写冲突标志,使SPI空闲
#elif ((defined(_IAR_EW_MCS51_)) || (defined(_KEIL_UV_MCS51_)))

#elif (   defined(_IAR_EW_STM8_) \
       || defined(_COSMIC_STM8_) )                        // “......_STM8 编译器”条件编译开始
#ifdef _USE_STM8_FWLIB_                                   // “使用 STM8 FWLib 的库文件”条件编译开始
  I2C_Cmd(ENABLE);
  I2C_Init(cSpi0BaudRate, cSpiOwnAddr, I2C_DUTYCYCLE_2, I2C_ACK_CURR, I2C_ADDMODE_7BIT, (cSysCpuClk / 1000000UL));
  I2C_ITConfig((I2C_IT_ERR | I2C_IT_EVT | I2C_IT_BUF), ENABLE);
#else                                                     // “_USE_STM8_FWLIB_”
  SpiDeInit( );
  SPICR1          = (u8)( ((0<<spiMSTR )|                 // 主/从机模式=从机,
                           (0<<spiEN   )|                 // 禁止SPI接口模块,
                           cSpiSpicrCfgDLL256));          // SPI配置=数据锁存在第1个时钟沿、空闲时SCK为低电平、LSB首先发送
  SPICR2          = (u8)( ((1<<spiSSI  )|(1<<spiSSM  )|   // 内部从设备=主模式,使能软件从机设备管理
                           (0<<spiRXTX )|                 // 只接收,0:全双工(同时发送和接收),1:输出禁止(只接收)
                           (0<<spiCRCTX)|(0<<spiCRCEN)|   // 下一个发送的数据来自Tx缓冲区,禁止硬件CRC计算
                           (0<<spiBDOE )|(1<<spiBDM  ) ));// 禁止双向模式下输出,使能单线双向数据模式
  SPICRCPR        = (u8)( cSpiCrcPolynomial);             // 置SPICRC多项式寄存器的数值
  SPIICR          = (u8)( ((0<<spiWUIE )|(0<<spiERRIE)|   // 禁止唤醒中断,禁止错误中断
                           (1<<spiRXIE )|                 // 使能接收中断
                           (0<<spiTXIE) ));               // 禁止发送中断
#endif                                                    // “_USE_STM8_FWLIB_”
#else
#error 错误:
#endif                                                    // “PreMcuIs__......”
#endif                                                    // “PreCommSpiUse......SlaveMode”
/*------------------------------------------------------------------------------------------------
初始化各个标志位
------------------------------------------------------------------------------------------------*/
  gbitSpi.Busy              =  CLEAR;                     // 清除“SPI接口〖忙〗”标志
  gbitSpi.RxOk              =  CLEAR;                     // 清除“接收数据缓冲区己更新”标志
  gbitSpi.RxOvf             =  CLEAR;                     // 清除“接收数据缓冲区溢出”标志
  gbitSpi.Error             =  CLEAR;                     // 清除“通讯收发作业发生错误”标志
  gbitSpi.Txd               =  CLEAR;                     // 清除“正在进行发送数据作业”标志
  gbitSpi.TxRdy             =  CLEAR;                     // 清除“发送数据作业准备结束标志”标志
  gbitSpi.OverS             =  CLEAR;                     // 清除“通讯任务时间超时”标志
  gbitSpi.SpiOk             =  CLEAR;                     // 清除“占用SPI接口”标志

  // 初始化SPI接口通讯收发数据处理变量
  MemClearSram(pSpi, sizeof(CommSpiDataStru));
}
磊元lystudio 回答时间:2015-10-6 21:49:36


/*==========================================================================================================
函数名称:  查询SPI接口通讯发送数据作业工作状态
函数功能:  本函数用于检查SPI接口通讯发送数据作业工作状态的函数。
函数入口参数:没有
函数返回值: SPI接口收发器的工作状态,0(空闲状态)。
调用函数:  1.
备注:        1.
==========================================================================================================*/
unsigned char  CommSpiBusBusy (void)
{
#if   (defined(_IAR_EW_AVR_))
  return (SPCR & (1<<SPIE)) ;                             // 如果SPI中断使能则收发器处于忙碌状态
#elif ((defined(_IAR_EW_MCS51_)) || (defined(_KEIL_UV_MCS51_)))

#elif (   defined(_IAR_EW_STM8_) \
       || defined(_COSMIC_STM8_) )                        // “......_STM8 编译器”条件编译开始
#ifdef _USE_STM8_FWLIB_                                   // “使用 STM8 FWLib 的库文件”条件编译开始

#else                                                     // “_USE_STM8_FWLIB_”
  return (SPISR & (u8)( ((1<<spiBSY  ))) );               // 如果SPI接口忙则总线处于忙碌状态
#endif                                                    // “_USE_STM8_FWLIB_”
#else
#error 错误:
#endif                                                    // “PreMcuIs__......”
}

/*==========================================================================================================
函数名称:  设置SPI接口的数据发送次序、时钟极性、时钟相位
函数功能:  本函数用于设置SPI接口的数据发送次序、时钟极性、时钟相位的函数。
函数入口参数:Model ----------------- 数据发送次序、时钟极性、时钟相位的设置值。
函数返回值: 没有
调用函数:  1.
备注:        1.
==========================================================================================================*/
void  CommSpiBusModeDfLhMl (unsigned char Model)
{
#if   (defined(_IAR_EW_AVR_))

#elif ((defined(_IAR_EW_MCS51_)) || (defined(_KEIL_UV_MCS51_)))

#elif (   defined(_IAR_EW_STM8_) \
       || defined(_COSMIC_STM8_) )                        // “......_STM8 编译器”条件编译开始
#ifdef _USE_STM8_FWLIB_                                   // “使用 STM8 FWLib 的库文件”条件编译开始

#else                                                     // “_USE_STM8_FWLIB_”
  SPICR1         &= (u8)(~((1<<spiEN   )));               // 禁止SPI接口模块,
  SPICR1         &= (u8)(~(cSpiSpicrCfgMask));            // 屏蔽非SPI配置寄存器的位值
  SPICR1         |= (u8)( Model);                         // 导入SPI配置值
  // 因为SPI接口模块还未使能,无法控制SCK引脚电平
  if (SPICR1 & (u8)( ((1<<spiCPOL ))))                    // 如果空闲时SCK为高电平?
  {
    MFH_PIN_OUT_SETH_SpiSclk;                             // 确保SPI串行时钟引脚为H电平(没有操作时)
  }
  else
  {
    MFH_PIN_OUT_CLRL_SpiSclk;                             // 确保SPI串行时钟引脚为L电平(没有操作时)
  }
#endif                                                    // “_USE_STM8_FWLIB_”
#else
#error 错误:
#endif                                                    // “PreMcuIs__......”
}

#ifdef PreCommSpiUseSingleMasterMode                      // “SPI接口工作于单主机方式”的条件编译
/*==========================================================================================================
函数名称:  SPI接口工作于单主机方式,重新启动SPI接口前一个通讯收发作业
函数功能:  本函数用于SPI接口工作于单主机方式,重新启动SPI接口前一个通讯收发作业操作的函数。
函数入口参数:gbitSpi.Txd ------------- “正在进行发送数据作业”标志。
函数返回值: 没有
函数出口参数:gstvSpi.TxBuf[0] ------ 每次发送数据缓冲区数组变量,出口值=要发送的地址。
              gstvSpi.TxCnt --------- 每次发送数据个数计数器变量,出口值=0。
              gstvSpi.RxCnt --------- 每次接收数据个数计数器变量,出口值=0。
调用函数:  1.
备注:        1.调用本函数将SPI接口接收或者发送中断和错误中断请求。
==========================================================================================================*/
static void  CommSpiBusAgain (void)
{
#if cSpiTxBufSize < 256
  register unsigned char    i;                            // 循环变量
#else
  register unsigned int     i;
#endif
  unsigned char             temp;                         // 临时变量
  CommSpiDataStru           *pSpi;                        // 指向SPI接口通讯收发数据处理变量的指针

  pSpi                      = &gstvSpi;                   // 取SPI接口通讯收发数据处理变量的首个地址

  pSpi->TxCnt               =  0x01;                      // 每次发送数据计数器值清0
  pSpi->RxCnt               =  0x00;                      // SPI接口每次接收数据个数计数器清0
  if (gbitSpi.Txd == SET)                                 // SPI接口是否正在进行发送数据作业?
  {
    MFH_PIN_CFG_OUTL_SpiMosi;                             // 设置SPI主出/ 从入引脚为输出引脚,并为L电平
    MFHSpiFlgAllClr( );                                   // 清0SPI接口全部中断标志位
    temp                    =  SPIDR;                     // 清0SPI接口接收中断标志
    SPIDR                   =  pSpi->TxBuf[0];            // 从发送缓冲区中将发送数据写入到SPI接口
    MFHSpiIntTxdOnn( );                                   // 使能SPI接口发送中断、错误中断,唤醒中断
#if   (defined(_IAR_EW_AVR_))

#elif ((defined(_IAR_EW_MCS51_)) || (defined(_KEIL_UV_MCS51_)))

#elif (   defined(_IAR_EW_STM8_) \
       || defined(_COSMIC_STM8_) )                        // “......_STM8 编译器”条件编译开始
#ifdef _USE_STM8_FWLIB_                                   // “使用 STM8 FWLib 的库文件”条件编译开始

#else                                                     // “_USE_STM8_FWLIB_”
    SPICR2        = (u8)( ((1<<spiSSI  )|(1<<spiSSM  )|   // 内部从设备=主模式,使能软件从机设备管理
                           (0<<spiRXTX )|                 // 全双工,0:全双工(同时发送和接收),1:输出禁止(只接收)
                           (0<<spiCRCTX)|(0<<spiCRCEN)|   // 下一个发送的数据来自Tx缓冲区,禁止硬件CRC计算
                           (1<<spiBDOE )|(1<<spiBDM  ) ));// 使能双向模式下输出,使能单线双向数据模式
#endif                                                    // “_USE_STM8_FWLIB_”
#else
#error 错误:
#endif                                                    // “PreMcuIs__......
  }
  else
  {
    MFH_PIN_CFG_INHZ_SpiMosi;                             // 设置SPI主出/ 从入引脚为输入引脚,并为高阻输入态
    MFHSpiFlgAllClr( );                                   // 清0SPI接口全部中断标志位
    SPIDR                     =  temp;                    // 清0SPI接口发送中断标志
    temp                      =  SPIDR;                   // 清0SPI接口接收中断标志
    MFHSpiIntRxdOnn( );                                   // 使能SPI接口接收中断、错误中断,唤醒中断
#if   (defined(_IAR_EW_AVR_))

#elif ((defined(_IAR_EW_MCS51_)) || (defined(_KEIL_UV_MCS51_)))

#elif (   defined(_IAR_EW_STM8_) \
       || defined(_COSMIC_STM8_) )                        // “......_STM8 编译器”条件编译开始
#ifdef _USE_STM8_FWLIB_                                   // “使用 STM8 FWLib 的库文件”条件编译开始

#else                                                     // “_USE_STM8_FWLIB_”
    SPICR2        = (u8)( ((1<<spiSSI  )|(1<<spiSSM  )|   // 内部从设备=主模式,使能软件从机设备管理
                           (1<<spiRXTX )|                 // 只接收,0:全双工(同时发送和接收),1:输出禁止(只接收)
                           (0<<spiCRCTX)|(0<<spiCRCEN)|   // 下一个发送的数据来自Tx缓冲区,禁止硬件CRC计算
                           (0<<spiBDOE )|(1<<spiBDM  ) ));// 禁止双向模式下输出,使能单线双向数据模式
#endif                                                    // “_USE_STM8_FWLIB_”
#else
#error 错误:
#endif                                                    // “PreMcuIs__......”
  }
  MFHSpiModSpiOnn( );                                     // 使能SPI接口模块

  (void)temp;                                             // 用以阻止编译器产生[temp]未使用的警告消息
}
磊元lystudio 回答时间:2015-10-6 21:50:03

/*==========================================================================================================
函数名称:  启动SPI接口应用中断方式发送数据
函数功能:  本函数用于启动SPI接口使用中断方式,进行通讯发送数据作业操作的函数。
函数入口参数:*pData ------------------ 指向首个要发送数据在SRAM中的地址指针。
              Length ------------------ 要发送数据的数据总长度。
函数返回值: 没有
函数出口参数:gbitSpi.Busy ------------ SPI接口〖忙〗,出口值=置位。
              gbitSpi.Txd ------------- “正在进行发送数据作业”标志,出口值=置位。
       gstvSpi.TxSize ---------- 每次发送数据个数大小变量,出口值=Length。
       gstvSpi.TxCnt ----------- 每次发送数据个数计数器变量,出口值=0。
       gstvSpi.TxBuf[] --------- 每次发送数据缓冲区数组变量,出口值=要发送的数据。
       gstvSpi.Cycle ----------- 重新启动通讯收发作业圈数,出口值=0。
调用函数:  1.
备注:        1.注意:调用本函数之前,必须确定SPI接口在空闲状态。即必须先调用
            “unsigned char CommSpiBusBusy(void)”函数,来检查SPI接口的工作状态,
            只有SPI接口处于空闲状态,才允许调用本函数。
       2.调用本函数将SPI接口发送中断和错误中断请求。
==========================================================================================================*/
#if cSpiTxBufSize < 256
void  CommSpiTxWithData (unsigned char *pData, unsigned char Length)
#else
void  CommSpiTxWithData (unsigned char *pData, unsigned int  Length)
#endif
{
#if cSpiTxBufSize < 256
  register unsigned char    i;                            // 循环变量
#else
  register unsigned int     i;
#endif
  unsigned char             temp;                         // 临时变量
  CommSpiDataStru           *pSpi;                        // 指向SPI接口通讯收发数据处理变量的指针

  pSpi                      = &gstvSpi;                   // 取SPI接口通讯收发数据处理变量的首个地址

#ifdef PreCommSpiWithRedundantCode                        // “使用冗余程序代码”条件编译开始
  if (   (Length >= (cSpiTxBufSize - 0))
      || (Length == 0)                   )
  {
    return;
  }
#endif                                                    // “PreCommSpiWithRedundantCode”

//  while(CommSpiBusBusy( ));                               // 等待直到对TWI下一个收发作业准备就绪为止

  gbitSpi.Busy              =  SET;                       // 置“SPI接口〖忙〗”标志
  gbitSpi.Txd               =  SET;                       // 置“正在进行发送数据作业”标志
  gbitSpi.OverS             =  SET;                       // 置“通讯任务时间超时”标志
  pSpi->OverS               =  RtcGetSecByte(cSpiOverSec);// 启动通讯任务时间计时秒表
  MemCopySramToSram(pData, &pSpi->TxBuf[0], Length);      // 复制发送的数据序列到发送数据缓冲区中
  pSpi->TxSize              =  Length;                    // 置每次发送数据个数大小值
  pSpi->TxCnt               =  0x01;                      // 每次发送数据计数器值清0
  pSpi->Cycle               =  0x00;                      // 重新启动通讯收发作业圈数清0
  MFH_PIN_CFG_OUTL_SpiMosi;                               // 设置SPI主出/ 从入引脚为输出引脚,并为L电平
  MFHSpiFlgAllClr( );                                     // 清0SPI接口全部中断标志位
  temp                      =  SPIDR;                     // 清0SPI接口接收中断标志
  SPIDR                     =  pSpi->TxBuf[0];            // 从发送缓冲区中将发送数据写入到SPI接口
  MFHSpiIntTxdOnn( );                                     // 使能SPI接口发送中断、错误中断,唤醒中断
#if   (defined(_IAR_EW_AVR_))

#elif ((defined(_IAR_EW_MCS51_)) || (defined(_KEIL_UV_MCS51_)))

#elif (   defined(_IAR_EW_STM8_) \
       || defined(_COSMIC_STM8_) )                        // “......_STM8 编译器”条件编译开始
#ifdef _USE_STM8_FWLIB_                                   // “使用 STM8 FWLib 的库文件”条件编译开始

#else                                                     // “_USE_STM8_FWLIB_”
  SPICR2          = (u8)( ((1<<spiSSI  )|(1<<spiSSM  )|   // 内部从设备=主模式,使能软件从机设备管理
                           (0<<spiRXTX )|                 // 全双工,0:全双工(同时发送和接收),1:输出禁止(只接收)
                           (0<<spiCRCTX)|(0<<spiCRCEN)|   // 下一个发送的数据来自Tx缓冲区,禁止硬件CRC计算
                           (1<<spiBDOE )|(1<<spiBDM  ) ));// 使能双向模式下输出,使能单线双向数据模式
#endif                                                    // “_USE_STM8_FWLIB_”
#else
#error 错误:
#endif                                                    // “PreMcuIs__......”
  MFHSpiModSpiOnn( );                                     // 使能SPI接口模块

  (void)temp;                                             // 用以阻止编译器产生[temp]未使用的警告消息
}

/*==========================================================================================================
函数名称:  启动SPI接口应用中断方式接收数据
函数功能:  本函数用于启动SPI接口使用中断方式,进行通讯接收数据作业操作的函数。
函数入口参数:Object ------------------ 要接收数据的的目标设备地址值。
              Length ------------------ 要接收数据的数据总长度。
函数返回值: 没有
函数出口参数:gbitSpi.Busy ------------ SPI接口〖忙〗,出口值=置位。
              gbitSpi.Txd ------------- “正在进行发送数据作业”标志,出口值=清位。
       gstvSpi.TxSize ---------- 每次发送数据个数大小变量,出口值=Length。
       gstvSpi.TxCnt ----------- 每次发送数据个数计数器变量,出口值=0。
       gstvSpi.TxBuf[] --------- 每次发送数据缓冲区数组变量,出口值=全部为0x00。
       gstvSpi.Cycle ----------- 重新启动通讯收发作业圈数,出口值=0。
              gstvSpi.RxSize ---------- 每次接收数据个数大小变量,出口值=Length。
              gstvSpi.RxCnt ----------- 每次接收数据个数计数器变量,出口值=0。
调用函数:  1.
备注:        1.注意:调用本函数之前,必须确定SPI接口在空闲状态。即必须先调用
            “unsigned char CommSpiBusBusy(void)”函数,来检查SPI接口的工作状态,
            只有SPI接口处于空闲状态,才允许调用本函数。
       2.调用本函数将SPI接口接收中断和错误中断请求。
==========================================================================================================*/
#if cSpiRxBufSize < 256
void  CommSpiRxWithData (unsigned char Length)
#else
void  CommSpiRxWithData (unsigned int  Length)
#endif
{
#if cSpiRxBufSize < 256
  register unsigned char    i;                            // 循环变量
#else
  register unsigned int     i;
#endif
  unsigned char             temp;                         // 临时变量
  CommSpiDataStru           *pSpi;                        // 指向SPI接口通讯收发数据处理变量的指针

  pSpi                      = &gstvSpi;                   // 取SPI接口通讯收发数据处理变量的首个地址
#ifdef PreCommSpiWithRedundantCode                        // “使用冗余程序代码”条件编译开始
  if (   (Length > cSpiRxBufSize) )                       // 检查要接收数据的总个数是否超过缓冲区长度?
  {
    Length                  =  cSpiRxBufSize;             // 截断要接收数据的总个数
  }
#endif                                                    // “PreCommSpiWithRedundantCode”

//  while(CommSpiBusBusy( ));                               // 等待直到对TWI下一个收发作业准备就绪为止

  gbitSpi.Busy              =  SET;                       // 置“SPI接口〖忙〗”标志
  gbitSpi.Txd               =  CLEAR;                     // 清除“正在进行发送数据作业”标志
  gbitSpi.OverS             =  SET;                       // 置“通讯任务时间超时”标志
  pSpi->OverS               =  RtcGetSecByte(cSpiOverSec);// 启动通讯任务时间计时秒表
//  MemClearSram(pSpi->TxBuf, Length);                      // 复制发送的数据序列到发送数据缓冲区中
//  pSpi->TxSize              =  Length;                    // 置每次发送数据个数大小值
//  pSpi->TxCnt               =  0x00;                      // 每次发送数据计数器值清0
  pSpi->Cycle               =  0x00;                      // 重新启动通讯收发作业圈数清0

  pSpi->RxSize              =  Length;                    // 置SPI接口每次接收数据个数大小的值
  pSpi->RxCnt               =  0x00;                      // SPI接口每次接收数据个数计数器清0

  MFH_PIN_CFG_INHZ_SpiMosi;                               // 设置SPI主出/ 从入引脚为输入引脚,并为高阻输入态
  MFHSpiFlgAllClr( );                                     // 清0SPI接口全部中断标志位
  SPIDR                     =  temp;                      // 清0SPI接口发送中断标志
  temp                      =  SPIDR;                     // 清0SPI接口接收中断标志
  MFHSpiIntRxdOnn( );                                     // 使能SPI接口接收中断、错误中断,唤醒中断
#if   (defined(_IAR_EW_AVR_))

#elif ((defined(_IAR_EW_MCS51_)) || (defined(_KEIL_UV_MCS51_)))

#elif (   defined(_IAR_EW_STM8_) \
       || defined(_COSMIC_STM8_) )                        // “......_STM8 编译器”条件编译开始
#ifdef _USE_STM8_FWLIB_                                   // “使用 STM8 FWLib 的库文件”条件编译开始

#else                                                     // “_USE_STM8_FWLIB_”
  SPICR2          = (u8)( ((1<<spiSSI  )|(1<<spiSSM  )|   // 内部从设备=主模式,使能软件从机设备管理
                           (1<<spiRXTX )|                 // 只接收,0:全双工(同时发送和接收),1:输出禁止(只接收)
                           (0<<spiCRCTX)|(0<<spiCRCEN)|   // 下一个发送的数据来自Tx缓冲区,禁止硬件CRC计算
                           (0<<spiBDOE )|(1<<spiBDM  ) ));// 禁止双向模式下输出,使能单线双向数据模式
#endif                                                    // “_USE_STM8_FWLIB_”
#else
#error 错误:
#endif                                                    // “PreMcuIs__......”
  MFHSpiModSpiOnn( );                                     // 使能SPI接口模块

  (void)temp;                                             // 用以阻止编译器产生[temp]未使用的警告消息
}
磊元lystudio 回答时间:2015-10-6 21:50:21

/*==========================================================================================================
函数名称:  SPI接口工作于单主机方式,使用中断进行接收和发送数据的中断服务程序。
函数功能:  本函数用于SPI接口工作于单主机方式,使用中断进行接收和发送数据的中断服务程序。
函数入口参数:gbitSpi.Rxd ------------- “正在进行接收数据作业”标志。
       gstvSpi.TxSize ---------- 每次发送数据个数大小变量。
       gstvSpi.TxCnt ----------- 每次发送数据个数计数器变量。
       gstvSpi.TxBuf[] --------- 每次发送数据缓冲区数组变量。
              gstvSpi.RxSize ---------- 每次接收数据个数大小变量。
函数返回值: 没有
函数出口参数:gbitSpi.Busy ------------ SPI接口〖忙〗,出口值=清位(可能)。
              gbitSpi.Error ----------- 通讯收发作业发生错误,出口值=置位(可能)。
       gstvSpi.TxCnt ----------- 每次发送数据个数计数器变量,出口值=gstvSpi.TxCnt。
              gstvSpi.RxCnt ----------- 每次接收数据个数计数器变量,出口值=gstvSpi.RxSize。
              gstvSpi.RxBuf[] --------- 每次接收数据缓冲区变量,出口值=从SPI接口上接收到的数据。
调用函数:  1.
备注:        1.注意:本函数需在SPI接口中断请求的中断向量函数中调用。
                     在调用之前需对该中断向量进行初始化,使能该中断。
       2.全部完成通讯收发作业后,本函数将禁止SPI接口中断。
==========================================================================================================*/
#if   (   defined(_IAR_EW_AVR_)   \
       || defined(_IAR_EW_STM8_)  )
#pragma vector = int_SPI_vector
INTERRUPT_KEY void  CommSpi_isr (void)
#elif (defined(_KEIL_UV_MCS51_) )
void  CommSpi_isr (void) INTERRUPT_KEY int_SPI_vector using 0
#elif (   defined(_COSMIC_STM8_)  )
INTERRUPT_KEY void  CommSpi_isr (void)
#else
void CommSpiIsr(void);
#endif                                                    // “_IAR_EW_......”
#if   (defined(_IAR_EW_AVR_))

#elif ((defined(_IAR_EW_MCS51_)) || (defined(_KEIL_UV_MCS51_)))

#elif (   defined(_IAR_EW_STM8_) \
       || defined(_COSMIC_STM8_) )                        // “......_STM8 编译器”条件编译开始
{
#if ((cSpiTxBufSize < 256) && (cSpiRxBufSize < 256))
  register unsigned char    cnt;                          // USART每次发送数据个数计数器变量
#else
  register unsigned int     cnt;
#endif
  CommSpiDataStru           *pSpi;                        // 指向SPI接口通讯收发数据处理变量的指针

  if (MFHSpiIntErrChk( ))                                 // 检查SPI接口是否存在错误?
  {
    MFHSpiModSpiOff( );                                   // 禁止SPI接口模块
    MFHSpiIntAllClr( );                                   // 进入中断后,在中断句柄中,清0SPI接口全部中断标志位(在中断服务程序中)
    MFHSpiIntAllOff( );                                   // 禁止SPI接口事件全部中断
    gbitSpi.Error           =  SET;                       // 置“通讯收发作业发生错误”标志
  }
  else                                                    // SPI接口没有错误
  {
    pSpi                    = &gstvSpi;                   // 取SPI接口通讯收发数据处理变量的首个地址
    if (gbitSpi.Txd == SET)                               // SPI接口是否正在进行发送数据作业?
    {
      cnt                   =  pSpi->TxCnt;               // 取SPI接口每次发送数据个数计数器变量
      if (cnt >= pSpi->TxSize)                            // 检查是否己完成发送通讯任务的全部数据?
      {
        // 不能在中断中等待,直至发送通讯作业全部完成后,才可以禁止SPI接口模块
        gbitSpi.TxRdy       =  SET;                       // 置“发送数据作业准备结束标志”标志
        MFHSpiIntAllClr( );                               // 进入中断后,在中断句柄中,清0SPI接口全部中断标志位(在中断服务程序中)
        MFHSpiIntAllOff( );                               // 禁止SPI接口事件全部中断
      }
      else
      {
        SPIDR               =  pSpi->TxBuf[cnt];          // 从发送缓冲区中将发送数据写入到SPI接口
        cnt++;                                            // SPI接口每次发送数据个数计数器+1
        pSpi->TxCnt         =  cnt;                       // 返回SPI接口每次发送数据个数计数器值
        MFHSpiIntAllClr( );                               // 进入中断后,在中断句柄中,清0SPI接口全部中断标志位(在中断服务程序中)
      }
    }
    else
    {
      cnt                   =  pSpi->RxCnt;               // 取SPI接口每次接收数据个数计数器变量
      pSpi->RxBuf[cnt]      =  SPIDR;                     // 复制SPI接口读取到的字节到接收数据缓冲区中
      cnt++;                                              // SPI接口每次接收数据个数计数器+1
      pSpi->RxCnt           =  cnt;                       // 返回SPI接口每次接收数据个数计数器值
      MFHSpiIntAllClr( );                                 // 进入中断后,在中断句柄中,清0SPI接口全部中断标志位(在中断服务程序中)
      if      (cnt >= pSpi->RxSize)                       // 检查是否完成需要读取的数据长度?
      {
        MFHSpiModSpiOff( );                               // 禁止SPI接口模块
        MFHSpiIntAllOff( );                               // 禁止SPI接口事件全部中断
        gbitSpi.Busy        =  CLEAR;                     // 清除“SPI接口〖忙〗”标志
        gbitSpi.OverS       =  CLEAR;                     // 清除“通讯任务时间超时”标志
      }
    }
  }

  INTERRUPT_RETURN( );
}
#else
#error 错误:
#endif                                                    // “PreMcuIs__......”


/*==========================================================================================================
函数功能:    本函数是用于SPI接口工作于单主机方式,在SPI接口的前一次通讯收发作业发生
              失败时的处理操作函数。
§.本函数将在函数体中隐式调用下面这些相当于入口参数的全局变量和局部静态变量:
入口静态变量:sign:TRANS_ERROR --------------- SPI接口通讯收发作业发生错误标志变量。
              gstvSpi0.Cycle ----------------- SPI接口的重新启动通讯收发作业发生错误次
                                                数值变量。
§.本函数将在函数体中隐式修改下面这些相当于出口参数的全局变量和局部静态变量:
出口全局变量:sys_error_type:SYS_ERROR_TYPE_IS_GENERAL ----- 【普通】错误类型的位操作值
                                                标志,出口值=置位(仅在重新启动收发作业
                                                错误次数大于最大值时,才会置此变量值)。
              sys_error_value ----------------- 系统运行中产生各种错误类型的错误代码数值变量
                                                ,出口值=SYS_ERROR_COMM_I2CBUS(仅在重新启动
                                                收发作业错误次数大于最大值时,才会置此变量值)。
出口静态变量:sign:TRANS_ERROR --------------- SPI接口通讯收发作业发生错误标志,出口值=
                                                清位。
              gstvSpi0.Cycle ----------------- SPI接口的重新启动通讯收发作业发生错误次
                                                数值变量,出口值=不确定。
              gstvSpi0.ErrNum ------------------- SPI接口的通讯收发作业发生错误次数值变量,
                                                出口值= 0。
调用内部函数:①.unsigned char CommSpiBusBusy(void)
                  (检查SPI接口的总线状态函数)。
              ②.unsigned char I2C_Get_State_Info(void)
                  (读取SPI接口前一个操作的总线状态信息函数)。
              ③.void CommSpiBusAgain(void)
                  (重新启动SPI接口前一个通讯收发作业操作函数)。
备注:        ▲.注意:本函数为消息任务队列函数,要在主函数中不间断循环调用运行。
==========================================================================================================*/
#endif                                                    // “SPI接口工作于单主机方式”条件编译结束


#if defined(PreCommSpiUseSingleSlaveMode) || defined(PreCommSpiUseMultiSlaveMode)
                                                          // “SPI接口工作于从机方式”的条件编译

#endif                                                    // “SPI接口工作于从机方式”条件编译结束

/*==========================================================================================================
函数名称:  设置“占用SPI接口”标志
函数功能:  本函数用于设置“占用SPI接口”标志的函数。
函数入口参数:没有
函数返回值: 没有
调用函数:  1.
备注:        1.
==========================================================================================================*/
void  CommSpiSetSpiOk (void)
{
  gbitSpi.SpiOk       =  SET;                             // 置“占用SPI接口”标志
  gstvSpi.OverSpi     =  RtcGetSecByte(cSpiOverSpiOk);    // 启动占用SPI接口计时秒表
}

/*==========================================================================================================
函数名称:  清除“占用SPI接口”标志
函数功能:  本函数用于清除“占用SPI接口”标志的函数。
函数入口参数:没有
函数返回值: 没有
调用函数:  1.
备注:        1.
==========================================================================================================*/
void  CommSpiClrSpiOk (void)
{
  gbitSpi.SpiOk       =  CLEAR;                           // 清除“占用SPI接口”标志
  gstvSpi.StepSpi     =  0;                               // SPI接口操作步骤指向第一步
}

/*==========================================================================================================
函数功能:    本函数是SPI接口通信接收和发送作业不间断循环调用运行函数。
备注:        ▲.注意:本函数为消息任务队列函数,要在主函数中不间断循环调用运行。
              ▲.当SPI接口工作于从机方式时,SPI接口中断总是处于使能状态,以便
                  SPI接口处于随时接收数据状态。
==========================================================================================================*/
void  CommSpiCircleFunc (void)
{
#ifdef DEBUG
  unsigned char i;                           // 循环计数器变量
  unsigned char j;
  unsigned char hex_data[2];
  unsigned char *ptr;
#endif
  unsigned char              i;                           // 循环计数器变量
  CommSpiDataStru           *pSpi;                        // 指向SPI接口通讯收发数据处理变量的指针

  pSpi                      = &gstvSpi;                   // 取SPI接口通讯收发数据处理变量的首个地址
#ifdef PreCommSpiUseSingleMasterMode                      // “SPI接口工作于单主机方式”的条件编译
  if (   (gbitSpi.Error == SET)                           // 如果SPI接口通讯收发作业发生错误,
      && ( ! CommSpiBusBusy( )) )                         // 且SPI接口收发器处于空闲状态?
  {
    if (pSpi->Cycle > cSpiErrorMax)                       // 检查重新启动收发作业错误次数是否大于最大值?
    {
      pSpi->Cycle           =  0x00;                      // SPI接口的重新启动收发作业发生错误次数清0
      gbitSpi.Error         =  CLEAR;                     // 清除“通讯收发作业发生错误”标志
      gbitSpi.Busy          =  CLEAR;                     // 清除“SPI接口〖忙〗”标志
#ifdef _SYSTEM_ERROR_MANAGE_H_
      sys_error_type       |=  SYS_ERROR_TYPE_IS_GENERAL; // 置【普通】错误类型消息任务标志位
      sys_error_value       =  SYS_ERROR_COMM_SPIBUS    ; // 置“SPI接口通信收发作业”错误代码值
#endif
    }
    else
    {
      pSpi->Cycle++;                                      // SPI接口的重新启动收发作业发生错误次数值+1
      gbitSpi.Error         =  CLEAR;                     // 清除“通讯收发作业发生错误”标志
      CommSpiBusAgain( );                                 // 重新启动SPI接口前一个通讯收发作业操作
    }
  }
  // 等待,直至发送通讯作业全部完成处理后,才可以禁止SPI接口模块
  if (   (gbitSpi.TxRdy == SET)                           // 如果SPI接口发送数据作业准备结束标志,
      && ( ! CommSpiBusBusy( )) )                         // 且SPI接口收发器处于空闲状态?
  {
    MFHSpiModSpiOff( );                                   // 禁止SPI接口模块
    MFHSpiFlgAllClr( );                                   // 清0SPI接口全部中断标志位
    MFHSpiIntAllOff( );                                   // 禁止SPI接口事件全部中断
    gbitSpi.Busy            =  CLEAR;                     // 清除“SPI接口〖忙〗”标志
    gbitSpi.OverS           =  CLEAR;                     // 清除“通讯任务时间超时”标志
    gbitSpi.TxRdy           =  CLEAR;                     // 清除“发送数据作业准备结束标志”标志
    MFH_PIN_CFG_INHZ_SpiMosi;                             // 设置SPI主出/ 从入引脚为输入引脚,并为高阻输入态
  }
  // 通讯任务时间超时计时处理,用以处理SPI接口直处于“BUSY”状态。
  if (gbitSpi.OverS == SET)
  {
    if (RtcSecByteOverflow(pSpi->OverS))                  // 如果通讯任务时间计时秒表时间已溢出?
    {
      MFHSpiModClkOff( );                                 // 禁止SPI接口模块外设时钟
      DelayUs(10);
      MFHSpiModClkOnn( );                                 // 使能SPI接口模块外设时钟
      DelayUs(10);
      CommSpiInit( );                                     // 重新初始化SPI接口
    }
  }
  // 占用SPI接口超时计时处理,用以处理分时占用SPI接口。
  if (gbitSpi.SpiOk == SET)
  {
    if (RtcSecByteOverflow(pSpi->OverSpi))                // 如果通讯任务时间计时秒表时间已溢出?
    {
      gbitSpi.SpiOk         =  CLEAR;                     // 清除“占用SPI接口”标志
      gstvSpi.StepSpi       =  0;                         // SPI接口操作步骤指向第一步
    }
  }
#endif                                                    // “PreCommSpiUseSingleMasterMode”

#if defined(PreCommSpiUseSingleSlaveMode) || defined(PreCommSpiUseMultiSlaveMode)
                                                          // “SPI接口工作于从机方式”的条件编译

#endif                                                    // “PreCommSpiUse......SlaveMode”
}



#ifdef __cplusplus
}                                                         // extern "C" 链接指示符作用域结束
#endif


/*
************************************************************************************************************
                     本C语言源程序文件到此结束
************************************************************************************************************
*/
磊元lystudio 回答时间:2015-10-6 21:52:09
__IO_REG8_BIT(SPICR1    , 0x5200, __READ_WRITE, __BITS_SPI_CR1      );// SPI控制寄存器1
__IO_REG8_BIT(SPICR2    , 0x5201, __READ_WRITE, __BITS_SPI_CR2      );// SPI控制寄存器2
__IO_REG8_BIT(SPIICR    , 0x5202, __READ_WRITE, __BITS_SPI_ICR      );// SPI中断控制寄存器
__IO_REG8_BIT(SPISR     , 0x5203, __READ_WRITE, __BITS_SPI_SR       );// SPI状态寄存器
__IO_REG8    (SPIDR     , 0x5204, __READ_WRITE                      );// SPI数据寄存器(SPI_DR)
__IO_REG8    (SPICRCPR  , 0x5205, __READ_WRITE                      );// SPICRC多项式寄存器(SPI_CRCPR)
__IO_REG8    (SPICRCRR  , 0x5206, __READ                            );// SPI接收CRC寄存器(SPI_RXCRCR)
__IO_REG8    (SPICRCTR  , 0x5207, __READ                            );// SPI发送CRC寄存器(SPI_TXCRCR)

/*------------------------------------------------------------------------------------------------
         串行外围设备接口(SPI)
------------------------------------------------------------------------------------------------*/
// SPICR1(SPI_CR1)——— SPI控制寄存器1
#define spiCPHA               0                           // 时钟相位控制位,0:数据锁存在下降沿.,1:数据锁存在上升沿
#define spiCPOL               1                           // 时钟空闲极性(仅主机模式有效),0:空闲时SCK 为低电平,1:空闲时SCK 为高电平。
#define spiMSTR               2                           // 主/从机模式选择
#define spiCS0                3                           // 波特率预分频器选择控制位0
#define spiCS1                4                           // 波特率预分频器选择控制位1
#define spiCS2                5                           // 波特率预分频器选择控制位2
#define spiEN                 6                           // SPI启动/停止使能位
#define spiDORD               7                           // 发送数据次序(LSB/MSB字节先后顺序)

// SPICR2(SPI_CR2)——— SPI控制寄存器2
#define spiSSI                0                           // 内部从设备选择
#define spiSSM                1                           // 软件从机设备管理
#define spiRXTX               2                           // 只接收,0:全双工(同时发送和接收),1:输出禁止(只接收)
#define spiCRCTX              4                           // 接着发送CRC,0:下一个发送的数据来自Tx缓冲区,1:下一个发送的数据来自SPICRCTR。
#define spiCRCEN              5                           // 硬件CRC计算启动/停止使能位
#define spiBDOE               6                           // 双向模式下输出使能
#define spiBDM                7                           // 双向数据模式使能

// SPIICR(SPI_ICR)——— SPI中断控制寄存器
#define spiWUIE               4                           // 唤醒中断使能位
#define spiERRIE              5                           // 错误中断使能位
#define spiRXIE               6                           // 接收中断使能位
#define spiTXIE               7                           // 发送中断使能位

// SPISR(SPI_SR)——— SPI状态寄存器
#define spiRXNE               0                           // 接收缓冲区非空标志
#define spiDRE                1                           // 发送缓冲区空标志
#define spiWUF                3                           // 唤醒标志
#define spiCRCEF              4                           // CRC错误标志
#define spiMODF               5                           // 模式错误标志
#define spiOVF                6                           // 溢出标志位
#define spiBSY                7                           // 总线忙标志
lkl0305 回答时间:2015-10-6 22:28:53
多谢分享,好长哈 4.png 3.png 2.png 1.png 0.png 5.png
guiyi 回答时间:2015-10-7 14:13:45
好长。。。
12下一页

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

相似分享

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版