【PSoC4心得】这是吐槽.....关于温度传感器例程
[复制链接]
这是吐槽,的确,这些话我早就想说,但一直作为工程师似乎不该这样吐槽一些没什么建设性意义的东西,也就一直忍着。
对我来说,我说过就算,但是还是希望相关人员看到了会有一些重视。因为,作为一种感概真的由来已久。不管是赛普拉斯,还是老牌大牌ST TI这些厂商,他们提供的例程,第三方程序库都好,真的是~~~
难听点,上不了台面。
你们用心点,我们会少受很多罪,节省很多时间。
作为顾客,如果得到一些重视和尊敬,其实,对于卖方应该是很有意义的。
-------------------------------
根据我要做的 温控箱,我首先选择了两个直接相关的外设来做。 1.温度传感器; 2.定时器 ——定时器基本是单片机居家必备。
在例程里翻出了唯一一个PSoC4的温度传感器例程 ADC_SAR_Seq_DieTemp_PSoC401
玩了几次以后,现在知道首先去看 cysch文件里的说明了。于是发现,它这个例程真是相当复杂。 开始我只是以为它只是把 温度传感器 和 LCD 混在一起,就已经够复杂了—— 所谓复杂,就是牵扯了无关的因素。不知道有没人和我一样持一种态度。 当我们想了解 温度传感器 或者其他任何一种外设时,我们都希望获得一个非常单一的操作例程。 尽管从厂商针对开发板提供可以马上看到效果的动机来说,这也无可厚非。
然而对于我们开发的人来说,说真的,其实从LCD上看到结果还是在debug时看到结果,个人真心认为区别不大。反而,对我来说,因为这个LCD,而且因为这个LCD,它还需要用PWM,反而增加了我们去学习单一外设的障碍。
这个先放下,退一万步来说,即使真的是从厂商为开发板配套的立场出发,我仍然觉得例程里有个地方很别扭。那就是 我的天,Result[]这个数组,从名字和出现的位置来看,都应该是转换后的温度结果,可是见鬼,它居然是int类型! 哦,刚才跑回去又看了看程序,说明一下,首先result[]数组存的不是我想象的那个 温度值的结果。 它只是读出寄存器的结果。然后在主函数里放入LCD显示以前转换成温度值。 然而我发现我果然没有冤枉它......
在主函数里,它还是很万恶的用了32位int去存储转换值。 - int32 temperature;
- temperature = DieTemp_CountsTo_Celsius(result[TEMP_CH]);
复制代码我真的没有冤枉它......
刚开始,我还对它抱有一丝希望,也许它只是略坑爹地把这个转换过程放在LCD显示的函数里。然而我找了半天,还是发现没有。 也就是说,即使我现在去搞来一个LCD,然后插上底板,我还是不会看到我所期望的带个小数点的温度值,甚至我怀疑那个数值我能不能看懂都是个问题。 这是不是略微有点坑爹呢.......
然后我决定,试一下读出这个temperature,看看到底是什么值。虽然现在停电,我也不知道现在具体多少度,但从接近蜡烛,数值从25上升到27,我觉得这个应该还是温度值没错,然后看了看转换函数,应该的确是温度值不错。不过,作为温度值居然没有小数点,这的确是略有点坑爹。 当然再想一下,由于这个片内温度传感器本身就是利用晶体管be结的温度特性,所以本身就只有5度的精度,因此,如此说来,它这么干,似乎也是有点道理的。
好吧,这个地方我们暂时原谅它。
如果说上面都只是我这个人太过挑剔的话,那接下来这个就真的是比较坑爹了,因为这属于客观错误。 在SAR_ADC的中断里,两个中断触发,我们会发现第二个中断条件始终是进不去的!!
- CY_ISR(ADC_SAR_SEQ_ISR_LOC)
- {
- uint32 intr_status;
- uint32 range_status;
-
- intr_status = ADC_SAR_SEQ_SAR_INTR_MASKED_REG;
- if((intr_status & ADC_SAR_SEQ_EOS_MASK) != 0u)
- {
- /* Read range detect status */
- range_status = ADC_SAR_SEQ_SAR_RANGE_INTR_MASKED_REG;
- /* Verify that the conversion result met the condition Low_Limit <= Result < High_Limit */
- if((range_status & (uint32)(1ul << CH0_N)) != 0u)
- {
- /* Read conversion resoult */
- result[CH0_N] = ADC_SAR_SEQ_GetResult16(CH0_N);
- /* Set PWM compare from channel0 */
- PWM_WriteCompare(result[CH0_N]);
- }
- /* Clear range detect status */
- ADC_SAR_SEQ_SAR_RANGE_INTR_REG = range_status;
- dataReady |= ADC_SAR_SEQ_EOS_MASK;
- }
- /* Check for Injection End of Conversion */
- if((intr_status & ADC_SAR_SEQ_INJ_EOC_MASK) != 0u)
- {
- result[TEMP_CH] = ADC_SAR_SEQ_GetResult16(TEMP_CH);
- dataReady |= ADC_SAR_SEQ_INJ_EOC_MASK;
- }
- /* Clear handled interrupt */
- ADC_SAR_SEQ_SAR_INTR_REG = intr_status;
- }
- 这个中断里有两个标志位if检查,第一个是EOS_MASK 意思扫描结束中断;
- 第二个是INJ_EOC,是(温度传感器读取温度)转换结束中断;这个地方好像是记反了?
复制代码 我在这两个条件判断里设置断点,我就发现了,第二个条件从来没有满足过。我还以为需要去理解一下这个外设,这可真是一个很复杂的玩意,pdf里说了一堆东西。但最后发现啥跟这个问题有关的都没有发现。 还好看了一下寄存器手册,至少知道这些都什么意思。最后我突然猜测,不会是第二个中断根本就没有允许触发吧.......
于是我在判断以前,读出了中断触发设置位,丫的,果然没有......于是我就在主函数设置完以后,在进入死循环等待以前直接设置这两个位,好家伙,中断终于进去了......
接下来还要吐槽的地方,就是它的代码了。 即使是现在我对它自动生成的代码的组织和编写方式还是相当的不爽,但是我仍然认为这是单片机开发环境的一个进步,它就像vc++这些图形界面PC程序一样先进,可以根据图形化的设置方式,自动生成所需代码,这的确是一个可以非常减轻开发者工作负担的事情。
但是,说实话,它的代码真的是写的相当混乱,看起来很辛苦。当然,和很多半导体厂商,如st ti这些厂商提供的例程或者什么第三方程序库一样。都很混乱,典型的是 “搞单片机的人才会写出的恶心代码”。
由于编程风格和思路本身是一件极具个人主观意识和习惯的事情,另外,毕竟它要考虑到很多其他我尚且没有意识到的因素。我只是做应用的,而他是提供底层库支持的,这是两种层次的编码。但是我不得不说,至少有几个地方,由于他选择的策略问题,使得这些生成的代码相当难以理解,这在很大程度上足以瓦解它自动生成代码,给上层应用开发者带来的好处。 首先,比如每个外设的init函数。当我看到它的长度和大量的宏条件编译,就足以吓坏一大堆人。 我们都很清楚,一个外设可能具有很多功能,需要初始化的地方很多,另外,使用的功能不同,它所操作的寄存器,操作的数值也是不一样的。但是,即使如此,它仍然没有必要把所有这些设置都挤在一个函数里。
有一个很常见的,并且足以被绝大多数程序员接受的原则是,与其把一堆其实分属不同功能(设置)的代码通过条件编译也好,通过if条件分离也好 地硬挤在一个函数体里,产生一个一堆注释,一堆宏选择的巨无霸,那么情愿写成一个又一个名字明确,功能单一的函数。即使最后你不想在main函数里写那么多个功能很小的子函数,你仍然可以在这个init里一个一个函数调用,都好过这样。
[ 本帖最后由 辛昕 于 2013-10-31 00:29 编辑 ]
|