Menu Close

SOC系列教程 SOC编程和EMIO的使用2-数码管

前面的实验内容主要介绍了如何设置EMIO,并驱动LED和获取开关变量。本文的实验主要进行EMIO扩展,并驱动6个数码管的显示,数码管的位选排列D1-6,是从又往左排列的。

(1)数码管的内容可以是数字钟或自拟内容

(2)数码管的硬件连接如下图所示:

%title插图%num

数码管的硬件介绍与FPGA管脚的对应关系:

(1)数码管的型号:LG3361BH;

(2)为共阳极数码管

(3)为了降低共阳端FPGA的电流,采用NDS336P MOS管进行驱动;由于MOS管是P沟道,因此FPGA管脚为低电平是导通,FPGA及软件编程时应注意。

(4)数码管的8段与FPGA之间经行1.5V到3.3V的电平转换,具体细节请参照FII-PE7030的原理图

数码管8段 与FPGA管脚的映射表

数码管(段) a b c d e f g p
网络名称 SEG_PA SEG_PB SEG_PC SEG_PD SEG_PE SEG_PF SEG_PG SEG_DP
FPGA -PIN J10 J9 A7 B7 A8 A9 A10 B10

数码管位选与FPGA管脚的映射表

数码管(位) 1 2 3 4 5 6
网络名称 SEG_D1 SEG_D2 SEG_D3 SEG_D4 SEG_D5 SEG_D6
FPGA PIN C1 E3 F7 D6 H11 J11

数码管XDC的设置

(1)数码管段的XDC部分

#EGPIO_INOUT[8-15] used as segments selection

set_property PACKAGE_PIN J10 [get_ports EGPIO_INOUT[8]]

set_property IOSTANDARD LVCMOS15 [get_ports EGPIO_INOUT[8]]

set_property PACKAGE_PIN J9 [get_ports EGPIO_INOUT[9]]

set_property IOSTANDARD LVCMOS15 [get_ports EGPIO_INOUT[9]]

set_property PACKAGE_PIN A7 [get_ports EGPIO_INOUT[10]]

set_property IOSTANDARD LVCMOS15 [get_ports EGPIO_INOUT[10]]

set_property PACKAGE_PIN B7 [get_ports EGPIO_INOUT[11]]

set_property IOSTANDARD LVCMOS15 [get_ports EGPIO_INOUT[11]]

set_property PACKAGE_PIN A8 [get_ports EGPIO_INOUT[12]]

set_property IOSTANDARD LVCMOS15 [get_ports EGPIO_INOUT[12]]

set_property PACKAGE_PIN A9 [get_ports EGPIO_INOUT[13]]

set_property IOSTANDARD LVCMOS15 [get_ports EGPIO_INOUT[13]]

set_property PACKAGE_PIN A10 [get_ports EGPIO_INOUT[14]]

set_property IOSTANDARD LVCMOS15 [get_ports EGPIO_INOUT[14]]

set_property PACKAGE_PIN B10 [get_ports EGPIO_INOUT[15]]

set_property IOSTANDARD LVCMOS15 [get_ports EGPIO_INOUT[15]]

数码管位选XDC部分:

注意:位选的前两位在Bank33, 该Bank的IO电平为1.8V, 因此在XDC文件中IOSTANDARD 应设为LVCMOS18

这里仅列出新增部分

#1

set_property PACKAGE_PIN C1 [get_ports EGPIO_INOUT[16]]

set_property IOSTANDARD LVCMOS18 [get_ports EGPIO_INOUT[16]]

#2

set_property PACKAGE_PIN E3 [get_ports EGPIO_INOUT[17]]

set_property IOSTANDARD LVCMOS18 [get_ports EGPIO_INOUT[17]]

#3

set_property PACKAGE_PIN F7 [get_ports EGPIO_INOUT[18]]

set_property IOSTANDARD LVCMOS15 [get_ports EGPIO_INOUT[18]]

#4

set_property PACKAGE_PIN D6 [get_ports EGPIO_INOUT[19]]

set_property IOSTANDARD LVCMOS15 [get_ports EGPIO_INOUT[19]]

#5

set_property PACKAGE_PIN H11 [get_ports EGPIO_INOUT[20]]

set_property IOSTANDARD LVCMOS15 [get_ports EGPIO_INOUT[20]]

#6

set_property PACKAGE_PIN J11 [get_ports EGPIO_INOUT[21]]

set_property IOSTANDARD LVCMOS15 [get_ports EGPIO_INOUT[21]]

FPGA 程序更改:

顶层文件修改:

inout DDR_we_n,

// user added

inout [21:0]EGPIO_INOUT,

// user added

inout FIXED_IO_ddr_vrn,

顶层文件:

// user added

(*mark_debug=”true”*)wire [31:0] EGPIO_tri_o;

(*mark_debug=”true”*)wire [31:0] EGPIO_tri_i;

(*mark_debug=”true”*)wire [31:0] EGPIO_tri_t; //GPIO wire connection

    • //扩展到22 EGPIO, 0-7 仍然用于LED
    • //8-15 用作数码管显示
    • //16-21 用于第几个数码管选择

genvar i;

generate

for (i=0;i<32;i=i+1) begin

assign EGPIO_INOUT=EGPIO_tri_t?1’bZ:EGPIO_tri_o; //GPIO as output wire connection

assign EGPIO_tri_i= EGPIO_INOUT; //GPIO as input wire connection

end

endgenerate

软件设计:

(1)设计任务:

将开关的输入以16进制的形式显示在数码管上:

1)读取开关量

2)7段数码管(7 segment digital tube) ,译码设计

3)位扫描

//8段共阳数码管译码程序(其中段8为小数点P):

int seven_seg(unsigned char x)

{int seg=0;

switch (x&0x0f) {

case 0: seg =0xc0; break; //1100,0000,0为亮,1为熄灭,0需要亮6个灯

case 1: seg=0xcf; break; //1100,1111,0为亮,1为熄灭,1需要亮2个灯

case 2: seg=0xa4; break; //解释同上

case 3: seg=0xb0; break;

case 4: seg=0x99; break;

case 5: seg=0x92; break;

case 6: seg =0x82; break;

case 7: seg =0xf8; break;

case 8: seg=0x80; break;

case 9: seg=0x90; break;

case 0x0a: seg=0x88; break;

case 0x0b: seg=0x83; break;

case 0x0c: seg=0xc6; break;

case 0x0d: seg=0xa1; break;

case 0x0e: seg=0x86; break;

case 0x0f: seg=0x8e; break;}

return seg;}

//GPIO 的组合,k 是传进来的开关量,//bit_sel是位选,高电平有效,led是和开

//关共享FPGA管脚的8个指示灯

void dis( unsigned char bit_sel,unsigned char k ,unsigned char led,XGpioPs *x)

{ unsigned int emio_out=0;

unsigned int tmp=0;

unsigned char tmp_k=0;

unsigned char seg=0;

seg=seven_seg(tmp_k); //显示数码管,0为亮,1为熄灭

tmp=~(bit_sel<<16); //bit_sel选择数码管,01表示数码管1,10表示数码管2,100表示数码管3,1000表示数码管4,10000表示数码管5,100000表示数码管6

tmp=0xff0000&tmp; //tmp表示数码管选择的地址,一次选择一个,从000001到100000

emio_out=(tmp)|(seg<<8)|(led); //led最右边8位,表示LED,seg<<8,表示数码管的显示数值,tmp

XGpioPs_Write(x, 2, emio_out); // bank 2的数值写入,低位8位为led,中间8位为seg数值,高6位为数码管选择

delay(2);

}

主程序流程:

0.设置数码管子程序

1.初始化GPIO口程序

2.初始化变量3

3.显示数码管,显示开关量(由7循环过来)

4.交叉显示奇偶数位LED

5.GPIO设为输入

6.读取开关的值

7.串口打印开关的值

8.循环到第3步

while(1)

{ unsigned int tmp_k=0;

XGpioPs_SetDirection(&psGpioInstancePtr,2, 0x3fffff); //GPIO设为输出 dis(0x01,k,led,&psGpioInstancePtr); //低四位开关量显示在第一个数码管

tmp_k=k>>4;

dis(0x02,tmp_k,led,&psGpioInstancePtr); //高四位开关量显示在第二个数码管

dis(0x04,0,led,&psGpioInstancePtr); //第三个数码管显示0

dis(0x8,0,led,&psGpioInstancePtr); //第四个数码管显示0

dis(0x10,0,led,&psGpioInstancePtr); //第五个数码管显示0

dis(0x20,0,led,&psGpioInstancePtr); //第六个数码管显示0

if(count>100){

count=0;

led=~led; //取反,奇数偶数led互换

XGpioPs_SetDirection(&psGpioInstancePtr,2, 0x3fff00); // GPIO设为输入

delay(1);

k=XGpioPs_Read(&psGpioInstancePtr, 2); //读取拨码开关的值

xil_printf(“switch value,k= %x\n\r”,k); //打印拨码开关的值

}

else

count++; }

总结:本实验介绍了EMIO的基本映射,FPGA接口设计,XDC的管脚约束,软件的驱动以及应用程序的设计等,这里只起到抛砖引玉的作用,只介绍基本的映射方法,用户也可以将MIO中的一部分映射到EMIO,如可以把网络的MAC接口映射到PL端与PL的千兆PHY相连,这里不再累述。

 

Posted in SoC, 教材与教案

发表评论

相关链接