📄 slave_spi.c
字号:
#include"stc12c2052ad.h"
#include <string.h>
#define SPIF (SPSTAT & 0X80) //中断标志
#define SPWCOL (SPSTAT & 0X40) //冲突标志
unsigned char data bchar;
unsigned char bdata flags;
sbit read_flag=flags^0;
sbit spi_idle = flags^1; //SPI 空闲
sbit spi_packet = flags^3;
sbit sdi = P1^5; //数据输入 P1^5 <-----> P1^3 在此输入 应置漏极开路 11
sbit sdo = P1^6; //数据输出 P1^6 <-----> P1^2 在此输出 应置推挽输出 01
sbit spi_clk = P1^7; //双向时钟 P1^7 <-----> P3^3 00
/*
void run_disp()
{
unsigned int i,j;
for(i=0;i<1000;i++)
{
for(j=0;j<1000;j++)
{
;
}
}
}*/
/*******************************************************************************************************
********* 将 STC12C4052配置成从机模式,先传LSB,上升沿数据输入,下降沿数据输出 *****************
***** SSIG = 1,忽略/SS脚。SPEN = 1允许SPI工作。DORD = 1先传LSB;(0先传MSB)。MSTR =0设为从机。********
******** CPOL = 0,时钟在空闲时为0;CPOL = 1,时钟在空闲时为1。上升CPOL = 0或下降 CPOL = 1
******** CPOL = 1 数据上升沿输入到SPI模块,数据下降输出到SPI总线。
******** CPHA=0,在串行同步时钟的“第一个跳变沿”(上升或下降)数据被采样。
******** CPHA=1,在串行同步时钟的“第二个跳变沿”(上升或下降)数据被采样。
******** SPR1、0 = 00 FOSC/4 参考P132 Fig5mast = 1 数据在mosi输出,mast = 0 数据在miso输出
******************* 时钟极性和相位配置正确后,数据才能够被准确的发送和接收********************************
******** 主设备的SDO同从设备的SDO配置一致,主设备的SDI同从设备的SDI配置一致 主设备这边的时钟极性和相位都是
******** 以从设备为基准的。在时钟极性的配置上一定要搞清楚从设备是在时钟的上升沿还是下降沿接收数据。是在时
******** 钟的下降沿还是上升沿发送数据。另外由于主设备的SDO连接从设备的SDI,从设备的SDO连接主设备的SDI,
******** 从设备SDI接收的数据是主设备的SDO发送过来的,主设备SDI接收的数据是从设备SDO发送过来的,所以主设备这边
******** SPI时钟极性的配置(即SDO的配置)跟从设备的SDI接收数据的极性是相反的,跟从设备SDO发送数据的极性是相同的。
******** “主设备在时钟的下降沿发送数据,从设备在时钟的上升沿接收数据”。因此主设备这边SPI时钟极性应该配置为下降沿有效
******** “从设备在时钟的上升沿接收数据,因此主设备的SPI时钟极性同样应该配置为下降沿有效”
********************************************************************************************************************/
void spi_comm_init()
{
P1M0 = 0x20; //P1.7设置为双向口,P1.6设置为推挽输出,P1.5设置漏极开路。
P1M1 = 0x60;
SPCTL = 0xec; // SSIG,SPEN,DORD,MSTR,CPOL,CPHA,SPR1,SPR0。 1110,1100
SPSTAT |= 0xc0; //清除中断
AUXR |= 0x08; //允许SPI中断ESPI = 1 0000,1000
EADC_SPI = 1; //IE允许SPI中断 EADC_SPI = 1
}
//向SPI口发送一个字符
void spi_send_comm(unsigned char ch)
{
EADC_SPI = 0; //关掉ADC_SPI共享中断
if(SPSTAT &0x80 == 0x80) //如果中断,清除中断
SPSTAT |= 0xc0;
SPDAT = ch; //发送数据
while(SPSTAT & 0x80 == 0x00) //等待发送完毕 SPIF = 1
SPSTAT |= 0xc0; //清除中断
EADC_SPI = 1; //打开中断
}
/*
//从SPI口接收一个字符
unsigned char receive_spi_comm()
{
while(SPSTAT & 0x80 == 0x00)
SPSTAT = 0xc0;
bchar = SPDAT;
bchar += 1;
spi_packet = 1;
return bchar;
}
*/
//向串口发送一个字符
void send_char_com(unsigned char ch)
{
SBUF=ch;
while(TI==0);
TI=0;
}
/*
//向串口发送一个字符串,strlen为该字符串长度
void send_string_com(unsigned char *str,unsigned char strlen)
{
unsigned int k=0;
do
{
send_char_com(*(str + k));
k++;
} while(k < strlen);
}
*/
//SPI口接收中断函数
/*SPI中断服务程序中,先从SPDR中读一个接收的字节存入接收数据缓冲器中
再从发送数据缓冲器取出一个字节写入SPDR中由ISP发送到主机。数据一旦写入SPDR,
ISP硬件开始发送数据。下一次ISP中断时,表示发送完成,并同时收到一个数据。 **/
void adc_spi_interrupt(void) interrupt 5 //
{
// unsigned char bchar;
while(SPSTAT & 0x80 == 0x00)
SPSTAT = 0xc0; //清0标志位,SPI和WCOL; 11000000
//是向SPI/WCOL写1,将SPI/WCOL清0。
//不是向SPI/WCOL写1,将SPI/WCOL清0。
bchar = SPDAT; //读取SPI数据
bchar = bchar+10;
// SPDAT = 0xff;
spi_packet = 1;
}
void init_serialcomm(void)
{
SCON = 0x50; //SCON: serail mode 1, 8-bit UART, enable ucvr
PCON = 0x00; //SMOD=0;
ET1 = 0; //禁止定时器1中断
// AUXR |= 0x00; //T0,T1 12分频0001,11xx。T0,T1,UART_M0,ADC,ESPI,LVDI,X,X
TMOD = 0x20; //TMOD: timer 1, mode 2, 8-bit reload
TH1 = 0xfd; //Baud:9600 fosc=11.0592MHz
TL1 = 0xfd;
TR1 = 1; // timer 1 run
ES = 1; //IE = 0x90Enable Serial Interrupt
}
/*串口接收中断函数
void serial () interrupt 4 using 3
{
unsigned char ch;
if(RI)
{
RI = 0;
ch=SBUF;
inbuf1[count3]=ch;
count3++;
if( count3==INBUF_LEN)
{count3=0;
read_flag=1; //如果串口接收的数据达到INBUF_LEN个,且校验没错,
} //就置位取数标志
}
} */
main()
{
spi_comm_init(); //初始化串口
init_serialcomm();
EA = 1;
// spi_send_comm(0xff);
while(1)
{
// receive_spi_comm();
if(spi_packet) //如果spi数标志已置位,就将读到的数从串口发出
{
spi_packet=0; //取数标志清0
// send_char_com(bchar); //从串口发出
spi_send_comm(bchar); //从spi口发出
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -