为了学习使用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信号。