您好、欢迎来到现金彩票网!
当前位置:至尊彩票 > 浮点型 >

I²C总线、UART总线和AD转换器应用设计

发布时间:2019-05-14 10:39 来源:未知 编辑:admin

  在传统的基于寄存器的开发模式中,使用一个外设往往要阅读英文手册,理解寄存器每一位的含义,一步一步操作、调试,十分麻烦。AWorks提供的外设通用接口不仅可以跨平台复用,而且非常简洁,一个外设往往只有2~3个接口。本文将介绍通用的IC、UART和ADC接口。

  本文为《面向AWorks框架和接口的编程(上)》第三部分软件篇第7章通用外设接口第4~6小节:

  IC器件的两线制总线,不仅硬件电路非常简洁,而且还具有极强的复用性和可移植性。IC总线不仅适用于电路板内器件之间的通信,而且通过中继器还可以实现电路板与电路板之间长距离的信号传输,因此使用

  器件非常容易构建系统级电子产品开发平台。其特点如下:总线根信号线,减少了电路板的空间和芯片管脚的数量,降低了互连成本;

  支持多种通信方式,一主多从是最常见的通信方式。此外还支持双主机通信、多主机通信与广播模式;

  通信速率高,其标准传输速率为100Kbps(每秒100K位),在快速模式下为400Kbps,按照后来修订的版本,位速率可高达3.4Mbps。

  绝大部分情况下,MCU都作为IC主机与IC从机器件通信,因此这里仅介绍AWorks中将MCU作为

  主机的相关接口,接口原型详见表7.14。表7.14IC标准接口函数

  对于用户来讲,使用IC总线的目的往往是用于操作一个从机器件,比如,LM75、E2PROM

  等。MCU作为IC主机与从机器件通信,需要知道从机器件的相关信息,比如,IC从机地址等。在AWorks中,定义了统一的从机器件类型:aw_i2c_device_t,用于包含从机器件相关的信息,以便主机正确的与之通信。该类型的具体定义用户无需关心,在使用IC操作一个从机器件前,必须先使用该类型定义一个与从机器件对应的器件实例,例如:

  其中,dev为用户自定义的从机实例,其地址可以作为接口函数中p_dev的实参传递。

  当完成从机器件实例的定义后,还需要完成其初始化,指定从机器件相关的信息,初始化函数的原型为:

  在AWorks中,一个系统往往具有多条IC总线,各总线之间通过busid区分,一个系统实际支持的IC总线条数与具体硬件平台相关。例如,在i.MX28x系统中,最高可以支持2条IC总线,对应的总线。busid参数即用于指定使用那条IC总线与从机器件进行通信。

  addr为从机器件的IC地址,由于读/写方向位由系统自动控制,因此,地址中不需要包含读写方向位。地址可以为7位地址和10位地址。

  flags为从机器件相关的属性标志,可分为3大类:从机地址的位数、是否忽略无应答和器件内子地址(通常又称之为“寄存器地址”)的字节数。具体可用属性标志详见表7.15,可使用“”操作连接多个属性标志。

  要获取这些信息,就必须查看芯片相关的数据手册,对于LM75B,其引脚分布图详见图7.12。LM75B的器件地址为7位地址:1001A

  0均与地连接,因此,LM75的地址中相应位的值均为0,由此可得LM75B的7位地址为:1001000,即0x48。从机属性分为从机地址属性、应答属性和器件内子地址属性。LM75B的从机地址为7位,其对应的属性标志为AW_IC_ADDR_7BIT。如果从机实例不能应答,则设置AW_IC_IGNORE_NAK标志,一般来说,标准的IC从机器件均可产生应答信号,除非特殊说明,否则都不需要使用该标志。LM75B内部共计有4个寄存器,它们的定义详见表7.16。

  通过以上分析,得到了LM75B相关的从机信息,为此,可以定义并初始化一个与LM75B对应的从机器件实例,范例程序详见程序清单7.26。

  因此,分别打印了整数部分和小数部分,整数部分可以将temp整除256得到。计算小数部分时,先将temp扩大了1000倍,再除以256,得到的值即为实际温度的1000倍,最后对1000取余,即可得到实际温度小数点后3位的值。例如,实际温度为11.375度,则temp的值为11.375的256倍,即2912,整数部分即为该值整除256:

  这样的计算过程虽然看起来复杂了一些,但是其却从根本上避免了浮点运算,保证了程序运行的效率。在没有硬件浮点运算单元的MCU中,浮点运算是通过软件模拟的,效率非常低下。在AWorks中,如非必要,都应该尽可能避免浮点运算。即使是在有浮点运算单元的MCU中,也应该在一些基础的运算中避免使用浮点运算,因为在少量简单的浮点运算中,使用硬件浮点运算单元计算时,效率并不能得到明显的提升,反而增加了系统的负担,例如,当外部中断产生时,需要保护现场,如果使用了硬件浮点运算单元,则保护现场的数据量将大大增加。一般来讲,只有在需要大量浮点运算的场合(比如,在一些算法计算中,很难使用整数运算来避免浮点运算),才使用浮点运算。

  OS),Thyst必须小于TOS,两个温度值均是可读可写的,默认情况下,Thyst的值为75℃,TOS的值为80℃。它们存储温度值的格式和地址0中温度值的格式类似,唯一不同的是,其表示温度的分辨率只有0.5度,因此,小数部分只有一位有效,低7位全为0。例如,同样将2字节数据看作一个有符号的16位整数temp,则temp的值为温度值的256倍。由此可得,若要表示80.5度,则对应的16位数据的值为:80.5 * 256 = 20608,即0x5080。LM75B每次采集到新的温度时,都将与这两个温度值作比较,比较的结果将决定OS引脚的输出,以作为一种温度报警的机制。具体比较的方法与LM75B所处的模式相关,LM75B可以工作在比较模式或中断模式(可通过配置寄存器配置):若LM75B工作在比较模式,则当采样温度大于T

  时,OS引脚输出激活电平(激活电平可以通过配置寄存器配置为高电平或低电平),当采样温度降低到THYST以下时,OS引脚恢复到正常电平;若LM75B工作在中断模式,首先,采样温度与TOS比较,当采样温度大于TOS时,OS引脚输出激活电平,直到主机读取一次LM75B后,OS引脚将自动恢复为正常电平。接着,采样温度将切换为与THYST比较,当采样温度低于THYST时,OS引脚输出激活电平,直到主机读取一次LM75B后,OS引脚将自动恢复为正常电平。接着,又将采样温度切换为与TOS比较,当采样温度大于TOS时,OS引脚输出激活电平,以此类推。示意图详见图7.13。图7.13 LM75B的OS引脚输出示意图

  OS寄存器的值为0x5080,写入时,高字节先写入,低字节后写入,即先写入0x50,后写入0x80。范例程序详见程序清单7.29。程序清单7.29 写入数据范例程序

  读取接口,再读取出TOS寄存器的值,如果读出的值与写入的值相同,则表明写入成功。范例程序详见程序清单7.30。程序清单7.30 验证写入数据是否成功的范例程序

  (Universal Asynchronous Receiver/Transmitter)是一种通用异步收发传输器,其使用串行的方式在双机之间进行数据交换,实现全双工通信。数据引脚仅包含用于接收数据的RXD和用于发送数据的TXD。

  UART是一种串行通信协议,数据在数据线上按位一位一位的发送,UART协议主要有以下几个概念需要了解:

  奇校验:通过设置该位的值(“1”或“0”),使该位和数据位中逻辑“1”的总个数为奇数。例如,数据位为8位,值为:10011001,1的个数为4个(偶数),则奇校验时,为了使1的个数为奇数,就要设置奇偶校验位的值为1,使1的总个数为5个(奇数)。

  偶校验:通过设置该位的值(“1”或“0”),使该位和数据位中逻辑“1”的总个数为偶数。例如,数据位为8位,值为:10011001,1的个数为4个(偶数),则偶校验时,为了使1的个数为偶数,就要设置奇偶校验位的值为0,使1的个数保持不变,为4(偶数)。

  通信双方使用的校验方法应该一致,接收方通过判断“1”的个数是否为奇数(奇校验)或偶数(偶校验)来判定数据在通信过程中是否出错。

  停止位表示一帧数据的结束,其电平逻辑为“1”,其宽度可以是1位、1.5位、2位。即其持续的时间为位数乘以传输一位的时间(由波特率决定),例如,波特率为115200,则传输一位的时间为1/115200秒,约为8.68us。若停止位的宽度为1.5位,则表示停止位持续的时间为:1.5 × 8.68us 13us。

  常见的帧格式为:1位起始位,8位数据位,无校验,1位停止位。由于起始位的宽度恒为1位,不会变化,而数据位,校验位和停止位都是可变的,因此,往往在描述串口通信协议时,都只是描述其波特率、数据位,校验位和停止位,不再单独说明起始位。

  注意,通信双方必须使用完全相同的协议,包括波特率、起始位、数据位、停止位等。如果协议不一致,则通信数据会错乱,不能正常通信。在通信中,若出现乱码的情况,应该首先检查通信双方所使用的协议是否一致。

  在使用UART进行数据传输前,需要正确配置串行通信协议,比如:波特率、数据位、停止位、校验位等。其函数原型为:

  其中,com为串口设备的ID,request表示本次请求控制的命令,p_arg为与request对应的参数,其具体类型与request的值相关。返回值为标准的错误号,返回AW_OK时表示本次控制成功,否则,表示控制失败。

  在AWorks中,一个系统往往可以有多路串口输出,例如,在i.MX28x中,有1路调试串口,5路应用串口,为了区分各个串口,为各个串口设备分配了唯一的编号,如在i.MX28x中,各个串口设备分配的编号详见表7.19。

  设置波特率使用SIO_BAUD_SET命令,该命令(包括后文以SIO_口味前缀的各个命令宏定义)在aw_sio_common.h文件中定义,aw_serial.h文件已经自动包含该文件,用于无需再额外包含。设置波特率为115200的范例程序详见程序清单7.31。

  获取波特率使用SIO_BAUD_GET命令,获取波特率的范例程序详见程序清单7.32。

  设置硬件参数包括通信协议相关的参数,比如:数据位、校验位、停止位等。设置硬件参数对应的命令为SIO_HW_OPTS_SET,其对应的p_arg为32位整数,是由多个参数宏通过或(“”)运算符连接组成。相关的参数宏详见表7.21。

  获取当前硬件参数的命令为SIO_HW_OPTS_GET。例如,通过获取硬件参数,判断当前使用何种校验方式的范例程序详见程序清单7.34。

  此外,在发送或接收数据时,还会使用到几个命令,这些命令在讲解发送数据和接收数据时再详细介绍。

  在AWorks中,为每个串口设备都分配了一个发送数据缓冲区(默认大小为128字节),用于缓存用户发送的数据。当用户发送数据时,首先会将数据加载到缓冲区中,加载到缓冲区后,串口设备将按照设定的波特率自动发送缓冲区中的数据。用户将数据写入缓冲区后,即可不用再处理串口的发送,转而处理其它事务。发送数据的函数原型为:

  其中,com为串口设备的编号,p_buffer指向待发送数据的缓冲区,nbytes为发送数据的字节数。返回值为成功写入缓冲区的数据个数。比如,发送一个字符串“Hello World!“,范例程序详见程序清单7.35。

  在AWorks中,同样为每个串口设备都分配了一个接收数据缓冲区(默认大小为128字节),用于缓存串口设备接收到的数据,用户可以通过命令查询当前接收到的数据字节数,其对应的命令为:AW_FIONREAD,获取COM1的接收缓冲区中已接收数据个数的范例程序详见程序清单7.36。

  其中,com为串口设备的编号,p_buffer指向存储读取数据的缓冲区,maxbytes为读取数据的最大字节数,其值往往与p_buffer指向的缓冲区大小一致。返回值为成功读取的数据个数。例如,接收数据的范例程序详见程序清单7.37。

  若当前接收缓冲区中具有足够的数据,即已接收数据不小于maxbytes,则成功读取maxbytes字节的数据,函数立即返回。若没有足够的数据,即已接收数据小于maxbytes小,则默认情况下,会一直阻塞等待,直到接收的数据量达到maxbytes。若用户不希望一直阻塞等待,则可以设定一个超时时间,当等待时间达到该值时,无论是否接收到maxbytes字节的数据,函数都会返回。

  设定超时时间的命令为:AW_TIOCRDTIMEOUT(在aw_ioctl.h文件中定义)。设置超时时间为100ms的范例程序详见程序清单7.38。

  例如,通过串口控制LED0的亮灭,当接收到on时,则点亮LED0,当接收到off时,则熄灭LED0。同时,当接收到可以识别的on或off命令时,回复OK!,若是非法命令,无法识别,则回复Failed! Unknown Command!,范例程序详见程序清单7.39。

  1. 基本原理我们经常接触的噪声和图像信号都是模拟信号,要将模拟信号转换为数字信号,必须经过采样、保持、量化与编码几个过程,详见图7.14。

  将以一定的时间间隔提取信号的大小的操作称为采样,其值为样本值,提取信号大小的时间间隔越短越能正确地重现信号。由于缩短时间间隔会导致数据量增加,所以缩短时间间隔要适可而止。注意,取样频率大于或等于模拟信号中最高频率的2倍,就能够无失真地恢复原信号。

  将采样所得信号转换为数字信号往往需要一定的时间,为了给后续的量化编码电路提供一个稳定值,采样电路的输出还必须保持一段时间,而采样与保持过程都是同时完成的。虽然通过采样将在时间轴上连续的信号转换成了不连续的(离散的)信号,但采样后的信号幅度仍然是连续的值(模拟量)。

  此时可以在振幅方向上以某一定的间隔进行划分,决定个样本值属于哪一区间,将记在其区间的值分配给其样本值。图7.14将区间分割为0~0.5、0.5~1.5、1.5~2.5,再用0、1、2代表各区间,对小数点后面的值按照四舍五入处理,比如,201.6属于201.5~202.5,则赋值202;123.4属于122.5~123.5,则赋值123,这样的操作称为量化。

  量化前的信号幅度与量化后的信号幅度出现了不同,这一差值在重现信号时将会以噪声的形式表现出来,所以将此差值称为量化噪声。为了降低这种噪声,只要将量化时阶梯间的间隔减小就可以了。但减小量化间隔会引起阶梯数目的增加,导致数据量增大。所以量化的阶梯数也必须适当,可以根据所需的信噪比(S/N)确定。

  将量化后的信号转换为二进制数,即用0和1的码组合来表示的处理过程称为编码,“1”表示有脉冲,“0”表示无脉冲。当量化级数取为64级时,表示这些数值的二进制的位数必须是6位;当量化级数取为256级时,则必须用8位二进制数表示。

  现在很多MCU都内置A/D,即可以使用电源电压作为其基准电压,也可以使用外部基准电压。如果将电源电压作为基准电压使用的线V输入电压的测量结果为:(输入电压/基准电压)×255=(3/5)×255=99H。显然,如果电源电压升高1%,则输出值为(3/5.05)×255=97H。实际上典型电源电压的误差一般在2~3%,其变化对A/D的输出影响是很大的。

  A/D的输出精度是由基准输入和输出字长共同决定的,输出精度定义了A/D可以进行转换的最小电压变化。转换精度就是A/D最小步长值,该值可以通过计算基准电压和最大转换值的比例得到。对于上面给出的使用5V基准电压的8位A/D来说,其分辨率为19.5mV,也就是说,所有低于19.5mV的输入电压的输出值都为0,在19.5mV~39mV之间的输入电压的输出值为1,而在39mV~58.6mV之间的输入电压的输出值为3,以此类推。

  提高分辨率的一种方法是降低基准电压,如果将基准电压从5V降到2.5V,则分辨率上升到2.5/256=9.7mV,但最高测量电压降到了2.5V。而不降低基准电压又能提高分辨率的唯一方法是增加A/D的数字位数,对于使用5V基准电压的12位A/D来说,其输出范围可达4096,其分辨率为1.22mV。

  如果在放大器前端使用误差5%的电阻,则该误差将会导致12位A/D无法正常工作。也就是说,A/D的测量精度一定小于其转换误差、基准电压误差与所有模拟放大器误差的累计之和。虽然转换精度会受到器件误差的制约,但通过对每个系统单独进行定标,也能够得到较为满意的输出精度。如果使用精确的定标电压作为标准输入,且借助存储在MCU程序中的定标电压常数对所有输入进行纠正,则可以有效地提高转换精度,但无论如何无法对温漂或器件老化而带来的影响进行校正。

  比如,要求12 位A/D分辨到1LSB,即相当于1/212=244ppm。如果工作温度范围在10℃,那么一个初始精度为0.01%(相当于100ppm),温度系数为10ppm/℃(温度范围内偏移100ppm)的基准已能满足系统的精度要求,因为基准引起的总误差为200ppm,但如果工作温度范围扩大到15℃以上,该基准就不适用了。

  如果考虑到其它误差的影响,则实际的初始精度要选得比上式更高一些,比如,按1/2LSB的分辨率精度来计算,即上式所得结果再除以2,即:

  同样地,考虑到其它误差的影响,实际的TC值还要选得比上式更小一些。温度范围T通常以25℃为基准来计算,以工业温度范围-40℃~+85℃为例,T可取60℃(85℃-25℃),因为制造商通常在25℃附近将基准因温度变化引起的误差调到最小。

  如图7.15所示是一个十分有用的速查工具,它以25℃为变化基准,温度在1℃~00℃变化时,8~20位ADC在1LSB分辨精度的要求下,将所需基准的TC值绘制成图,由该图表可迅速查得所需的TC值。

  TL431和REF3325/3330均为典型的电压基准源产品,详见表7.22。TL431的输出电压仅用两个电阻就可以在2.5~36V范围内实现连续可调,负载电流1~100mA。在可调压电源、开关电源、运放电路常用它代替稳压二极管。REF3325输出2.5V,REF3330输出3.0V。

  REF33xx是一种低功耗、低压差、高精密度的电压基准产品,采用小型的SC70-3和SOT23-3封装。体积小和功耗低(最大电流为5A)的特点使得REF33xx系列产品成为众多便携式和电池供电应用的最佳选择。在负载正常的情况下,REF33xx系列产品可在高于指定输出电压180mV的电源电压下工作,但REF3312除外,因为它的最小电源电压为1.8V。

  从初始精度和温漂特性来看,REF3325/3330均优于TL431,但是TL431的输出电压范围很宽,且工作电流范围很大,甚至可以代替一些LDO。

  由于基准的初始精度和温漂特性是影响系统整体精度的关键参数,因此它们都不能用于高精密的采集系统和高分辨率的场合。而对于12bits的AD来说,由于精度要求在0.1%左右的采集系统,到底选哪个型号呢?测量系统的初始精度,均可通过对系统校准消除初始精度引入的误差;对于温漂的选择,必须参考1LSB分辨精度来进行选择,详见图7.16。

  如果不是工作在严苛环境下,通常工作温度为-10℃~50℃,温度变化在60℃,如果考虑0.1%系统精度,温度特性低于50ppm,则选择REF3325/3330。

  获取当前ADC通道的采样率,采样率的单位为Samples/s,表示每秒进行多少次采样。其函数原型为:

  其中,ch为ADC的通道号,p_rate为输出参数,用以得到指定通道的采样率。返回值为标准的错误号,返回AW_OK时表示获取成功,否则,表示获取失败,失败的原因可能是通道号不存在。

  通常情况下,一个A/D转换器往往支持多个通道,即可以支持多路模拟信号输入,在部分微控制器中,还存在多个A/D转换器。在AWorks中,为了区分各个模拟信号输入的通道,为每个通道定义了一个唯一的通道号。例如,在i.MX28x中,有LRADC和HSADC两个A/D转换器,它们分别支持16个通道和8个通道。各通道对应的编号在{chip}_adc_def.h文件中使用宏的形式进行了定义。例如,在i.MX28x中,各个通道号在imx28x_adc_def.h文件中定义如下:

  通道号的类型为aw_adc_channel_t,其本质上是一个无符号整数类型,具体的位宽与平台相关。如一个平台中仅支持24个通道,则其类型可能为uint8_t,即使用8位来表示通道号。获取通道0的采样率范例程序详见程序清单7.40。

  由于采样频率必须大于或等于模拟信号中最高频率的2倍,才能够无失真地恢复原信号,因此,实际中,可能需要根据模拟信号的频率调整A/D转换器的采样率。设置某一通道采样率的函数原型为:

  其中,ch为ADC的通道号,rate为设置的采样率。返回值为标准的错误号,返回AW_OK时表示设置成功,否则,表示设置失败。

  一般情况下,若对采样率没有特殊的要求,使用默认的采样率即可。此外,A/D转换器可能只支持部分采样率,并不能支持任意的采样率,当使用该函数设置采样率时,系统会自动设定一个最为接近的采样率,因此,实际采样率可能与设置的采样率存在差异,实际采样率可由aw_adc_rate_get()函数获取。注意,通常情况下,一个A/D转换器的所有通道共用一个采样率,因此,设置其中一个通道的采样率时,可能会影响其它通道的采样率。

  设置采样率为1000 Samples/s。表示每秒采集1000个数据点,即每隔1毫秒采集一个数据点。

  一般来讲,在对精度要求不是特别严格的场合,可以直接使用MCU的电源电压作为ADC的基准电压。但若对精度要求较高,往往需要使用具有更高精度的外部基准源电压作为ADC的基准电压。当前ADC实际使用的基准电压可通过该接口获得,其函数原型为:

  其中,ch为ADC的通道号。基准电压通过返回值返回:若返回值大于0,则获取成功,其值即为基准电压(单位:mV);若返回值小于0,则获取失败。

  其中,ch为ADC的通道号。转换位数通过返回值返回:若返回值大于0,则获取成功,其值即为转换位数;若返回值小于0,则获取失败。

  其中,ch为ADC的通道号,p_val为存储采样值的缓冲区,samples指定本次采样的次数,urgent指定本次读取操作的优先级。返回值为标准的错误号,返回AW_OK时表示读取成功,否则,表示读取失败。

  p_val指向用于存储采样值的缓冲区,缓冲区实际类型与ADC的位数相关:若ADC的位数为 1 ~ 8,则其类型为uint8_t;若ADC的位数为9 ~ 16,则其类型为uint16_t;若ADC的位数为 17 ~ 32,则其类型为uint32_t。例如,在i.MX28x中,ADC的位数为12,则应使用uint16_t类型的缓冲区来存储ADC的采样值。如定义一个大小为100的缓冲区,以存储100个采样值:

  实际上,读取采样值的操作包含的完整过程为:首先需要启动ADC转换,然后等待转换完成(转换的时间与采样率相关),转换完成后,再将转换结果存储在用户提供的缓冲区中。显然,整个过程需要消耗一定的时间。虽然一个A/D转换器往往有多个通道,但某一时刻只能对某一个通道的输入进行转换,并不能同时转换多个通道。若当前A/D转换器正在转换中,则后续其它通道的转换请求就只能排队等待,urgent指定了转换请求的紧急性,其决定了排队的方式,若urgent为TRUE,表示紧急转换请求,排队时将插队到头部,以便当前A/D转换结束后,立即启动需要紧急转换的通道;若urgent为FALSE,则排队时将依次排至尾部。一般情况下,没有特殊需求,urgent均设置为FALSE。

  此时,多个采样值存储在adc_val中,实际中,每次读取多个采样值只是为了通过处理得到一个更加精确的采样值,最简单的处理方法就是取平均值,范例程序详见程序清单7.45。

  注意,程序中,为了避免sum溢出,将sum的类型定义为了32位无符号数。最终的结果存储在code变量中。

  至此,获得了一个较为精确的ADC采样值,但在实际使用A/D转换器时,其目的往往并非简单的获取一个ADC采样值,而是获取相应通道的电压值。可以通过基准电压和转换位数将code转换为电压值,公式如下:

  在i.MX28x中,通道0对应的外部输入引脚时LRADC0引脚,运行程序后,可以通过向该引脚接入模拟电压来测试ADC采集的结果是否正确。

  程序中,电压值的计算未使用到浮点运算,仅使用了整数运算,效率较高。但运算结果vol的值也只能精确的mV,若需要提高计算结果的精度,可以使用浮点数来存储计算的结果,将vol的类型定义为float,即:

http://steveouch.com/fudianxing/236.html
锟斤拷锟斤拷锟斤拷QQ微锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷微锟斤拷
关于我们|联系我们|版权声明|网站地图|
Copyright © 2002-2019 现金彩票 版权所有