设计内容是早定好的,但是始终找不到合适的名字,因为和普通万用表相比吧,只有频率和电压测量。少了电流啊,电阻啊(其实有ADC,只要加上运放电路,一样可以测)。但是测量中更多的是要通过代码来展示测量过程,供学习使用,所以在频率测量上准备尝试不同的方法,通过实验展示各种方案的优缺点,同时也是对timer不同模式的使用,也可以展现mcu本身的特性。所以这个多功能测量表,更多的是对测量方法和mcu外设使用的展现,而并不是一个最终的商品,或者说只是一个学习的参考产品。
进入正题。上次玩过codegenerator(以下简称CG)后,觉得实在好用,这次试试用来做AD看看。很多细节图就不上,选择20M振荡频率,IO口配置默认。使用片上调试器。使用P01口,设为IN,用作AD输入(因为正好接了电位器,后面的电压表的被测电压也默认从这里进来)。P04弄了个输出,默认输出0,因为用timer定时来读取AD值,在这个脚上测试下timer时间设置结果对不对。其他IO暂时不用
在使用中要注意,ms看门口默认是启用的,所以要把他取消掉。点击generate code,就得到代码啦。看起来好复杂的样子,比前面第一个函数多多了。有点吓倒人的感觉。
这里面大部分内容大家一看就一目了然,prot是端口设置、tau是timer单元、adc就是模数,Systeminit系统初始化,那cgc是什么呢?看了下注释,原来是时钟设置函数。可是?怎么是个空函数呢?试了一下用其他振荡频率,还是空的,难道要自己写?不应该啊。
看看timer的定义中,会不会变化,显示10M,100ms。Clk改成20M,设置不变
改成200ms有变化
不管了,先开动吧。其实要改动的地方不多,只要在r_cg_tau_user.c的中断程序里面启动ad(R_ADC_Start();),然后在r_cg_adc_user.c里面中断设把adc_eoc置1,然后在主函数里面循环判断adc_eoc,一旦转换结束,就去读取AD(R_ADC_Get_Result(&adc_data);)。最后AD值是在调试的watch窗口看到的。话说上面这些函数可是CG给大家都写好的哦!!!
结果还是出事了,AD值不断在变,而且不准。最后查了半天,是CG设置问题。原来电位器接在P01上,可是对应的AIN的编号却是0!!!,我把AD通道给选错了。正常选成AIN0后,测试一切正常。另外,要注意这个P01,好像要选unused,而不是我们想象中AD应该用in
一切正常后,开始测量AD的准确性。实测输入电压:3.069,3.067,AD值是647,电源电压,4.860.换算结果V=647/1024*4.86=3.07,还是相当准的嘛。又测了一个很小的电压,9.3mV,9.2mV,结果位2/1024*4.86=9.5mV。这个可能是人品好,因为分辨率基本在5/1024=4mV左右,这个9.2mV可能刚好在准确值附近,所以也比较精确。这里有两个注意,为什么我用了两个很接近的输入电压,因为前面写电路的时候写过,电位器输入是串接一个10K的电阻再进去MCU的AD输入端的,所以两个电压分别是点位器输出电压和AIN0的入端电压(就是那个10K电阻两头),实测来看,这个电阻都被测电压影响极小。可是这个电阻到底有什么用,我还是想不明白,请高手指点。另外,我这里的测量全部是单次测量,没有用多次平均,可见结果也是比较准确的。不像有些家的AD,号称前几次都不准,非要来个10次平均。另外中断中对P04做输出翻转,可以得到1Hz的D1闪烁周期,基本上还准的(咱是对着秒表看的,哈哈,原谅我暂时没有好点的仪器,我那只破万用表测出来有4Hz,明显不对的说)。因为最后设定的是500ms的中断。可能是分频不准缘故,CG中还给出了实际周期。
最后上压缩代码包,供大家参考吧。一句话评论,这code generator弄清楚了,真的很快。不过,定时器灵活性差一点,因为好像只能设一个固定的时间。其他定时长度怎么设,光靠CG是学不到的,还是要看寄存器。这个留待后面吧,话说这timer是最麻烦的。