对于嵌入式的开发来说,只会C语言是远远不够的,只会C语言,我们最多只能做一些流程和算法的控制,比如我们的智能车,我们很少对底层进行操作,大部分的时间我们都只是用现成的数据进行分析和计算,生成算法。控制输出。虽然这也是一个很重要的方面,但是我认为,不了解底层,不会对芯片内部寄存器进行操作,就好比两条腿走路短了一条腿,蹦不远的。

可是我们接触到芯片也有好几种了,每种的操作虽说大同,但总归有小异,而且有时候异还不小。所以查阅芯片手册是我们必备的技能,今天我就来通过我的亲身项目经历举例来说我们怎样才能比较有效率的查阅芯片手册。

首先我要说明的是,我一直说的是查阅,而不是阅读。因为我一直觉得芯片手册是一种工具书一样的存在,我们用这款芯片,我们不可能将芯片手册都读完一遍在开始项目吧。且不说芯片手册动辄几百上千页,就算能够都读完,到用的时候还是抓瞎。那么多寄存器读了拿记得住。

所以我的意思是我们读芯片手册就应该像查字典一样,当我们需要实现某个功能的时候,遇到哪里不清楚怎样实现的时候我们才来查,那么具体的怎么查呢,我大言不惭班门弄斧脸不红来心不跳的说一下我自己的习惯。。。

首先我们应该是在做项目的时候遇到了问题,某一个功能需要实现而又有困惑的时候我们才来查手册。我不是说没事待着就不可以把手册当小说来读,如果有这样的大神我也是很欣赏的,,,我的中心论点是,手册是用来查的,在没有遇到问题的时候干读是很低效的。

好吧,查查查,怎么查啊,我怎么知道查哪里啊,所以我们终于进入了我们的正题,怎么查,呼,累死我了,,,前面任性的扯淡了那么久。。。

比如说,我们现在要用LPC15xx系列的芯片,手册也准备好了。我再扯一句,我自己而言,手册我还是喜欢英文的。因为我总觉得好多事情翻译过来好别扭。当然英文水平不好如我也会经常误解英文手册的意思,后面再说。

好啦,现在我们需要用这个芯片的SCT产生PWM波和中断时间,那,怎么办捏~~~

我还是想再扯一句,如果要用到的模块你是完完全全一点点都不了解的,那应该先百度,我的亲身经历告诉我,指望通过手册来了解一个模块的功能和用法虽然不是不可能,但是太累人了,手册为了严谨和全面我们常用的不常用的写了很多,我们一头扎进去不分轻重的看实在太累,所以我觉得先百度一下获得一个这个模块的整体功能还是很重要的。

来吧真的不再扯了,查手册吧,跟查字典一样,先查目录:

啊,第十五章有两个大的,第十六章有两个小的。直觉告诉我资源允许的时候有大的不用小的,就是这么任性。。。

点进第十五章,第一页奏是这样子的~

一般手册在一章的开始都会讲一下这一章要讲什么,有什么可用的资源可用,有什么特点,等等等等……我一般都会通读,第一这些不会太长,第二读一下对从宏观上掌握我用这个模块大概能够做到什么会有一个大概的认识,尤其是如果我们读到了,比如说,PWM用SCT产生不了。。。好吧那剩下就不用看了,咱们换别的着吧。。。

好在手册上没看到这句,那咱们就接着看吧,Features里说每一个SCT支持16个match/capture ,16个event和16个states等等,至于这些是啥我觉得应该百度完成,手册里确实说了这些东西,但是我觉得,百度来的更快一些,我们来这里是想看看到底怎么用这些东西。

我不喜欢看中文手册的一点就是如果把match翻译成匹配,captre译成捕获,ecent译为事件,states译为状态,从翻译上确实没问题,但是给人的感觉……好吧,给我的感觉,总觉得怪怪的。。。

所以我一路看下来……忽然,没字了,手册开始上图了:

就这样。。。关于要不要看这些图我觉得我很难说,我一般只扫一眼,看明白了我就明白了,看不明白我基本也就算了,这些图主要,啊,主要,涉及的是模块内部的实现方法,如果弄明白了会对模块有很深刻的认识,如果不明白,我认为关系也不大,重要的使用顺序和逻辑在寄存器和使用方法中还是会再被语言描述一遍的。

我们一路看(忽略)下去,突然又有字了,这一段可是一字千金:

这是啥,使用方法啊,虽然我们不一定 use SCT as a simple timer. 但是看看总会有帮助的吧。

果然,3.d 里明确说了,如果你想要一个match event enable 一个 interrupt, 看 table 219. 其实之前如果对sct有了解的,就会知道我们用3.c 和 3.e 加起来就会产生多路频率脉宽皆可变的PWM波。

所以说百度还是有用的,我们如果之前百度过,我们看到这里,基本就会有一个大致的思路了。如果我们之前没百度过,我们还要看到后面的event和match和output之间的关系我们才有可能明白,而且万一英语不好绕晕了咋办。

好啦所以我们按照他这个123456执行就好了么~我不这样建议,读到这里我们已经对整个模块的功能和实现手段有了一点点的眉目,虽然我们不知道具体怎么做,但是我们起码大概知道了我们要用到什么东西的,我们可以点下去各个table去看一看,看完了可能我们就大概知道要干点啥了。

但是我并不建议这样做,如果只这样就动手写代码,我们可能还没有窥见这个模块的全部,所以行了倒还好办,万一废了那么大的劲,代码也写了,就是不出效果,咋办,你只知道是手册让你这么办,但是为什么要这么办啊?还需不需要办点别的啊?你都不知道,这是不对滴。。。。。。

所以我的建议是,继续往下看,我们已经知道我们都要用些什么了,我们就可以居高临下的看,高屋建瓴的看,抓重点的看,挑主要的看,就冲我这词汇量,将来我要是当了老师准坑学生。

所以咱们快一点的往下看,下面就是各个寄存器的配置了,我们先大概看看功能,有用的看,没用的,不需要我们配置的就过。比如说:

这是SCTCTRL寄存器,能控制它停止,启动和计数方式,肯定要用吧,所以这个我们就要看看。

举个简单的例子,上面的 bit 2. HALT_L 旁边是怎么描述的:我大言不惭班门弄斧脸不红来心不跳的说一下我自己的翻译。。。。当这一位是1的时候,低位计数器或者联合计数器不能够跑,与之相连的event都不会发生,reset会把这一位置为1,当HALT_L为1的,STOP_L被清掉的时候,如果你想要去除halt 状态并且保持SCT在STOP状态(不跑),那么你用一次写操作就可以改变 halt 和 stop condition 了,翻译的也是人性,大家见笑,领会精神。

所以呢,我们要是想把,halt状态清掉怎么办,把这一位置零啊,这就用到我们第一课讲到的位操作了吧~嘿嘿嘿嘿

LPC_SCT1->CTRL &=  ~(1<<2);

再比如说:

这个寄存器决定我们在event n 发生的时候是否产生 DMA request,我们的工程不需要,所以我们就不用再看了啊。。。

下面我们来看看我们怎么通过match event 产生中断,在这里,我一个不仔细读手册的失误浪费我一天的时间来排除错误,也是醉了:

enter image description here

我大言不惭班门弄斧脸不红来心不跳的说一下我自己的翻译。。。。。。。。

15.6.16说这个寄存器会使能中断的要求位,如果SCT event flag 也被置位的话,而且0—15位里哪一个被置一就代表哪一个事件的发生会产生中断请求。

好吧咱们再来看15.6.17咋说,我就……翻译一下啊,这个既存此记录了事件的发生,只要reset或者1被写入了之后的某个事件发生了这一位就会被置一, 不要将上一个翻译当真,这是我当时的错误翻译,好吧这不说的清楚了么,他俩只要都是1,事件一发生就会产生中断(错的),于是我欢脱的写下了代码。

LPC_SCT1->EVEN |= (1<<5);
LPC_SCT1->EVFLAG |= (1<<5);

然后就开始调试啊,能进中断,很开心,诶,,,等等,,,怎么一直在进中断程序啊,,,也给别的程序一点执行的机会啊啊啊啊。。。。。

一天之后,我终于明白了,其实15.6.17根本不是我想的这个样子,上面的描述很清楚了: Writing ones to this register clears the corresponding flags and negates the SCT interrupt request if all enabled Flag bits are zero.

我就…………不翻译了咳咳,丢人,这是写1清零的寄存器,也就是所,上面的代码的第二句,要放在中断函数里面去执行,而不是要在SCT配置的时候说明。。。按我之前的错误做法他俩一直是1可不是一直产生中断请求么。

所以写了这么长我主要想说的是,我们查阅芯片手册,应该从大处着眼,在小处留心,大处着眼要求我们迅速的定位到我们需要的模块,需要看的地方;小处留心就要我们查阅的时候一定要仔细看自己要设置的地方,设置错了会给调试带来很多的麻烦。影响效率。

当然我只举例了我目前正在看的手册,不同的手册虽然大同,难免小异。别的手册我也草草看过一些,大体套路应该也是相似的。

不悔流年去,只恨太匆匆。。。(昨晚看的匆匆那年。。。)