利用CSBX-1A實(shí)驗(yàn)板上的CPLD和單片機(jī),可以做很多實(shí)驗(yàn),以下舉一個(gè)例子。 1、功能描述 單片機(jī)的P1.0、P1.1和P1.2與CPLD相應(yīng)引腳相連,本例是將CPLD作為一個(gè)串行接口,相當(dāng)于兩片74HC595串接,由單片機(jī)將數(shù)據(jù)以串行方式發(fā)送過(guò)來(lái),CPLD讀出數(shù)據(jù)并在CPLD的顯示器上顯示出來(lái)。 使用單片機(jī)智能模塊中的Up和Down鍵,分別按下這兩個(gè)鍵可使預(yù)定的數(shù)據(jù)增加或減少,該數(shù)據(jù)顯示在智能模塊的LED顯示器上,同時(shí)以串行方式發(fā)送往CPLD。 2、單片機(jī)程序 /*************************************************************** ;* 平凡單片機(jī)工作室 ;* http://www.mcustudio.com ;* (c) Copyright 2004,Mcustudio,JiangSu,LiYang ;* All Rights Reserved ;* key.c ;* 編程:周堅(jiān) ;* 用于CPLD實(shí)驗(yàn)板 ;* 定時(shí)中斷實(shí)現(xiàn)顯示的程序 ;* 按Up鍵加1,按Down鍵減1 ;* 數(shù)據(jù)同時(shí)通過(guò)串行方式發(fā)送往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; //計(jì)數(shù)器,顯示程序通過(guò)它得知現(xiàn)正顯示哪個(gè)數(shù)碼管 uchar DispBuf[6]={1,2,3,4,5,6}; //6字節(jié)的顯示緩沖區(qū) #define Hidden 0x10; //消隱碼
////定義用于單片機(jī)顯示器的引腳 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;
/* 發(fā)送往顯示 */ 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; } }
/* 發(fā)送往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; //定時(shí)時(shí)間為2500個(gè)周期,采用stc89c52rc單片機(jī),倍速 tBit=BitTab[Count]; //取位值 tSeg=DispBuf[Count]; //取出待顯示的數(shù) tSeg=DispTab[tSeg]; //取字形碼 RCK=0; SendData(tSeg); //段驅(qū)動(dòng) SendData(tBit); //位驅(qū)動(dòng) 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; //在本程序中沒(méi)有什么用處 case 0xfd: //Up鍵 { if(Data<9999) Data++; break; } case 0xfe: //Down鍵 { if(Data>0) Data--; break; } } }
//預(yù)處理鍵值,將鍵位移入虛擬鍵值中 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) //無(wú)鍵按下 return; else { mDelay(10); //延時(shí)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; //定時(shí)時(shí)間為2500個(gè)周期 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程序
//說(shuō)明:用于csbx-1A實(shí)驗(yàn)板 //功能:接收單片機(jī)通過(guò)串行方式發(fā)送過(guò)來(lái)的數(shù)據(jù)并以十六進(jìn)制形式顯示在4位LED上 //與之配套的單片機(jī)程序?yàn)镵eys.c //狀態(tài):?jiǎn)纹瑱C(jī)程序及CPLD程序均已通過(guò)調(diào)試
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; //計(jì)數(shù)器 end
always@(count[14:13]) //定義顯示數(shù)據(jù)觸發(fā)事件 begin case(count[14:13]) //選擇掃描顯示數(shù)據(jù) 2'h0:disp_dat=reciveDat[15:12]; //顯示個(gè)位數(shù)據(jù) 2'h1:disp_dat=reciveDat[11:8]; 2'h2:disp_dat=reciveDat[7:4]; 2'h3:disp_dat=reciveDat[3:0]; //顯示百位數(shù)據(jù) endcase case(count[14:13]) //選擇數(shù)碼管顯示位 2'h0:sl_reg=4'b1110; //選擇個(gè)位數(shù)碼管 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
|
|