为了学习使用SPI外设中的SS信号,做了以下三组测试。
方式一、不做特殊配置,检查SPI收发中SS引脚信号的变化
#include "Ai8051U.H"
#include "intrins.h"
#include "stdio.h"
#define FOSC 22118400L
sbit SS = P2^4;
//sbit SS = P1^0;
sbit LED = P1^1;
// 延时
void delay_ms(unsigned int ms) {
unsigned int i;
do {
i = FOSC/6000;
while(--i);
} while(--ms);
}
void main() {
unsigned char dat = 0;
EAXFR = 1; //允许访问扩展的特殊寄存器,XFR
//(32 位模式请使用这句,注释下一句)
// P_SW2 |= 0x80; //允许访问扩展的特殊寄存器,XFR
//(8 位模式请使用这句,注释上一句)
WTST = 0; //设置取程序代码等待时间,
//赋值为 0 表示不等待,程序以最快速度运行
CKCON = 0; //设置访问片内的 xdata 速度,
//赋值为 0 表示用最快速度访问,不增加额外的等待时间
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
LED = 1;
SS = 1;
busy = 0;
SPCTL = 0x50|0x80; //使能 SPI 主机模式
SPI_S1 = 0; //00: P1.4 P1.5 P1.6 P1.7, 01: P2.4 P2.5 P2.6 P2.7, 10: P4.0 P4.1 P4.2 P4.3, 11: P3.5 P3.4 P3.3 P3.2
SPI_S0 = 1;
SPSTAT = 0xc0; //清中断标志
//ESPI = 1; //使能 SPI 中断
//EA = 1;
delay_ms(10);
LED = 0;
while(1) {
dat++;
SS = 0; //拉低从机 SS 管脚
SPDAT = dat; //发送测试数据
while (!SPIF); //查询完成标志
SPIF = 1; //清中断标志
SS = 1; //拉高从机的 SS 管脚
}
}测试结果:

二、方式2:使用SPI外设的SS引脚
#include "Ai8051U.H"
#include "intrins.h"
#include "stdio.h"
#define FOSC 22118400L
sbit SS = P2^4;
//sbit SS = P1^0;
sbit LED = P1^1;
bit busy;
// 延时
void delay_ms(unsigned int ms) {
unsigned int i;
do {
i = FOSC/6000;
while(--i);
} while(--ms);
}
void main() {
unsigned char dat = 0;
EAXFR = 1; //允许访问扩展的特殊寄存器,XFR
//(32 位模式请使用这句,注释下一句)
// P_SW2 |= 0x80; //允许访问扩展的特殊寄存器,XFR
//(8 位模式请使用这句,注释上一句)
WTST = 0; //设置取程序代码等待时间,
//赋值为 0 表示不等待,程序以最快速度运行
CKCON = 0; //设置访问片内的 xdata 速度,
//赋值为 0 表示用最快速度访问,不增加额外的等待时间
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
LED = 1;
SS = 1;
busy = 0;
SPCTL = 0x50;
SPI_S1 = 0; //00: P1.4 P1.5 P1.6 P1.7, 01: P2.4 P2.5 P2.6 P2.7, 10: P4.0 P4.1 P4.2 P4.3, 11: P3.5 P3.4 P3.3 P3.2
SPI_S0 = 1;
SPSTAT = 0xc0; //清中断标志
//ESPI = 1; //使能 SPI 中断
//EA = 1;
delay_ms(10);
LED = 0;
while(1) {
dat++;
SS = 0; //拉低从机 SS 管脚
SPDAT = dat; //发送测试数据
while (!SPIF); //查询完成标志
SPIF = 1; //清中断标志
SS = 1; //拉高从机的 SS 管脚
}
}测试结果:

可以看到结果比较奇怪,数据没有发出,SS引脚信号也不正常。
方式三、使用SPI外设的SSGN引脚
#include "Ai8051U.H"
#include "intrins.h"
#include "stdio.h"
#define FOSC 22118400L //定义为无符号长整型,避免计算溢出
sbit SS = P1^0;
sbit LED = P1^1;
// 延时
void delay_ms(unsigned int ms) {
unsigned int i;
do {
i = FOSC/6000;
while(--i);
} while(--ms);
}
void main() {
unsigned char dat = 0;
EAXFR = 1; //允许访问扩展的特殊寄存器,XFR
//(32 位模式请使用这句,注释下一句)
// P_SW2 |= 0x80; //允许访问扩展的特殊寄存器,XFR
//(8 位模式请使用这句,注释上一句)
WTST = 0; //设置取程序代码等待时间,
//赋值为 0 表示不等待,程序以最快速度运行
CKCON = 0; //设置访问片内的 xdata 速度,
//赋值为 0 表示用最快速度访问,不增加额外的等待时间
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
LED = 1;
SS = 1;
busy = 0;
SPCTL = 0x50;//|0x80; //使能 SPI 主机模式
SPI_S1 = 0; //00: P1.4 P1.5 P1.6 P1.7, 01: P2.4 P2.5 P2.6 P2.7, 10: P4.0 P4.1 P4.2 P4.3, 11: P3.5 P3.4 P3.3 P3.2
SPI_S0 = 1;
SPSTAT = 0xc0; //清中断标志
//ESPI = 1; //使能 SPI 中断
//EA = 1;
delay_ms(10);
LED = 0;
while(1) {
dat++;
SS = 0; //拉低从机 SS 管脚
SPDAT = dat; //发送测试数据
while (!SPIF); //查询完成标志
SPIF = 1; //清中断标志
SS = 1; //拉高从机的 SS 管脚
//LED = !LED; //测试端口
}
}测试结果:

可以看到,设置SPCTL寄存器的最高位B7为1,就可以想使用其它IO口那样使用SPI外设的SS信号。
我要赚赏金
