第一篇:北邮日历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;} } 北京邮电大学 嵌入式系统开发实验报告 学院: 班级: 姓名: 学号: 序号: 目录 一、实验目的..............................................................................................1 二、实验设备..............................................................................................1 三、基础实验(实验一~实验七)............................................................1 1.实验五..................................................................................................1 2.实验六..................................................................................................1 3.实验七..................................................................................................1 四、驱动程序..............................................................................................5 1.设备驱动程序的概念..........................................................................5 2.驱动程序结构......................................................................................6 3.设备注册和初始化..............................................................................7 4.设备驱动程序的开发过程..................................................................8 五、基本接口实验......................................................................................8 1.实验十二简单设备驱动程序..............................................................9 2.实验十三 CPU GPIO驱动程序设计...................................................9 3.实验十四中断实验...........................................................................10 4.实验十五数码管显示实验................................................................12 5.实验十六 LED点阵驱动程序设计...................................................19 6.实验十七 AD驱动实验....................................................................23 7.实验十八 DA驱动实验....................................................................26 六、实验中遇到的问题及解决方法........................................................30 七、实验总结及心得................................................................................31 一、实验目的 通过实验熟悉Linux环境,并掌握一些基本接口驱动的写法和用C语言编写简单的实验程序。学习LINUX开发环境的搭建,通讯配置等。并熟练掌握LINUX驱动程序的编写及开发流程。对嵌入式系统有进一步的了解。 二、实验设备 1.一套PXA270EP嵌入式实验箱 2.安装Redhat9的宿主PC机,并且配置好ARM Linux的开发环境 三、基础实验(实验一~实验七) 实验一~七为基础实验,目的是为后续实验搭建好软、硬件环境,配置好相关的协议、服务,并通过编写最简单的HelloWorld程序进行测试。由于后面的实验都要依靠前面实验的配置,故本段只着重叙述实验七的具体实现。 1.实验五 实验五为宿主PC机配置了TFTP服务。TFTP(Trivial File Transfer Protocol)是简单文件传输协议,由于特定开发环境的制约,这一服务是必须的。在配置完成后,每次重启宿主PC机时,都须先输入命令:service xinetd restart,以启动TFTP服务。 2.实验六 实验六为宿主PC机配置了NFS服务。NFS(Network File System)指网络文件系统,它实现了文件在不同的系统间使用。当我们想用远端档案时,只需调用“mount”就可以远端系统挂接在自己的档案系统之下。每次重启宿主PC机时,都须先输入命令:service nfs restart,以启动nfs服务。 3.实验七 实验七通过用c语言编写的简单程序HelloWorld,测试前面几个实验是否成功配置好环境,从超级终端可以看到HelloWorld程序的运行结果。 实验步骤如下: 1)硬件连接: 连接宿主 PC 机和一台 PXA270-RP目标板。2)打开宿主PC 机电源,进入 Linux操作系统。 3)启动RedHat 9.0 的图形界面,如下图,若您是以 root 身份登陆在文本模式下,则输入命令startx启动图形界面。进入RedHat 9.0 图形界面后,打开一个终端窗(Terminal)。 4)输入minicom然后回车,minicim设置为115200 8NI无流控。 5)打开PXA270_RP目标板电源,按目标板上的BOOT键,在minicom中应该会看到如下图: 6)在minicom终端窗口中,如图,输入下列四条命令 root ifconfig eth 192.168.0.50 up mount-o nolock 192.168.0.100:/ /mnt cd /mnt 此时,先将该窗口最小化,在后面的第 10 操作步骤中还将会回到该窗口中进行操作。 7)宿主机上打开一个终端窗口(Terminal),点击【红帽/System Tools/Terminal】启动终端窗口,输入下列 4 条命令: ① cd /home ②mkdir HW ③ cd HW ④ vi HelloWorld.c /*请您输入程序 7.1 程序清单*/ 此时会显示一个空白的屏幕,这条命令的含义是,使用 Vi 编辑器,对一个名叫HelloWorld.c的文件进行编辑,我们看到的空白窗口是对文件进行编辑的窗口,如下图。就像在 Windows系统下面使用写字板等一样道理。 在 vi 里面先单击键盘 A 键,然后左下角会变成—INSER。输入程序的时候和其他编辑器是一样的,如下图。 当输入程序完毕后,单击键盘 Esc 键,然后按“:”(冒号)此时左下角会出现冒号然后输入“wq”最后按“Enter”确认存盘退出 vi 编辑器,如下图。 8)在上面同一个终端窗口中,输入下列 2 条命令交叉编译HelloWorld.c源程序,并查看生成的.o 目标文件,如图 7-10,图7-11: ① arm-linux-gcc–oHelloWorldHelloWorld.c ②ls 等到再次出现提示符,代表程序已经正确编译。如果此步出现错误信息,请查看错误信息,并且重新编辑原来的 C文件,修改错误。直到正确编译。 9)重新打开第 7 步最小化的开有minicom的终端窗口,即到 PXA270-RP 目标板的mnt目录下,请您输入下列 3 条命令,运行HelloWorld编译成功的HelloWorld目标程序: ① cd home/HW /*回到minicom中目标板的/mnt/home/HW目录下*/ ②ls ③./ HelloWorld /*此时会看到如下图*/ 四、驱动程序 1.设备驱动程序的概念 设备驱动程序实际是处理和操作硬件控制器的软件,从本质上讲,是内核中具有最高特权级的、驻留内存的、可共享的底层硬件处理例程。驱动程序是内核的一部分,是操作系统内核与硬件设备的直接接口,驱动程序屏蔽了硬件的细节,完成以下功能: 对设备初始化和释放; 对设备进行管理,包括实时参数设置,以及提供对设备的操作接口; 读取应用程序传送给设备文件的数据或者回送应用程序请求的数据; 检测和处理设备出现的错误。 Linux操作系统将所有的设备全部看成文件,并通过文件的操作界面进行操作。对用户程序而言,设备驱动程序隐藏了设备的具体细节,对各种不同设备提供了一致的接口,一般来说,是把设备映射为一个特殊的设备文件,用户程序可以像对其他文件一样对此设备文件进行操作。这意味着: 由于每一个设备至少由文件系统的一个文件代表,因而都有一个“文件名”。应用程序通常可以通过系统调用open()打开设备文件,建立起与目标设备的连接。 打开了代表着目标设备的文件,即建立起与设备的连接后,可以通过read()、write()、ioctl()等常规的文件操作对目标设备进行操作。 设备文件的属性由三部分信息组成:第一部分是文件的类型,第二部分是一个主设备号,第三部分是一个次设备号。其中类型和主设备号结合在一起惟一地确定了设备文件驱动程序及其界面,而次设备号则说明目标设备是同类设备中的第几个。 由于Linux 中将设备当做文件处理,所以对设备进行操作的调用格式与对文件的操作类似,主要包括open()、read()、write()、ioctl()、close()等。应用程序发出系统调用命令后,会从用户态转到核心态,通过内核将open()这样的系统调用转换成对物理设备的操作。 2.驱动程序结构 一个设备驱动程序模块的基本框架 在系统内部,I/O设备的存取通过一组固定的入口点来进行,入口点也可以理解为设备的句柄,就是对设备进行操作的基本函数。字符型设备驱动程序提供如下几个入口点: open入口点。打开设备准备I/O操作。对字符设备文件进行打开操作,都会调用设备的open入口点。open子程序必须对将要进行的I/O操作做好必要的准备工作,如清除缓冲区等。如果设备是独占的,即同一时刻只能有一个程序访问此设备,则open子程序必须设置一些标志以表示设备处于忙状态。 close入口点。关闭一个设备。当最后一次使用设备完成后,调用close子程序。独占设备必须标记设备方可再次使用。 read入口点。从设备上读数据。对于有缓冲区的I/O操作,一般是从缓冲区里读数据。对字符设备文件进行读操作将调用read子程序。 write入口点。往设备上写数据。对于有缓冲区的I/O操作,一般是把数据写入缓冲区里。对字符设备文件进行写操作将调用write子程序。 ioctl入口点。执行读、写之外的操作。 select入口点。检查设备,看数据是否可读或设备是否可用于写数据。select系统调用在检查与设备文件相关的文件描述符时使用select入口点。 3.设备注册和初始化 设备的驱动程序在加载的时候首先需要调用入口函数init_module(),该函数最重要的一个工作就是向内核注册该设备,对于字符设备调用register_chrdev()完成注册。register_chrdev的定义为:intregister_chrdev(unsigned int major, const char *name, struct file_ operations *fops);其中,major是为设备驱动程序向系统申请的主设备号,如果为0,则系统为此驱动程序动态分配一个主设备号。name是设备名,fops是对各个调用的入口点说明。此函数返回0时表示成功;返回-EINVAL,表示申请的主设备号非法,主要原因是主设备号大于系统所允许的最大设备号;返回-EBUSY,表示所申请的主设备号正在被其他设备程序使用。如果动态分配主设备号成功,此函数将返回所分配的主设备号。如果register_chrdev()操作成功,设备名就会出现在/proc/dvices文件中。 Linux在/dev目录中为每个设备建立一个文件,用ls–l命令列出函数返回值,若小于0,则表示注册失败;返回0或者大于0的值表示注册成功。注册以后,Linux将设备名与主、次设备号联系起来。当有对此设备名的访问时,Linux通过请求访问的设备名得到主、次设备号,然后把此访问分发到对应的设备驱动,设备驱动再根据次设备号调用不同的函数。 当设备驱动模块从Linux内核中卸载,对应的主设备号必须被释放。字符设备在cleanup_ module()函数中调用unregister_chrdev()来完成设备的注销。unregister_chrdev()的定义为:intunregister_chrdev(unsigned int major, const char *name);包括设备注册在内,设备驱动的初始化函数主要完成的功能是有以下5项。(1)对驱动程序管理的硬件进行必要的初始化。 对硬件寄存器进行设置。比如,设置中断掩码,设置串口的工作方式、并口的数据方向等。 (2)初始化设备驱动相关的参数。 一般说来,每个设备都要定义一个设备变量,用以保存设备相关的参数。在这一步骤里对设备变量中的项进行初始化。 (3)在内核注册设备。 调用register_chrdev()函数来注册设备。(4)注册中断。 如果设备需要IRQ支持,则要使用request_irq()函数注册中断。(5)其他初始化工作。 初始化部分一般还负责给设备驱动程序申请包括内存、时钟、I/O端口等在内的系统资源,这些资源也可以在open子程序或者其他地方申请。这些资源不用时,应该释放,以利于资源的共享。 若驱动程序是内核的一部分,初始化函数则要按如下方式声明: int __initchr_driver_init(void);其中__init是必不可少的,在系统启动时会由内核调用chr_driver_init,完成驱动程序的初始化。 当驱动程序是以模块的形式编写时,则要按照如下方式声明: intinit_module(void)当运行后面介绍的insmod命令插入模块时,会调用init_module函数完成初始化工作。 4.设备驱动程序的开发过程 由于嵌入式设备由于硬件种类非常丰富,在默认的内核发布版中不一定包括所有驱动程序。所以进行嵌入式Linux系统的开发,很大的工作量是为各种设备编写驱动程序。除非系统不使用操作系统,程序直接操纵硬件。嵌入式Linux系统驱动程序开发与普通Linux开发没有区别。可以在硬件生产厂家或者Internet上寻找驱动程序,也可以根据相近的硬件驱动程序来改写,这样可以加快开发速度。实现一个嵌入式Linux设备驱动的大致流程如下。 (1)查看原理图,理解设备的工作原理。一般嵌入式处理器的生产商提供参考电路,也可以根据需要自行设计。 (2)定义设备号。设备由一个主设备号和一个次设备号来标识。主设备号惟一标识了设备类型,即设备驱动程序类型,它是块设备表或字符设备表中设备表项的索引。次设备号仅由设备驱动程序解释,区分被一个设备驱动控制下的某个独立的设备。 (3)实现初始化函数。在驱动程序中实现驱动的注册和卸载。(4)设计所要实现的文件操作,定义file_operations结构。(5)实现所需的文件操作调用,如read、write等。 (6)实现中断服务,并用request_irq向内核注册,中断并不是每个设备驱动所必需的。 (7)编译该驱动程序到内核中,或者用insmod命令加载模块。(8)测试该设备,编写应用程序,对驱动程序进行测试。 五、基本接口实验 在完成了基本实验后,我们开始着手基本接口实验。在这些实验中,我们学习如何编写设备驱动程序,及如何用测试程序检验驱动程序是否正确,并通过改写测试程序正常地对驱动程序进行相关操作。 1.实验十二 简单设备驱动程序 本次实验的任务是编写一个字符型设备驱动程序,并学习在应用程序中调用驱动。考虑到我们初次接触驱动程序的编写,对此还十分陌生,因此指导书中提供了本次实验所要用到的程序源代码。虽然这样一个字符型设备驱动程序并没有任何实际作用,但是它让我们轻松掌握了嵌入式驱动的编写过程,因为复杂繁琐的驱动,其骨架都是相同的。因此,看懂本实验的源代码,学习并模仿其编写方法,对于后续实验有着非常重要的意义。 2.实验十三 CPU GPIO驱动程序设计 在本实验中,我们要编写第一个针对实际硬件的驱动程序。我们知道,凡是操作系统控制外部设备,即使是最简单的硬件电路,也是需要驱动的。本实验涉及的外部硬件只有电阻和发光二极管。我们使用自己编写的驱动程序与应用程序控制 GPIO96的电平,通过 LED 的亮灭来判断,是否 CPU 做出了正确的响应。 补充代码(1) //-------------------WRITE-----------------------ssize_tSIMPLE_GPIO_LED_write(struct file * file ,const char * buf, size_t count, loff_t * f_ops){ #ifdef OURS_GPIO_LED_DEBUG printk(“SIMPLE_GPIO_LED_write [--kernel--]n”); #endif return count;} 补充代码(2) //-------------------OPEN------------------------ssize_tSIMPLE_GPIO_LED_open(structinode * inode ,struct file * file){ #ifdef OURS_GPIO_LED_DEBUG printk(“SIMPLE_GPIO_LED_open [--kernel--]n”); #endif MOD_INC_USE_COUNT; return 0;} 补充代码(3) //------------------structfile_operationsGPIO_LED_ctl_ops ={ 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, };实验作业 要求在目标板上LED闪烁产生亮7秒,灭2秒的效果 在测试程序中有这样一段代码: while(1){ ioctl(fd,LED_OFF);sleep(1); sleep(1);while(1){ ioctl(fd,LED_OFF);sleep(2); sleep(7);} 3.实验十四 中断实验 // 灭2秒 // 亮7秒 ioctl(fd,LED_ON);} // 休眠1秒 ioctl(fd,LED_ON);只需将上面的代码改为如下代码即可: 在理论课中,我们学习了许多中断方面的知识,包括中断向量、中断优先级、中断过程等。在PXA270系统里,中断控制器分外部设备和 PXA270X 处理器设备产生的两个层次的中断,前者是初级的中断源,后者是次级中断源,大量的次级中断源通常被映射为一个初级中断源。 补充代码1 voidshowversion(void){ printk(“*********************************************n”); printk(“t %s tn”, VERSION); printk(“*********************************************nn”); } static intSimpleINT_temp_count = 0;补充代码2 //-------------------READ------------------------ssize_tSIMPLE_INT_read(struct file * file ,char * buf, size_t count, loff_t * f_ops){ #ifdef OURS_INT_DEBUG #endif return count;printk(“SIMPLE_INT_read [--kernel--]n”);} 补充代码3 //-------------------WRITE-----------------------ssize_tSIMPLE_INT_write(struct file * file ,const char * buf, size_t count, loff_t * f_ops){ #ifdef OURS_INT_DEBUG } 补充代码4 //------------------structfile_operationsINT_ctl_ops ={ open: SIMPLE_INT_open, read: SIMPLE_INT_read, #endif return count;printk(“SIMPL_INT_write [--kernel--]n”);write:SIMPLE_INT_write, ioctl:SIMPLE_INT_ioctl, release:SIMPLE_INT_release, }; 通过此实验,我了解了硬件中断管脚与中断号的对应关系,以及中断号与中断处理程序的对应关系,对于今后编写更为复杂的中断程序打下基础。 4.实验十五 数码管显示实验 在此实验中,我们要编写针对 74LV164 的驱动程序,并用其串并转换功能来控制八段LED数码管的显示。 补充代码1 voidshowversion(void){ printk(“*********************************************n”); printk(“t %s tn”, VERSION); printk(“*********************************************nn”); } 补充代码2 //-------------------READ------------------------ssize_tSERIAL_LED_read(struct file * file ,char * buf, size_t count, loff_t * f_ops){ #ifdef OURS_HELLO_DEBUG } 补充代码3 //-------------------WRITE-----------------------ssize_tSERIAL_LED_write(struct file * file ,const char * buf, size_t count, loff_t * f_ops)return count;printk(“SERIAL_LED_read [--kernel--]n”);#endif { #ifdef OURS_HELLO_DEBUG } 补充代码4 //-------------------IOCTL-----------------------ssize_tSERIAL_LED_ioctl(structinode * inode ,struct file * file, unsigned intcmd, long data){ #ifdef OURS_HELLO_DEBUG #endif } 补充代码5 //-------------------OPEN------------------------ssize_tSERIAL_LED_open(structinode * inode ,struct file * file){ #ifdef OURS_HELLO_DEBUG #endif return 0;} MOD_INC_USE_COUNT;printk(“SERIAL_LED_open [--kernel--]n”);return 0;printk(“SERIAL_LED_ioctl [--kernel--]n”);return count;#endif write_byte(* buf);printk(“SERIAL_LED_write [--kernel--]n”);补充代码6 //-------------------RELEASE/CLOSE---------------ssize_tSERIAL_LED_release(structinode *inode ,struct file * file){ #ifdef OURS_HELLO_DEBUG printk(“SERIAL_LED_release [--kernel--]n”); #endif MOD_DEC_USE_COUNT;return 0;} 补充代码7 //------------------structfile_operationsSERIAL_LED_ops ={ open: SERIAL_LED_open,read: SERIAL_LED_read,write:SERIAL_LED_write,ioctl:SERIAL_LED_ioctl,release:SERIAL_LED_release, };补充代码8 staticint __initHW_SERIAL_LED_init(void){ int ret =-ENODEV; ret = devfs_register_chrdev(SERIAL_LED_MAJOR, &SERIAL_LED_ops); showversion();if(ret < 0)“serial_led_ctl”,} { } else { } return ret;printk(“ pxa270 serial_led_driver register success!![--kernel--]n”);printk(“ pxa270 init_module failed with %dn [--kernel--]”, ret);return ret;补充代码9 staticint __init pxa270_SERIAL_LED_init(void){ int ret =-ENODEV; printk(“pxa270_SERIAL_LED_init [--kernel--]n”); #endif ret = HW_SERIAL_LED_init();if(ret)return ret;return 0;} 补充代码10 static void __exit cleanup_SERIAL_LED(void){ #ifdef OURS_HELLO_DEBUG #ifdef OURS_HELLO_DEBUG #endif } 补充代码11 MODULE_DESCRIPTION(“serial_led driver module”); MODULE_AUTHOR(“liduo”); MODULE_LICENSE(“GPL”); module_init(pxa270_SERIAL_LED_init);module_exit(cleanup_SERIAL_LED);使用测试程序看到的测试结果是数码管按0-9显示输出。实验作业要求在上述基础上,分别实现一下两个功能: ①要求您再编写一个测试程序,实现 PXA270-EP 目标板上的 LED 数码管循环显示的数字9-0。 ②要求您再编写一个测试程序,实现 PXA270-EP 目标板上的 LED 数码管循环显示的数字02468。 由于在测试程序中定义了数组buf[10]分别存储了0-9是个数,因此上述功能的实现方法是,分别对测试程序做如下修改: 原测试程序: while(1){ for(count=0;count<10;count++){ data[0] = buf[count];ret=write(fd,data,1);sleep(1);} } 实现功能①: while(1){ for(count=9;count>=0;count--)} } 结果显示 // 倒序显示数字 { data[0] = buf[count];ret=write(fd,data,1);sleep(1);devfs_unregister_chrdev(SERIAL_LED_MAJOR, “serial_led”);printk(“cleanup_SERIAL_LED [--kernel--]n”);实现功能②: while(1){ for(count=0;count<9;count=count+2)} } 结果显示 // 更改显数顺序 { data[0] = buf[count];ret=write(fd,data,1);sleep(1); 通过更改显数的顺序,很容易实现实验作业里要求的功能。 5.实验十六 LED点阵驱动程序设计 通过本实验的操作,我们将 8X8 的点阵 LED 驱动起来并通过编写测试程序,使其能够按照您的意图进行显示。要求您还编写更多的测试程序 补充代码1 voidshowversion(void){ printk(“*********************************************n”);printk(“t %s tn”, VERSION);printk(“*********************************************nn”); } 补充代码2 //-------------------READ------------------------ssize_tSIMPLE_LED_read(struct file * file ,char * buf, size_t count, loff_t * f_ops){ #ifdef OURS_LED_DEBUG #endif return count;printk(“SIMPLE_LED_read [--kernel--]n”);} 补充代码3 //-------------------IOCTL-----------------------ssize_tSIMPLE_LED_ioctl(structinode * inode ,struct file * file, unsigned intcmd, long data){ #endif } 补充代码4 //------------------structfile_operationsLED_ctl_ops ={ open: SIMPLE_LED_open, read: SIMPLE_LED_read, write: SIMPLE_LED_write, ioctl: SIMPLE_LED_ioctl, release:SIMPLE_LED_release, };补充代码5 staticint __init pxa270_LED_CTL_init(void){ int ret =-ENODEV; printk(“pxa270_LED_CTL_init [--kernel--]n”); #endif ret = HW_LED_CTL_init();if(ret) return ret;#ifdef OURS_LED_DEBUG return 0;printk(“SIMPLE_LED_ioctl [--kernel--]n”);#ifdef OURS_LED_DEBUG return 0;} 补充代码6 static void __exit cleanup_LED_ctl(void){ #ifdef OURS_LED_DEBUG #endif } ①要求您再编写一个测试程序,实现按横的方向隔行顺序扫描 LED 点阵数码管。 ②要求您再编写一个测试程序,实现按竖的方向顺序扫描 LED 点阵数码管。作业一,隔行扫描: printk(“cleanup_LED_ctl [--kernel--]n”);outw(0x0000,ioremap_addr); devfs_unregister_chrdev(SIMPLE_LED_MAJOR, “led_ary_ctl”);for(i=1;i<=8;i2++){ buf[0]=c;buf[1]=~r;// row for(j=1;j<=8;j++){ } r = 1;c = c<<1; 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; buf[1]=~r;// column 结果显示 作业二,竖向扫描: for(i=1;i<=8;i++){ buf[0]=c;buf[1]=~r;// row for(j=1;j<=8;j++){ } r = 1;c = c<<1; 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; buf[1]=~r;// column 结果显示 6.实验十七 AD驱动实验 通过本实验的操作,我们将 AD 转换器驱动起来并通过编写测试程序,使其能够将模拟信号量按照我们的要求转换成数字信号量。为了更加清楚地理解 AD 转换器的工作过程,请您再编写一个测试程序,将 UCB_ADC_INP_AD0 换成其他通道,来观察其他 AD 通道情况。 补充代码1 voidshowversion(void){ printk(“%sn”,VERSION);} struct ucb1x00 *ad_ucb; 补充代码2 //-------------------READ------------------------staticssize_tadctl_read(struct file * file ,char *buf, size_t count, loff_t *offset){ } 补充代码3 //-------------------WRITE-----------------------ssize_tadctl_write(struct file * file ,const char *buf, size_t count, loff_t *offset){ #ifdef OURS_HELLO_DEBUG printk(“writen”); #endif } 补充代码4 //-------------------OPEN------------------------ssize_tadctl_open(structinode * inode ,struct file * file){ #ifdef OURS_HELLO_DEBUG printk(“openn”); #endif } 补充代码5 //-------------------RELEASE/CLOSE---------------ssize_tadctl_release(structinode *inode ,struct file * file){ #ifdef OURS_HELLO_DEBUG printk(“releasen”); #endif return 0;return 0;return count;#ifdef OURS_HELLO_DEBUG printk(“readn”);#endif return count;} 补充代码6 staticstructfile_operationsadctl_ops = { };补充代码7 //-------------------INIT------------------------staticint __initHW_AD_CTL_init(void){ return ret;} 补充代码8 staticint __init pxa270_AD_CTL_init(void){ int ret =-ENODEV;#ifdef OURS_HELLO_DEBUG int ret =-ENODEV;ret = devfs_register_chrdev(ADCTL_MAJOR, “adctl”, &adctl_ops);showversion();ad_ucb=ucb1x00_get();if(ret < 0){ } else { } adctl_dev_handle = devfs_register(NULL, “ad_ctl”, DEVFS_FL_DEFAULT, printk(“adctl driver register success!n”);printk(“fail %dn”,ret);return 0;read: ioctl: adctl_read, adctl_ioctl, write: adctl_write, open: adctl_open, release:adctl_release,ADCTL_MAJOR, 0, S_IFCHR, &adctl_ops, NULL);printk(“initn”);#endif ret=HW_AD_CTL_init();if(ret)} 补充代码9 static void __exit cleanup_AD_ctl(void){ } 7.实验十八 DA驱动实验 通过本实验的操作,我们使用示波器看到了通过DA转换而输出的波形。在此基础上,要求试写一个实现输出三角波的测试程序。 补充代码1 #include } printk(“t %st n”,VERSION);printk(“*****************************n”);static long ioremap_addr;补充代码3 //-------------------READ------------------------ssize_tSIMPLE_DA_read(struct file * file ,char * buf, size_t count, loff_t * f_ops){ #ifdef OURS_DA_DEBUG } 补充代码4 //-------------------WRITE-----------------------ssize_tSIMPLE_DA_write(struct file * file ,const char * buf, size_t count, loff_t * f_ops){ printk(“SIMPLE_DA_write[--kernel--]n”); #endif return count;} 补充代码5 //-------------------IOCTL-----------------------ssize_tSIMPLE_DA_ioctl(structinode * inode ,struct file * file, unsigned intcmd, outb(buf[0],ioremap_addr);#ifdef OURS_DA_DEBUG return count;#endif printk(“SIMPLE_DA_read[--kernel--]n”);long data){ #ifdef OURS_DA_DEBUG printk(“SIMPLE_DA_ioctl[--kernel--]n”); #endif return 0;} 补充代码6 //-------------------OPEN------------------------ssize_tSIMPLE_DA_open(structinode * inode ,struct file * file){ #ifdef OURS_DA_DEBUG printk(“SIMPLE_DA_open [--kernel--]n”); MOD_INC_USE_COUNT;return 0; #endif } 补充代码7 /------------------structfile_operationsDA_ctl_ops ={ read: SIMPLE_DA_read,}; 补充代码8 release: SIMPLE_DA_release, ioctl: SIMPLE_DA_ioctl, write: SIMPLE_DA_write, //-------------------INIT------------------------staticint __initHW_DA_CTL_init(void){ int ret =-ENODEV; } 补充代码9 staticint __init pxa270_DA_CTL_init(void){ int ret =-ENODEV; printk(“pxa270_DA_CTL_init [--kernel--]n”); #endif #ifdef OURS_DA_DEBUG } printk(“ pxa270 led_driver register success!![--kernel--]n”);{ else } return ret;printk(“ pxa270: init_module failed with %dn [--kernel--]”, ret);{ if(ret < 0)showversion();ret = devfs_register_chrdev(SIMPLE_DA_MAJOR, “da_ctl”, &DA_ctl_ops); ret = HW_DA_CTL_init();if(ret) return ret;return 0;} 补充代码10 static void __exit cleanup_DA_ctl(void){ #endif } 补充代码11 MODULE_DESCRIPTION(“DA_ctl driver module”);MODULE_AUTHOR(“liduo”);MODULE_LICENSE(“GPL”);module_init(pxa270_DA_CTL_init);module_exit(cleanup_DA_ctl);printk(“cleanup_DA_ctl [--kernel--]n”);#ifdef OURS_DA_DEBUG 六、实验中遇到的问题及解决方法 每一次上课重新启动后,当需要将宿主PC机的根目录挂在到PXA270-EP目标板的mnt目录下(即在超级终端中输入命令“mount –o soft,timeo=100,rsize=1024 192.168.0.100:/ /mnt”)时,常显示无法挂载。 解决方法:在超级终端下的挂载命令应该用”mount –o nolock 192.168.0.100:/ /mnt”,如果依然不能挂载需要重启NFS服务,即在PC机终端中输入命令”service nfs restart”两遍后就可以挂载,当然有时候也可能是因为网线没插好。 在每次重启机器之后都需要将PC机终端的IP地址和开发板中的系统的IP地址设定正确,不然也无法挂载。 七、实验总结及心得 本学期的所有实验均在宿主PC机与PXA270-EP目标板上进行。在实验中,我们先建立硬件实验平台,又建立主机软件开发环境,接着为实验进行各项配置,最后完成了各个实验中的多种功能。值得注意的是,前期的硬件、软件准备必须完整无误地实现,后续的实验才能顺利进行。所以,打基础的工作一定要仔细谨慎。后续实验中虽然给出了驱动程序的框架,仍需要我们自己补充完整,并开动脑筋举一反三,在原代码的基础上进行一定修改以实现新的功能。 通过这学期的实验,我逐步完成了建立实验软件开发平台,搭建实验编译软件环境,在PC上编辑、编译一个应用程序,并且在嵌入式系统上运行和调试它的过程。在实验中,不难发现,编译驱动程序大体框架都是一样的,比如里面的读函数、写函数、ioctl函数、打开、关闭以及函数模块的初始化并且在超级终端上显示出等。但所不同的是,要根据不同的实验要求修改名称,并且对其中必要的部分进行修改。 除此之外,我认为很多基础知识对实验的进行也起着非常大的作用,例如数码管的显示原理。在掌握了基础知识之后,上机的过程会显得相对简单,尤其是代码框架已经给出,我们所以需要做的就是根据需要稍作改动来得到我们想要的结果。 在实验过程中常常会遇到各种各样的问题,刚开始时我不知如何是好,只能求助于老师和同学,后来随着实验的进行,我对实验的内容和虚拟机都有了一定的了解,遇到问题时也可以静下心来思考其原因,自己尝试各种方法去解决问题。整个实验让我了解了一套完整的嵌入式系统驱动程序开发的全过程,学到的内容非常丰富,相信在学习了这些内容后,在今后的学习工作中接触到类似内容,我不会感到无从下手,而是能够有条不紊。 感谢老师的辛勤指导! 数据库实验报告 (三)姓名:学号:班级: 1.用Transact-SQL语句、数据导入、SQL Server Management Studio(企业管理器)输入的方法对所给定的8张表的数据输入到数据库中。自行决定每张表的数据导入办法,但每种方法各针对二或三张表。 Transact-SQL语句: 导入department,student, student_course表。 insertinto department select*from openrowset ('microsoft.jep.oledb.4.0','excel 5.0;hdr=yes;database=D:课件数据库database2.xls',department$); insertinto student select*from openrowset ('microsoft.jep.oledb.4.0','excel 5.0;hdr=yes;database=D:课件数据库database2.xls',student$); insertinto student_course select*from openrowset ('microsoft.jep.oledb.4.0','excel 5.0;hdr=yes;database=D:课件数据库database2.xls',student_course$); 数据导入: 操作:选中数据库studentsdb,右键-任务-导入数据。导入book, class, course表。 SQL Server Management Studio: 操作:右键需要编辑的表,选择编辑前200行。 Teacher: Teacher_course_class: 导入结果: Book: Class: Course: Department: Student: Student_course: Teacher: Teacher_course_class: 2.用Transact-SQL向Course表中插入一条记录,course_name为空,看运行的结果。 SQL语句: INSERTINTO course VALUES('dep02_s002', null,'dep02_s002', '72', '5', '4');运行结果: 分析:course_name有not null的约束,因此这条语句不能执行。 3.用Transact-SQL修改Course表中credit为5的记录,将其credit改为7, credit小于4的改为2,看运行的结果。 SQL语句: update course set credit=7 where credit=5;执行结果: 分析:约束C1指定了credit的范围为1至6.SQL语句: update course set credit=2 where credit<4;执行结果: 4.删除一条学生记录,看运行结果,对运行结果进行分析。SQL语句: deletefrom student where student_id='g9940201';执行结果: 分析:因为有参照完整性约束,不能删除。 5.用Transact-SQL完成将编号为dep04_b001的课程的选修信息插入到一个新的选课信息表中。 SQL语句: Creattablestudent_course2(course_idchar(20), student_idchar(20)gradeint, creditint, semesterint,school_yearchar(20),primarykey(course_id,student_id)); insertintostudent_course2 select*fromstudent_course wherecourse_id='dep04_b001';执行结果: 6.用Transact-SQL完成删除单片机原理课程的选课信息,分析运行结果。 SQL语句: deletefrom student_course where course_id in(select course_id from course where course_name='单片机原理')执行结果: 分析:所有课程号为dep04_s003的课程被删除。 本实验中遇到的问题和解决方法: 本实验的顺利完成需要预先作很多准备工作。以下就是我在遇到缺少组件accessdatabaseengine时的解决过程的记录。 AccessDatabaseEngine的安装 accessdatabaseengine用于和office连接,导入导出数据,本实验中需要导入excel文件。安装配合office的版本,我安装的是accessdatabaseengine2017(English)版本。安装32位版本,因office2016是32位。之前误操作安装了不能使用的老旧版本accessdatabaseengine2007,通过控制面板-应用程序卸载将其卸载了。安装accessdatabaseengine依然报错,是因为microsoftofficeclicktorun阻碍sqlserver的一些功能,需要将其卸载。这是微软推出的用于减少office打开速度的应用程序,安装office2016时会自动安装上,原理是开机时将一部分内容放到内存中,因此打开文件时会更快一些。检测自己的office是通过clickto run 还是MSI安装的,可以在word中点击文件-账户,查看产品信息,如果有下图中“office更新”这个选项,则说明安装过click to run。这个程序在控制面板-应用程序中找不到,因此用删除注册表的方式卸载。快捷键“win+R”输入“regedit”打开注册表编辑器,左边HKEY_CLASSES_ROOT-Installer-Product-00006开头的选项,有四个。单击这几个选项,在右侧查看详细信息,可以看到ProductNam是Microsoft Access database engine 2007(我原来误安装的老版本)。删除之前先备份注册表。方法一:选中要删除的文件,右键-导出,保存。只保存了要删除的文件。方法二:注册表编辑器,文件-导出,保存。保存了注册表所有信息。这是因为如果误删了重要文件会导致严重后果,可能需要重装系统,留此备份是为了可以恢复系统。 备份完之后,选中要删除的文件(00006开头的四个),右键-删除即可。回到Access database engine 32位的程序安装包,安装。我无法安装64位,可能是因为office是32位。安装成功之后就可以在sqlserver中导入excel文件了。 嵌入式系统开发实验报告 班 级: 姓 名: 班内序号: 学 号: 日 期: 目录 一、实验目的..............................................................................................1 二、实验设备..............................................................................................1 三、基础实验(实验一~实验七)............................................................1 1.实验五..................................................................................................2 2.实验六..................................................................................................2 3.实验七..................................................................................................2 四、驱动程序..............................................................................................3 1.设备驱动程序的概念..........................................................................3 2.驱动程序结构......................................................................................3 3.设备注册和初始化..............................................................................4 4.设备驱动程序的开发过程..................................................................6 五、基本接口实验......................................................................................6 1.实验十二 简单设备驱动程序............................................................6 2.实验十三 CPU GPIO驱动程序设计...................................................7 3.实验十四 中断实验...........................................................................8 4.实验十五 数码管显示实验................................................................9 5.实验十六 LED点阵驱动程序设计...................................................11 6.实验十七 AD驱动实验....................................................................12 7.实验十八 DA驱动实验....................................................................13 六、实验中遇到的问题及解决方法........................................................15 七、实验总结及心得................................................................................15 一、实验目的 通过实验熟悉Linux环境,并掌握一些基本接口驱动的写法和用C语言编写简单的实验程序。学习LINUX开发环境的搭建,通讯配置等。并熟练掌握LINUX驱动程序的编写及开发流程。对嵌入式系统有进一步的了解。 二、实验设备 1.一套PXA270EP嵌入式实验箱 2.安装Redhat9的宿主PC机,并且配置好ARM 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 1.实验五 实验五为宿主PC机配置了TFTP服务。TFTP(Trivial File Transfer Protocol)是简单文件传输协议,由于特定开发环境的制约,这一服务是必须的。在配置完成后,每次重启宿主PC机时,都须先输入命令:service xinetd restart,以启动TFTP服务。 2.实验六 实验六为宿主PC机配置了NFS服务。NFS(Network File System)指网络文件系统,它实现了文件在不同的系统间使用。当我们想用远端档案时,只需调用“mount”就可以远端系统挂接在自己的档案系统之下。每次重启宿主PC机时,都须先输入命令:service nfs restart,以启动nfs服务。 3.实验七 实验七通过用c语言编写的简单程序HelloWorld,测试前面几个实验是否成功配置好环境,从超级终端可以看到HelloWorld程序的运行结果。 四、驱动程序 1.设备驱动程序的概念 设备驱动程序实际是处理和操作硬件控制器的软件,从本质上讲,是内核中具有最高特权级的、驻留内存的、可共享的底层硬件处理例程。驱动程序是内核的一部分,是操作系统内核与硬件设备的直接接口,驱动程序屏蔽了硬件的细节,完成以下功能: 对设备初始化和释放; 对设备进行管理,包括实时参数设置,以及提供对设备的操作接口; 读取应用程序传送给设备文件的数据或者回送应用程序请求的数据; 检测和处理设备出现的错误。 Linux操作系统将所有的设备全部看成文件,并通过文件的操作界面进行操作。对用户程序而言,设备驱动程序隐藏了设备的具体细节,对各种不同设备提供了一致的接口,一般来说,是把设备映射为一个特殊的设备文件,用户程序可以像对其他文件一样对此设备文件进行操作。这意味着: 由于每一个设备至少由文件系统的一个文件代表,因而都有一个“文件名”。 应用程序通常可以通过系统调用open()打开设备文件,建立起与目标设备的连接。 打开了代表着目标设备的文件,即建立起与设备的连接后,可以通过read()、write()、ioctl()等常规的文件操作对目标设备进行操作。 设备文件的属性由三部分信息组成:第一部分是文件的类型,第二部分是一个主设备号,第三部分是一个次设备号。其中类型和主设备号结合在一起惟一地确定了设备文件驱动程序及其界面,而次设备号则说明目标设备是同类设备中的第几个。 由于Linux 中将设备当做文件处理,所以对设备进行操作的调用格式与对文件的操作类似,主要包括open()、read()、write()、ioctl()、close()等。应用程序发出系统调用命令后,会从用户态转到核心态,通过内核将open()这样的系统调用转换成对物理设备的操作。 2.驱动程序结构 一个设备驱动程序模块的基本框架 在系统内部,I/O设备的存取通过一组固定的入口点来进行,入口点也可以理解为设备的句柄,就是对设备进行操作的基本函数。字符型设备驱动程序提供如下几个入口点: open入口点。打开设备准备I/O操作。对字符设备文件进行打开操作,都会调用设备的open入口点。open子程序必须对将要进行的I/O操作做好必要的准备工作,如清除缓冲区等。如果设备是独占的,即同一时刻只能有一个程序访问此设备,则open子程序必须设置一些标志以表示设备处于忙状态。 close入口点。关闭一个设备。当最后一次使用设备完成后,调用close子程序。独占设备必须标记设备方可再次使用。 read入口点。从设备上读数据。对于有缓冲区的I/O操作,一般是从缓冲区里读数据。对字符设备文件进行读操作将调用read子程序。 write入口点。往设备上写数据。对于有缓冲区的I/O操作,一般是把数据写入缓冲区里。对字符设备文件进行写操作将调用write子程序。 ioctl入口点。执行读、写之外的操作。 select入口点。检查设备,看数据是否可读或设备是否可用于写数据。select系统调用在检查与设备文件相关的文件描述符时使用select入口点。 3.设备注册和初始化 设备的驱动程序在加载的时候首先需要调用入口函数init_module(),该函数最重要的一个工作就是向内核注册该设备,对于字符设备调用register_chrdev()完成注册。register_chrdev 的定义为:int register_chrdev(unsigned int major, const char *name, struct file_ operations *fops);其中,major是为设备驱动程序向系统申请的主设备号,如果为0,则系统为此驱动程序动态分配一个主设备号。name是设备名,fops是对各个调用的入口点说明。此函数返回0时表示成功;返回-EINVAL,表示申请的主设备号非法,主要原因是主设备号大于系统所允许的最大设备号;返回-EBUSY,表示所申请的主设备号正在被其他设备程序使用。如果动态分配主设备号成功,此函数将返回所分配 的主设备号。如果register_chrdev()操作成功,设备名就会出现在/proc/dvices文件中。 Linux在/dev目录中为每个设备建立一个文件,用ls –l命令列出函数返回值,若小于0,则表示注册失败;返回0或者大于0的值表示注册成功。注册以后,Linux将设备名与主、次设备号联系起来。当有对此设备名的访问时,Linux通过请求访问的设备名得到主、次设备号,然后把此访问分发到对应的设备驱动,设备驱动再根据次设备号调用不同的函数。 当设备驱动模块从Linux内核中卸载,对应的主设备号必须被释放。字符设备在cleanup_ module()函数中调用unregister_chrdev()来完成设备的注销。unregister_chrdev()的定义为:int unregister_chrdev(unsigned int major, const char *name);包括设备注册在内,设备驱动的初始化函数主要完成的功能是有以下5项。(1)对驱动程序管理的硬件进行必要的初始化。 对硬件寄存器进行设置。比如,设置中断掩码,设置串口的工作方式、并口的数据方向等。 (2)初始化设备驱动相关的参数。 一般说来,每个设备都要定义一个设备变量,用以保存设备相关的参数。在这一步骤里对设备变量中的项进行初始化。 (3)在内核注册设备。 调用register_chrdev()函数来注册设备。(4)注册中断。 如果设备需要IRQ支持,则要使用request_irq()函数注册中断。(5)其他初始化工作。 初始化部分一般还负责给设备驱动程序申请包括内存、时钟、I/O端口等在内的系统资源,这些资源也可以在open子程序或者其他地方申请。这些资源不用时,应该释放,以利于资源的共享。 若驱动程序是内核的一部分,初始化函数则要按如下方式声明: int __init chr_driver_init(void);其中__init是必不可少的,在系统启动时会由内核调用chr_driver_init,完成驱动程序的初始化。 当驱动程序是以模块的形式编写时,则要按照如下方式声明: int init_module(void)当运行后面介绍的insmod命令插入模块时,会调用init_module函数完成初始化工作。 4.设备驱动程序的开发过程 由于嵌入式设备由于硬件种类非常丰富,在默认的内核发布版中不一定包括所有驱动程序。所以进行嵌入式Linux系统的开发,很大的工作量是为各种设备编写驱动程序。除非系统不使用操作系统,程序直接操纵硬件。嵌入式Linux系统驱动程序开发与普通Linux开发没有区别。可以在硬件生产厂家或者Internet上寻找驱动程序,也可以根据相近的硬件驱动程序来改写,这样可以加快开发速度。实现一个嵌入式Linux设备驱动的大致流程如下。 (1)查看原理图,理解设备的工作原理。一般嵌入式处理器的生产商提供参考电路,也可以根据需要自行设计。 (2)定义设备号。设备由一个主设备号和一个次设备号来标识。主设备号惟一标识了设备类型,即设备驱动程序类型,它是块设备表或字符设备表中设备表项的索引。次设备号仅由设备驱动程序解释,区分被一个设备驱动控制下的某个独立的设备。 (3)实现初始化函数。在驱动程序中实现驱动的注册和卸载。(4)设计所要实现的文件操作,定义file_operations结构。(5)实现所需的文件操作调用,如read、write等。 (6)实现中断服务,并用request_irq向内核注册,中断并不是每个设备驱动所必需的。 (7)编译该驱动程序到内核中,或者用insmod命令加载模块。(8)测试该设备,编写应用程序,对驱动程序进行测试。 五、基本接口实验 在完成了基本实验后,我们开始着手基本接口实验。在这些实验中,我们学习如何编写设备驱动程序,及如何用测试程序检验驱动程序是否正确,并通过改写测试程序正常地对驱动程序进行相关操作。 1.实验十二 简单设备驱动程序 本次实验的任务是编写一个字符型设备驱动程序,并学习在应用程序中调用驱动。考虑到我们初次接触驱动程序的编写,对此还十分陌生,因此指导书中提供了本次实验所要用到的程序源代码。虽然这样一个字符型设备驱动程序并没有任何实际作用,但是它让我们轻松掌握了嵌入式驱动的编写过程,因为复杂繁琐的驱动,其骨架都是相同的。因此,看懂本实验的源代码,学习并模仿其编写方 法,对于后续实验有着非常重要的意义。 2.实验十三 CPU GPIO驱动程序设计 在本实验中,我们要编写第一个针对实际硬件的驱动程序。我们知道,凡是操作系统控制外部设备,即使是最简单的硬件电路,也是需要驱动的。本实验涉及的外部硬件只有电阻和发光二极管。我们使用自己编写的驱动程序与应用程序控制 GPIO96的电平,通过 LED 的亮灭来判断,是否 CPU 做出了正确的响应。 实验第一步是编写 PXA270 GPIO 驱动程序。驱动的写法参照实验十二,大体相同,主要区别如下: //-------------------控制IO设备-----------------------switch(cmd){ case LED_ON : {GPCR3 |= 0x1;break;} 为1 case LED_OFF: {GPSR3 |= 0x1;break;} 为1 default : { //如果cmd=LED_OFF,那么GPSR3置//如果cmd=LED_ON,那么GPCR3置printk(“lcd control : no cmd run [--kernel--]n”);return(-EINVAL);} //-------------------驱动程序初始化--------------------------GPDR3 |= 0x00000001;//设置GPIO96输出模式:开灯 GPSR3 |= 0x00000001;// 关灯 对Makefile中的目标体和依赖文件也要做相应的修改,此处省略。在测试程序中有这样一段代码: while(1){ ioctl(fd, LED_OFF);sleep(1); // 休眠1秒 ioctl(fd,LED_ON);sleep(1);} 实验作业要求在目标板上LED闪烁产生亮7秒,灭5秒的效果,很容易实现,只需将上面的代码改为如下代码即可: while(1){ ioctl(fd, LED_OFF);sleep(5); sleep(7);} // 灭5秒 // 亮7秒 ioctl(fd,LED_ON); 3.实验十四 中断实验 在理论课中,我们学习了许多中断方面的知识,包括中断向量、中断优先级、中断过程等。在PXA270系统里,中断控制器分外部设备和 PXA270X 处理器设备产生的两个层次的中断,前者是初级的中断源,后者是次级中断源,大量的次级中断源通常被映射为一个初级中断源。 在此实验中,我们要编写一个中断程序,利用目标板上的按键SW2来产生中断,使得当每次按下此按键时,在超级终端上打印出响应的信息。编写中断程序与前两个实验的主要区别如下: /*--------------------------初始化 request_irq申请硬件中断,参数包括申请的硬件中断号、设备id、中断处理的 一些属性(SA_INTERRUPT是快速处理程序,调用时屏蔽所有中断)等 -----------------*/ ret = request_irq(SIMPLE_INT_IRQ, &SIMPLE_INT_interrupt, SA_INTERRUPT, “int_ctl”, NULL);//--------------------卸载,对应request_irq释放中断---------------------free_irq(SIMPLE_INT_IRQ,NULL);通过此实验,我了解了硬件中断管脚与中断号的对应关系,以及中断号与中断处理程序的对应关系,对于今后编写更为复杂的中断程序打下基础。 4.实验十五 数码管显示实验 在此实验中,我们要编写针对 74LV164 的驱动程序,并用其串并转换功能来控制八段LED数码管的显示。 在编写驱动程序时,主要有以下需要注意的: // 按位写入 void write_bit(int data){ { } else {GPCR2 |=(0x1 << 26); GPCR2 |=(0x1 << 27);GPSR2 |=(0x1 << 26);if((data & 0x80)== 0x80) } GPSR2 |=(0x1 << 27);} // 按字节写,一次写8位 void write_byte(int data){ { } } int i; write_bit(data << i);for(i=0;i<8;i++) 使用测试程序看到的测试结果是数码管按0-9显示输出。实验作业要求在上述基础上,分别实现一下两个功能: ① 要求您再编写一个测试程序,实现 PXA270-EP 目标板上的 LED 数码管循环显示的数字9-0。 ② 要求您再编写一个测试程序,实现 PXA270-EP 目标板上的 LED 数码管循环显示的数字02468。 由于在测试程序中定义了数组buf[10]分别存储了0-9是个数,因此上述功能的实现方法是,分别对测试程序做如下修改: 原测试程序: while(1){ { } } for(count=0;count<10;count++) data[0] = buf[count];ret=write(fd,data,1);sleep(1); 实现功能①: while(1){ { } } for(count=9;count>=0;count--)// 倒序显示数字 data[0] = buf[count];ret=write(fd,data,1);sleep(1); 实现功能②: while(1){ { } } for(count=0;count<9;count=count+2)// 更改显数顺序 data[0] = buf[count];ret=write(fd,data,1);sleep(1); 通过更改显数的顺序,很容易实现实验作业里要求的功能。 5.实验十六 LED点阵驱动程序设计 通过本实验的操作,我们将 8X8 的点阵 LED 驱动起来并通过编写测试程序,使其能够按照您的意图进行显示。要求您还编写更多的测试程序 ① 要求您再编写一个测试程序,实现按横的方向隔行顺序扫描 LED 点阵数码管。 ② 要求您再编写一个测试程序,实现按竖的方向顺序扫描 LED 点阵数码管。作业一,隔行扫描: for(i=1;i<=8;i2++){ buf[0]=c;buf[1]=~r;// row for(j=1;j<=8;j++){ } r = 1;c = c<<1;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;buf[1]=~r;// column 作业二,竖向扫描: for(i=1;i<=8;i++){ buf[0]=c;buf[1]=~r;// row for(j=1;j<=8;j++){ } r = 1;c = c<<1;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;buf[1]=~r;// column 6.实验十七 AD驱动实验 通过本实验的操作,我们将 AD 转换器驱动起来并通过编写测试程序,使其能够将模拟信 号量按照我们的要求转换成数字信号量。为了更加清楚地理解 AD 转换器的工作过程,请您再 编写一个测试程序,将 UCB_ADC_INP_AD0 换成其他通道,来观察其他 AD 通道情况。 主要代码: for(i=0;i<50;i++){ val0 = ioctl(fd,UCB_ADC_INP_AD1,0);usleep(100);val1 = ioctl(fd,UCB_ADC_INP_AD0,0); usleep(100);val2 = ioctl(fd,UCB_ADC_INP_AD2,0);usleep(100); 7.实验十八 DA驱动实验 通过本实验的操作,我们使用示波器看到了通过 DA 转换而输出的波形。在此基础上,要求试写一个实现输出三角波的测试程序。 主要代码: while(flag_func_run == FUNC_RUN){ print_prompt();// print select functions scanf(“%d”,&flag_select_func);// user input select getchar();// get ENTER switch(flag_select_func){ case DA_SIN : {da_create_sin(fd);break;} case DA_FANG case FUNC_QUIT : { flag_func_run = FUNC_NOT_RUN;printf(“Quit DA function.byebyen”);break;} case DA_TRI :{da_create_tri(fd);break;} default : { printf(“input = %xn”,flag_select_func);printf(“statys = %xn”,flag_func_run); : {da_create_fang(fd);break;} printf(“--please input your select use 1 to 4--n”);} } 六、实验中遇到的问题及解决方法 每一次上课重新启动后,当需要将宿主PC机的根目录挂在到PXA270-EP目标板的mnt目录下(即在超级终端中输入命令“mount –o soft,timeo=100,rsize=1024 192.168.0.100:/ /mnt”)时,常显示无法挂载。 解决方法:在超级终端下的挂载命令应该用”mount –o nolock 192.168.0.100:/ /mnt”,如果依然不能挂载需要重启NFS服务,即在PC机终端中输入命令”service nfs restart”两遍后就可以挂载,当然有时候也可能是因为网线没插好。 在每次重启机器之后都需要将PC机终端的IP地址和开发板中的系统的IP地址设定正确,不然也无法挂载。 七、实验总结及心得 本学期的所有实验均在宿主PC机与PXA270-EP目标板上进行。通过这些为数不多课时的实验,我逐步完成了建立实验软件开发平台,搭建实验编译软件环境,在PC上编辑、编译一个应用程序,并且在嵌入式系统上运行和调试它的过程。在实验中,不难发现,编译驱动程序大体框架都是一样的,比如里面的读函数、写函数、ioctl函数、打开、关闭以及函数模块的初始化并且在超级终端上显示出等。但所不同的是,要根据不同的实验要求修改名称,并且对其中必要的部分进行修改。 除此之外,我认为很多基础知识对实验的进行也起着非常大的作用,例如数码管的显示原理。在掌握了基础知识之后,上机的过程会显得相对简单,尤其是代码框架已经给出,我们所以需要做的就是根据需要稍作改动来得到我们想要的结果。 之后,我们又进行了更加深入的应用试验,如人机接口方面的键盘驱动实验、LCD控制实验和触摸屏数据采集与控制实验,应用方面的多线程应用实验等。由于涉及到嵌入式实验板的开发,我们在之前实验基础上自己动手编写了程序,对算法和开发环境有了更深入的掌握,在自我与互相学习中解决了许多问题,受益匪浅。 整个实验让我了解了一套完整的嵌入式系统驱动程序开发的全过程,学到的内容非常丰富,相信在学习了这些内容后,在今后的学习工作中接触到类似内容,我不会感到无从下手,而是能够有条不紊。 感谢老师的辛勤指导! 《数据库原理》实验报告 实验名称班 级组 号组员姓名 数据库实验平台的安装、数据库创建与维护实验 计算机科学与技术8班2011211308 梁展伟、李安 一、实验目的 1.通过对Microsoft SQL Server数据库的安装和简单使用: (1)了解安装Microsoft SQL Server数据库的软硬件环境和安装方法;(2)熟悉Microsoft SQL Server数据库相关使用;(3)熟悉Microsoft SQL Server数据库的构成和相关工具; (4)通过Microsoft SQL Server数据库的使用来理解数据库系统的基本概念。 2.通过创建数据库、并进行相应的维护,了解并掌握Microsoft SQL Server数据库数据库的创建和维护的不同方法和途径,并通过这一具体的数据库理解实际数据库所包含的各要素。 二、实验环境 Windows7下的Microsoft SQL Server 2012 standard edition。 三、实验内容与步骤 一、Microsoft SQL Server数据库安装 1.下载相应版本。选择实验室Windows XP或者Win7系统或者虚拟机(vmware)上自行安装的操作系统或者是自己的机器之一安装该版本的Microsoft SQL Server。可选版本有Microsoft SQL Server 2005/2008或者2012的Express,Develop或者Enterprise等各版本。安装时通常可同时安装SQL Server Management Studio Express,以后建立数据库等很方便。 2.练习启动和停止数据库服务。 打开控制面板|管理工具|服务,找出与所使用数据库相关的服务,尝试停止和启动它们。再使用SQL Server Configuration Manager下的SQL Server Services选项进行相关操作。最后保持这些服务为启动状态。如果这些服务没有启动,非常可能导致数据库系统无法工作,从而后续实验无法进行。 二、熟悉Microsoft SQL Server数据库基本用户界面: 1. 请运行SQL Server Management Studio Express。熟悉数据库管理系统的基本用户界面。 三、使用Microsoft SQL Server创建数据库: 1.Microsfot SQL Server数据库创建(1)了解数据库系统的命令行操作界面: 编写包含CREATE DATABASE命令的脚本文件,SQL Server Management Studio Express下打开该文件并执行之。 如下图,新创建的数据库lian出现在数据库目录中: (2)SQL Server Management Studio Express下使用向导创建数据库。并将创建数据库脚本保存到文件中。打开文件查看相应命令。理解用户界面上相关参数。后续实验也同样的学习脚本和理解参数的要求。 连接参数的意义就是与其他的数据库进行连接;查询即使用数据库查询语言对已选择数据库进行查询 (3)找出系统数据库,查看其下的表及其它数据库对象。 四、Microsoft SQL Server数据库维护 (1)对数据库属性和参数进行查询、相应的修改和维护,内容包括: a)调整数据库的大小,完成数据库大小的增加、减小; b)增加文件组; c)修改日志文件的最大值; d)查看数据库的属性值。 (2)数据库的删除 a)使用脚本文件删除数据库。 命令 drop database 如图,先前的数据库lian已被删除: b)使用SQL Server Management Studio Express删除数据库 直接右击该数据库,选择删除命令。 四、实验要求 1. Microsoft SQL Server数据库的安装实验要求学生在微机上安装Microsoft SQL Server数据库数据库系统,为后续各个实验搭建实验环境。 2. 数据库创建与维护实验以GSM网络配置数据库为背景,要求面向具体应用领域,利用Microsoft SQL Server数据库相关机制,创建并维护数据库系统,为后续各个实验提供前期准备。 3. 要求学生根据以上要求确定实验步骤,独立完成以上实验内容。并在安装和数据库运行后熟悉Microsoft SQL Server数据库的各种运行管理。 4.对实验结果进行总结和分析;给出完成以上实验内容的Transact_SQL语句,并对相应的SQL语句进行分析;说明建立的数据库的相关内容,和维护后的相关属性的改变。 使用了create database 和 drop database这两个语句,前者用来建立一个新的数据库,包括其名称、位置、以及日志文件的相关属性定义;后者用来删除之前建立好的数据库,直接在其后面加上数据库名称即可。 通过修改维护相关属性的操作之后,数据库会做相应的变化,例如添加属性、修改大小等等。 5. 实验完成后完成实验报告。 五、实验总结 在实验中有哪些重要问题或者事件?你如何处理的?你的收获是什么?有何建议和意见等等。 1、安装时没有出现任何问题,就是在一些插件的选择以及用户的添加上略微繁琐,在使用SQL server配置管理器时,其中有一个服务无法直接手动打开,在网上查阅资料后使用高级选项中的操作才将其打开; 2、在使用脚本文件创建数据库时,确认好编写的代码无误后编译还是会出错,仔细检查之后发现是冒号的打成了中文的,改正后运行无误; 首先,学习数据库还是要多查阅资料,因为有大量的软件操作,所以熟悉软件至关重要,其次,在做一些编码的任务时,一定要细心,切不可再因为疏忽大意导致时间白白浪费。第二篇:北邮嵌入式实验报告
第三篇:北邮数据库实验报告
第四篇:北邮嵌入式实验报告
第五篇:北邮数据库第一次实验报告