第一篇:北邮java智能卡实验报告实验三电子钱包(一)
智能卡技术实验报告
学院: 电子工程学院
班级: 2011211204 学号: 2011210986 姓名:
实验三 Java卡电子钱包程序
一、实验目的
建立Java卡电子钱包程序,并进行java卡程序的编译和调试
二、实验设备
PC机、智能卡读卡器、Java卡
三、实验内容
1、建立一个JavaCard工程
2、编写电子钱包应用代码
3、使用卡模拟器对应用代码进行编译调试
4、使用Java卡对应用代码进行编译调试
四、实验设计
1、实验说明
设计一个电子钱包小应用程序,应该至少能够实现以下功能:电子钱包的安装、选择与撤销选择、存款、借款、获取钱包余额以及身份验证。
2、流程图绘制 A、总体框图
B、存款模块图
C、消费模块图
D、PIN验证模块图
E、查询余额模块图
五、关键代码部分
A、PIN的次数判断
public boolean select(){
//在选择钱包应用之前,对pin可尝试次数进行判断,若可尝试次数为零,即钱包已锁定,则该钱包应用不能被选择
if(pin.getTriesRemaining()==0)
}
}
//当钱包应用被取消选择是,将pin的状态清空为初始值 pin.reset();return false;return true;public void deselect(){ B、APDU入口
public void process(APDU apdu){
buffer[ISO7816.OFFSET_CLA]=(byte)(buffer[ISO7816.OFFSET_CLA]&(byte)0xFC);//判断命令头是否正确
if((buffer[ISO7816.OFFSET_CLA]==0)&&(buffer[ISO7816.OFFSET_INS]==
return;//若为select命令,则直接返回,不做其他操作(byte)(0xA4)))
byte[] buffer=apdu.getBuffer();/*APDU对象为JCRE临时入口点对象,它可
发送的APDU命令。通过APDU.getBuffer()即APDU命令数组*/ 以被任何应用所访问,负责传递终端 命令即可以得到APDU对象的通信缓冲区,if(buffer[ISO7816.OFFSET_CLA]!=Wallet_CLA)ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);/*若为其
若为支持范围外他命令,则判断命令CLA和INS是否能为钱包应用所支持,的其他值,则返回对象的错误状态字*/
switch(buffer[ISO7816.OFFSET_INS]){
}
} case GET_BALANCE:
getBalance(apdu);return;debit(apdu);return;credit(apdu);return;verify(apdu);return;ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);case DEBIT: case CREDIT: case VERIFY: default: C、存款模块
private void credit(APDU apdu){ if(!pin.isValidated())ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);//钱包应用鉴权
byte[] buffer=apdu.getBuffer();byte numBytes=(byte)(buffer[ISO7816.OFFSET_LC]);//取命令LC,并将byte byteRead =(byte)(apdu.setIncomingAndReceive());/*接收APDU
之存储在numBytes中
命令数据,并将之存储在APDU通信缓冲区的 ISO7816.OFFSET.CDATA处,接着5字节的APDU命令头*/
if((numBytes!=1)||(byteRead!=1))//判断LC是否为1,否则抛出异常。本应用只支持一个字节长度的存钱交易
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
byte creditAmount =buffer[ISO7816.OFFSET_CDATA];//取将存入的值
if((creditAmount>MAX_TRANSACTION_AMOUNT)||(creditAmount<0))//判断交易额是否满足要求
ISOException.throwIt(SW_INVALID_TRANSACTION_AMOUNT);
if((short)(balance+creditAmount)>MAX_BALANCE)//判断若进行存钱交易,余额是否超出允许最大值
ISOException.throwIt(SW_EXCEED_MAXIMUM_BALANCE);balance =(short)(balance + creditAmount);//若以上条件全部满足,则更新钱包余额
}
private void debit(APDU apdu){ if(!pin.isValidated())ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);//钱包应用鉴权
byte[] buffer=apdu.getBuffer();
byte numBytes=(byte)(buffer[ISO7816.OFFSET_LC]);byte byteRead=(byte)(apdu.setIncomingAndReceive());if((numBytes!=1)||(byteRead!=1))ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);byte debitAmount =buffer[ISO7816.OFFSET_CDATA];//取即将消费的值 if((debitAmount>MAX_TRANSACTION_AMOUNT)||(debitAmount<0))ISOException.throwIt(SW_INVALID_TRANSACTION_AMOUNT);//判断交易额度是否满足要求
if((short)(balance-debitAmount)<(short)0)ISOException.throwIt(SW_NEGATIVE_BALANCE);//判断钱包余额是否大于消费的数额,即钱包是否透支
balance=(short)(balance-debitAmount);//若满足以上条件,最后更改钱包余额
} private void getBalance(APDU apdu){ byte[] buffer = apdu.getBuffer();
short le = apdu.setOutgoing();/*设置通信传输方向为卡片到终端,同时也
发送命令响应给终端,其中le为APDU命令中的响应数据的长度*/ 表示卡片运行结束,准备 LE,表示终端要求卡片返回的
if(le<2)ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);apdu.setOutgoingLength((byte)2);//设置卡片发送数据的实际长度 buffer[0] =(byte)(balance >> 8);//复制余额数据到APDU缓冲区中,准备发送给终端
buffer[1] =(byte)(balance & 0xFF);
apdu.sendBytes((short)0,(short)2);//调用通信函数发送余额数据 } private void verify(APDU apdu){ byte[] buffer = apdu.getBuffer();
byte byteRead =(byte)(apdu.setIncomingAndReceive());//接收终端发送的PIN数据,并将之存储到APDU通信缓冲区中
if(pin.check(buffer,ISO7816.OFFSET_CDATA,byteRead)==false)//判断终端数据的PIN是否和卡片内的PIN相符
ISOException.throwIt(SW_VERIFICATION_FAILED);} }
D、消费模块代码
private void debit(APDU apdu){
//钱包应用鉴权
if(!pin.isValidated())ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);byte[]buffer=apdu.getBuffer();
byte numByetes=(byte)(buffer[ISO7816.OFFSET_LC]);
byte byteRead=(byte)(apdu.setIncomingAndReceive());
if((numByetes!=1)||byteRead!=1)ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
//取即将消费的值
byte debitAmount=buffer[ISO7816.OFFSET_CDATA];
//判断消费交易额度是否满足要求
if((debitAmount>MAX_TRANSACTION_AMOUNT)||debitAmount<0)
ISOException.throwIt(SW_INVALID_TRANSACTION_AMOUNT);
//判断钱包余额是否大于消费的数额,即钱包是否透支
if((short)(balance-debitAmount)<(short)0)ISOException.throwIt(SW_NEGATIVE_BALANCE);
//若以上条件全部满足,最后更改钱包余额
balance=(short)(balance-debitAmount);}
六、测试数据部分
运行:
select card:
验证时错误密码:
验证时密码正确:
存钱55:
取钱30:
查询发现剩余25:
密码输入错误卡被锁定:
没有验证即存款:
验证成功后超额取款:
存款超额:
原款57,存入99超额后再查询余额依旧是57:
原款57,超额取款后在查询余额依旧是57:
七、实验总结
本次实验需要我们对照课本上的代码进行修改和敲定。通过绘制流程图完成设计部分内容,我们更好地理顺了电子钱包的设计思路及完成相应功能的模块划分。在实验过程中虽然遇到了一些困难,但经过与课本仔细对照反复调试,最终使问题得到了解决。
测试程序过程中,需要我们对程序有充分的了解,对功能有全面的认识,才能将不遗漏测试项目。此外,还要会看测试结果,能通过测试结果知道程序是否是正确无误的。
总而言之,这次实验培养了我们耐心细致的精神,也为我们今后的实验打下了良好的基础。
第二篇:北邮日历java实验报告
Java日历实验报告
信息工程27班项明钧
一、实验要求
写一个建议日历图形用户界面
二、设计思路
此次作业主要用到了窗口布局设计及各个组件的功能显示,事件处理机制。首先需要建立一个frame框架,然后进行布局设计。需要用到p0,p1,p2,p3,p4面板,其中p0,p1,p2,p4为正常静态面板,p3位自己定义的JScrollPane滚动面板,内容从p0获取,可以通过滑动滚动条来达到显示超出界面显示范围的内容。接着定义若干button,label,TextField通过add函数添加到对应的面板中。通过将主日历显示界面设置成GridLayout来达到网格式显示,当有文本输入和按钮按下,事件处理机制将会判断输入的年和月份是否符合正确格式。是的话将通过getMonthDay和getStartDay得到的所查询月份的日历一个个插入网格中,完成日历显示。
在p3面板中我还借用了 new JLabel(new ImageIcon函数插入本地图片,使界面更加美观。界面最下一栏放入了关于日历由来的简介,由于字数较多在界面范围内不能全部显示,我使用了JScrollPane滚动面板,这样就可以左右移动条来翻阅日历简介了。
三、实验结果
四、心得体会
这次实验我选了java日历软件。在学习了图形界面(GUI)设计后,我知道了窗口里面板,标签,文本框的基本设置和代码应用。但是就单单简单地添加几个组件画面难免显得简单,因此我在网上查询代码分别给面板增添了背景色,给我的信息字体设置了字体,大小,还给最下一栏日理由来增加了滚动条。通过这次学习,我发现书上很多知识只有在实际编写代码运用到时才能有更好的理解,而且我未知的函数好还有很多,需要我去主动探索学习。
五、源代码及注释
import java.awt.*;import java.awt.event.*;import javax.swing.*;public class Calendar extends JFrame implements ActionListener { static int year,month;
//设置静态变量 private String [] ast = {“
星期日”,“
星期一”, “
星期二”, “
星期三”, “
星期四”, “
星期五”, “
星期六”};private JLabel [] ai = new JLabel[49];private JLabel label0,label1,label2,label00,label4,label5;
//定义标签
private JTextField t0,t1;
//定义文本输入框
private JButton btn1;
//定义按钮
private JPanel p0,p1,p2,p4;
//定义静态面板
private JScrollPane p3;
//定义滚动面板
public Calendar(){
super(“简易日历”);//窗口名字
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//窗口关闭函数
this.setBounds(100,100,800,600);//窗口尺寸 和位置
Container c=getContentPane();
p1 = new JPanel();//建立新面板
p0 = new JPanel();
p2 = new JPanel(new GridLayout(7,7,10,1));//设置网格布局
p4 = new JPanel(new GridLayout(7,20,10,1));
final JScrollPane p3 = new JScrollPane(p0);//将面板p0导入滚动面板p3
this.add(p3);
p3.setPreferredSize(new Dimension(100, 50));设置p3大小
label0=new JLabel(“
年份(如:2016)”);//标签赋值
label1=new JLabel(“
月份(如: 3)”);
label2=new JLabel(“");
label00=new JLabel(”
我国始有历法大约在四千多年以前。根据甲骨文中的一 页甲骨历,证明殷代的历法已具有相当的水平,这一页甲骨。历是全人类最古老的历书实物,这页甲骨历也就叫日历。但真正的日历产生,大约在一千一百多年前的唐顺宗永贞元年,皇宫中就已经使用皇历。最初一天一页,记载国家、宫廷大事和皇帝的言行。皇历分为十二册,每册的页数和每月的天数一样,每一页都注明了天数和日期。发展到后来,就把月日、于支、节令等内容事先写在上面,下部空白处留待记事,和现在的“台历”相似。那时,服侍皇帝的太监在日历空白处记下皇帝的言行,到了月终,皇帝审查证明无误后,送交史官存档,这在当时叫日历,这些日.历以后就作为史官编写《国史》的依据。后来,朝廷大臣们纷纷仿效,编制自家使用的日历。至于月历以后又发展成挂历、台历等各种形式,只是近一个世纪的事。随着时代的发展,·尽管日历的品种增多、花样也不断翻新,但仍旧保持着古老日历的格局。“);
label4=new JLabel(”
信息工程27班项明钧“);
JLabel label5 = new JLabel(new ImageIcon(”E:/timg.jpg“));
//从本地文件夹导入图片
label4.setFont(new Font(”宋体“, Font.BOLD, 20));
//设置字体大小
t0=new JTextField(5);//文本框
t1=new JTextField(3);
btn1=new JButton(”search“);//按钮
int i;
//日历面板分块函数
for(i=0;i<7;i++)
p2.add(ai[i]=new JLabel(ast[i]));
//将星期日到星期六赋给第一行
for(i= 7;i < 49;i++)
p2.add(ai[i]=new JLabel(”“));
//定义为空,为填入日期做准备
p1.add(label0);
p1.add(t0);
p1.add(label1);
//将标签导入面板
p1.add(t1);
p1.add(btn1);
p1.add(label2);
p0.add(label00);
p4.add(label5);
p4.add(label4);
c.add(p1,BorderLayout.NORTH);
//设置面板位置
c.add(p2,BorderLayout.CENTER);
c.add(p3,BorderLayout.SOUTH);
c.add(p4,BorderLayout.EAST);
btn1.addActionListener(this);
//注册监视器
t0.addActionListener(this);
t1.addActionListener(this);
p2.setBackground(Color.LIGHT_GRAY);
//设置面板背景颜色
p1.setBackground(Color.red);
p3.setBackground(Color.green);
p4.setBackground(Color.magenta);
this.setVisible(true);
//显示窗口
}
public static void main(String[] args)
//主函数
{
Calendar a=new Calendar();
a.showCalendar(2016,1);
//初始化日期2016年1月
}
//事件处理方法
public void actionPerformed(ActionEvent e){
if(e.getSource()== t0 || e.getSource()== t1 || e.getSource()== btn1)
{
Try
//控制输入的年份正确,异常控制
{
if(t0.getText().length()!= 4)
throw new NumberFormatException();
}
catch(NumberFormatException ex)
{
return;
}
String s1=t0.getText();
//获取输入年份
year=Integer.parseInt(s1);
//将输入年的字符串转换为int类型
String s2=t1.getText();
//将输入月 的字符串转换为int类型
month=Integer.parseInt(s2);
showCalendar(year,month);
//调用网格日历显示函数
} }
public void showCalendar(int year,int month)
//定义网格日历显示函数
{
int monthDay=getMonthDay(year,month);
//获取一个月几天
int startDay=getStartDay(year,month);
//获取一个月开始星期几
//显示当前窗口中显示日历的年月
String rr=”
当前日历“+”(“+Integer.toString(year)+”-“+Integer.toString(month)+”)“;
label2.setText(rr);
//控制各月日历的正确显示
int i;
} for(i= 7;i < startDay+7;i++)ai[i].setText(”“);for(i =startDay+7;i String bb;//存在意义:便于实现setText函数的带格式输入 if(i-startDay-6<10) bb=” “+Integer.toString(i-startDay-6);//将int型转换为String型 else bb=” “+Integer.toString(i-startDay-6); ai[i].setText(bb);} for(i=startDay + monthDay + 7;i<49;i++)ai[i].setText(”"); //leapYear:判断闰年 public static boolean leapYear(int year){ if((year % 400 == 0)||((year % 4 == 0)&&(year % 100!= 0))) return true;return false;} //getMonthDay获取每月总天数 public static int getMonthDay(int year, int month) { if(month == 1 || month==3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) return 31; if(month == 4 || month == 6 || month == 9 || month == 11) return 30; if(month == 2) if(leapYear(year)) //闰年二月29天 return 29; else return 28; return 0;//if month is incorrect.//如果月份输入错误返回0.} //getStartDay:返回每月第一天是周几 public static int getStartDay(int year,int month){ //从1800年1月1日开始 int startDay1800 = 3; long totalDays = getTotalDays(year, month); return(int)((totalDays + startDay1800)% 7);} //从1800年1月1日到所查月份的总天数 public static long getTotalDays(int year, int month){ long total = 0; for(int i = 1800;i < year;i++) if(leapYear(i)) total = total + 366; else total = total + 365; for(int i = 1;i < month;i++) total = total + getMonthDay(year, i); return total;} } 电子工程学院 ASIC专业实验报告 班级: 姓名: 学号: 班内序号: 第一部分 语言级仿真 LAB 1:简单的组合逻辑设计一、二、实验目的 实验原理 掌握基本组合逻辑电路的实现方法。 本实验中描述的是一个可综合的二选一开关,它的功能是当sel = 0时,给出out = a,否则给出结果out = b。在Verilog HDL中,描述组合逻辑时常使用assign结构。equal=(a==b)?1:0是一种在组合逻辑实现分支判断时常用的格式。parameter定义的size参数决定位宽。测试模块用于检测模块设计的是否正确,它给出模块的输入信号,观察模块的内部信号和输出信号。 三、源代码 mux.v module scale_mux(out,sel,b,a);parameter size=1;output[size-1:0] out;input[size-1:0]b,a;input sel;assign out =(!sel)?a: (sel)?b: {size{1'bx}};endmodule mux_test.v `define width 8 `timescale 1 ns/1 ns module mux_test; reg[`width:1]a,b; wire[`width:1]out; reg sel; scale_mux#(`width)m1(.out(out),.sel(sel),.b(b),.a(a)); initial begin $monitor($stime,“sel=%b a=%b b=%b out=%b”,sel,a,b,out); $dumpvars(2,mux_test); sel=0;b={`width{1'b0}};a={`width{1'b1}}; #5sel=0;b={`width{1'b1}};a={`width{1'b0}}; #5sel=1;b={`width{1'b0}};a={`width{1'b1}}; #5sel=1;b={`width{1'b1}};a={`width{1'b0}}; #5 $finish; end endmodule 四、仿真结果与波形 LAB 2:简单时序逻辑电路的设计一、二、实验目的 实验原理 掌握基本时序逻辑电路的实现。 在Verilog HDL中,相对于组合逻辑电路,时序逻辑电路也有规定的表述方式。在可综合的Verilog HDL模型中,我们常使用always块和@(posedge clk)或@(negedge clk)的结构来表述时序逻辑。 在always块中,被赋值的信号都必须定义为reg型,这是由时序逻辑电路的特点所决定的对于reg型数据,如果未对它进行赋值,仿真工具会认为它是不定态。为了正确地观察到仿真结果,在可综合的模块中我们通常定义一个复位信号rst-,当它为低电平时对电路中的寄存器进行复位。 三、源代码 counter.v `timescale 1 ns/100 ps module counter(cnt,clk,data,rst_,load);output[4:0]cnt;input [4:0]data;input clk;input rst_;input load;reg [4:0]cnt; always@(posedge clk or negedge rst_) if(!rst_) #1.2 cnt<=0; else if(load) cnt<=#3 data; else cnt<=#4 cnt + 1; endmodule counter_test.v `timescale 1 ns/1 ns module counter_test; wire[4:0]cnt; reg [4:0]data; reg rst_; reg load; reg clk; counter c1 (.cnt(cnt),.clk(clk),.data(data),.rst_(rst_),.load(load)); initial begin clk=0; forever begin #10 clk=1'b1; #10 clk=1'b0; end end initial begin $timeformat(-9,1,“ns”,9); $monitor(“time=%t,data=%h,clk=%b,rst_=%b,load=%b,cnt=%b”,$stime,data,clk,rst_,load,cnt); $dumpvars(2,counter_test); end task expect;input [4:0]expects; if(cnt!==expects)begin $display(“At time %t cnt is %b and should be %b”,$time,cnt,expects); $display(“TEST FAILED”); $finish; end endtask initial begin @(negedge clk) {rst_,load,data}=7'b0_X_XXXXX;@(negedge clk)expect(5'h00); {rst_,load,data}=7'b1_1_11101;@(negedge clk)expect(5'h1D); {rst_,load,data}=7'b1_0_11101; repeat(5)@(negedge clk); expect(5'h02); {rst_,load,data}=7'b1_1_11111;@(negedge clk)expect(5'h1F); {rst_,load,data}=7'b0_X_XXXXX;@(negedge clk)expect(5'h00); $display(“TEST PASSED”); $finish; end endmodule 四、仿真结果与波形 五、思考题 该电路中,rst-是同步还是异步清零端? 在counter.v的always块中reset没有等时钟,而是直接清零。所以是异步清零端。 LAB 3:简单时序逻辑电路的设计一、二、实验目的 实验原理 使用预定义的库元件来设计八位寄存器。 八位寄存器中,每一位寄存器由一个二选一MUX和一个触发器dffr组成,当load=1,装载数据;当load=0,寄存器保持。对于处理重复的电路,可用数组条用的方式,使电路描述清晰、简洁。 三、源代码 clock.v `timescale 1 ns /1 ns module clock(clk);reg clk;output clk;initial begin clk=0;forever begin #10 clk=1'b1;#10 clk=1'b0;end end endmodule mux及dffr模块调用代码 mux mux7(.out(n1[7]),.sel(load),.b(data[7]),.a(out[7]));dffr dffr7(.q(out[7]),.d(n1[7]),.clk(clk),.rst_(rst_));mux mux6(.out(n1[6]),.sel(load),.b(data[6]),.a(out[6]));dffr dffr6(.q(out[6]),.d(n1[6]),.clk(clk),.rst_(rst_));mux mux5(.out(n1[5]),.sel(load),.b(data[5]),.a(out[5]));dffr dffr5(.q(out[5]),.d(n1[5]),.clk(clk),.rst_(rst_));mux mux4(.out(n1[4]),.sel(load),.b(data[4]),.a(out[4]));dffr dffr4(.q(out[4]),.d(n1[4]),.clk(clk),.rst_(rst_)); mux mux3(.out(n1[3]),.sel(load),.b(data[3]),.a(out[3]));dffr dffr3(.q(out[3]),.d(n1[3]),.clk(clk),.rst_(rst_));mux mux2(.out(n1[2]),.sel(load),.b(data[2]),.a(out[2]));dffr dffr2(.q(out[2]),.d(n1[2]),.clk(clk),.rst_(rst_));mux mux1(.out(n1[1]),.sel(load),.b(data[1]),.a(out[1]));dffr dffr1(.q(out[1]),.d(n1[1]),.clk(clk),.rst_(rst_));mux mux0(.out(n1[0]),.sel(load),.b(data[0]),.a(out[0]));dffr dffr0(.q(out[0]),.d(n1[0]),.clk(clk),.rst_(rst_)); 例化寄存器 register r1(.data(data),.out(out),.load(load),.clk(clk),.rst_(rst_));例化时钟 clock c1(.clk(clk)); 添加检测信号 initial begin $timeformat(-9,1,“ns”,9);$monitor(“time=%t,clk=%b,data=%h,load=%b,out=%h”, $stime,clk,data,load,out);$dumpvars(2,register_test);end 四、仿真结果与波形 LAB 4:用always块实现较复杂的组合逻辑电路 一、实验目的 掌握用always实现组合逻辑电路的方法; 了解assign与always两种组合逻辑电路实现方法之间的区别。 二、实验原理 仅使用assign结构来实现组合逻辑电路,在设计中会发现很多地方显得冗长且效率低下。适当地使用always来设计组合逻辑,会更具实效。 本实验描述的是一个简单的ALU指令译码电路的设计示例。它通过对指令的判断,对输入数据执行相应的操作,包括加、减、或和传数据,并且无论是指令作用的数据还是指令本身发生变化,结果都要做出及时的反应。 示例中使用了电平敏感的always块,电平敏感的触发条件是指在@后括号内电平列表的任何一个电平发生变化就能触发always块的动作,并且运用了case结构来进行分支判断。 在always中适当运用default(在case结构中)和else(子if…else结构中),通常可以综合为纯组合逻辑,尽管被赋值的变量一定要定义为reg型。如果不使用default或else对缺省项进行说明,易产生意想不到的锁存器。 三、源代码 电路描述 always@(opcode or data or accum)begin if(accum==8'b00000000)#1.2 zero=1;else #1.2 zero=0; case(opcode)PASS0: #3.5 out =accum;PASS1: #3.5 out =accum;ADD: #3.5 out = data + accum;AND: #3.5 out =data&accum;XOR: #3.5 out =data^accum;PASSD: #3.5 out=data;PASS6:#3.5 out=accum;PASS7:#3.5 out=accum;default:#3.5 out=8'bx;endcase end 四、仿真结果与波形 LAB 5:存储器电路的设计一、二、实验目的 实验原理 设计和测试存储器电路。 本实验中,设计一个模块名为mem的存储器仿真模型,该存储器具有双线数据总线及异步处理功能。由于数据是双向的,所以要注意,对memory的读写在时序上要错开。 三、源代码 自行添加的代码 assign data=(read)?memory[addr]:8'hZ; always @(posedge write)begin memory[addr]<=data[7:0];end 四、仿真结果与波形 LAB 6:设计时序逻辑时采用阻塞赋值与非阻塞赋值的区别 一、实验目的 明确掌握阻塞赋值与非阻塞赋值的概念和区别; 了解阻塞赋值的使用情况。 二、实验原理 在always块中,阻塞赋值可以理解为赋值语句是顺序执行的,而非阻塞赋值可以理解为并发执行的。实际时序逻辑设计中,一般情况下非阻塞赋值语句被更多的使用,有时为了在同一周期实现相互关联的操作,也使用阻塞赋值语句。 三、源代码 blocking.v `timescale 1 ns/ 100 ps module blocking(clk,a,b,c); output[3:0]b,c; input [3:0]a; input clk; reg [3:0]b,c; always@(posedge clk) begin b =a; c =b; $display(“Blocking: a=%d,b=%d,c=%d.”,a,b,c); end endmodule non_blocking.v `timescale 1 ns/ 100 ps module non_blocking(clk,a,b,c); output[3:0] b,c;input[3:0] a;input clk;reg [3:0]b,c;always @(posedge clk)begin b<=a;c<=b;$display(“Non_blocking:a=%d,b=%d,c=%d”,a,b,c);end endmodule compareTop.v `timescale 1 ns/ 100 ps module compareTop;wire [3:0] b1,c1,b2,c2;reg[3:0]a;reg clk;initial begin clk=0;forever #50 clk=~clk;end initial $dumpvars(2,compareTop);initial begin a=4'h3;$display(“_______________________________”);# 100 a =4'h7;$display(“_______________________________”);# 100 a =4'hf;$display(“_______________________________”);# 100 a =4'ha;$display(“_______________________________”);# 100 a =4'h2;$display(“_______________________________”);# 100 $display(“_______________________________”);$finish;end non_blocking nonblocking(clk,a,b2,c2);blocking blocking(clk,a,b1,c1);endmodule 四、仿真结果与波形 LAB 7:利用有限状态机进行复杂时序逻辑的设计一、二、实验目的 实验原理 掌握利用有限状态机(FSM)实现复杂时序逻辑的方法。 控制器是CPU的控制核心,用于产生一系列的控制信号,启动或停止某些部件。CPU何时进行读指令,何时进行RAM和I/O端口的读写操作等,都由控制器来控制。 三、源代码 补充代码 nexstate<=state+1'h01;case(state)1:begin sel=1;rd=0;ld_ir=0;inc_pc=0;halt=0;ld_pc=0;data_e=0;ld_ac=0;wr=0;end 2:begin sel=1;rd=1;ld_ir=0;inc_pc=0;halt=0;ld_pc=0;data_e=0;ld_ac=0;wr=0;end 3:begin sel=1;rd=1;ld_ir=1;inc_pc=0;halt=0;ld_pc=0;data_e=0;ld_ac=0;wr=0;end 4:begin sel=1;rd=1;ld_ir=1;inc_pc=0;halt=0;ld_pc=0;data_e=0;ld_ac=0;wr=0;end 5:begin sel=0;rd=0;ld_ir=0;inc_pc=1;ld_pc=0;data_e=0;ld_ac=0;wr=0;if(opcode==`HLT)halt=1;end 6:begin sel=0;rd=alu_op;ld_ir=0;inc_pc=0;halt=0;ld_pc=0;data_e=0;ld_ac=0;wr=0;end 7:begin sel=0;rd=alu_op;ld_ir=0;halt=0;data_e=!alu_op;ld_ac=0;wr=0;if(opcode==`SKZ)inc_pc<=zero;if(opcode==`JMP)ld_pc=1;end 0:begin sel=0;rd=alu_op;ld_ir=0;halt=0;data_e=!alu_op;ld_ac=alu_op;inc_pc=(opcode==`SKZ)&zero||(opcode==`JMP);if(opcode==`JMP)ld_pc=1;if(opcode==`STO)wr=1;end //default:begin sel=1'bZ;rd=1'bZ;ld_ir=1'bZ;inc_pc=1'bZ;halt=1'bZ;ld_pc=1'bZ;data_e=1'bZ;ld_ac=1'bZ;wr=1'bZ;end endcase end control_test.v /***************************** * TEST BENCH FOR CONTROLLER * *****************************/ `timescale 1 ns / 1 ns module control_test; reg [8:0] response [0:127]; reg [3:0] stimulus [0:15]; reg [2:0] opcode; reg clk; reg rst_; reg zero; integer i,j; reg[(3*8):1] mnemonic; // Instantiate controller control c1(rd , wr , ld_ir , ld_ac , ld_pc , inc_pc , halt , data_e , sel , opcode , zero , clk , rst_); // Define clock initial begin clk = 1; forever begin #10 clk = 0; #10 clk = 1; end end // Generate mnemonic for debugging purposes always @(opcode) begin case(opcode) 3'h0 : mnemonic = “HLT”; 3'h1 : mnemonic = “SKZ”; 3'h2 : mnemonic = “ADD”; 3'h3 : mnemonic = “AND”; 3'h4 : mnemonic = “XOR”; 3'h5 : mnemonic = “LDA”; 3'h6 : mnemonic = “STO”; 3'h7 : mnemonic = “JMP”; default : mnemonic = “???”; endcase end // Monitor signals initial begin $timeformat(-9, 1, “ ns”, 9); $display(“ time rd wr ld_ir ld_ac ld_pc inc_pc halt data_e sel opcode zero state”); $display(“--------------------------------------------------------------”);// $shm_open(“waves.shm”);// $shm_probe(“A”);// $shm_probe(c1.state); end // Apply stimulus initial begin $readmemb(“stimulus.pat”, stimulus); rst_=1; @(negedge clk)rst_ = 0; @(negedge clk)rst_ = 1; for(i=0;i<=15;i=i+1) @(posedge ld_ir) @(negedge clk) { opcode, zero } = stimulus[i]; end // Check response initial begin $readmemb(“response.pat”, response); @(posedge rst_) for(j=0;j<=127;j=j+1) @(negedge clk) begin $display(“%t %b %b %b %b %b %b %b %b %b %b %b”,$time,rd,wr,ld_ir,ld_ac,ld_pc,inc_pc,halt,data_e,sel,opcode,zero,c1.state); if({rd,wr,ld_ir,ld_ac,ld_pc,inc_pc,halt,data_e,sel}!== response[j]) begin : blk reg [8:0] r; r = response[j]; $display("ERRORTEST1 PASSED! 111_00000 // 18 JMP BEGIN //run test again @1A 00000000 // 1A DATA_1: //constant 00(hex) 11111111 // 1B DATA_2: //constant FF(hex) 10101010 // 1C TEMP: //variableTEST2 PASSED! 111_00000 // 11 JMP BEGIN //run test again @1A 00000001 // 1A DATA_1: //constant 1(hex) 10101010 // 1B DATA_2: //constant AA(hex) 11111111 // 1C DATA_3: //constant FF(hex) 00000000 // 1D TEMP: CPUtest3.dat //opcode_operand // addr assembly code //--------------//------------------------- 111_00011 // 00 JMP LOOP //jump to the address of LOOP @03 101_11011 // 03 LOOP: LDA FN2 //load value in FN2 into accum 110_11100 // 04 STO TEMP //store accumulator in TEMP 010_11010 // 05 ADD FN1 //add value in FN1 to accumulator 110_11011 // 06 STO FN2 //store result in FN2 101_11100 // 07 LDA TEMP //load TEMP into the accumulator 110_11010 // 08 STO FN1 //store accumulator in FN1 100_11101 // 09 XOR LIMIT //compare accumulator to LIMIT 001_00000 // 0A SKZ //if accum = 0, skip to DONE 111_00011 // 0B JMP LOOP //jump to address of LOOP 000_00000 // 0C DONE: HLT //end of program 101_11111 // 0D AGAIN: LDA ONE 110_11010 // 0E STO FN1 101_11110 // 0F LDA ZERO 110_11011 // 10 STO FN2 111_00011 // 11 JMP LOOP //jump to address of LOOP @1A 00000001 // 1A FN1: //variablestores 2nd Fib.No.00000000 // 1C TEMP: //temporary variable 10010000 // 1D LIMIT: //constant 144stores 1st Fib.No.00000101 // 1B data2: //5 variablemax value 00000110 // 1E LIMIT: // 6 constant 1 11111111 // 1F AND1: //FF and 四、仿真结果与波形 第二部分 电路综合一、二、三、四、实验目的 实验内容 源代码 门级电路仿真结果与波形 掌握逻辑综合的概念和流程,熟悉采用Design Compiler进行逻辑综合的基本方法。采用SYNOPSYS公司的综合工具Design Compiler对实验7的control.v做综合。与实验指导书中相同。 五、思考题 1.control_pad.v文件是verilog语言及的描述还是结构化的描述? 是结构化的描述。 2.control_pad.sdf文件中,对触发器的延迟包括哪些信息? 包括对逻辑单元和管脚的上升/下降时延的最大值、最小值和典型值。 第三部分 版图设计一、二、三、四、实验目的 实验内容 源代码 仿真结果与波形 掌握版图设计的基本概念和流程,熟悉采用Sysnopsys ICC工具进行版图设计的方法。对电路综合输出的门级网表control_pad.v进行布局布线。与实验指导书中相同。布局规划后结果 未产生core ring和mesh前 产生core ring和mesh后 电源线和电影PAD连接后 filler PAD填充后 布局后结果 时钟树综合后结果 布线后结果 寄生参数的导出和后仿 五、思考题 1.简述ICC在design setup阶段的主要工作。 创建设计库,读取网表文件并创建设计单元,提供并检查时间约束,检查时钟。在对之前的数据与信息进行读取与检查后保存设计单元。2.为什么要填充filler pad? filler pad把分散的pad单元连接起来,把pad I/O区域供电连成一个整体。使它们得到持续供电并提高ESD保护能力。3.derive_pg_connection的作用是什么? 描述有关电源连接的信息。4.简述floorplan的主要任务。 对芯片大小、输入输出单元、宏模块进行规划,对电源网络进行设计。5.简述place阶段的主要任务。 对电路中的延时进行估计与分析,模拟时钟树的影响,按照时序要求,对标准化单元进行布局。 6.简述CTS的主要步骤。 设置时钟树公共选项;综合时钟树;重新连接扫描链;使能传播时钟;Post-CTS布局优化;优化时钟偏移;优化时序。 实验总结 经过数周的ASIC专业实验,我对芯片设计流程、Verilog HDL语言、Linux基本指令和Vi文本编辑器有了基本的了解。虽然之前对芯片设计、VHDL一无所知,但通过实验初步熟悉了ASIC的体系结构和VHDL的基本语法,对电路中时钟、寄生参数、元件布局带来的影响也有了了解。我在实验中也遇到了许多问题,但我在老师、助教、同学的帮助下解决了这些问题,也有了更多收获。通过这次ASIC专业实验,我加深了对本专业的认识。我会继续努力成为合格的电子人。 北京邮电大学 信息网络应用基础实验报告 实验一 静态网页的设计 学院:电子工程学院 班级: 姓名: 学号: 一、实验主题 1、设计主题:本次实验我设计的该网页主题是围绕当前热门的多人联机在线网游DOTA2进行的。并对该游戏的由来、背景及其内容做了一些简要的描述。 2、功能:在主页中可以观看该游戏的宣传视频以及该游戏的一些精美的图片,并且通过选择相应选项可以了解更多的游戏内容。 3、运行流程: ① 首先打开主页时可以选择播放视频,并且看到丰富的图片; ② 然后点击相应的选项可以进入到分别的附页中查看内容; ③ 并且在主页点击最下的图片可以回到主页顶部,在其他页面点击最下的图片也可以回到主页。 4、实现功能的html技术: ① 在主页中观看视频利用的是html多媒体中的 ② 在页面中的图片是利用了html多媒体中的标签进行图片的加入; ③ 设置页面的背景图片是在第三篇:北邮电子院专业实验报告
第四篇:北邮-信息与网络实验报告一
④ 在页面内、本机页面间及本机文档连接互联网页面时则是利用了超链接的三种方法建立;
⑤ 在页面中显示表格则是利用了相关的表格创建的语句来建立一个表格,并且可以对表格中插入图片并且可以改变表格的背景颜色以及背景图片。
二、实验内容运行结果
① 打开主页可以看到插入的图片以及背景图片
② 点击页面中插入的视频,点击播放即可以进行播放
插入视频的html代码如下:
③ 点击主页中的超链接则可以跳转到相应的页面。如:
点击英雄介绍链接
则可以显示英雄介绍页面
当选择一个类型的英雄时可以在本页面跳转到对应类型的介绍
当选择某个英雄时则可以链接到互联网上的详细介绍页面
④ 当在副页面点击最下面的图片则可以跳转到主页面
⑤ 在页面中建立的表格并且改变表格背景颜色并且插入图片
三、实验心得与感受
本次实验真正的了解到了如何设计一个最基本的网页,也是将所学的html语言的知识进行了充分的应用,也对这些知识有了更加可视化的了解。由于是第一次进行网页的设计,我选择的是利用记事本来编辑html代码来进行设计的,由于代码都是利用各种标签手动输入的,所以对语句有了深刻的记忆,包括在以后的学习中也会很好的利用它们。我认为这样相对于利用dreamweaver来设计有很多的好处,因为这样第一次可以让我们了解页面的每一部分是怎么实现的,不过在了解过后可以选择软件来设计,因为那样更加具有可视化且方便。
在设计的过程中,也遇到了不少的困难。首先感觉就是对于一个网页的背景图片选择来说比较困难,因为在网页中不会对一个图片进行伸缩,显示的是图片本身的大小,所以只好找到与页面较符合的图片。而且在插入视频时,我利用书中的代码写入时不能在页面中无法播放视频。后来我在网上查阅相关资料,后来直接利用视频网站中的分享视频的代码加入即可在页面中显示一个可播放的视频。
通过这个实验来进行静态网页的设计还是很有意思的,既能学到知识又能了解自己喜欢的东西,而且在网页完成后再进行浏览是一件很有成就感的事情!
第五篇:北邮电子院嵌入式实验报告大四上
嵌入式实验报告
学院: 电子工程学院
一、实验目的
1、了解嵌入式系统及其相关基础知识。
2、了解宿主PC机与PXA270目标版,能正确连接宿主PC机与PXA270目标版。
3、学会在宿主机上安装Linux操作系统——RedHat9.0。、4、学会建立宿主PC机端的开发环境。
5、学会配置宿主PC机端的超级终端。
6、配置宿主PC机端的TFTP服务,并开通此服务。
7、配置宿主PC机端的NFS服务,并开通此服务。
8、学会简单Linux驱动程序的设计。
二、实验内容
(一)基本实验
实验一到六为基础实验,主要是为了在熟悉实验操作平台的同时为后续实验搭建好软、硬件环境,配置好相关的协议、服务。
其中实验一是各个硬件的互联,搭建好了实验的硬件环境。实验二是在宿主PC端安装虚拟机,提供了实验需要的Linux操作系统。实验三是宿主PC端开发环境的安装与配置。
实验四是配置宿主PC机端的超级终端,使PC机与PXA270目标板之间可以通过串口通讯。在每次重启宿主PC机时,都需要重新将超级终端挂载到虚拟机上,挂载之前须通过ifconfig命令查看该机的IP地址,若其已经复位,须用命令:ifconfig eth0 192.168.0.100 up重置宿主PC机的IP地址。挂载虚拟机的代码为:
root ifconfig eth0 192.168.0.50 up mount –o nolock 192.168.0.100:/ /mnt 实验五是配置宿主PC机的TFTP服务。TFTP是简单文件传输协议。每次重启宿主PC机时,都要重启该服务,重启命令为:
service xinetd restart。
实验六是配置宿主PC机端NFS服务。NFS是指网络文件系统,它实现了文件在不同的系统间使用。当使用者想用远端档案时,只需调用“mount”就可以远端系统挂接在自己的档案系统之下。每次重启宿主PC机时,也都要重启该服务,重启命令为: service nfs restart service nfs restart
(二)基本接口实验
实验
十二、简单设备驱动程序
本次实验的目的是让我们动手实践一个简单的字符型设备驱动程序,学习Linux驱动程序构架,学习在应用程序中调用驱动。驱动程序代码及注释为: // 头文件
#include
#define VERSION “PXA2700EP-SIMPLE_HELLO-V1.00-060530” // 定义版本号 void showversion(void)//显示版本的函数 { printk(“***************************************”);printk(“t %s tn”,VERSION);printk(“***************************************”);}
/*-------read:用于在指定文件描述符中读取数据 file:是文件指针 buf:读取数据缓存区 count:请求传输的字节数 f_ops:文件当前偏移量
当读取标识符OURS_HELLO_DEBUG时,打印信息,然后返回count----------*/ ssize_t SIMPLE_HELLO_read(struct file * file ,char * buf, size_t count, loff_t * f_ops){ #ifdef OURS_HELLO_DEBUG
printk(“SIMPLE_HELLO_read[--kernel--]n”);#endif return count;}
/*-----write:用于向打开的文件写数据 file:是文件指针 buf:写入数据缓存区 count:求传输的字节数 f_ops:文件当前偏移量
当读取标识符OURS_HELLO_DEBUG时,打印信息,然后返回count----------*/ ssize_t SIMPLE_HELLO_write(struct file * file ,const char * buf, size_t count, loff_t * f_ops){ #ifdef OURS_HELLO_DEBUG
printk(“SIMPLE_HELLO_write[--kernel--]n”);#endif
return count;}
/*-----ioctl:对设备的I/O通道进行管理的函数 inode:设备节点
flip:打开的一个文件
cmd:驱动程序的特殊命令编号 data:接收剩余参数
----------*/ ssize_t SIMPLE_HELLO_ioctl(struct inode * inode ,struct file * file, unsigned int cmd, long data){ #ifdef OURS_HELLO_DEBUG
printk(“SIMPLE_HELLO_ioctl[--kernel--]n”);#endif return 0;}
/*----------open:打开函数
inode:打开文件所对应的i节点,获取从设备号 flip:打开的一个文件
open()方法最重要的是调用了宏MOD_INC_USE_COUNT,这个宏主要用来使驱动程序使用计数器,避免不正确卸载程序
----------*/ ssize_t SIMPLE_HELLO_open(struct inode * inode ,struct file * file){ #ifdef OURS_HELLO_DEBUG
printk(“SIMPLE_HELLO_open[--kernel--]n”);#endif MOD_INC_USE_COUNT;return 0;}
/*----------released:关闭函数
Inode:打开文件所对应的i节点,主要获取从设备号 flip:打开的一个文件
release()方法最重要的是调用了宏MOD_DEC_INC_USE_COUNT,这个宏主要用来减少驱动程序使用计数器
----------*/ ssize_t SIMPLE_HELLO_release(struct inode * inode ,struct file * file){ #ifdef OURS_HELLO_DEBUG
printk(“SIMPLE_HELLO_release[--kernel--]n”);#endif MOD_DEC_INC_USE_COUNT;return 0;}
struct file_operations HELLO_ops ={ // SIMPLE_HELLO设备向系统注册
open: SIMPLE_HELLO_open, read: SIMPLE_HELLO_read, write: SIMPLE_HELLO_write, ioctl: SIMPLE_HELLO_ioctl, release: SIMPLE_HELLO_release, };
/*----------INIT:驱动程序初始化
devfs_register_chrdev(SIMPLE_HELLO_MAJOR,“hello_serial_ctl”,& HELLO_ops)最为主要
devfs_register_chrdev注册设备驱动程序,包括主设备号、驱动程序名、结构体指针----------*/ static int __init HW_ HELLO_init(void){ int ret =-ENODEV;
ret = devfs_register_chrdev(SIMPLE_HELLO_MAJOR, “hello_serial_ctl”,& HELLO_ops);
showversion();
if(ret<0)
{
printk(“pxa270 init_module failed with %d n[--kernel--]”,ret);
}
else
{
printk(“pxa270 hello_driver register success!![--kernel--]n”);
} return ret;}
static int __init pxa270_ HELLO_init(void)//模块初始化函数,调用HW_ HELLO_init 函数
{ int ret =-ENODEV;
#ifdef OURS_HELLO_DEBUG
printk(“pxa270_ HELLO_init[--kernel--]n”);
#endif ret = HW_ HELLO_init();if(ret)return ret;return 0;}
/*----------模块卸载函数
devfs_unregister_chrdev(SIMPLE_HELLO_MAJOR,“hello _ctl”)最为主要 devfs_unregister_chrdev卸载设备驱动程序,包括主设备号、驱动程序名
----------*/ static void __exit cleanup_ HELLO_ctl(void){ #ifdef OURS_HELLO_DEBUG
printk(“cleanup_HELLO_ctl[--kernel--]n”);#endif devfs_unregister_chrdev(SIMPLE_HELLO_MAJOR, “hello_ctl”);}
MODULE_DESCRIPTION(“simple hello driver module”);//描述信息 MODULE_AUTHOR(“liduo”);
//驱动程序作者姓名 MODULE_LICENSE(“GPL”);module_init(pxa270_HELLO_init);
//指定驱动程序初始化函数 module_exit(cleanup _HELLO_ctl);
//指定驱动程序卸载函数
Makefile文件代码:
#TOPDIR:=$(shell cd..;pwd)TOPDIR:=.KERNELDIR=/pxa270_linux/linux INCLUDEDIR=$(KERNELDIR)/include CROSS_COMPILE=arm-linux-
AS =$(CROSS_COMPILE)as LD =$(CROSS_COMPILE)ld CC =$(CROSS_COMPILE)gcc CPP =$(CC)-E AR =$(CROSS_COMPILE)ar NM =$(CROSS_COMPILE)nm STRIP =$(CROSS_COMPILE)strip OBJCOPY=$(CROSS_COMPILE)objcopy OBJDUMP=$(CROSS_COMPILE)objdump
CFLAGS+=-I..CFLAGS+=-Wall –O –D_KERNEL_-DMODULE –I$(INCLUDEDIR)
TARGET = pxa270_hello_drv.o modules: $(TARGET)
all: $(TARGET)
pxa270_hello_drv.o:pxa270_hello_drv.c $(CC)-c $(CFLAGS)$^-o $@
clean: rm-f *.o *~ core.depend Makefile文件的内容用于执行编译工作,一个Makefile文件包括:① 由make工具创建的目标体(target),通常是目标文件或可执行文件;② 要创建目标体所依赖的文件(dependency_file);③ 创建每个目标需要运行的命令(command)。
以上两个文件编辑完成后后,用make modules编译驱动程序,编写测试文件simple_test_driver.c,然后GCC编辑器编译测试程序生成测试文件。成功生成测试文件后用超级终端开始挂载,加载驱动程序,使用命令./test测试,观察测试结果,实验完成。
实验十三 CPU GPIO驱动程序设计
本实验是让我们在linux系统中插入自己的驱动程序,调用它。实现用CPU GPIO控制外部LED,利用PXA270核心板上的LED验证我们的工作。驱动程序代码:
驱动程序代码与实验十二无大区别,下面列出需要补充的代码。
一、补充代码
补充代码1:
#ifdef OURS_GPIO_LED_DEBUG printk(“SIMPLE_GPIO_LED_write [--kernel--]n”);#endif return count;
补充代码2:
#ifdef OURS_GPIO_LED_DEBUG printk(“SIMPLE_GPIO_LED_open [--kernel--]n”);#endif
补充代码3:
open: SIMPLE_GPIO_LED_open, read: SIMPLE_GPIO_LED_read, write: SIMPLE_GPIO_LED_write, ioctl: SIMPLE_GPIO_LED_ioctl, release: SIMPLE_GPIO_LED_release, 不同之处:GPIO_LED,主文件名、二、Makefile文件:
将实验十二相关代码作如下修改即可: TARGET = pxa270_gpio_led_drv.o modules: $(TARGET)
all: $(TARGET)
pxa270_gpio_led_drv.o:pxa270_gpio_led_drv.c $(CC)-c $(CFLAGS)$^-o $@
三、作业代码
要求:使得目标板的核心板上的LED闪烁产生亮7秒,灭5秒的效果。作业主要代码:
while(1)
{ ioctl(fd,LED_OFF);
sleep(5);//原来为sleep(1);
ioctl(fd,LED_ON);sleep(7);//原来为sleep(1); }
不同之处:改变代码中加粗位置括号数字,可以改变灯亮和熄灭的时间比
四、测试显示
测试时,超级终端上的显示如下:
实验十四 中断实验
本实验是让我们学习中断的相关概念,以及Linux系统是如何处理中断的,并且学会编写获取和处理外中断的驱动程序。
一、补充代码
补充代码1:
printk(“*****************************************n”);printk(“t %s tn”,VERSION);printk(“************************************************nn”);补充代码2:
#ifdef OURS_GPIO_LED_DEBUG printk(“SIMPLE_GPIO_LED_read [--kernel--]n”);#endif return count;
补充代码3:
#ifdef OURS_GPIO_LED_DEBUG printk(“SIMPLE_GPIO_LED_write [--kernel--]n”);#endif return count;
补充代码4:
open: SIMPLE_INT_open, read: SIMPLE_INT_read, write: SIMPLE_INT_write, ioctl: SIMPLE_INT_ioctl, release: SIMPLE_INT_release, 二、Makefile文件如实验十三做相应修改。
三、测试时,超级终端上显示如下:
实验十五 数码管显示驱动实验
本实验中,我们要编驱动程序以实现在Linux系统下控制LED数码管的显示。
一、补充代码
补充代码1:
printk(“*****************************************n”);printk(“t %s tn”,VERSION);printk(“************************************************nn”);
补充代码2: #ifdef OURS_HELLO_DEBUG printk(“SERIAL_LED_read [--kernel--]n”);#endif return count;
补充代码3: #ifdef OURS_HELLO_DEBUG printk(“SERIAL_LED_write [--kernel--]n”);#endif return count;
补充代码4: #ifdef OURS_HELLO_DEBUG printk(“SERIAL_LED_ioctl [--kernel--]n”);#endif return 0;
补充代码5: #ifdef OURS_HELLO_DEBUG printk(“SERIAL_LED_open [--kernel--]n”);#endif MOD_INC_USE_COUNT;return 0;
补充代码6: #ifdef OURS_HELLO_DEBUG printk(“SERIAL_LED_release [--kernel--]n”);#endif MOD_DEC_USE_COUNT;return 0;
补充代码7: open: SERIAL_LED_open, read: SERIAL_LED_read, write: SERIAL_LED_write, ioctl: SERIAL_LED_ioctl, release: SERIAL_LED_release
补充代码8: int ret =-ENODEV;ret = devfs_register_chrdev(SERIAL_LED_MAJOR, “serial_led_ctl”, &SERIAL_LED_ops);Showversion();If(ret<0){ printk(“pxa270 init_module failed with %dn [--kernel--]”,ret);return ret;} else { printk(“pxa270 serial_led_driver register success!![--kernel--]n”);} return ret;
补充代码9: int ret =-ENODEV;#ifdef OURS_HELLO_DEBUG printk(“pxa270_SERIAL_LED_init [--kernel--]n”);#endif ret = HW_SERIAL_LED_init();if(ret)return ret;return 0;
补充代码10: #ifdef OURS_HELLO_DEBUG printk(“cleanup_SERIAL_LED [--kernel--]n”);#endif devfs_unregister_chrdev(SERIAL_LED_MAJOR, “serial_led”);
补充代码11: MODULE_DESCRIPTION(“serial_led driver module”);MODULE_AUTHOR(“liduo”);MODULE_LICENSE(“GPL”);module_init(pxa270_SERIAL_LED_init);module_exit(cleanup_SERIAL_LED);
二、Makefile文件与实验十四相同,只需作相应修改即可
三、作业代码
1、实现目标板上的LED数码管循环显示数字9-0。
for(count=0;count<10;count++)
{ data[0] = buf[9-count];//原来为data[0] = buf[count] ret=write(fd,data,1);sleep(1);} 修改之处:将显示的数有buf[count]改为buf[9-count],实现反向循环显示。
2、实现目标板上的LED数码管循环显示数字2、4、6、8、0或者8、6、4、2、0。代码: for(count=0;count<10;count+=2)//原来为count++
{data[0] = buf[count];ret=write(fd,data,1);sleep(1);}
修改之处:修改count的变化方式,让其每次增加2,而不是1,使0、2、4、6、8循环显示,如要循环显示8、6、4、2、0的话,只要在上述代码中将buf[count]改为buf[8-count]即可。
四、测试显示:
测试时,显示如下:
作业1: 作业2:
实验十六 LED点阵驱动程序设计
本实验要求我们学会编写驱动程序,实现在Linux系统下控制LED点阵显示,并在此基础上稍加改进,实现对LED的控制。驱动程序代码:
一、补充代码
补充代码1:
printk(“*****************************************n”);printk(“t %s tn”,VERSION);printk(“************************************************nn”);
补充代码2:
#ifdef OURS_LED_DEBUG printk(“SIMPLW_LED_read [--kernel--]n”);#endif return count;
补充代码3:
#ifdef OURS_LED_DEBUG printk(“SIMPLE_LED_ioctl [--kernel--]n”);#endif return 0;
补充代码4:
open: SIMPLE_LED_open, read: SIMPLE_LED_read, write: SIMPLE_LED_write, ioctl: SIMPLE_LED_ioctl, release: SIMPLE_LED_release
补充代码5:
int ret =-ENODEV;#ifdef OURS_LED_DEBUG printk(“pxa270_LED_CTL_init [--kernel--]n”);#endif ret = HW_LED_CTL_init();if(ret)return ret;return 0;
补充代码6:
#ifdef OURS_LED_DEBUG printk(“cleanup_LED_ctl [--kernel--]n”);#endif devfs_unregister_chrdev(SIMPLE_LED_MAJOR, “led_ctl”);
二、Makefile程序仍然可以用前一个实验的,只要把相关函数名改了就可以,此处不再赘述。
三、作业代码
1、按横方向隔行扫描led点阵数码管。代码:
for(i=1;i<=4;i++){ //原来为i<8
buf[0]=c;
buf[1]=~r;// row
for(j=1;j<=8;j++){
write(fd,buf,2);
printf(“buf[0],buf[1]: [%x,%x]n”,buf[0],buf[1]);
usleep(200000);// sleep 0.2 second
c = c<<1;
buf[0]=c;// column
}
c = 1;
r = r<<2;
} //原来为r=r<<1
修改之处:外层for循环中间i<8改为i<4,同时,将else中的r=r<<1改为r<<2。这样就可以让点阵在显示时跳跃一行进行显示。
2、按竖方向顺序扫描led点阵数码管。代码:
for(i=1;i<=8;i++){
buf[0]=c;
buf[1]=~r;// row
for(j=1;j<=8;j++){
write(fd,buf,2);
printf(“buf[0],buf[1]: [%x,%x]n”,buf[0],buf[1]);
usleep(200000);// sleep 0.2 second
r = r<<1;//原来此处为c=c<<1 buf[1]=~r;//原来此处为buf[1]=~c } r = 1;//原来此处为c=1 c = c<<1;//原来此处为r=r<<1 修改之处(现对于最初的测试程序,而不是作业1的测试程序):将r和c 进行对调。实现将横和竖的对调,已达到竖方向扫描的目的。四、测试显示
测试时,超级终端显示如下:
作业1: 作业2:
实验十七 AD驱动程序
本实验要求我们学会编写驱动程序对模拟量输入进行采集,并转换为数字量显示在超级终端上,从而实现AD转换。
驱动程序代码
一、补充代码
补充代码1:
printk(“*****************************************n”);printk(“t %s tn”,VERSION);
printk(“************************************************nn”);
补充代码2:
#ifdef OURS_HELLO_DEBUG printk(“SIMPLE_HELLO_read [--kernel--]n”);#endif return count;
补充代码3:
#ifdef OURS_HELLO_DEBUG printk(“SIMPLE_HELLO_write [--kernel--]n”);#endif return count;
补充代码4:
#ifdef OURS_HELLO_DEBUG printk(“SIMPLE_HELLO_open [--kernel--]n”);#endif MOD_INC_USE_COUNT;return 0;
补充代码5:
#ifdef OURS_HELLO_DEBUG printk(“SIMPLE_HELLO_release [--kernel--]n”);#endif MOD_DEC_USE_COUNT;return 0;
补充代码6:
open: SIMPLE_HELLO_open, read: SIMPLE_HELLO_read, write: SIMPLE_HELLO_write, ioctl: SIMPLE_HELLO_ioctl, release: SIMPLE_HELLO_release
补充代码7:
ad_ucb = ucb1x00_get();
int ret =-ENODEV;ret = devfs_register_chrdev(ADCTL_MAJOR, “ad_ctl”, &adctl_ops);Showversion();If(ret<0){ printk(“pxa270 init_module failed with %dn [--kernel--]”,ret);return ret;} else { printk(“pxa270 serial_led_driver register success!![--kernel--]n”);} return ret;
补充代码8:
int ret =-ENODEV;#ifdef OURS_HELLO_DEBUG printk(“pxa270_AD_CTL_init [--kernel--]n”);#endif ret = HW_AD_CTL_init();if(ret)return ret;return 0;
补充代码9:
#ifdef OURS_HELLO_DEBUG printk(“cleanup_AD_ctl [--kernel--]n”);#endif devfs_unregister_chrdev(ADCTL_MAJOR, “ad_ctl”);
二、Makefile文件可以用前一个程序的文件,只要将相应部分的代码修改即可
三、作业代码
要求:将UCB_ADC_INP_AD0换为其他通道并观察。代码:
for(i=0;i<50;i++)
{ Val0 = ioctl(fd,UCB_ADC_INP_AD1,0);usleep(100);val1 = ioctl(fd,UCB_ADC_INP_AD0,0);printf(“val0 = %dtval1 = %dn”,val0,val1;usleep(500000);
}
修改之处:只需交换AD1和AD0即可实现输出通道的改变。四、测试时显示
测试时、超级终端显示如下:
实验十八 DA驱动程序
本实验要求我们编写驱动程序,实现将数字信号转换成模拟信号并在示波器上显示出模拟信号波形,即实现DA转换。驱动程序代码:
一、补充代码
补充代码1:
#include“../AD/pxa_ad_drv.h” /引用AD驱动程序的头文件/
补充代码2:
printk(“*****************************************n”);printk(“t %s tn”,VERSION);
printk(“************************************************nn”);
补充代码3:
#ifdef OURS_DA_DEBUG printk(“SIMPLE_DA_read [--kernel--]n”);#endif return count;
补充代码4:
#ifdef OURS_DA_DEBUG printk(“SIMPLE_DA_write [--kernel--]n”);#endif return count;
补充代码5:
#ifdef OURS_DA_DEBUG printk(“SIMPLE_DA_ioctl [--kernel--]n”);#endif return 0;
补充代码6:
#ifdef OURS_DA_DEBUG printk(“SIMPLE_DA_open [--kernel--]n”);#endif MOD_INC_USE_COUNT;return 0;
补充代码7:
open: SIMPLE_DA_open, read: SIMPLE_DA_read, write: SIMPLE_DA_write, ioctl: SIMPLE_DA_ioctl, release: SIMPLE_DA_release
补充代码8:
int ret =-ENODEV;ret = devfs_register_chrdev(SIMPLE_DA_MAJOR, “DA_ctl”, &DA_ctl_ops);Showversion();If(ret<0){ printk(“pxa270 init_module failed with %dn [--kernel--]”,ret);return ret;} else { printk(“pxa270 serial_led_driver register success!![--kernel--]n”);} return ret;
补充代码9:
int ret =-ENODEV;#ifdef OURS_DA_DEBUG printk(“pxa270_DA_CTL_init [--kernel--]n”);#endif ret = HW_DA_CTL_init();if(ret)return ret;return 0;
补充代码10:
#ifdef OURS_DA_DEBUG printk(“cleanup_DA_ctl [--kernel--]n”);#endif devfs_unregister_chrdev(SIMPLE_DA_MAJOR, “DA_ctl”);补充代码11:
MODULE_DESCRIPTION(“serial_led driver module”);MODULE_AUTHOR(“liduo”);MODULE_LICENSE(“GPL”);module_init(pxa270_DA_CTL_init);module_exit(cleanup_DA_ctl);
二、Makefile文件可以继续用前面程序Mekefile的代码,只需要将相应部分的代码修改即可。
三、作业代码
要求:输出三角波。代码:(需要修改部分)
//---------------------print--------------------void da_create_sin(int fd){ unsigned char buf[(int)POINT];unsigned char*c;unsigned long I;int j;double x;for(j=0;j
x=(j/POINT)*(5*M_PI);//此处原来为x=sin((j/POINT
//*(2*M_PI))#ifdef OURS_DEBUG printf(“%ft”,x);#endif buf[j] =(unsigned char)255*(x/2+1)/2;#ifdef OURS_DEBUG printf(“%xn”, buf[j]);#endif } printf(“create sin waven”);printf(“Use”Ctrl + c“quit the functionn”);while(1){ c = buf;for(j=0;j
四、测试显示:(以下为三角波)
(以下为sin)
三、实验总结:
在本次嵌入式实验中,我们首先在老师的指导下了解了嵌入式系统,初步接触了Linux环境。我们的实验板是OURS-PXA270-EP,它是一款基于INTEL XSCALE PXA270处理器,针对高校嵌入式系统教学和实验科研的平台。这款设备主要包括核心板与底板两个部分,核心板主要集成了高速的PXA270 CPU,配套的存储器,网卡等设备;底板主要是各种类型的接口与扩展口。
了解了实验的平台后,在接下来的基本实验中我们学会了嵌入式开发系统硬件环境的搭建、Linux操作系统RedHat9的安装、软件环境的搭建,以及配置超级终端,配置通讯服务。这些实验内容只要按照实验指导书上的步骤一步一步做即可,不会出现难以解决的问题,一般都会做的很顺利。有三个需要注意的地方时,在配置端口时,一定要确定实验箱接的是端口一,还是端口二。否则会出现无法建立呼叫的问题(其表现为超级终端接口内没有输出内容)。其次要确定虚拟机上网桥的设定是否正确。不然也会出现无法呼叫现象。最后,要确定网线是否连接上。在实验时,由于有些电脑的网线接口有断裂的现象,如果插口没接好的话,将会出现nfs连接错误。
在基本实验之后,进行的就是接口实验。总的来说,实验的难度不大。当然这是建立在对实验代码有一定理解的基础之上的。在实验十二中,我们对实验的接口代码规则已经有了一定的了解。而之后的几个实验都是基于实验十二进行相应的改动即可。所以完成下来难度不是很大。而对应的作业中,我们仅需要对测试代码进行相应的改写。在对c语言有一定的了解的前提下,可以很容易相应代码所实现的功能,仅需要对相应代码做些修改即可。
不过,值得注意的还有两点,第一:代码的编写一定要符合规则,同时,代码的输入要避免输入错误。否则,在需要一次一次编译一次次查看错误一次次改正错误,这会是个费时费力的工作。第二:每次实验时,需要从新设定虚拟机的ip,即每次实验开始时都需要重复做实验五实验六。不然在挂载时会出现无法挂载的现象。
通过这次实验,我对嵌入式编程有了更深层次的理解,加深了我对理论知识的认识,有助于今后的学习和工作。感谢黄惠英老师的细心指导。