硬件驱动编程

来源:百度文库 编辑:神马文学网 时间:2024/04/25 00:52:47
这里主要是涉及硬件驱动编程的问题,许多是drew在论坛和E-MAIL上和网友探讨过的一些问题,有些是个人编程经验.不一定全面.一些相关程序代码会陆续补到程序示例 上.
系统初始化VxWorks网络配置及分析
硬件中断FlashROM 驱动
文件系统网卡驱动(Linux)
LCD和触摸屏MODEM 拨号
实时时钟 RTCVxWorks PCI驱动编程步骤
MPC860串口SCC UART模式编程
系统初始化
可参见PowerPC初始化示例 和ARM_Boot示例
Cache的初始化
ARM9的BSP,在romInit()函数里对cache进行的操作为:
1.设置几个cache区;
2.flush caches(通过以下代码实现:
LDR R0,=0x00000000
MCR p15,0,R0,c7,c5,0
MCR p15,0,R0,c7,c6,0
)
问题:
1.flush cache是什么意思?
2.在romInit()函数里一般对cache进行的操作是什么?
1.flush cache是什么意思?
使所有的 IDC 无效,这样CPU读取数据和指令时可以直接到原存储地址去读取,而不必从cache中得到,因为cache保留的是以前的数据,而当前原地址的数据可能发生了变化,这样保证了数据的正确性.使CPU得到最新的数据,当然,这样会降低CPU的处理速度.
2.在romInit()函数里一般对cache进行的操作是什么?
在romInit()函数里,对cache主要的操作就是flush cache,因为对系统初始化前,必须要保证初始化过程的正确和连续,所以要有flush cache,disable interrupt 等操作.
VxWorks系统装入ARM的过程
问题:开发基于ARM7和VxWorks的嵌入式系统,Tornado/VxWorks 和一个基于ARM7TDMI的单板机是否足够了?VxWorks 怎么样装入单板机运行?不用JEENI可以装入么?
把 VXWORKS IMGAGE 装入ARM 的过程大体上是这样的:
ARM 7 内部有 128 BYTE 的 BOOT ROM,和 2K 的 SRAM,当需要DOWNLOAD VXWORKS 时 ARM 采用 BOOT 方式启动运行存在 BOOTROM 中的程序初始化 ARM 内部的 COM 口,从 COM 口接受数据到 2K 的 SRAM,这 2K 程序是用来真正 LOAD VXWORKS 的,2K 程序 LOAD 完毕后系统自动跳转到这 2K 程序执行它的作用是首先通过 COM 口接受 VXWORKS 到 DRAM ,然后由 DRAM 写入 FLASH 。
写入完毕后,切换到 NORMAL 模式重新启动系统,系统自动跳到 FLASH 0X00000000 开始运行 VXWORKS。
可以用 PC 机上的 COM1 与 ARM 内部的 UART1(COM) 通信来 DOWNLOAD VXWORKS。
Bootloader怎么得到,如果对开发板有些改动,还能使用开发板的bootloader吗?bootloader起到什么作用?
Bootloader相当于PC机主板上的BIOS,是最底层的引导软件,初始化主板的基本设置,为接收外部程序做硬件上的准备.
有些bootloader已经嵌在CPU内了,没有bootloader的CPU可以在片外的eeprom内做bootloader,也可以不要bootloader,直接通过JTAG口灌入程序,开发板改动基本上不会影响bootloader.
VxWorks 下的驱动的问题
问题:vxworks中有两种驱动模式,一个是是分层结构,特别对网络协议栈来说有network protocol/MUX/network driver(END,BSD).还有一种就是没有层次的概念,在应用程序中直接访问硬件的。比方说现在有两种类型的驱动,譬如USB 和ATM,他们需要直接交换数据,不想走OS那一套标准的流程,也就是我们想用后面的一种(OS Independent)。应如何去做?
我没有做过 ATM,USB 的驱动,在 VXWORKS 上做过其它驱动, MODEM,SPI等,我认为如果 VXWORKS 不支持莫种协议的话,可以在 VXWORKS 上直接对硬件操作,自己按照相关协议标准封装数据包按照硬件定义放入相应的地址空间。这等于自己写协议和驱动。
这种方法是可行的,当然如能找到 VXWORKS 下支持该协议的驱动更好。 这种程序和 VXWORKS 系统也是相关的:
1。MMU 对该硬件的地址映射正确 (改 BSP )
2。中断向量表(改 BSP )
3。硬件中断登记 (INTCONNECT ),及 ISR
4。系统任务协调,保证在该程序执行时,没有其它任务占用 CPU
基本上和开发其它的驱动程序是一样的。
返回页首
硬件中断
参见硬件中断示例
中断编程中应该注意的问题
1.中断程序的调试不能用单步执行,因为中断发生很快,无法跟踪。
2.中断例程中尽量不要用C,库函数.因为中断处理中所有的任务都被挂起。
3.在中断调试过程中轮询方式简明,易于调试。在实时多任务程序中肯定用中断方式,不能用轮询。
中断出错时调试检查的方法(以ARM IRQ中断为例)
1。确定一下是否中断发生,在中断发生时,查中断标志寄存器INTST1中相应的IRQ为是否置1,或用示波器量该IRQ管脚。有中断产生且中断enable,就应该执行相应的ISR。
2。如上面没有问题,仍不执行,再查一下是否有比该IRQ等级更高的中断持续发生屏蔽了该IRQ中断。
特别要注意一些FIQ中断,在ARM中FIQ中断永远高于IRQ,可能会导致IRQ中断不被执行。
在中断屏蔽寄存器INTMR1中屏蔽所有优先级高于该IRQ的FIQ,会disable这些FIQ.
主题:请高手指引:EP7312的中断
请高手指引:在C语言下EP7312,怎样将中断(比如:EINT1)与一段需要执行的程序挂钩。这里先谢谢啦!
Re:请高手指引:EP7312的中断
EP72xx定义IRQ的中断向量地址为0x18,你可以在该地址处放一跳转指令,跳到你的中断处理函数(IRQHandler),这个中断处理函数的主要作用是根据中断标志寄存器的标志位来分析IRQ中断类别(EINT1,EINT2...),然好根据中断的类别跳转到相应的中断服务程序(ISR)进行处理.
大概步骤基本如上,不过一般这些程序是操作系统已经有的,用相应的函数(如intConnect)直接使用即可.
你不会是在写操作系统吧?
另外,ARM的中断有FIQ和IRQ,FIQ的优先级总是高于IRQ的优先级,由于某些操作系统本身的问题,可能导致有时FIQ的中断屏蔽了IRQ的中断,使IRQ中断不能及时响应,这种情况下,可能需要从新写这些程序来进行替换.
不知这些是否对你有所帮助.
Re:Re:请高手指引:EP7312的中断
您好!
我是个新手,资料也不全,您说的intConnect函数我没有查到,您能告诉我它的功能,基本用法吗?谢谢!
Re:Re:Re:请高手指引:EP7312的中断
intConnect()是VxWorks的函数,如果你的操作系统不是VxWorks,就不能用这个函数,你的操作系统也应该提供类似的函数,你可以找找看.这个函数主要是把中断和中断例程联系起来.就是解决你提到的问题.
Re:Re:Re:Re:请高手指引:EP7312的中断
谢谢您,
我的操作系统是linux的,有类似的函数吗?
再问:怎样在EP72xx中断向量地址为0x18中放置一跳转指令(比如 goto:),跳到中断处理函数呢?
Re:Re:Re:Re:Re:请高手指引:EP7312的中断
linux操作系统下,函数应该是request_irq(),你可以查一下这个函数的具体用法.
不过,我建议最好不要对中断的入口地址进行操作,因为系统已经做得很完善了,并提供了了接口函数,如果你对这个地址操作不当的话,会严重影响系统,会破环整个系统的中断响应.
如果一定要重新写的话,可用memmove()将你的跳转函数放到0x18处,注意这个跳转函数不能大于4个字节,跳转在C程序中就是简单的函数调用,和goto是不一样的.
Re:Re:Re:Re:Re:Re:请高手指引:EP7312的中断
真的谢谢您 ,您给我这么多知识。
主题:怎样实现在程序中产生一个系统中断
怎样实现在程序中产生一个系统中断,比如向串口发一个中断?
Re:怎样实现在程序中产生一个系统中断
一般中断的产生是由硬件定义的,如串口中断的定义:
1.接收中断:当接收中断使能,接收数据存储器 RxData 存在有效数据,则产生中断.
2.发送中断:当发送中断使能,发送数据存储器 TxData 为空,则产生中断.

硬件发送中断产生逻辑示意

硬件接收中断产生逻辑示意
所以要产生一个串口中断,主要有两步:
1.使能这两个串口中断,RX Enable,TX Enable,函数intEnable().
2.用intConnect()登记中断号,和相应的中断例程ISR.
只要TX中断使能,什么都不必做,因为数据存储器 TxData 本身为空,就会有TX中断产生,自动执行你的中断程序.
同样,RX中断产生,只要做程序向串口发送数据,使RxData中有数据,也会产生中断.
好像不行
vxworks也没有软中断。如果你知道了办法,请告诉我。
Re:好像不行
为什么不行呢?能否说一下你的理由呢?
这里我没有用软中断,这是用程序来触发串口的硬件中断呀,RX中断我曾经用过多次.
VxWorks中好像没有实现软中断的函数,一般硬件定义有软中断的(Software Interrupt或Program Interrupt),如PowerPC 定义软中断向量地址为0x0700,由tw和twi指令来触发中断.ARM定义软中断向量地址为0x8,由SWI指令来触发中断.
如果想在VxWorks中使用软中断的话,可能最好的办法是在BSP中写一个汇编程序,然后在其他地方调用.
我猜测软件中断一般和系统联系紧密如系统错误等等,应用层和一般的系统编程基本上用不到,所以VxWorks没有提供这样的函数.
讨教
你的串口硬件中断的产生我没看明白。你是针对的哪种cpu或是cpu+外围芯片?860没有这样的机制。
Re:讨教
串口硬件中断的定义应该和CPU的种类没有关系,也和cpu或cpu+外围芯片形式无关.
我曾用过IBM PowerPC4xx和ARM7(clps7xxx),这两种CPU都集成了两个内部的串口UART,我还在外部扩展过串口芯片ns16552,基本上是一样的.
MPC860的结构和上面两种不同,尽管它的核也是PowerPC,它集成了两个处理块,一个处理块是嵌入的PowerPC核,另一个是通信处理模块(CPM).通信处理模块有4个SCC和2个SMC,这六个通信口可以通过设置来支持多种协议和通信方式,也可设置为串口UART模式(大概是通过寄存器GSMR或SMCMR),功能和中断的定义和通常的串口没有区别,你可以查一下寄存器SCCM/SCCE的位14和位15定义,这里定义了在何种情况下产生硬件中断.
所以MPC860也有这样的机制.
Re:Re:讨教
860的cpm我还算熟悉,但我实在想不出如何能用程序触发一个中断,即使在看了你的贴子之后。你能不能说仔细些?
Re:Re:Re:讨教
根据MPC860中SCC UART Event Register(SCCE)的位14和位15定义,如位15是数据接收中断标志位,如果串口收到数据,则产生硬件中断,所以可以写程序向串口发数据,并不是程序产生的的中断,而是用程序发送数据,数据到达串口后,串口有数据收到就会产生RX中断,通知系统有数据到达,有相应的中断例程ISR来取数据.
发送的情况类似,数据FIFO为空,产生中断,告诉系统发送准备就绪,可以发送,ISR把数据放入FIFO中,发送中断位清零.当发送完毕后,FIFO再为空,再次产生中断,告诉系统发送准备就绪,继续发送.
不知这样解释的是否清楚.
Re:Re:Re:Re:讨教
你说:
“所以可以写程序向串口发数据,并不是程序产生的的中断,而是用程序发送数据”。
如何向串口发送数据?
我明白你的意思
"如何向串口发送数据?"
这一点主要是实现的问题,和中断关系不大
有三种方法实现:
1.一般串口都支持LOOP BACK模式,即片子内部自发自收,设置成这种模式即可.
2.将串口的发送脚TX和接收脚TX连接.
3.用PC机上的Hyper Terminal和串口相连,不用做程序,直接可通过终端向串口发数据.
ARM 计时器中断编程实现过程
ARM7一般内部有两个16位计时器(Timer counter)和一个32位实时时钟(RTC),计时器中断属于IRQ中断,这里以计时器1为例叙述一下中断的编程过程
设置interrup mask INTMR1寄存器 0x80000240 第8位TC1OI计时器1为使能. 在0x800000300 计时器 1 的数据寄存器TC1D写入指定数据,这样数据开始从这个给定的数开始递减计数,计数递减至 0 后,会产生一个溢出underflow IRQ中断请求,中断状态寄存器INTSR1 0x80000240 第8位TC1OI置位.系统会跳到中断向量表地址 0x00000018 处,执行相应的中断程序,中断程序通过判断中断的类型(判断中断状态寄存器的位),来执行相应的中断服务程序ISR. 中断状态寄存器标志位复位,计时器开始重新开始计时.
返回页首
Intel Flash芯片
参见Flash ROM示例
问题 1 :我们现在用的是intel E28F640 J3A120型号的falsh芯片.在该芯片上要存放配置信
息、某些标志位,动态增长,减少的数据.现在有个问题: 在向某个地址写数据之前,是否一定要擦除该地址所在的块?
应该要擦除该地址所在的块block,先要Unlock这个块,然后擦除该块,再写操作.通常的操作都是这样。所以一个4K--128K块擦除要用几百或几千毫秒,全部Flash擦除用到多达30秒时间,很费时.这就是为什么现在有些Flash(如ATMEL的AT29C040等)采用较小的block,sector或page(64---512bytes)的原因.
问题 2 :(一个块是128KBytes,这样我仅仅为了改写一个Byte,就必须读128Kbytes,然后擦除该块,然后再写128KBytes,太累了,不可能吧??)有没有擦除一个字节或子的方式?
我想肯定是这样的,因为flash的命令:Unlock,Erase,Write对flash的操作都是以块为单位的,即使你想只擦除一个字节,实际上擦除的是一个块,即128k.这是flash硬件定义的,对编程来说并不麻烦,是一样的,只是花费时间长一些。没有擦除一个字节或位的方式。
为了解决以上的问题,有些芯片如AT29c040和W29c040采用小的Sector(块)方式,每个sector大小只有256bytes,写的时候,只要打开写保护,不需要擦处,直接按sector写入.尽管也要以Sector为单位操作,由于Sector非常小,所以特别适用于修改少量字节的操作。
问题 3 : 我现在要实现对INTEL 28F320J3A的操作,但是有一个很大的问题就是我感觉擦除和写数据都比较慢,我想和我没有使用它提供的写BUFFER的命令有关,所以想向您请教写BUFFER的问题.请问是不是每一个大小为128K的块只有32bytes的buffer,如果我想用写buffer操作,应该注意哪些问题呢?
对Flash擦除和写数据是慢的,如果用写BUFFER的命令肯定会快一点,具手册上说,会快20倍,我没试过,不知道.32bytes的buffer不是每个block都有,是整个flash只有一个32bytes的buffer,用写BUFFER命令对所有的blocks写操作,都要用同一个buffer,写Buffer是主要要检查buffer是否available,其实buffer起缓冲作用,来提高工作效率,
写Buffer的主要步骤:
1.写write buffer命令到该Block的首地址.
2.先查status,看buffer是否available,
3.写入所写数据的的字节数到Flash的实际地址.
4,写数据
5.写WRITE_BUFF_CONFIRM命令到该Block的首地址
6.写READ_ARRAY命令到该Block的首地址
其中要注意同一组数据跨越不同block时的处理.
上述步骤是肯定对的,你可以先试着写出程序,有什么问题,我们再交流,不要客气,
问题 4 :如果我不使用写buffer的命令操作是不是就会很慢(写300多K大小的东西要半分多钟),如果写300多K大小的东西要半分多钟,我觉得是不正常的,另外,我对block erase suspend command和>program suspend command等suspend命令的作用也不是很明白,一下子提了这么多问题,希望您没看烦,也很希望你能给我一些帮助,先谢过了
你应该检查一下程序,是不是程序有问题,不应该这么慢.这些suspend命令,我也没有用过,应该是在对一个block造作过程中,暂停操作,来对另一个block操作(读数据或执行程序),待完成后,再恢复原来的.block erase suspend command和program suspend command其实是一个命令B0H
返回页首
Cillus网卡CS8900A Linux驱动
可参见网卡示例
Re: 谁做过网络接口控制芯片CS8900A的驱动?
我曾经写过这种网卡的驱动,它相对来说比其它的驱动要难一些主要在于EEPROM 和 I/O MODE上,EEPROM 是你必须要操作的,因为一般网卡的 MAC 地址要侟在这里,另外还有一些用户设置。如果你只用网卡默认的设置,可暂时不用,网卡有两种运行模式,MEMORY MODE 和 I/O MODE,MEMORY MODE 较为简单,对任何寄存器直接操作,不过你的硬件电路应支持才行,主要看有多少地址线和网卡连.
如果采用 I/O MODE 则较为麻烦,对任何寄存器操作均要通过 I/O PORT 0X300 写入或读出.
你所做的只是对一些寄存器进行必要的设置(TX RX ENABLE,IP FILTER,....),然后将莫一地址的数据包放入数据寄存器即可,无须考虑 MAC 封包解包的事.
你的问题我看了一下,我没有在linux下做过这类程序,不过我原来用的操作系统
VxWorks是从UNIX移植过来的,和linux的环境相似,用的都是GNU环境,另外我不清楚或模
糊的地方也查了一些资料.对你的问题回答了一下.大概基本上是正确的.
有什么不清楚的,再来信,能帮得上你,我很高兴.
问题 1 :在<>P371:如果一个驱动程序做为主流Linux核心的一部分发行的话,它并不声明自己的device结构,而是使用在drivers/net/Space.c中声明的结构。Space.c声明了所有网络设备的链表,即包括plip1一类驱动程序特定的结构,也包括通用目的的eth设备。以太网根本不关心它们的device结构,因为它们使用通用目的的结构。这种通用的eth设备结构声明ethif_probe为它们的init函数。程序员要想在主流核心中插入一个新的以太网接口只需要在ethif_probe中加入一个对驱动程序初始化函数的调用。另一方面,非eth驱动程序的作者需要在Space.c中插入它们的device结构。在两种情况下,如果驱动程序必须被链到核心,只需要修改源文件Space.c。
在Space.c中:
ethif_probe(struct device *dev)
{
u_long base_addr = dev->base_addr;
if ((base_addr == 0xffe0)  ||  (base_addr == 1))
return 1;  /* ENXIO */
if (1
/* All PCI probes are safe, and thus should be first. */
#ifdef CONFIG_DE4X5              /* DEC DE425, DE434, DE435 adapters */
&& de4x5_probe(dev)
#endif
#ifdef CONFIG_UCCS8900
&& cs89x0_probe(dev)
#endif
.................
.................
这里我想问的是,当我写完了自己的驱动代码比如cs89x0.c,cs89x0.h,并在space.c中#define CONFIG_UCCS8900,接 下来在编译内核的时候我该去修改哪个文件,可以将cs89x0.c直接编译到内核中?   如果是按模块化方式写驱动,那么编译生成.o文件然后insmod一下就可以了;但现在要按非模块化的方式,直接编译到内核里去,该怎么做呢?
1. 把cs89xx编译成独立模块,执行下列命令:
gcc -D_KERNEL_-I/usr/src/linux/include-I/usr/src/linux/net/inet-Wall -Wstrictprototypes -02 -fomit-frame-pointer -DMODULE -DCONFIG_MODVERSIONS -ccs89x0.c
编译结果是名为cs89x0.o的驱动程序目标模块。要装载此驱动程序,
输入下列命令: insmod cs89x0.o io=0x360irq=10
//假如网卡的起始端口号为0x360,中断号为10
要卸载此驱动程序,用rmmod命令:
rmmod cs89x0.o
2.如果要将驱动程序编进系统核心,
修改/usr/src/linux/drivers/net/CONFIG,加入:
CS89x0_OPTS=
修改/usr/src/linux/drivers/net/Config.in,加入:
tristate‘CS8920 Support’CONFIG_CS8920
以上两行是为了让make config在配置过程中询问是否增加CS89xx网卡的支
持。
修改/usr/src/linux/drivers/net/Makefile加入:
ifeq((CONFIG_CS8920),y)  L_OBJS+=cs89x0.o
endif
修改/usr/src/linux/drivers/net/Space.c,加入:
extern int cs89x0_probe(struct device *dev);
……
#ifdef CONFIG_CS8920&& cs89x0_probe(dev);
#endif
以上两段是为了编译并输出网卡驱动程序及其例程。
把驱动程序源代码拷到/usr/src/linux/drivers/net目录下。
在/usr/src/linux目录下执行 make config或 make menuconfig,选择核心CS89xx网卡支      持。
执行make dep、make clean命令。最后用 make zImage 编译Linux核心。
问题 2 :.uCcs8900.c中的send_test_pkt函数有什么用呢?其中定义的test_packet数组
那样赋值该怎么理解?
send_test_pkt(struct device *dev)
{
int ioaddr = dev->base_addr;
char test_packet[] = { 0,1,2,3,4,5,0,3,4,5,6,7,
0, 46, /* A 46 in network order */
0, 0, /* DSAP=0 & SSAP=0 fields */
0xf3, 0 /* Control (Test Req + P bit set) */ };
long timenow = jiffies;
unsigned short event;
writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) |
SERIAL_TX_ON);
memcpy(test_packet,           dev->dev_addr, ETH_ALEN);
memcpy(test_packet+ETH_ALEN, dev->dev_addr, ETH_ALEN);
outw(TX_AFTER_ALL, ioaddr + TX_CMD_PORT);
outw(ETH_ZLEN, ioaddr + TX_LEN_PORT);
/* Test to see if the chip has allocated memory for the packet */
while (jiffies - timenow < 5)
if (readreg(dev, PP_BusST) & READY_FOR_TX_NOW)
break;
if (jiffies - timenow >= 5)
return 0; /* this shouldn't happen */
/* Write the contents of the packet */
outsw(ioaddr + TX_FRAME_PORT,test_packet,(ETH_ZLEN+1) >>1);
if (net_debug > 1) printk("Sending test packet ");
/* wait a couple of jiffies for packet to be received */
for (timenow = jiffies; jiffies - timenow < 60; ) ;
if (((event = readreg(dev, PP_TxEvent)) & TX_SEND_OK_BITS) ==TX_OK)
{
if (net_debug > 1) printk("succeeded\n");
return 1;
}
if (net_debug > 1) printk("failed \n");
return 0;
}
这是一个测试程序,不仅过linux操作系统和上层TCP/IP,直接向网卡发数据包,来
测试网卡是否工作正常,数组使用的标准的以太网帧格式(参见相关的RFC文档),不用管
它,直接拿来就用的,这个数组的意思是向网络个点发包,网络点收到包好,进行回复.
问题 3 :我在别的一些cs89x0.c文件中看到这个函数是被detect_aui,detect_bnc等这样
的函数所调用,但在uCcs8900.c中的detect_tp中没有用到?
BNC基本上现在网络都不用了,一般是RJ45的插头,你可以看一下现在的网卡,没有BNC
头.AUI类似串口通信,尽管现在网卡都支持,但很少用到.所以这里只用了detect_tp()来检测RJ45连线是否存在.
问题 4 :这个函数里还用到了ETH_ALEN和ETH_ZLEN这两个宏,这两个宏的解释我看到过,但
理解的不是很清楚,在这里test_packet,ETH_ALEN和ETH_ZLEN相互间是什么样的关系呢?
ETH_ZLEN时所发数据包的长度,ETH_ALEN应该是6,是MAC地址的字结数.
问题 5 :.驱动编译到内核里,生成映像文件当到目标板上让系统在目标板上运行起来后,
该怎么测试我的驱动程序呢?需要再写相应的测试代码吗?
测试应该是两步:
1.底层硬件测试,可用它的send_test_pkt()来测,或自己写一个LOOPBACK测试程序,具体方法可参见CS89手册,test mode.
2.上层网络测试,可用BSD写一个网络通信程序,开发板和PC及通信传送大量数据.
或用linux上FTP服务来传送文件.
问题 6 :request_irq(IRQ_MACHSPEC | 20,
cs8900_interrupt,
IRQ_FLG_STD,
"CrystalLAN_cs8900a", NULL))
panic("Unable to attach cs8900 intr\n");
IRQ_MACHSPEC | 20, 该是硬件中断号,不知道为什么要这样写
IRQ_FLG_STD ,这个标志是要做些什么设置?中断共享等等?
IRQ_MACHSPEC | 20中20是硬件中断号, IRQ_MACHSPEC 应该是(0x10000000L),第一位1只是一个说明标志,说明是特殊设备中断.
IRQ_FLG_STD是中断处理的一些属性设置,如快速,屏蔽等,我没有找到这个的定义,
可能是标准中断处理吧.
返回页首
LCD 与触摸屏
主题:LCD 与触摸屏分辨率不一样
我的LCD 分辨率与触摸屏的分辨率不一样, 但尺寸相同, 在触摸屏
上点击的坐标与LCD显示的坐标不一致, 请问有什么办法可
以解决(软件或硬件解决方案均可)。
环境: CodeWarrior for 68K, with PPSM
Re:LCD 与触摸屏分辨率不一样
LCD 分辨率与触摸屏的分辨率一般来说是不一样,坐标也不一样,这需要做程序进行转换.
我曾做过这样的转换,我的LCD分辨率是320*240,坐标原点在右下角.
触摸屏分辨率是900*900,坐标原点在左上角.
计算公式如下:
xLCD=320-[320*(x-x2)/(x1-x2)];
yLCD=240-[240*(y-y2)/(y1-y2)];
其实就是中学学的坐标转换.这种方法肯定能行的,试试看吧.
LCD 编程要点
返回页首
Modem拨号
VxWorks下Modem拨号的主要实现过程
这里用到一些串口RS232的定义和AT命令,Modem串口采用ns16552.主要步骤如下
1. off hook,发出摘机命令(ATH1\r),
等待modem返回状态,如果是"OK",则表示成功.进行第二步.
2. on hook 发出挂机命令(ATH\r),
等待modem返回状态,如果是"OK",则表示成功.进行第三步.
3. off hook,dialing,摘机拨号(ATDT....\r),
等待modem返回状态,如果是"CONNECT",则表示成功.进行第四步.
4. send data,发送数据.
最好按上述步骤一步一步调,并要等待正确的返回值后再进行下一步.
具体程序例子如下,拨号:
// 清空接收FIFO
REG(FCR, nsChan) |=FCR_RXCLR;
// 等待,直到清空为止
while((REG(FCR, nsChan) & FCR_RXCLR) != 0x00);
// 拨号
while(atdt1[i]!=0)
{
// 检查发送FIFO是否准备好,为空
while((REG(LSR, nsChan) & LSR_THRE) == 0x00);
// 在发送FIFO中放入数据
REG(THR, nsChan) = atdt1[i];
i++;
}
// 等待是否有数据到达,即modem返回数据.
while((REG(LSR, nsChan) & LSR_DR) == 0x00);
// 接收数据并判断返回值
response[i-19]=REG(RBR,nsChan);
if(response[0]!=0x43)
..................
else
..................
// 如果返回值是"connect",
while(*data!=0)
{
while((REG(LSR, nsChan) & LSR_THRE) == 0x00);
REG(THR, nsChan) = *data++;
}
其他步骤基本一样.
附: RS232(9 PINS)的主要定义:
Pin 1: DCD (Data Carrier Detect) Pin 2: RXD (Receive)       Pin 3: TXD (Transmit)
Pin 4: DTR (Data Terminal Ready) Pin 5: SG (Signal Grund)   Pin 6: DSR (Data Set Ready)
Pin 7: RTS (Request To Send)      Pin 8: CTS (Clear To Send) Pin 9: RI (Ring Indicator)
其中:    DTE for Data Terminal Equipment, such as computer, printer & terminal
DCE for Data Communication Equipment, such as modems.
+3 To +12 volts indicates On or O- state (space)
-3 To -12 volts indicates Off
Usually use swing between +12V~~-12V, dead area between +3V~~-3V
返回页首
RTC
怎样写PowerPc的Real-Time Clock(RTC)的BSP?
PowerPC 内部一般只有3个timer,没有内部RTC,PowerPC专门为外部RTC芯片设置了接口,一般外部RTC芯片是选择Dallas的,带有备用电源,通过SPI进行操作,可精确设置年月日时.... RTC驱动总的来说是不复杂的,只是要注意一些数据格式的转换,如BCD码等.
RTC一般有SPI接口和标准的三线接口,主要取决于管脚SERMODE,如果SERMODE接Vcc,则为SPI方式。SPI方式用到4个管脚:SDO,SDI,CE,SCLK.
三线制和SPI方式类似,只不过是用一个I/O管脚代替了SDO和SDI.
返回页首
PCI驱动
PCI 驱动编程步骤
1。复制C:\Tornado\target\h\drv\pci目录下pciAutoConfigLib.h,pciConfigLib.h等PCI头文件文件和C:\Tornado\target\src\drv\pci目录下pciAutoConfigLib.c,pciConfigLib.c等PCI文件到BSP目录下。
2。根据实际的PCI硬件定义改写或从写这些PCI文件。
3。改写BSP配置文件
a. 在BSP 文件config.h中加入语句 #define INCLUDE_PCI (添加PCI模块)。
b. 在BSP 文件sysLib.c中加入语句 #include "pci/pciConfigLib.c"(主要PCI初始化函数在这个文件中)。
c。在BSP 文件sysLib.c中加入语句 IMPORT void sysOutLong(); (导入PCI需要的一些基本函数)。
IMPORT char sysInByte();
IMPORT char sysOutByte();
...................
返回页首