OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3797|回复: 1

STC15F4K60S4单片机 单主单从的SPI中断方式程序举例

[复制链接]

2

主题

3

帖子

0

精华

新手入门

积分
8
金钱
8
注册时间
2018-12-18
在线时间
0 小时
发表于 2018-12-18 15:56:03 | 显示全部楼层 |阅读模式
#include "reg51.h"

//#define MASTER                  //define:master undefine:slave
#define FOSC        11059200L
#define BAUD        (256 - FOSC / 32 / 115200)

typedef unsigned char BYTE;
typedef unsigned int WORD;
typedef unsigned long DWORD;

#define     URMD    0           //0:使用定时器2作为波特率发生器
                                //1:使用定时器1的模式0(16位自动重载模式)作为波特率发生器
                                //2:使用定时器1的模式2(8位自动重载模式)作为波特率发生器

sfr T2H   = 0xd6;               //定时器2高8位
sfr T2L   = 0xd7;               //定时器2低8位

sfr  AUXR       =   0x8e;       //辅助寄存器                              
sfr SPSTAT      =   0xcd;       //SPI状态寄存器                           
#define SPIF        0x80        //SPSTAT.7                                
#define WCOL        0x40        //SPSTAT.6                                
sfr SPCTL       =   0xce;       //SPI控制寄存器                           
#define SSIG        0x80        //SPCTL.7                                 
#define SPEN        0x40        //SPCTL.6                                 
#define DORD        0x20        //SPCTL.5                                 
#define MSTR        0x10        //SPCTL.4                                 
#define CPOL        0x08        //SPCTL.3                                 
#define CPHA        0x04        //SPCTL.2                                 
#define SPDHH       0x00        //CPU_CLK/4                              
#define SPDH        0x01        //CPU_CLK/16                              
#define SPDL        0x02        //CPU_CLK/64                              
#define SPDLL       0x03        //CPU_CLK/128                             
sfr SPDAT       =   0xcf;       //SPI数据寄存器                           
sbit SPISS      =   P1^1;       //SPI从机选择口, 连接到其它MCU的SS口
                                //当SPI为一主多从模式时,请使用主机的普通IO口连接到从机的SS口

sfr IE2         =   0xAF;       //中断控制寄存器2
#define ESPI        0x02        //IE2.1

sfr P1M1 = 0x91;    //PxM1.n,PxM0.n     =00--->Standard,    01--->push-pull
sfr P1M0 = 0x92;    //                  =10--->pure input,  11--->open drain
sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xB1;
sfr P3M0 = 0xB2;
sfr P4M1 = 0xB3;
sfr P4M0 = 0xB4;
sfr P5M1 = 0xC9;
sfr P5M0 = 0xCA;
sfr P6M1 = 0xCB;
sfr P6M0 = 0xCC;
sfr P7M1 = 0xE1;
sfr P7M0 = 0xE2;

void InitUart();
void InitSPI();
void SendUart(BYTE dat);        //发送数据到PC
BYTE RecvUart();                //从PC接收数据

///////////////////////////////////////////////////////////

void main()
{
    P0M0 = 0x00;
    P0M1 = 0x00;
    P1M0 = 0x00;
    P1M1 = 0x00;
    P2M0 = 0x00;
    P2M1 = 0x00;
    P3M0 = 0x00;
    P3M1 = 0x00;
    P4M0 = 0x00;
    P4M1 = 0x00;
    P5M0 = 0x00;
    P5M1 = 0x00;
    P6M0 = 0x00;
    P6M1 = 0x00;
    P7M0 = 0x00;
    P7M1 = 0x00;

    InitUart();                 //初始化串口   
    InitSPI();                  //初始化SPI   
    IE2 |= ESPI;
    EA = 1;

    while (1)
    {
#ifdef MASTER                   //对于主机(接收串口数据 并发送给从机,同时
                                //            从从即接收SPI数据并回传给PC)
        ACC = RecvUart();
        SPISS = 0;              //拉低从机的SS
        SPDAT = ACC;            //触发SPI发送数据
#endif
    }
}

///////////////////////////////////////////////////////////

void spi_isr() interrupt 9 using 1     //SPI中断服务程序 9 (004BH)
{
    SPSTAT = SPIF | WCOL;       //清除SPI状态位
#ifdef MASTER
    SPISS = 1;                  //拉高从机的SS
    SendUart(SPDAT);            //返回SPI数据
#else                           //对于从机(从主机接收SPI数据,同时
    SPDAT = SPDAT;              //           发送前一个SPI数据给主机)
#endif
}

///////////////////////////////////////////////////////////

void InitUart()
{
    SCON = 0x5a;                //设置串口为8位可变波特率
#if URMD == 0
    T2L = 0xd8;                 //设置波特率重装值
    T2H = 0xff;                 //115200 bps(65536-18432000/4/115200)
    AUXR = 0x14;                //T2为1T模式, 并启动定时器2
    AUXR |= 0x01;               //选择定时器2为串口1的波特率发生器
#elif URMD == 1
    AUXR = 0x40;                //定时器1为1T模式
    TMOD = 0x00;                //定时器1为模式0(16位自动重载)
    TL1 = 0xd8;                 //设置波特率重装值
    TH1 = 0xff;                 //115200 bps(65536-18432000/4/115200)
    TR1 = 1;                    //定时器1开始启动
#else
    TMOD = 0x20;                //设置定时器1为8位自动重装载模式
    AUXR = 0x40;                //定时器1为1T模式
    TH1 = TL1 = 0xfb;           //115200 bps(256 - 18432000/32/115200)
    TR1 = 1;
#endif
}

///////////////////////////////////////////////////////////

void InitSPI()
{
    SPDAT = 0;                  //初始化SPI数据
    SPSTAT = SPIF | WCOL;       //清除SPI状态位
#ifdef MASTER
    SPCTL = SPEN | MSTR;        //主机模式
#else
    SPCTL = SPEN;               //从机模式
#endif
}

///////////////////////////////////////////////////////////

void SendUart(BYTE dat)
{
    while (!TI);                //等待发送完成
    TI = 0;                     //清除发送标志
    SBUF = dat;                 //发送串口数据
}

///////////////////////////////////////////////////////////

BYTE RecvUart()
{
    while (!RI);                //迅雷种子等待串口数据接收完成
    RI = 0;                     //清除接收标志
    return SBUF;                //返回串口数据
}
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

2

主题

3

帖子

0

精华

新手入门

积分
8
金钱
8
注册时间
2018-12-18
在线时间
0 小时
 楼主| 发表于 2018-12-18 15:56:57 | 显示全部楼层
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-23 17:09

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表