51/AVR单片机技术驿站!  <在线翻译>     便利工具    特色网址   无弹窗、无插件的绿色站点...  英才招聘   学历查询  喜欢>>收藏我站 

当前位置:首页 > ARM/CPLD/综合 > 详细内容
CPLD作为串行接口
发布时间:2009/7/21  阅读次数:679  字体大小: 【】 【】【
利用CSBX-1A实验板上的CPLD和单片机,可以做很多实验,以下举一个例子。
1、功能描述
  单片机的P1.0、P1.1和P1.2与CPLD相应引脚相连,本例是将CPLD作为一个串行接口,相当于两片74HC595串接,由单片机将数据以串行方式发送过来,CPLD读出数据并在CPLD的显示器上显示出来。
  使用单片机智能模块中的Up和Down键,分别按下这两个键可使预定的数据增加或减少,该数据显示在智能模块的LED显示器上,同时以串行方式发送往CPLD。
2、单片机程序
/***************************************************************
;*                                                平凡单片机工作室
;*   http://www.mcustudio.com
;*        (c)  Copyright  2004,Mcustudio,JiangSu,LiYang
;*          All    Rights  Reserved
;*        key.c
;*        编程:周坚
;*        用于CPLD实验板
;*        定时中断实现显示的程序
;*        按Up键加1,按Down键减1
;*        数据同时通过串行方式发送往CPLD
***************************************************************/
#include  <intrins.h>
#include  "reg52.h"
#define  uchar  unsigned  char
#define  uint    unsigned  int  

uchar      Xnjz; //虚拟键值
uint Data=100;

sbit   KeyShift=P3^5; //移位键
sbit KeyUp=P3^6; //Up键
sbit KeyDown=P3^7; //Down键

uchar  code  BitTab[]={0x01,0x02,0x04,0x08,0x10,0x20};
uchar  code  DispTab[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0xFF};

uchar  Count=0; //计数器,显示程序通过它得知现正显示哪个数码管
uchar  DispBuf[6]={1,2,3,4,5,6}; //6字节的显示缓冲区
#define  Hidden  0x10; //消隐码

////定义用于单片机显示器的引脚
sbit        Dat=P3^2; //
sbit        Clk=P3^3;
sbit        RCK=P3^4; //

//定义用于CPLD的串行接口引脚
sbit cDat=P1^0;
sbit cRck=P1^1;
sbit cClk=P1^2;

/*  发送往显示    */
void  SendData(unsigned  char  SendDat)
{ unsigned  char  i;
for(i=0;i<8;i++)
{ if((SendDat&0x80)==0)
Dat=0;
else
Dat=1;
_nop_();
Clk=0;
_nop_();
                 Clk=1;
SendDat=SendDat<<1;
}
}

/*  发送往CPLD    */
void  SendToCpld(unsigned  char  SendDat)
{ unsigned  char  i;
for(i=0;i<8;i++)
{ if((SendDat&0x80)==0)
cDat=0;
else
cDat=1;
_nop_();
cClk=0;
_nop_();
                 cClk=1;
SendDat=SendDat<<1;
}
}


void  Timer0()  interrupt  1
{ uchar  tBit=0,tSeg=0;
TH0=(65536-5000)/256;
TL0=(65536-5000)%256; //定时时间为2500个周期,采用stc89c52rc单片机,倍速
tBit=BitTab[Count]; //取位值
tSeg=DispBuf[Count]; //取出待显示的数
tSeg=DispTab[tSeg]; //取字形码
RCK=0;
SendData(tSeg); //段驱动
SendData(tBit); //位驱动
RCK=1;
Count++;
if(Count==6)
Count=0;
}

void  mDelay(unsigned  int  Delay)
{ unsigned  int  i;
for(;Delay>0;Delay--)
{ for(i=0;i<124;i++)
{;}
}
}


void  KeyProcess(uchar  KeyVal)
{
switch(KeyVal)
{ case  0xfb: //移位键
break; //在本程序中没有什么用处
case  0xfd: //Up键
{ if(Data<9999)
Data++;
break;
                }
                case  0xfe:                //Down键
                { if(Data>0)
Data--;
                    break;
                }
}
}

//预处理键值,将键位移入虚拟键值中
void  PreKey()
{ uchar Ktmp=0;

KeyShift=1; //移位键
KeyUp=1; //Up键
KeyDown=1; //Down键

Ktmp=Ktmp<<1;
if(KeyShift)
Ktmp|=0x01;
Ktmp=Ktmp<<1;
if(KeyUp)
Ktmp|=0x01;
Ktmp=Ktmp<<1;
if(KeyDown)
Ktmp|=0x01;
Xnjz=Ktmp; //虚拟键值
}

void  Key() /*键处理*/
{ uchar  tmp1,tmp2;
PreKey();
tmp1=Xnjz|0xf8;
if(tmp1==0xff) //无键按下
return;
else
{ mDelay(10); //延时10ms
PreKey();
tmp1=Xnjz|0xf8;
if(tmp1==0xff)
return;
else
{ tmp2=tmp1;
for(;;)
{ PreKey();
tmp1=Xnjz|0xf8;
if(tmp1==0xff)
break;
}
KeyProcess(tmp2);
}
}
}

void  main()
{ uint  tmp;
TMOD=0x11;
TH0=(65536-5000)/256;
TL0=(65536-5000)%256; //定时时间为2500个周期
TR0=1;
EA=1;
ET0=1;

for(;;)
{ Key();
tmp=Data;
DispBuf[5]=tmp%10;
tmp/=10;
DispBuf[4]=tmp%10;
tmp/=10;
DispBuf[3]=tmp%10;
tmp/=10;
DispBuf[2]=tmp%10;
DispBuf[1]=Hidden;
DispBuf[0]=Hidden;
cRck=1;
SendToCpld(Data/256);
SendToCpld(Data%256);
cRck=0;
}
}
3、CPLD的Verilog程序

//说明:用于csbx-1A实验板
//功能:接收单片机通过串行方式发送过来的数据并以十六进制形式显示在4位LED上
//与之配套的单片机程序为Keys.c
//状态:单片机程序及CPLD程序均已通过调试

module  serial(clock,seg,sl,iData,Sclk,Rclk);
  input  iData; //  serial  input  Data  Pin        Pin1    P1.0
  input    Rclk; //serial  Enable  Clock  Pin      Pin2    P1.1
  input    Sclk; //serial    input  Clock  Pin      Pin3    P1.2

        input  clock;
        output  [7:0]  seg;
        output  [3:0]  sl;

  reg  [7:0]  seg_reg;
  reg  [3:0]  sl_reg;
  reg  [3:0]  disp_dat;
  reg  [36:0]  count;
  reg  [16:0]  reciveDat,reciveDat0;


   always@(posedge  Rclk)
reciveDat=reciveDat0;

    always@(posedge  Sclk)
begin
reciveDat0=reciveDat0<<1;
reciveDat0[0]=iData;
end


always@(posedge  clock)
begin
   count=count+1; //计数器
end

always@(count[14:13]) //定义显示数据触发事件
begin
   case(count[14:13]) //选择扫描显示数据
2h0:disp_dat=reciveDat[15:12]; //显示个位数据
2h1:disp_dat=reciveDat[11:8];
2h2:disp_dat=reciveDat[7:4];
2h3:disp_dat=reciveDat[3:0]; //显示百位数据
      endcase
      case(count[14:13]) //选择数码管显示位
2h0:sl_reg=4b1110; //选择个位数码管
2h1:sl_reg=4b1101;
2h2:sl_reg=4b1011;
2h3:sl_reg=4b0111;
endcase
  end

  always@(disp_dat)
  begin
   case(disp_dat)
4h0:  seg_reg  =  8hc0; //显示0
4h1:  seg_reg  =  8hf9; //显示1
4h2:  seg_reg  =  8ha4; //显示2
4h3:  seg_reg  =  8hb0; //显示3
4h4:  seg_reg  =  8h99; //显示4
4h5:  seg_reg  =  8h92; //显示5
4h6:  seg_reg  =  8h82; //显示6
4h7:  seg_reg  =  8hf8; //显示7
4h8:  seg_reg  =  8h80; //显示8
4h9:  seg_reg  =  8h90; //显示9
4ha:  seg_reg  =  8h88; //显示a
4hb:  seg_reg  =  8h83; //显示b
4hc:  seg_reg  =  8hc6; //显示c
4hd:  seg_reg  =  8ha1; //显示d
4he:  seg_reg  =  8h86; //显示e
4hf:  seg_reg  =  8h8e; //显示f
endcase
end

assign  seg=seg_reg;
assign  sl=sl_reg;


endmodule
我要评论
  • 匿名发表
  • [添加到收藏夹]
  • 发表评论:(匿名发表无需登录,已登录用户可直接发表。) 登录状态:未登录
最新评论
所有评论[0]
    暂无已审核评论!

网站导航 管理登陆 ┊ 免责声明 问题反馈  友链说明
本站部分内容来自网络共享资源,如有冒犯您的权利请来信告之删除或纠正!
不得对本站进行复制、盗链或镜像,转载内容须获得同意或授权;欢迎友情链接、站务合作!

    我要报警 Alexa
 mcusy_cn#126.com (请把#改成@) 交流:522422171
本站学习交流群:138..158(高级群1-)、77930286(高级群2)、61804809(群3)
Copyright© MCUSY All Rights Reserved
本站网警备案号: WZ36040002485
  ICP备案证书号:粤ICP备09034963号