完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
` MSP430教程之十二ADC(下) 上次我们讲了相关的ADC知识,那么这次我们将这些知识实际应用于我们的实际使用中。同样的建立工程和添加库的步骤我们就不在说明了,两份文档,数据手册和我们的库文件使用手册也是必不可少的了,有时候我们还会需要用到我们的Launchpad的开发板原理图来查看某些引脚,这些步骤也都是我们之前一直说到的,希望可以给大家一些学习方法上面的参考。 今天这一讲我们将进入代码的书写上面,同样我们还是以库函数的形式来进行编写,后续我们会更新寄存器的编写方式,同时大家可以进行参考MSP430Ware的示例代码来自行编写寄存器的配置代码。 Ksps的意思是每秒转换次数为多少。 这里插播一个细节的东西,德州仪器(ti)的官网不管对于库函数还是寄存器都给出了示例代码,我们通过我们CCS环境下面的TI Resource Explorer下面查看到的示例代码都是基于寄存器的形式进行编写的,那么这里我们将和大家说一下要如何查看官方的库函数参考例程。 首先我们需要确认你有安装了MSP430Ware,如果你可以打开上面的界面,那毫无疑问是已经安装好了。然后我们需要找到这个MSP430Ware的存放位置。一个方法就是通过windows的搜索,直接搜索MSPWare(注意这里是搜索MSPWare而不是MSP430Ware)。其他方法没找到,需要你知道安装在哪里。不过一般情况下都会在软件的安装目录附近,自己稍微找一下应该就可以找到。(如图下面长这样的文件夹) 进去之后会有很多分支,红色方框里面的是我们的库函数的集合,而黑色方框对应的example就是我们上面TI Resource Explorer里面呈现的寄存器C参考例程了。 进入driverlib这个文件夹之后我们得到下面这么多文件,很显然例程就在我们的example里面,而这里面的driverlib对应就是我们器件的库函数源代码。其他的大家自己琢磨去看看了。不在说明了。 进入example这个文件夹就是我们德州仪器所有的430产品的系列型号对应的不同的参考代码了。我们进入FR5xx_6xx这个系列,对应我们的开发板芯片FR5969。 这里面就给出了我们所有的TI Resource Explorer对应的库函数参考代码。 大家可以参考学习官方提供的库函数,是官方提供的,写的也相对比较规范,但是官方的东西总一个有一个毛病亘古不变,就是难懂,一般官方给的东西要是很通熟易懂,那肯定火的不行了。所以在静心去琢磨琢磨官方的东西,虽然难懂,但是多看,多模仿,对自己能力的提高有着很大的帮助。 跑题了,我们是来说ADC的,下面我们回归我们的代码编写。 结构体变量初始化这里就不在说明了。 首先我们需要知道在使用430ADC的时候需要几个步骤: 1.需要确定参考电压值,这里指的是使用外部参考电压,或者是430的AVCC(3.3V),还是内部的参考电压值,这些是我们在使用的时候需要明白的。对了FR5969来说的32个ADC通道是可以各自设置不同的参考电压的,这个是非常强大的。所以在设置的时候我们需要明确我们的参考电压是什么,是多少。 2.然后就是要进行初始化ADC,那么这个初始化过程包括什么呢?一个是时钟的选择,这里面包括了时钟源的选择,和时钟的分频数。430的ADC的分频数有两部分构成,从下图可以看到,一个是我们的ADC12PDIV可以进行1、4、32、64分频,另外一个是我们的ADC12DIVx,可以进行1~8分频。这两个共同决定了时钟输入的频率。 对应到我们的代码中我们也可以看到,有两个配置的过程: 另外我们需要配置相关的通道,这里我们测量的是芯片内部的温度传感器,所以对应的A30这个通道我们需要映射到我们的内部温度传感器中。 最后要进行选择触发采样的方式,默认情况是软件触发的方式,当然可以根据需要选择定时器的触发采样或者其他方式。 3.然后需要设置我们的采样时间,对应我们的32个Memory都可以设置不同的采样时间。 这个采样时间对于我们的内部温度测量是有一个要求的,在我们的器件手册中的25.2.10这个章节中提到了一点,两个的采样周期必须大于30us。 所以在实际配置中我们需要考虑这个时间的关系才能保证采样数据的正确性。我们配置成了256个时钟周期来进行采样,那么为什么是这个数呢?因为我们使用的时钟是ADC内部的osc,这个是时钟是5MHz的频率,256个周期刚好是51.2us,刚好满足这个条件,至于这个函数为什么有两个采样周期的配置的参数的输入呢? 我们进入这个函数的定义中看到这两个参数都是配置都是CTL0这个寄存器,那么我们如果要知道这个为什么,就需要看这个寄存器的描述。 从寄存器描述中我们知道了这两个参数分别对应控制的是每一个采样Mem的采样周期。对430而言,它把这32个存储区域分成了两部分,所以这里会有对应的两个输入参数,第一个参数对应的是我们MEM0~7和MEM24~31,第二个参数对应的是MEM8~23。到这里我们应该就明白了为什么这么配置了。 4.之后我们需要配置的是采样通道存储的内存单元的配置,也就是说你采集的这个数据要放在哪一个单元,设置该单元的输入信号,设置他的参考电压,以及采样方式,是单词采样,还是循环采样,是否使用差分功能,还是窗口比较的功能。 这里我们选择是将A30的通道采集内容存储到Memory 0中,同时设置该通道为单次采样的模式,同时我们设置该Memory的采样参考电压为我们上面设置的内部参考电压1.2V,不适用差分和窗口比较的功能。 这里的窗口比较功能是一个比较特殊的功能,具体的话大家可以看下FR5969的官方教学视频,里面具体解释了这个功能的特点及使用方法。这里我们就不做讨论。 因为430可以对每一个通道进行相应的配置,所以这里我们可以进行32次的配置,具体的使用看我们的配置方式,这个是很方便的,我们可以通过每一个通道的不同设置,来达到各个通道不同的测量范围。 同时430的ADC中提供了一个差分的功能是十分强大的,差分是什么意思呢?我们通俗一点讲呢,就是测量两个通道之间的输入信号的差值。比如说我是1.213V,你是2.123V,那么输入得到的电压值就是两者之差了0.91V。那么这样有什么好处呢?差分的一个好处是可以比较好的抑制噪声的影响,比如说,上面采集到的两个电压处在同一个环境下面进行测量,所得到的噪声为0.002V的话,那么两者的测量电压都将包含这0.002V的噪声电压,那么通过差分的方式,两者相减,这0.002V的电压也就自然相互抵消了,这就是差分一个比较通熟易懂的好处。具体其他的大家可以自行百度看看咯。 5.最后就是是否进行使能中断,使能整个ADC采样了。 这样我们整个ADC的配置过程也就完成了。 下面就时对应我们的中断的内容编写,这里我们直接参考了官方的例子,暂时先不解释这个编写的方式。对应ADC的中断有非常多个,这里我们就不解释了,具体可以看我们的FR5969的数据手册和使用手册的中断章节。这里我们使用的是Memory 0的中断。 好了,这样我们就可以得到采样的温度传感器的初始值了,但是这只是初始值,我们还需要将其转换成温度才可以。 这个又是一个很麻烦的过程。(下面参考的是我们寄存器版本的内容,移植过来的,做相应的解释) 首先我们做了下面两个定义,我们看下这里两个定义,*((unsigned int *)0x1A1A),可能大家会感到很奇怪,这里不是就是unsigned int 1A1A,再加上两个指针不是多此一举。但是我们细细分析一下,首先对于第一个括号的内容,(unsigned int *)0x1A1A,这是一个指针,指向某个地址,而后我们在在最外面加上了一个指针符号*,那么这就意味着我们前面定义的这个值CALADC12_12V_30C是指向这个地址的一个unsigned int的数值。这个和我们的unsigned int 0x1A1A是完全不一样的,但是对于C语言的语法上面来讲,这两者确实是等价的。这个其实挺有意思的。那么关于具体的讨论大家可以参考: http://bbs.eeworld.com.cn/forum.php?mod=viewthread&tid=483687&highlight=unsigned 那么接下来我们需要知道这个0x1A1A是怎么来的,为什么是这个地址?这个就需要我们细细的看我们的数据手册了,在注释中也进行了说明,需要我们去看TLV table memory mapping,我们需要在数据手册中找。 在这个PDF文档中我们可以找到这个内容。 同时我们还需要在另外一份文档中找到这个内容,对于FR5969的整个内存区域是怎么分配的这里我们看到我们的TLV整个区域的起始是从001AFF~0x1A00,这中间,总共256B,这的B指的可不是Bit,而是Byte。其实也很好理解,如果是Bit,那才32个Byte,这中间的数据量太少,根本不可能。 那么现在我们知道了整个structure的开始地址为0x001A00,接下来我们只需确定我们的检验值在什么位置就可以了。 首先我们在手册中可以看到,每个TLV是有一个模块模块构成的,包括三个部分,也就是Tag,len,和value field三个部分。 同时我们需要看到另外一部分内容,我们需要看到下面Tag Value下面的一段话,具体内容如下。每个tag的领域都是对各自的描述都是独一无二的,往往后面跟着一个长度的单元,那么这个单元的是一个字节的,如果tag的值是从01h到0FDh。但是如果tag的值等于0FEh,那么下一个字节扩展为tag的值,接着两个自己的内容代表描述符号的长度。 那么我们懂得了每一个tag暂用一个字节,每一个len暂用一个字节,但是对于后面的value是暂用多少自己是由len决定的。 那么对于黄色区域的10个block,由于手册中没有给出相应的value的值,这里判断他的len的值应该为00h,所以这里我们推测这里10个tag block应该是各暂用了两个字节。所以到了红色箭头所指向的地方地址应该变成:0x001A00 + 20 = 0x1A14 此时我们到达的是ADC12CAL这个地方,我们需要跳转到Section 1.14.3.2这个部分,这里给出了该block详细的内容,所以这里我们可以看到,到CAL_ADC_12T30这个地方,前面还有6个字节,所以箭头所指的位置地址应该是0x001A00 + 20 + 6 = 0x001A14 + 6 = 0x001A1A 所以我们解释了前面为什么我们定义的地址为1A1A,然后后面的1A1C就比较好理解了,从上图看出,两个数据的位置相差两个字节。 (不知道这样解释对不对,但是大家权当了解,在我们知道结果的情况下有时候我们没有比较去深究这个东西是怎么来的,应用才是最重要的。其实在这个解释过程中我其实有点投机取巧,我知道了结论,然后去推这个结论可能是怎么来的,反着来,所以这个解释不一定正确,参考参考!) 接下来我们需要解释一个问题,就是温度计算公式是怎么来的? 在解释说明中我们看到,关于该公式的解释是在device user's guide 的System Resets, Interrupts, and Operating Modes, System Control Module章节下面的Device Descriptor Table section。所以有时候看官网的代码很重要就是在这里,一方面他的规范很好,另一方面他的注释很好。可以帮助我们理解。 从手册我们得到这个公式。那么在应用层面,其实我们到这里已经是可以了,我们知道了具体的使用方法,以及相关的计算方法,我们就可以得到相应的结果了。具体这个公式怎么来的,我也没弄明白。^_^。。。。 好了具体的代码大家通过下载附件的代码推敲一下。 整个ADC介绍的编写过程中会发现几个问题和大家分享一下: 1.一个是学识不精,很多东西思考了很久有时候还是没弄明白是怎么回事,以及这样做的原因是什么。看了很多遍的数据手册,官方的文档,最后通过官方的例程,包括寄存器版本的和我们的库函数版本的慢慢理解。 2.吐槽一下TI的库函数,TI的整个生态是非常棒的,他的芯片很多给出了设计参考,包括PCB,原理图都有。Launchpad这块也做的很棒,寄存器例程和库函数例程都相对来说很全面。但是我这里想说的是TI的数据手册有些细节的东西还是没说的很到位,这个也是可以谅解,但是可以通过后期的说明文档的版本更新来解决这个问题。其次一点是TI的库函数做的还不是那么好,很多定义还是不是那么具有代表意义,很多我点击进去发现那个定义内容和寄存器没多大区别,最后是换汤不换药的那种感觉,所以在使用库函数编写的过程中我其实看了好几遍寄存器的内容,有时候发现,天啊!我要是用寄存器早搞定了,何必用库函数呢?这其实我觉的很不应该啊,库函数理应是来帮助开发者更快的进行开发,免去接触底层的配置过程的,但是TI的库函数编写感觉还是没有脱离这个层面。虽然对于单片机而言,脱离寄存器本身来说要求就太过去苛刻了,但是我觉得TI的库函数还是有很大的改进内容的。 好了吐槽完了!有时候觉得怪别人是不对了,千错万错都是自己的错,所以学不懂,搞不出来,先静下心,好好思考为什么,一般都是自己的错,不会是别人的错。在写这个ADC的过程中放弃了很多次,思考了很久,想不明白,放弃了,隔天拿起来认真在看去,咦,兴许你就能明白,能够悟出一点你之前没想到的东西。 好了今天就到这里了,下次我们将进行讨论DMA的相关内容。 参考代码:
code12_1.rar
(418.25 KB, 下载次数: 72
)
msp430fr59xx_adc12_10.c.rar
(50.26 KB, 下载次数: 70
)
` |
|
相关推荐
|
|
|
|
|
|
|
|
|
|
|
|
|
|
本帖最后由 火火火山山 于 2016-8-16 14:23 编辑
楼主我想请问一下,ADC通道配置,你配置的是通道 A26~A31这6个通道,那A0-A25的通道是怎么看是芯片的哪个端口,例如P1.1的配置为A1,P1.1的功能有如下,怎么我选择具体是哪个功能? P1.1/TA0.2/TA1CLK/COUT/A1/C1/VREF+/VeREF+ 谢谢楼主 |
|
|
|
|
|
火火火山山 发表于 2016-8-16 14:16 这个我有具体说明的,该如何进行选择引脚功能,印象中对于芯片,官网有两份文档,其中一份有讲到。具体你参考下这篇文档: https://bbs.elecfans.com/forum.p ... d=534885&extra= |
|
|
|
|
|
楼主,我又来麻烦你啦,请问一下,无论是你的程序还是TI官方的例程,ADC总是转换一两次之后就停了,为什么呢?
无论是断点看数据还是串口打印数据,循环不超过3次,求指导,谢谢! |
|
|
|
|
|
火火火山山 发表于 2016-8-17 21:18 每次转换结果都吧buf清空,然后再重新测量。你检查下这部分的内容 |
|
|
|
|
|
|
|
|
|
|
|
学习了。。。。
|
|
|
|
|
|
只有小组成员才能发言,加入小组>>
3031个成员聚集在这个小组
加入小组2923 浏览 1 评论
MSP430FR5994 使用库函数 定时器触发AD问题请教
3594 浏览 2 评论
请问怎么把下面51单片机的代码改成msp430 g2 pocket的代码,还有改下时间变成30秒
2341 浏览 1 评论
4800 浏览 1 评论
2573 浏览 1 评论
1324浏览 3评论
MSP430FR5994 使用库函数 定时器触发AD问题请教
3594浏览 2评论
2923浏览 1评论
1507浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-28 00:15 , Processed in 1.583838 second(s), Total 69, Slave 62 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号