找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4340|回复: 1
打印 上一主题 下一主题
收起左侧

CPLD作为并行接口

[复制链接]
跳转到指定楼层
楼主
ID:51472 发表于 2013-7-9 04:00 | 显示全部楼层 回帖奖励 |倒序浏览 |阅读模式
     利用51hei-7 cpld开发板http://www.51hei.com/bbs/dpj-19813-1.html 上的CPLD和单片机,可以做很多实验,以下举一个例子。
1、功能描述
  单片机的P0、P1和P2与CPLD各引脚相连,本例是将CPLD作为一个并行接口,读出各引脚的数据并在CPLD的显示器上显示出来。使用单片机智能模块中的Up和Down键,分别按下这两个键可使预定的数据增加或减少,该数据显示在智能模块的LED显示器上,同时送往P0和P1口。
  CPLD读出与P0和P1口相连的引脚的状态,以十六进制的格式显示在CPLD模块的四位显示器上。
2、单片机程序
/***************************************************************
;* 单片机教程网
;*    (c) Copyright 2004,Mcustudio,JiangSu,LiYang
;*     All  Rights Reserved
;*    key.c
;*    编程:周
;*    用于CPLD实验板
;*    定时中断实现显示的程序
;*    按Up键加1,按Down键减1
;*    数据同时输出到P0和P1口
***************************************************************/
#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; //


/* 发送往显示  */
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;
}
}

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;
P1=Data%256;
P0=Data/256;
}
}

3、CPLD所用的verilog程序
//说明:用于csbx-1A实验板
//功能:读出与单片机P0和P1口相连的16位引脚的状态,并将其值以十六进制的形式显示在数码管上
//与之配套的单片机程序为Key.c
//状态:单片机程序及CPLD程序均已通过调试
module parallel(iDat1,iDat2,clock,seg,sl);
    input [7:0] iDat1; //read P0 port data
    input [7:0] iDat2; //read P1 port data
    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;


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

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

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

assign seg=seg_reg;
assign sl=sl_reg;


endmodule
4、实现方法
   ......
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表