/////SPI调试程序////////// /////SPI_master.c////////////// #include <C8051F040.h> typedef unsigned char uchar; typedef unsigned int uint; enum {aalen=6}; xdata uchar aa[aalen]={0x81,0x82,0x83,0x84,0x85,0x86}; xdata uchar rr[aalen]; xdata uchar k; xdata uchar t; void delay1ms(uint time){//延迟1ms uint i; uint j; for (i=0;i<time;i++){ for(j=0;j<300;j++); } } void spi_cfg(uchar spicfg,uchar spickr,uchar spicn){//SPI配置函数 SFRPAGE = 0x00; //给SFR页寄存器复零。该字节代表CIP-51MCU读或修改SFR时所用的SFR页 SPI0CFG = spicfg; //......? SPI0CKR = spickr; //......? SPI0CN = spicn; //......? EIE1|= 0x01; //扩展中断允许1:允许SPI0中断 } void config (void) { WDTCN = 0x07; //看门狗禁止 WDTCN = 0xDE; //写入0xDE后四个系统时钟周期内写入0xAD,将禁止WDT WDTCN = 0xAD; SFRPAGE = 0x0F; //......? XBR0 = 0x02; //端口I/O交叉寄存器,SPI0连到3个或4个端口引脚,其他I/O不可连 XBR1 = 0x00; XBR2 = 0x40; XBR3 = 0x00; P0MDOUT = 0x02; /*交叉开关配置,SPI总线SCK配置到P0.0口,为开漏输出;MISO为P0.1口, 推挽输出;MOSI为P0.2口,开漏输出,NSS为P0.3口开漏输出(注:这句是新华龙提供的源代码的注释,但其交叉开关寄存器具体是如何实现这些功能的,我没有看明白???)*/ SFRPAGE = 0x0F; //......? CLKSEL = 0x00; //系统时钟选择寄存器:内部晶振起作用 OSCXCN = 0x00; //外部振荡器控制寄存器:关闭外部晶振 OSCICN = 0x84; //内部振荡器寄存器:使能内部晶振,系统时钟为8分频 //采用内部晶振,为24.5MHZ8分频(注:24.5/8=3MHZ) } //End of config void main(){ config(); spi_cfg(0x50,0x2d,0x08); /* SPI0CFG = 0x50; 配置寄存器: 主机模式,SCK高电平为空闲,因为SCK采用上拉设计 SPI0CKR = 0x2D; 时钟速率寄存器: 波特率设置,系统时钟为3MHZ,所以SCK约为32KHZ SPI0CN = 0x08; 控制寄存器:0000“10”00,“10”四线方式;“00”三线从方式或三线主方式。NSS线好不连到端口引脚 系统为四线制单主机模式,且主机NSS输出为0,注意此时SPIEN为0,SPI尚未开启 */ EA=1; k=0; SFRPAGE=0x00; SPIEN=1;//开启SPI SPI0DAT=aa[k];//当对SPI0SAT写数据时,SPI总线传输开始 while(1){ if(SPIEN==0) k=0;//总线释放时,中断程序中将SPIEN清零,在此设断点可全速运行SPI至总线释放 } } void spi_ISR() interrupt 6{//SPI中断 SFRPAGE=0x00; if(k>=aalen) SPIEN=0;//数据发送完毕,将SPIEN清零,释放总线 if(WCOL)//写冲突处理,暂无处理 WCOL=0; if(MODF)//模式错误处理,暂无处理 MODF=0; if(RXOVRN){//接收缓冲区溢出处理 t=SPI0DAT;//t为接收数据暂存变量 RXOVRN=0; } while(!TXBMT); //如果TXBMT不等于0,说明发送未结束,继续发送 /*查询上次发送是否结束,因为有很多状态均可使SPI进入中断, 所以查询上次发送是否结束,以保证写发送缓冲区时不会对数据造成破坏*/ rr[k]=SPI0DAT;//由于是全双工总线,在发送完一个字节时,主机也收到从机所发的数据 k++; SPI0DAT=aa[k];//发送数据 SPIF=0; //SPIF是SPI0的终端标志。该位不能被硬件自动清0,必须软件清0 }
|