原创 STC12的SPI通信调试通过了!

2011-7-18 00:15 10518 9 16 分类: MCU/ 嵌入式

从昨天晚上到今天下午,一直在做STC12SPI通信,终于有所收获。<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

最初我阅读了STC公司的中文datasheet,初步了解了SPI通信的原理和STC12SPI寄存器操作。STC公司在datasheet中给了一些例程,这对初学者来说有很大的帮助。在SPI通信中,单主机和单从机通信当然是最简单的的了。于是我决定从最简单的通信开始调。Datasheet中给了单机通信的汇编程序,51的汇编还是很简单的,虽然写得不熟,但看还是可以看懂的。为了通用性,我按照上面程序的思路用C语言来实现。

调试是51最大的缺陷,没有仿真芯片,就不知道你传输的是什么数据。所以就只有用串口送到上位机来显示。所以在做SPI之前,建议一定要熟悉串口的操作。

其实程序结构还是很清晰的。只是在调试的过程中,我发现了datasheet的几个错误。这些错误严重地影响了我的调试进度。最严重的错误就是SPI的中断使能位。

Datasheet上是这样说的:

;AUXR 特殊功能寄存器的 bit3 是 SPI 中断允许控制位 ESPI

;IE 特殊功能寄存器的 bit5 是ADC 和SPI 两个中断共享的总中断允许控制位  EADC_SPI

;要产生 SPI 中断, 需要 ESPI/EADC_SPI/EA 都为 1

所以我就写了AUXR = 0x08; EADC_SPI =1 ;EA =1;开启中断。

但是实验告诉我,这是不对的。我在始终无果的情况下,寻求了网络的支持。在网上看到有人这样使能中断:IE2 |=0x02; 

于是我查看了IE2的寄存器定义,发现IE2.1是SPI的中断使能位。

啊!STC的datasheet这是误人子弟呀!

还有就是有个寄存器SPSTAT,bit7,bit6,对他们写1意味着清零。这个也太不方便了!大家用的时候要注意点。

在看datasheet时,感受最深的就是,这个datasheet写的太乱了!

哎!客观地说,这一点真不得不向人家国外的公司学学!

程序已调试通过:

一、主机程序

/* SPI主机程序,无中断串口接收并用SPI发送---------------------------------------

*硬件:STC12C5A60S2,晶振22.1184MHZ

*程序名称:main.c

*作者    :UESTC-35

*日期    :7/17/2011

连接方式 :三线连接

        主单片机 I/O 口         I/O 口 从单片机

;

; +--------------+ MISO <-- 位流方向 MISO +--------------+

; | SPI             |<<-----------------|      SPI       |

; |8 位移位寄存器   |                   |8 位移位寄存器  |

; |                 |---------------->> | |              |

; +-------+------+ MOSI 位流方向 --> MOSI +-------^------+

; |                 |                   |                |

; |                 | SCLK         SCLK |                |

; +---------------------------->>------------------------+

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

#include "STC_NEW_8051.h"

#define SPIF  ( SPSTAT & 0x80 )  //查询SPIF是否置位,SPIF不能进行位操作

/*通信端口设置-------------------------------------------------------*/

sbit SCLK = P1^7;

sbit MISO = P1^6;

sbit MOSI = P1^5;

sbit SS   = P1^4;

unsigned char UART_SendData=0;

unsigned char UART_RecData=0;

unsigned char SPI_RecData=0;

void Init_System();

void Init_UART();

void Init_SPI();

unsigned char SPI_SendByte(unsigned char SPI_SendData);

void UART_SendByte(unsigned char UART_Send);

void main()

{

Init_System();

while(1)           

{

/*  查询UART接收信号 ----------------------------------*/

while(!RI);     //查看串口是否接收到数据

{

RI=0;               //当接收到数据后,清除接收中断标志

UART_RecData=SBUF;   //读入数据

UART_SendData=SPI_SendByte(UART_RecData);//将收到的数据由SPI发送出去,又接收回来 

UART_SendByte(UART_SendData);

}

}

}

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

*函数名:Init_System

*函数功能:系统初始化

*输入参数:无

*返回参数:无

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

void Init_System()

{

Init_UART();

Init_SPI();

}

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

*函数名:Init_UART

*函数功能:串口初始化,无中断方式

*输入参数:无

*返回参数:无

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

void Init_UART()

{

TMOD=0x20;//设置定时器1为工作方式2

TH1=0xfa; //波特率为9600,晶振为22.1184MHz

TL1=0xfa;

TR1=1;   //启动T1

REN=1;   //串行允许位

//  PCON=0x80;  //PCON寄存器的SMOD位置一,波特率提高一倍

SM0=0;

SM1=1;   //串行方式1

// ES=1;    //中断接收则开串口中断,查询接收则关闭此句

}

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

*函数名:Init_SPI

*函数功能:SPI初始化,SPI的工作方式,不使用SPI中断方式

*输入参数:无

*返回参数:无

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

void Init_SPI()

{

SPCTL = 0xfd;//CPU_CLK/16,时钟前沿为下降沿,后沿采样,主模式,最低位在前,SPI使能

SPSTAT = 0xc0;//SPDAT.7SPDAT.611,可以将中断标志清零。注意是写1才清零

}

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

*函数名:SPI_SendByte

*函数功能:SPI发射接收一体程序

*输入参数:SPI_SendData,经主机发给从机的数据

*返回参数:从机发给主机的数据

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

unsigned char SPI_SendByte(unsigned char SPI_SendData)

{

SPDAT= SPI_SendData; //将串口接收的数据装入SPI数据寄存器

while(!SPIF);//等待发送完毕

SPSTAT = 0xc0; //清除中断标志,和写冲突标志,注意是对应位写1才能清零

SPI_RecData = SPDAT;

return  SPI_RecData;

}

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

*函数名:UART_SendByte

*函数功能:串口发送

*输入参数:UART_Send

*返回参数:无

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

void UART_SendByte(unsigned char UART_Send)

{

TI = 0;            //清除发送SBUF空标志

  SBUF =  UART_Send; //写入SBUF

while (!TI);       //等待发送完毕

TI = 0;            //清除发送SBUF空标志

}

二、从机程序

/* SPI从机程序,中断接收并发送---------------------------------------

*硬件:STC12C5A60S2,晶振22.1184MHZ

*程序名称:main.c

*作者    :UESTC-35

*日期    :7/17/2011

连接方式 :三线连接

        主单片机 I/O 口         I/O 口 从单片机

;

; +--------------+ MISO <-- 位流方向 MISO +--------------+

; | SPI             |<<-----------------|      SPI       |

; |8 位移位寄存器   |                   |8 位移位寄存器  |

; |                 |---------------->> | |              |

; +-------+------+ MOSI 位流方向 --> MOSI +-------^------+

; |                 |                   |                |

; |                 | SCLK         SCLK |                |

; +---------------------------->>------------------------+

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

#include "STC_NEW_8051.h"

#define SPIF  ( SPSTAT & 0x80 )  //查询SPIF是否置位,SPIF不能进行位操作

/*通信端口设置-------------------------------------------------------*/

sbit SCLK = P1^7;

sbit MISO = P1^6;

sbit MOSI = P1^5;

sbit SS   = P1^4;

unsigned char SPI_Buffer=0;

void Init_SPI();

void main()

{

Init_SPI();

while(1);

}

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

*函数名:Init_SPI

*函数功能:SPI初始化,SPI的工作方式,开中断

*输入参数:无

*返回参数:无

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

void Init_SPI()

{

SPCTL = 0xed;//CPU_CLK/16,时钟前沿为下降沿,后沿采样,从模式,最低位在前,SPI使能

SPSTAT = 0xc0;//SPDAT.7SPDAT.611,可以将中断标志清零。注意是写1才清零

IE2 |= 0x02; //允许SPI中断

EA =1;        //开总中断

}

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

*函数名:SPI_Rec

*函数功能:SPI接收处理中断函数,将接收到的数发送出去

*输入参数:

*返回参数:

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

void SPI_Rec() interrupt 9   //SPIF = 1时,且EADC=1AUXR  = 0x08EA=1时将进入此中断

{

SPSTAT = 0xc0;      //清除中断标志,和写冲突标志,注意是对应位写1才能清零

SPI_Buffer = SPDAT;   

SPDAT= SPI_Buffer;           

}

文章评论7条评论)

登录后参与讨论

724791548_274370249 2015-1-21 09:57

HX模式:发奇数出现减一的现象没规律,偶数很正常; 文本模式:一直都出现减一现象,没规律!

用户1370477 2014-11-17 23:32

有原理图吗?

用户377235 2014-8-3 22:08

还是有错误啊,发回来的数据不准确

用户377235 2014-5-3 23:00

我也都同感,那个STC12的datasheet写的实在是太不好了,怪不得我上次使用SPI的时候怎么都不行呢,让我看了好久才知道个所以然,浪费我的时间啊!

用户920610 2012-12-16 13:23

很好

用户310885 2011-7-20 10:43

你调试过一根数据线的SDATA和两根线的MOSI、和MISO的连接吗?我看了一下AD7713的连接,不知道怎么回事返回值总是7F FF FF

飞言走笔 2011-7-19 11:25

写得很规范啊~~
相关推荐阅读
用户468654 2014-04-27 19:30
MinGW编译cpp文件
1.下载MinGW:http://ishare.iask.sina.com.cn/f/23746562.html?retcode=0 2.安装MinGW; 3.添加环境变量中的Path值等...
用户468654 2014-04-26 23:21
“mspdb80.dll无法找到”之解决之道
我在电脑是安装了VS2010。在用命令行调用cl.exe来编译cpp文件时遇到如题的问题。最后查了网络资料。解决方法如下: 1>直接从C:\Program Files\Microsoft...
用户468654 2014-04-25 10:31
[博客大赛]按键消抖之终极解决方案
1.按键消抖的原理                  图1.按键抖动示意图 我们平常所用的按键为机械弹性开关,由于触点的弹性作用,按键在闭合时不会马上稳定的接通,而是有...
用户468654 2014-04-25 10:31
[博客大赛]74HC595-串行并出驱动器
1.芯片原理图 2.时序图(Timing diagram) 3.根据时序图编写74hc595的verilog驱动程序 功能:根据输入的8bits数据d...
用户468654 2014-04-23 16:25
【转】FPGA学习的一些误区
作者:某人(摘自网络,不知道作者) 我常年担任多个有关FPGA学习研讨的QQ群管理员,长期以来很多新入群的菜鸟们总是在重复的问一些非常简单但是又让新手困惑不解的问题。作为管理员经常要给这些菜鸟们...
用户468654 2014-04-23 16:13
何為"阻抗匹配"?
  阻抗匹配(Impedance matching)是微波电子学里的一部分,主要用于传输线上,来达至所有高频的微波信号皆能传至负载点的目的,不会有信号反射回来源点,从而提升能源效益。   大体...
我要评论
7
9
关闭 站长推荐上一条 /2 下一条