GPIO是什么?A/D采样频率问题

来源:百度文库 编辑:神马文学网 时间:2024/04/28 04:39:12
GPIO实验
    一、什么是GPIO   GPIO,英文全称为General-Purpose IO ports,也就是通用IO口。嵌入式系统中常常有数量众多,但是结构却比较简单的外部设备/电路,对这些设备/电路有的需要CPU为之提供控制手段,有的则需要被CPU用作输入信号。而且,许多这样的设备/电路只要求一位,即只要有开/关两种状态就够了,比如灯亮与灭。对这些设备/电路的控制,使用传统的串行口或并行口都不合适。所以在微控制器芯片上一般都会提供一个通用可编程IO接口,即GPIO   接口至少有两个寄存器,即通用IO控制寄存器通用IO数据寄存器。数据寄存器的各位都直接引到芯片外部,而对这种寄存器中每一位的作用,即每一位的信号流通方向,则可以通过控制寄存器中对应位独立的加以设置。这样,有无GPIO接口也就成为微控制器区别于微处理器的一个特征。       在实际的MCU中,GPIO是有多种形式的。比如,有的数据寄存器可以按照位寻址,有些却不能按照位寻址,这在编程时就要区分了。比如传统的8051系列,就区分成可位寻址和不可位寻址两种寄存器。另外,为了使用的方便,很多mcuglue logic等集成到芯片内部,增强了系统的稳定性能,比如GPIO接口除去两个标准寄存器必须具备外,还提供上拉寄存器,可以设置IO的输出模式是高阻,还是带上拉的电平输出,或者不带上拉的电平输出。这在电路设计中,外围电路就可以简化不少。    另外需要注意的是,对于不同的计算机体系结构,设备可能是端口映射,也可能是内存映射的。如果系统结构支持独立的IO地址空间,并且是端口映射,就必须使用汇编语言完成实际对设备的控制,因为C语言并没有提供真正的端口的概念。如果是内存映射,那就方便的多了。 举个例子,比如像寄存器A(地址假定为0x48000000)写入数据0x01,那么就可以这样设置了。  #define A (*(volatile unsigned long *)0x48000000)
...
    A = 0x01;
...
    这实际上就是内存映射机制的方便性了。其中volatile关键字是嵌入式系统开发的一个重要特点。上述表达式拆开来分析,首先(volatile unsigned long *)0x48000000的意思是把0x48000000强制转换成volatile unsigned long类型的指针,暂记为p,那么就是#define A *p,即AP指针指向位置的内容了。这里就是通过内存寻址访问到寄存器A,可以读/写操作。    二、S3C2410GPIO的特点    s3c2410GPIO117pin,下面应该到9 IO ports看看详细部分了。 The S3C2410X has 117 multi-functional input/output port pins. The ports are:
— Port A (GPA): 23-output port
— Port B (GPB): 11-input/output port
— Port C (GPC): 16-input/output port
— Port D (GPD): 16-input/output port
— Port E (GPE): 16-input/output port
— Port F (GPF): 8-input/output port
— Port G (GPG): 16-input/output port
— Port H (GPH): 11-input/output port 
    这么多的IO口,其实很多是复合功能的,既可以作为普通的IO口使用,也可以作为特殊外设接口。在程序设计时,要对整体的资源有所规划,初始化时就应该把所有资源安排合理。这样才会避免出现问题。      现在的8个端口,其寄存器是相似的。除了两个通用寄存器GPxCONGPxDAT外,还提供了GPxUP用于确定是否使用内部上拉电阻(其中xA-H,需要注意的是没有GPAUP)。应用的主要步骤就是:      ·设置GPIO控制寄存器GPxCON     ·设置GPIO上拉寄存器GPxUP 初始化完成后,就可以通过对GPxDAT的操作来实现相应的应用了。其中,PORT APORT B-H在功能选择方面有所不同,GPACON的每一位对应一根引脚(共23pin有效)。当某位设为0,相应引脚为输出引脚,此时往GPADAT中写0/1,可以让引脚输出低电平/高电平;当某位设为1,则相应引脚为地址线,或者用于地址控制,此时GPADAT没有用了。 一般而言,GPACON通常全设为1,以便访问外部存储器件。PORT B-H在寄存器操作方面完全相同。 GPxCON中每两位控制一根引脚:00表示输入,01表示输出,10表示特殊功能,11保留。GPxDAT用于读/写引脚:当引脚设为输入时,读此寄存器可知相应引脚状态是高/低;当引脚设为输出时,写此寄存器相应位可以使相应引脚输出低电平或高电平。GPxUP:某位设为0,相应引脚无内部上拉;为1,相应引脚使用内部上拉。关于特殊功能,那就得结合特殊外设来进行设置了。   基本实验 实验18段数码管显示,共四位   我的开发板上没有多余的GPIO插头,只好利用液晶的显示的插口了,对应的引脚: VD[07] 对应 GPC[815]     VD[823] 对应 GPD[015]    四个共阴极的数码管,选择信号对应GPC[811]    8段显示数据对应GPD[07] 这样一来就可以利用这四个数码管显示数字了 1)软件架构仿照了vivi,或者Linux Kernel。其实写这么小的程序用不到这么麻烦,但是可以训练这种架构,为写中型大型程序打好基础。     2)注意C语言下实现寄存器读写的(*(volatile unsigned long *)(addr))。其实就是要掌握volatile和指针的用法。     3)写c时,要注意头文件如何处理。写Makefile时,要注意是否采用隐含规则,如果不采用,就要自己定义明确规则,就像vivi里面的Rules.make。在这里,因为只是涉及到.s的编译不采用隐含规则,所以没有把Rules.make单独拿出,事实上可以单独写为Rules.make,然后在Makefile后加入include Rules.make就可以了。     4)要调用C子程序,必须分配堆栈空间。因为子程序调用时,要进行入栈出栈处理。又因为从nand flash启动,而nand flashS3C2410下的特点规定堆栈不能超过4K 文件打包

文件: led_c.tar.gz 大小: 10KB 下载: 下载

 


  Using the I2C Bus 

Judging from my emails, it is quite clear that the I2C bus can be very confusing for the newcomer. I have lots of examples on using the I2C bus on the website, but many of these are using high level controllers and do not show the detail of what is actually happening on the bus. This short article therefore tries to de-mystify the I2C bus, I hope it doesn‘t have the opposite effect!

The physical I2C bus
This is just two wires, called SCL and SDA. SCL is the clock line. It is used to synchronize all data transfers over the I2C bus. SDA is the data line. The SCL & SDA lines are connected to all devices on the I2C bus. There needs to be a third wire which is just the ground or 0 volts. There may also be a 5volt wire is power is being distributed to the devices. Both SCL and SDA lines are "open drain" drivers. What this means is that the chip can drive its output low, but it cannot drive it high. For the line to be able to go high you must provide pull-up resistors to the 5v supply. There should be a resistor from the SCL line to the 5v line and another from the SDA line to the 5v line. You only need one set of pull-up resistors for the whole I2C bus, not for each device, as illustrated below:

The value of the resistors is not critical. I have seen anything from 1k8 (1800 ohms) to 47k (47000 ohms) used. 1k8, 4k7 and 10k are common values, but anything in this range should work OK. I recommend 1k8 as this gives you the best performance. If the resistors are missing, the SCL and SDA lines will always be low - nearly 0 volts - and the I2C bus will not work.

Masters and Slaves
The devices on the I2C bus are either masters or slaves. The master is always the device that drives the SCL clock line. The slaves are the devices that respond to the master. A slave cannot initiate a transfer over the I2C bus, only a master can do that. There can be, and usually are, multiple slaves on the I2C bus, however there is normally only one master. It is possible to have multiple masters, but it is unusual and not covered here. On your robot, the master will be your controller and the slaves will be our modules such as the SRF08 or CMPS03. Slaves will never initiate a transfer. Both master and slave can transfer data over the I2C bus, but that transfer is always controlled by the master.

The I2C Physical Protocol
When the master (your controller) wishes to talk to a slave (our CMPS03 for example) it begins by issuing a start sequence on the I2C bus. A start sequence is one of two special sequences defined for the I2C bus, the other being the stop sequence. The start sequence and stop sequence are special in that these are the only places where the SDA (data line) is allowed to change while the SCL (clock line) is high. When data is being transferred, SDA must remain stable and not change whilst SCL is high. The start and stop sequences mark the beginning and end of a transaction with the slave device.

Data is transferred in sequences of 8 bits. The bits are placed on the SDA line starting with the MSB (Most Significant Bit). The SCL line is then pulsed high, then low. Remember that the chip cannot really drive the line high, it simply "lets go" of it and the resistor actually pulls it high. For every 8 bits transferred, the device receiving the data sends back an acknowledge bit, so there are actually 9 SCL clock pulses to transfer each 8 bit byte of data. If the receiving device sends back a low ACK bit, then it has received the data and is ready to accept another byte. If it sends back a high then it is indicating it cannot accept any further data and the master should terminate the transfer by sending a stop sequence. 

How fast?
The standard clock (SCL) speed for I2C up to 100KHz. Philips do define faster speeds: Fast mode, which is up to 400KHz and High Speed mode which is up to 3.4MHz. All of our modules are designed to work at up to 100KHz. We have tested our modules up to 1MHz but this needs a small delay of a few uS between each byte transferred. In practical robots, we have never had any need to use high SCL speeds. Keep SCL at or below 100KHz and then forget about it.

I2C Device Addressing
All I2C addresses are either 7 bits or 10 bits. The use of 10 bit addresses is rare and is not covered here. All of our modules and the common chips you will use will have 7 bit addresses. This means that you can have up to 128 devices on the I2C bus, since a 7bit number can be from 0 to 127. When sending out the 7 bit address, we still always send 8 bits. The extra bit is used to inform the slave if the master is  writing to it or reading from it. If the bit is zero are master is writing to the slave. If the bit is 1 the master is reading from the slave. The 7 bit address is placed in the upper 7 bits of the byte and the Read/Write (R/W) bit is in the LSB (Least Significant Bit).

The placement of the 7 bit address in the upper 7 bits of the byte is a source of confusion for the newcomer. It means that to write to address 21, you must actually send out 42 which is 21 moved over by 1 bit. It is probably easier to think of the I2C bus addresses as 8 bit addresses, with even addresses as write only, and the odd addresses as the read address for the same device. To take our CMPS03 for example, this is at address 0xC0 ($C0). You would uses 0xC0 to write to the CMPS03 and 0xC1 to read from it. So the read/write bit just makes it an odd/even address. 

The I2C Software Protocol
The first thing that will happen is that the master will send out a start sequence. This will alert all the slave devices on the bus that a transaction is starting and they should listen in incase it is for them. Next the master will send out the device address. The slave that matches this address will continue with the transaction, any others will ignore the rest of this transaction and wait for the next. Having addressed the slave device the master must now send out the internal location or register number inside the slave that it wishes to write to or read from. This number is obviously dependant on what the slave actually is and how many internal registers it has. Some very simple devices do not have any, but most do, including all of our modules. Our CMPS03 has 16 locations numbered 0-15. The SRF08 has 36. Having sent the I2C address and the internal register address  the master can now send the data byte (or bytes, it doesn‘t have to be just one). The master can continue to send data bytes to the slave and these will normally be placed in the following registers because the slave will automatically increment the internal register address after each byte. When the master has finished writing all data to the slave, it sends a stop sequence which completes the transaction. So to write to a slave device: 
1. Send a start sequence
2. Send the I2C address of the slave with the R/W bit low (even address)
3. Send the internal register number you want to write to
4. Send the data byte
5. [Optionally, send any further data bytes]
6. Send the stop sequence.

As an example, you have an SRF08 at the factory default address of 0xE0. To start the SRF08 ranging you would write 0x51 to the command register at 0x00 like this:
1. Send a start sequence
2. Send 0xE0 ( I2C address of the SRF08 with the R/W bit low (even address)
3. Send 0x00 (Internal address of the command register)
4. Send 0x51 (The command to start the SRF08 ranging)
5. Send the stop sequence.

Reading from the Slave
This is a little more complicated - but not too much more. Before reading data from the slave device, you must tell it which of its internal addresses you want to read. So a read of the slave actually starts off by writing to it. This is the same as when you want to write to it: You send the start sequence, the I2C address of the slave with the R/W bit low (even address) and the internal register number you want to write to. Now you send another start sequence (sometimes called a restart) and the I2C address again - this time with the read bit set. You then read as many data bytes as you wish and terminate the transaction with a stop sequence. So to read the compass bearing as a byte from the CMPS03 module:
1. Send a start sequence
2. Send 0xC0 ( I2C address of the CMPS03 with the R/W bit low (even address)
3. Send 0x01 (Internal address of the bearing register)
4. Send a start sequence again (repeated start)
5. Send 0xC1 ( I2C address of the CMPS03 with the R/W bit high (odd address)
6. Read data byte from CMPS03
7. Send the stop sequence.

The bit sequence will look like this:

Wait a moment
That‘s almost it for simple I2C communications, but there is one more complication. When the master is reading from the slave, its the slave that places the data on the SDA line, but its the master that controls the clock. What if the slave is not ready to send the data! With devices such as EEPROMs this is not a problem, but when the slave device is actually a microprocessor with other things to do, it can be a problem. The microprocessor on the slave device will need to go to an interrupt routine, save its working registers, find out what address the master wants to read from, get the data and place it in its transmission register. This can take many uS to happen, meanwhile the master is blissfully sending out clock pulses on the SCL line that the slave cannot respond to. The I2C protocol provides a solution to this: the slave is allowed to hold the SCL line low! This is called clock stretching. When the slave gets the read command from the master it holds the clock line low. The microprocessor then gets the requested data, places it in the transmission register and releases the clock line allowing the pull-up resistor to finally pull it high. From the masters point of view, it will issue the first clock pulse of the read by making SCL high and then check to see if it really has gone high. If its still low then its the slave that holding it low and the master should wait until it goes high before continuing. Luckily the hardware I2C ports on most microprocessors will handle this automatically.

Sometimes however, the master I2C is just a collection of subroutines and there are a few implementations out there that completely ignore clock stretching. They work with things like EEPROM‘s but not with microprocessor slaves that use clock stretching. The result is that erroneous data is read from the slave. Beware!

Example Master Code
This example shows how to implement a software I2C master, including clock stretching. It is written in C for the PIC processor, but should be applicable to most processors with minor changes to the I/O pin definitions. It is suitable for controlling all of our I2C based robot modules. Since the SCL and SDA lines are open drain type, we use the tristate control register to control the output, keeping the output register low. The port pins still need to be read though, so they‘re defined as SCL_IN and SDA_IN. This definition and the initialization is probably all you‘ll need to change for a different processor.

#define SCL     TRISB4 // I2C bus
#define SDA     TRISB1 //
#define SCL_IN  RB4    //
#define SDA_IN  RB1    //

To initialize the ports set the output resisters to 0 and the tristate registers to 1 which disables the outputs and allows them to be pulled high by the resistors.
SDA = SCL = 1;
SCL_IN = SDA_IN = 0;

We use a small delay routine between SDA and SCL changes to give a clear sequence on the I2C bus. This is nothing more than a subroutine call and return.
void i2c_dly(void)
{
}

The following 4 functions provide the primitive start, stop, read and write sequences. All I2C transactions can be built up from these.
void i2c_start(void)
{
  SDA = 1;             // i2c start bit sequence
  i2c_dly();
  SCL = 1;
  i2c_dly();
  SDA = 0;
  i2c_dly();
  SCL = 0;
  i2c_dly();
}

void i2c_stop(void)
{
  SDA = 0;             // i2c stop bit sequence
  i2c_dly();
  SCL = 1;
  i2c_dly();
  SDA = 1;
  i2c_dly();
}

unsigned char i2c_rx(char ack)
{
char x, d=0;
  SDA = 1; 
  for(x=0; x<8; x++) {
    d <<= 1;
    do {
      SCL = 1;
    }
    while(SCL_IN==0);    // wait for any SCL clock stretching
    i2c_dly();
    if(SDA_IN) d |= 1;
    SCL = 0;
  } 
  if(ack) SDA = 0;
  else SDA = 1;
  SCL = 1;
  i2c_dly();             // send (N)ACK bit
  SCL = 0;
  SDA = 1;
  return d;
}

bit i2c_tx(unsigned char d)
{
char x;
static bit b;
  for(x=8; x; x--) {
    if(d&0x80) SDA = 1;
    else SDA = 0;
    SCL = 1;
    d <<= 1;
    SCL = 0;
  }
  SDA = 1;
  SCL = 1;
  i2c_dly();
  b = SDA_IN;          // possible ACK bit
  SCL = 0;
  return b;
}

The 4 primitive functions above can easily be put together to form complete I2C transactions. Here‘s and example to start an SRF08 ranging in cm:

i2c_start();              // send start sequence
i2c_tx(0xE0);             // SRF08 I2C address with R/W bit clear

i2c_tx(0x00);             // SRF08 command register address
i2c_tx(0x51);             // command to start ranging in cm
i2c_stop();               // send stop sequence

Now after waiting 65mS for the ranging to complete (I‘ve left that to you) the following example shows how to read the light sensor value from register 1 and the range result from registers 2 & 3.

i2c_start();              // send start sequence
i2c_tx(0xE0);             // SRF08 I2C address with R/W bit clear

i2c_tx(0x01);             // SRF08 light sensor register address
i2c_start();              // send a restart sequence
i2c_tx(0xE1);             // SRF08 I2C address with R/W bit set

lightsensor = i2c_rx(1);  // get light sensor and send acknowledge. Internal register address will increment automatically.
rangehigh = i2c_rx(1);    // get the high byte of the range and send acknowledge.
rangelow = i2c_rx(0);     // get low byte of the range - note we don‘t acknowledge the last byte.
i2c_stop();               // send stop sequence

Easy isn‘t it?

The definitive specs on the I2C bus can be found on the Philips website. It currently here but if its moved you‘ll find it easily be googleing on "i2c bus specification".
   

基于I2C总线的处理器联网设计

上网时间:2008年07月24日 收藏 打印版 推荐给同仁 发送查询
随着微控制器的价格越来越低,功能越来越强大,电气设计人员发现在单板和多板系统中都使用多个小型控制器是一种更加经济高效的方法。这种辅助处理器能够减轻主处理器在耗时任务上面的处理开销,例如扫描键盘、显示控制器和电机控制。这些控制器也可以配置为各种各样的专用外设。

最近,我接受了一项任务:开发一种能够方便地适用于多种应用的接口(软/硬件),且要符合嵌入式处理器中常用的行业标准。在分析了一些典型应用之后,我们列出了一些针对该硬件接口的设计需求:常用于32位和8位处理器;能够得到常用外设器件的支持;外设接口代码量低于0.5kB;引脚数量少;数据带宽可达10kBps;RAM用量少;一条总线上支持多种外设;方便使用API;不需要外部接口驱动硬件。

由于要求引脚数量少,所以必须采用串行接口。目前处理器中常见的串行接口包括SPI、I2C、USB和RS-232。通过从不同方面权衡比较这些接口,我最终选择了I2C,因为它接口简单,灵活性好,得到了大多数低成本控制器的支持。在不需要很高传输速度的情况下,较少的引脚数和流量控制功能还使得I2C接口相比SPI接口具有更大的优势。

I2C的工作原理

I2C是一种双线双向接口,包括一个时钟信号和一个数据信号(SCL和SDA)。在不增加任何其他信号的情况下,一条I2C总线就可以支持多达12个设备。I2C接口规范包括三种工作速度:100kbps、400kbps和3.4Mbps。大多数常见的控制器只支持100-和400kbps两种模式。I2C总线支持一个主设备多个从设备,或者多个主设备的配置结构。

I2C一个非常重要的特性就是它支持流量控制。如果某个从设备无法保持连续的字节传输,它可以将总线挂起,直到能够跟上主设备的传输速度。这对于包含最小规模的I2C硬件并且必须在固件上支持部分传输协议的从设备来说是非常有用的。I2C总线规范支持7b和10b两种寻址协议。我发现7b寻址模式在大部分应用中的效率更高。

在开始编写代码之前,我们需要很好地了解I2C总线的工作原理。任何情况下I2C总线至少要包含一个主设备,至少要挂有一个或多个从设备。主设备总是由主到从发起数据传输操作。无论有多少个外设挂接在总线上,I2C接口只有两个信号。

两个信号都是集电极开路的,通过大小为2.7k左右的上拉电阻接Vcc电源。SDA信号是双向的,可以由主设备或从设备驱动。SCL信号是由主设备驱动的,但是在一个数据字节的末尾从设备必须保持SCL信号为低,以延迟总线直到从设备开始处理数据。主设备在数据字节的最后一位传输完之后释放SCL信号,然后检查SCL信号是否变高。如果SCL没有变高,那么主设备认为从设备正在请求主设备延迟,直到其开始处理数据。

当通过I2C总线发送数据时,只有当SCL为低电平时才能进行数据变换。当SCL信号为高时,任何方向的数据都应该是稳定的(如图1所示)。

当总线空闲时,主设备和从设备都不下拉SDA和SCL信号。在发起一次数据传输时,主设备驱动SDA信号从高电平变成低电平,同时SCL信号为高。一般地,当SCL信号为高电平时,SDA信号的状态保持不变,但启动或停止条件下除外。当SCL信号为高并且SDA信号从低变高时,是传输停止的情况(如图2所示)。

I2C总线以8b为单位传输数据。每传输一个字节时,必须得到数据接收方的确认。所有的数据都是从MSB(最高有效位)开始传输的。

       采样率类似于动态影像的帧数,比如电影的采样率是24赫兹,PAL制式的采样率是25赫兹,NTSC制式的采样率是30赫兹。当我们把采样到的一个个静止画面再以采样率同样的速度回放时,看到的就是连续的画面。同样的道理,把以44.1kHZ采样率记录的CD以同样的速率播放时,就能听到连续的声音。显然,这个采样率越高,听到的声音和看到的图像就越连贯。当然,人的听觉和视觉器官能分辨的采样率是有限的,基本上高于44.1kHZ采样的声音,绝大部分人已经觉察不到其中的分别了。
而声音的位数就相当于画面的颜色数,表示每个取样的数据量,当然数据量越大,回放的声音越准确,不至于把开水壶的叫声和火车的鸣笛混淆。同样的道理,对于画面来说就是更清晰和准确,不至于把血和西红柿酱混淆。不过受人的器官的机能限制,16位的声音和24位的画面基本已经是普通人类的极限了,更高位数就只能靠仪器才能分辨出来了。比如电话就是3kHZ取样的7位声音,而CD是44.1kHZ取样的16位声音,所以CD就比电话更清楚。
当你理解了以上这两个概念,比特率就很容易理解了。以电话为例,每秒3000次取样,每个取样是7比特,那么电话的比特率是21000。而CD是每秒44100次取样,两个声道,每个取样是16比特,所以CD的比特率是44100*2*16=1411200,也就是说CD每秒的数据量大约是172KB,而一张CD的容量是74分等于4440秒,就是763680KB=745MB。
等等,一张CD的容量应该是640MB,那就是说前边的44.1kHZ取样率和16位精度这两个数据中至少有一个不准确。 第一个得745M是正确的,变成640M是因为cd音源写入碟片采用了PCM预测编码,编码的目的就是压缩,但是压缩很小,失真就小,所以说cd格式几乎是未压缩的。    什么是数据采集? 简介        在计算机广泛应用的今天,数据采集的重要性是十分显著的。它是计算机与外部物理世界连接的桥梁。各种类型信号采集的难易程度差别很大。实际采集时,噪声也可能带来一些麻烦。数据采集时,有一些基本原理要注意,还有更多的实际的问题要解决。 采样频率、抗混叠滤波器和样本数        假设现在对一个模拟信号 x(t) 每隔Δ t 时间采样一次。时间间隔Δ t 被称为采样间隔或者采样周期。它的倒数 1/ Δ t 被称为采样频率,单位是采样数 / 每秒。 t=0, Δ t ,2 Δ t ,3 Δ t …… 等等, x(t) 的数值就被称为采样值。所有 x(0),x( Δ t),x(2 Δ t ) 都是采样值。这样信号 x(t) 可以用一组分散的采样值来表示: 下图显示了一个模拟信号和它采样后的采样值。采样间隔是Δ t ,注意,采样点在时域上是分散的。   图 1 模拟信号和采样显示 如果对信号 x(t) 采集 N 个采样点,那么 x(t) 就可以用下面这个数列表示: 这个数列被称为信号 x(t) 的数字化显示或者采样显示。注意这个数列中仅仅用下标变量编制索引,而不含有任何关于采样率(或Δ t )的信息。所以如果只知道该信号的采样值,并不能知道它的采样率,缺少了时间尺度,也不可能知道信号 x(t) 的频率。 根据采样定理,最低采样频率必须是信号频率的两倍。反过来说,如果给定了采样频率,那么能够正确显示信号而不发生畸变的最大频率叫做恩奎斯特频率,它是采样频率的一半。如果信号中包含频率高于奈奎斯特频率的成分,信号将在直流和恩奎斯特频率之间畸变。 图2显示了一个信号分别用合适的采样率和过低的采样率进行采样的结果。 采样率过低的结果是还原的信号的频率看上去与原始信号不同。这种信号畸变叫做混叠( alias )。 出现的混频偏差( alias frequency )是输入信号的频率和最靠近的采样率整数倍的差的绝对值。 图 2 不同采样率的采样结果 图3给出了一个例子。假设采样频率 fs 是 100HZ, ,信号中含有 25 、 70 、 160 、和 510 Hz 的成分。 图3 说明混叠的例子 采样的结果将会是低于奈奎斯特频率( fs/2=50 Hz )的信号可以被正确采样。而频率高于 50HZ 的信号成分采样时会发生畸变。分别产生了 30 、 40 和 10 Hz 的畸变频率 F2 、 F3 和 F4 。计算混频偏差的公式是: 混频偏差= ABS (采样频率的最近整数倍-输入频率) 其中 ABS 表示“绝对值”,例如: 混频偏差 F2 = |100 – 70| = 30 Hz 混频偏差 F3 = |(2)100 – 160| = 40 Hz 混频偏差 F4 = |(5)100 – 510| = 10 Hz   为了避免这种情况的发生,通常在信号被采集( A/D )之前,经过一个低通滤波器,将信号中高于奈奎斯特频率的信号成分滤去。在图3的例子中,这个滤波器的截止频率自然是 25HZ 。这个滤波器称为 抗混叠滤波器 采样频率应当怎样设置呢?也许你可能会首先考虑用采集卡支持的最大频率。但是,较长时间使用很高的采样率可能会导致没有足够的内存或者硬盘存储数据太慢。理论上设置采样频率为被采集信号最高频率成分的2倍就够了,实际上工程中选用5~10倍,有时为了较好地还原波形,甚至更高一些。 通常,信号采集后都要去做适当的信号处理,例如 FFT 等。这里对样本数又有一个要求,一般不能只提供一个信号周期的数据样本,希望有5~10个周期,甚至更多的样本。并且希望所提供的样本总数是整周期个数的。这里又发生一个困难,有时我们并不知道,或不确切知道被采信号的频率,因此不但采样率不一定是信号频率的整倍数,也不能保证提供整周期数的样本。我们所有的仅仅是一个时间序列的离散的函数 x(n) 和采样频率。这是我们测量与分析的唯一依据。 数据采集系统的构成  
图4  数据采集系统结构 上图表示了数据采集的结构。在数据采集之前,程序将对采集板卡初始化,板卡上和内存中的 Buffer 是数据采集存储的中间环节。需要注意的两个问题是:是否使用 Buffer ?是否使用外触发启动、停止或同步一个操作。