[技术问答] 有个帖子说可以更改HIRC频率,去查了下就不懂了。。

[复制链接]
 楼主| chongdongchen 发表于 2018-6-2 17:20 | 显示全部楼层 |阅读模式
rc, iap, se, tmp, rim
原帖: https://bbs.21ic.com/icview-2513598-1-2.html
刚开始接触新唐,请大家多多指导。
看了这个帖子后,我也打开手册去看了下,文中原理和例程是这样的:

原理:
N76E003 有两个字节的SFR,更改这两个字节的数值,可以直接对HIRC频率产生改变,由于每更改一阶HIRC
更改的值是恒定的,且由于HIRC已调整至非常准确的16 MHz,所以对这两个寄存器目前的值直接减去15,就可
以得到
16.6 MHz的结果。
下列两个字节产生
9位的HIRC调整值,每个位更改大约产生16 MHz0.25%偏差,也就是一阶 40 KHz


例程:
  1. sfr RCTRIM0 = 0x84;
  2. sfr RCTRIM1 = 0x85;
  3. bit BIT_TMP;
  4. #define set_IAPEN BIT_TMP=EA;EA=0;TA=0xAA;TA=0x55;CHPCON|=SET_BIT0 ;EA=BIT_TMP
  5. #define set_IAPGO BIT_TMP=EA;EA=0;TA=0xAA;TA=0x55;IAPTRG|=SET_BIT0 ;EA=BIT_TMP
  6. #define clr_IAPEN BIT_TMP=EA;EA=0;TA=0xAA;TA=0x55;CHPCON&=~SET_BIT0;EA=BIT_TMP
  7. unsigned char hircmap0,hircmap1;
  8. unsigned int trimvalue16bit;
  9. void MODIFY_HIRC_VLAUE(void)
  10. {
  11.     set_IAPEN;
  12.     IAPAL = 0x30;
  13.     IAPAH = 0x00;
  14.     IAPCN = READ_UID;
  15.     set_IAPGO;
  16.     hircmap0 = IAPFD;
  17.     IAPAL = 0x31;
  18.     IAPAH = 0x00;
  19.     set_IAPGO;
  20.     hircmap1 = IAPFD;
  21.     clr_IAPEN;
  22.     trimvalue16bit = ((hircmap0<<1)+(hircmap1&0x01));
  23.     trimvalue16bit = trimvalue16bit - 15;
  24.     hircmap1 = trimvalue16bit&0x01;
  25.     hircmap0 = trimvalue16bit>>1;
  26.     TA=0XAA;
  27.     TA=0X55;
  28.     RCTRIM0 = hircmap0;
  29.     TA=0XAA;
  30.     TA=0X55;
  31.     RCTRIM1 = hircmap1;
  32. }
现在不懂的是:
更改之前的两个SFR的值为什么要用IAP从0x0030,0x0031的地址去读取,而不直接从本身读取呢?
手册上好像也没有特别说明。
然后也没发现有谁提出疑问,所以就不懂了,还请高人点拨一下。。。




 楼主| chongdongchen 发表于 2018-6-2 21:32 | 显示全部楼层
本帖最后由 chongdongchen 于 2018-6-2 21:46 编辑

还是自己先实验吧,针对我刚刚提出的寄存器读取的两种方法,专门做了一个实验,主要程序如下:
  1. <div>//读取寄存器值</div><div>uint16_t ReadRCTRIM(void)
  2. </div>{
  3.     uint8_t  hircmap0,hircmap1;
  4.     hircmap0 = RCTRIM0;
  5.     hircmap1 = RCTRIM1;
  6.     return (((uint16_t)hircmap0<<1)+(hircmap1&0x01));
  7. }
  8. <div>//手册方法</div><div>void MODIFY_HIRC_VLAUE_1(void)
  9. </div>{
  10.     uint8_t  hircmap0,hircmap1;
  11.     uint16_t trimvalue16bit;
  12.    
  13.     set_IAPEN;
  14.     IAPAL = 0x30;
  15.     IAPAH = 0x00;
  16.     IAPCN = READ_UID;
  17.     set_IAPGO;
  18.     hircmap0 = IAPFD;
  19.     IAPAL = 0x31;
  20.     IAPAH = 0x00;
  21.     set_IAPGO;
  22.     hircmap1 = IAPFD;
  23.     clr_IAPEN;
  24.    
  25.     trimvalue16bit = ((hircmap0<<1)+(hircmap1&0x01));
  26.     trimvalue16bit = trimvalue16bit - 15;
  27.    
  28.     hircmap1 = trimvalue16bit&0x01;
  29.     hircmap0 = trimvalue16bit>>1;
  30.     TA=0XAA;
  31.     TA=0X55;
  32.     RCTRIM0 = hircmap0;
  33.     TA=0XAA;
  34.     TA=0X55;
  35.     RCTRIM1 = hircmap1;
  36. <div>}</div><div>//直接寄存器法</div><div>void MODIFY_HIRC_VLAUE_2(void)
  37. </div>{
  38.     uint8_t  hircmap0,hircmap1;
  39.     uint16_t trimvalue16bit;
  40.    
  41.     hircmap0 = RCTRIM0;
  42.     hircmap1 = RCTRIM1;
  43.    
  44.     trimvalue16bit = ((hircmap0<<1)+(hircmap1&0x01));
  45.     trimvalue16bit = trimvalue16bit - 15;
  46.    
  47.     hircmap1 = trimvalue16bit&0x01;
  48.     hircmap0 = trimvalue16bit>>1;
  49.     TA=0XAA;
  50.     TA=0X55;
  51.     RCTRIM0 = hircmap0;
  52.     TA=0XAA;
  53.     TA=0X55;
  54.     RCTRIM1 = hircmap1;
  55. }

第一次实验(function函数1ms执行一次):
450895b129a3d79043.png
第一次进入断点(第5秒):
718705b129a8b4337c.png
第二次进入断点(第6秒):
32495b129acc2c8e3.png
第三次,(第7秒):
136475b129ae86332b.png
接下来每次进中断都保持不变。
得出这次实验的结果:
手册方法:每次都是 0x010A - 0x15 = 0xF5;//这里为什么是减去0x15?再研究。。
寄存器法:每次都是寄存器自减 15;

评论

奇怪,代码里的<DIV>删除不掉  发表于 2018-6-2 21:47
代码里面打字影响阅读效果了,见谅  发表于 2018-6-2 21:34
 楼主| chongdongchen 发表于 2018-6-2 21:37 | 显示全部楼层
第二次实验数据,只保留了寄存器法:
121795b129cfc798b5.png
首次中断:
692405b129d0e384f5.png
第二次:
866715b129d156c31d.png
第三次:
834105b129d1d14d82.png
这里可以看出,每次都是寄存器自减15,符合预期。
接下来再综合分析结果。。


 楼主| chongdongchen 发表于 2018-6-2 21:44 | 显示全部楼层
先猜想一下:
这个IAP地址里的数据是来自于寄存器,所以从这里读出并不影响结果,反而避免了用户在上电后不小心多次执行的错误操作。
如果像我说的,直接读取寄存器本身,那么用户的误操作就会带来严重后果!

先假设猜想成立。

然后新问题又来了:
1、IAP地址的数据是怎么复制过去的?
2、为什么会是减去0x15,而不是15?
 楼主| chongdongchen 发表于 2018-6-2 21:55 | 显示全部楼层
虽然现在还不清楚原因,但是有一点可以肯定,用官方这种方法才是正确的,它可以避免由于误操作(不小心调用多次)带来的影响,而且做了偏移,这种偏移量对于我们来说是未知的。
dongnanxibei 发表于 2018-6-2 22:28 | 显示全部楼层
hehe,那就是新唐规定的。没啥好解释吧。
 楼主| chongdongchen 发表于 2018-6-3 10:27 | 显示全部楼层
dongnanxibei 发表于 2018-6-2 22:28
hehe,那就是新唐规定的。没啥好解释吧。

新唐规定的就不用解释了?寄存器都不用解释了?都等着用官方库就好了?
那个IAP地址手册上没说明,那如果用户不小心用到了呢,什么后果?
dongnanxibei 发表于 2018-6-3 10:28 | 显示全部楼层
chongdongchen 发表于 2018-6-3 10:27
新唐规定的就不用解释了?寄存器都不用解释了?都等着用官方库就好了?
那个IAP地址手册上没说明,那如果 ...


楼主这么一说,我还真要去看看怎么写的。要不然,我也发帖吐槽他。
dongnanxibei 发表于 2018-6-3 10:31 | 显示全部楼层
N76E003 有两个字节的SFR,更改这两个字节的数值,可以直接对HIRC频率产生改变,由于每更改一阶HIRC更改的值是恒定的,且由于HIRC已调整至非常准确的16 MHz,所以对这两个寄存器目前的值直接减去15,就可以得到16.6 MHz的结果。
就是这两个寄存器的值应该是调整内部RC震荡电路的某个参数的,比如R或者C
 楼主| chongdongchen 发表于 2018-6-3 10:32 | 显示全部楼层
发帖不是为了要吐槽,是讨论问题!
 楼主| chongdongchen 发表于 2018-6-3 10:36 | 显示全部楼层
dongnanxibei 发表于 2018-6-3 10:31
N76E003 有两个字节的SFR,更改这两个字节的数值,可以直接对HIRC频率产生改变,由于每更改一阶HIRC更改的 ...

所以我提出问题,为什么更改这两个字节的数值,需要从别的地址那里取原始值?
dongnanxibei 发表于 2018-6-3 11:02 | 显示全部楼层
确实,没找到关于30和31地址的说辞,但是怎么从这里读数据写入84,85呢。跟前面的文字确实不符啊。不知道能否从84和85读取数据。
 楼主| chongdongchen 发表于 2018-6-3 11:10 | 显示全部楼层
dongnanxibei 发表于 2018-6-3 11:02
确实,没找到关于30和31地址的说辞,但是怎么从这里读数据写入84,85呢。跟前面的文字确实不符啊。不知道能 ...

我前面的实验已经证实:两种方法都可以。
 楼主| chongdongchen 发表于 2018-6-3 11:13 | 显示全部楼层
但是例程的方法有点想不通,明明是减15,但是实际上确有疑问,具体看我上面的数据
dongnanxibei 发表于 2018-6-3 11:30 | 显示全部楼层
chongdongchen 发表于 2018-6-3 11:13
但是例程的方法有点想不通,明明是减15,但是实际上确有疑问,具体看我上面的数据 ...

嗯,我的疑问是这两对是不是有映射。修改一下84,85.不从30,31读。然后再读出30和31,看看是不是也跟着变化了。
huangcunxiake 发表于 2018-6-3 11:34 | 显示全部楼层
发现了,这个例子当时看的我一愣一愣的。
 楼主| chongdongchen 发表于 2018-6-3 14:11 | 显示全部楼层
dongnanxibei 发表于 2018-6-3 11:30
嗯,我的疑问是这两对是不是有映射。修改一下84,85.不从30,31读。然后再读出30和31,看看是不是也跟着变 ...

这个实验里面已经有答案,改了84,85,30和31还是不变的
 楼主| chongdongchen 发表于 2018-6-3 14:15 | 显示全部楼层
huangcunxiake 发表于 2018-6-3 11:34
发现了,这个例子当时看的我一愣一愣的。

就是啊,绕一圈去读,浪费代码空间,当时一看我就不愿意了,所以才有了此贴
tianxj01 发表于 2018-6-3 15:29 | 显示全部楼层
本帖最后由 tianxj01 于 2018-6-3 15:31 编辑
chongdongchen 发表于 2018-6-3 14:15
就是啊,绕一圈去读,浪费代码空间,当时一看我就不愿意了,所以才有了此贴 ...

很明显,官方的IAP30 31地址是保留地址,这个人家是不需要给出特殊说明的,根据说明书16MHz已经调整到1%,那么手段肯定就是在这30  31地址上面,官方通过修改IAP30-31地址值,来修正主时钟频率偏移,达到16-1%精度,这个应该是根据芯片实际值微调后的保存结果,批量生产不经过微调,内部振荡器不可能有1%精度。
然后,芯片上电,肯定是从这2个地址,自动映射到SFR的84  85寄存器。这样就实现了时钟部分的所有功能,
即:上电自动恢复到16MHz 1%的时钟,通过修改84 85寄存器可以在本次上电,临时变换成每bit 40KHZ偏移量的任意频率范围。
根据这个情况,官方的例程很明显是最正宗的,虽然代码冗长了,但是不管你执行几次,目标唯一且正确。
 楼主| chongdongchen 发表于 2018-6-3 16:43 | 显示全部楼层
tianxj01 发表于 2018-6-3 15:29
很明显,官方的IAP30 31地址是保留地址,这个人家是不需要给出特殊说明的,根据说明书16MHz已经调整到1%, ...

谢谢你的回复,感觉你应该说对了。又去翻了一下手册,我再添加一点,整理如下:
1、IAP30,31是校准值(1%),并且独立于LDROM和APROM的,所以不影响用户,也可以不解释。
2、SFR84,85则是一个偏移控制量,专门用于偏移HIRC的频率,实际频率受控于此。
3、本质上都是偏移量控制。上电时SFR就是从IAP那里加载过来,所以例程就是从IAP30,31读,再写回SFR84,85。
4、为什么要这么绕圈,我已经想明白了,因为单片机在正常供电情况下,也有可能发生复位(比如某操作需要软复位)。那么就会多执行了一次频率偏移。如果每次都是从IAP那里读取,就没关系了。

不过还是有问题:
例程里,更改量是-15,但是根据我仿真结果(在2楼)却是-21(-0x15),也就是说SFR的数据还不是直接简单的从IAP那里复制的。虽然这里的具体我们可以不用管,但是手册里还说到了一句“对这两个寄存器目前的值直接减去15,就可以得到16.6 MHz的结果”。这又是矛盾的。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

55

主题

1238

帖子

10

粉丝
快速回复 在线客服 返回列表 返回顶部