打印
[技术问答]

有个帖子说可以更改HIRC频率,去查了下就不懂了。。

[复制链接]
3789|29
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
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


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




沙发
chongdongchen|  楼主 | 2018-6-2 21:32 | 只看该作者
本帖最后由 chongdongchen 于 2018-6-2 21:46 编辑

还是自己先实验吧,针对我刚刚提出的寄存器读取的两种方法,专门做了一个实验,主要程序如下:
<div>//读取寄存器值</div><div>uint16_t ReadRCTRIM(void)
</div>{
    uint8_t  hircmap0,hircmap1;
    hircmap0 = RCTRIM0;
    hircmap1 = RCTRIM1;
    return (((uint16_t)hircmap0<<1)+(hircmap1&0x01));
}
<div>//手册方法</div><div>void MODIFY_HIRC_VLAUE_1(void)
</div>{
    uint8_t  hircmap0,hircmap1;
    uint16_t trimvalue16bit;
   
    set_IAPEN;
    IAPAL = 0x30;
    IAPAH = 0x00;
    IAPCN = READ_UID;
    set_IAPGO;
    hircmap0 = IAPFD;
    IAPAL = 0x31;
    IAPAH = 0x00;
    set_IAPGO;
    hircmap1 = IAPFD;
    clr_IAPEN;
   
    trimvalue16bit = ((hircmap0<<1)+(hircmap1&0x01));
    trimvalue16bit = trimvalue16bit - 15;
   
    hircmap1 = trimvalue16bit&0x01;
    hircmap0 = trimvalue16bit>>1;
    TA=0XAA;
    TA=0X55;
    RCTRIM0 = hircmap0;
    TA=0XAA;
    TA=0X55;
    RCTRIM1 = hircmap1;
<div>}</div><div>//直接寄存器法</div><div>void MODIFY_HIRC_VLAUE_2(void)
</div>{
    uint8_t  hircmap0,hircmap1;
    uint16_t trimvalue16bit;
   
    hircmap0 = RCTRIM0;
    hircmap1 = RCTRIM1;
   
    trimvalue16bit = ((hircmap0<<1)+(hircmap1&0x01));
    trimvalue16bit = trimvalue16bit - 15;
   
    hircmap1 = trimvalue16bit&0x01;
    hircmap0 = trimvalue16bit>>1;
    TA=0XAA;
    TA=0X55;
    RCTRIM0 = hircmap0;
    TA=0XAA;
    TA=0X55;
    RCTRIM1 = hircmap1;
}

第一次实验(function函数1ms执行一次):

第一次进入断点(第5秒):

第二次进入断点(第6秒):

第三次,(第7秒):

接下来每次进中断都保持不变。
得出这次实验的结果:
手册方法:每次都是 0x010A - 0x15 = 0xF5;//这里为什么是减去0x15?再研究。。
寄存器法:每次都是寄存器自减 15;

使用特权

评论回复
评论
chongdongchen 2018-6-2 21:47 回复TA
奇怪,代码里的<DIV>删除不掉 
chongdongchen 2018-6-2 21:34 回复TA
代码里面打字影响阅读效果了,见谅 
板凳
chongdongchen|  楼主 | 2018-6-2 21:37 | 只看该作者
第二次实验数据,只保留了寄存器法:

首次中断:

第二次:

第三次:

这里可以看出,每次都是寄存器自减15,符合预期。
接下来再综合分析结果。。


使用特权

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

先假设猜想成立。

然后新问题又来了:
1、IAP地址的数据是怎么复制过去的?
2、为什么会是减去0x15,而不是15?

使用特权

评论回复
5
chongdongchen|  楼主 | 2018-6-2 21:55 | 只看该作者
虽然现在还不清楚原因,但是有一点可以肯定,用官方这种方法才是正确的,它可以避免由于误操作(不小心调用多次)带来的影响,而且做了偏移,这种偏移量对于我们来说是未知的。

使用特权

评论回复
6
dongnanxibei| | 2018-6-2 22:28 | 只看该作者
hehe,那就是新唐规定的。没啥好解释吧。

使用特权

评论回复
7
chongdongchen|  楼主 | 2018-6-3 10:27 | 只看该作者
dongnanxibei 发表于 2018-6-2 22:28
hehe,那就是新唐规定的。没啥好解释吧。

新唐规定的就不用解释了?寄存器都不用解释了?都等着用官方库就好了?
那个IAP地址手册上没说明,那如果用户不小心用到了呢,什么后果?

使用特权

评论回复
8
dongnanxibei| | 2018-6-3 10:28 | 只看该作者
chongdongchen 发表于 2018-6-3 10:27
新唐规定的就不用解释了?寄存器都不用解释了?都等着用官方库就好了?
那个IAP地址手册上没说明,那如果 ...


楼主这么一说,我还真要去看看怎么写的。要不然,我也发帖吐槽他。

使用特权

评论回复
9
dongnanxibei| | 2018-6-3 10:31 | 只看该作者
N76E003 有两个字节的SFR,更改这两个字节的数值,可以直接对HIRC频率产生改变,由于每更改一阶HIRC更改的值是恒定的,且由于HIRC已调整至非常准确的16 MHz,所以对这两个寄存器目前的值直接减去15,就可以得到16.6 MHz的结果。
就是这两个寄存器的值应该是调整内部RC震荡电路的某个参数的,比如R或者C

使用特权

评论回复
10
chongdongchen|  楼主 | 2018-6-3 10:32 | 只看该作者
发帖不是为了要吐槽,是讨论问题!

使用特权

评论回复
11
chongdongchen|  楼主 | 2018-6-3 10:36 | 只看该作者
dongnanxibei 发表于 2018-6-3 10:31
N76E003 有两个字节的SFR,更改这两个字节的数值,可以直接对HIRC频率产生改变,由于每更改一阶HIRC更改的 ...

所以我提出问题,为什么更改这两个字节的数值,需要从别的地址那里取原始值?

使用特权

评论回复
12
dongnanxibei| | 2018-6-3 11:02 | 只看该作者
确实,没找到关于30和31地址的说辞,但是怎么从这里读数据写入84,85呢。跟前面的文字确实不符啊。不知道能否从84和85读取数据。

使用特权

评论回复
13
chongdongchen|  楼主 | 2018-6-3 11:10 | 只看该作者
dongnanxibei 发表于 2018-6-3 11:02
确实,没找到关于30和31地址的说辞,但是怎么从这里读数据写入84,85呢。跟前面的文字确实不符啊。不知道能 ...

我前面的实验已经证实:两种方法都可以。

使用特权

评论回复
14
chongdongchen|  楼主 | 2018-6-3 11:13 | 只看该作者
但是例程的方法有点想不通,明明是减15,但是实际上确有疑问,具体看我上面的数据

使用特权

评论回复
15
dongnanxibei| | 2018-6-3 11:30 | 只看该作者
chongdongchen 发表于 2018-6-3 11:13
但是例程的方法有点想不通,明明是减15,但是实际上确有疑问,具体看我上面的数据 ...

嗯,我的疑问是这两对是不是有映射。修改一下84,85.不从30,31读。然后再读出30和31,看看是不是也跟着变化了。

使用特权

评论回复
16
huangcunxiake| | 2018-6-3 11:34 | 只看该作者
发现了,这个例子当时看的我一愣一愣的。

使用特权

评论回复
17
chongdongchen|  楼主 | 2018-6-3 14:11 | 只看该作者
dongnanxibei 发表于 2018-6-3 11:30
嗯,我的疑问是这两对是不是有映射。修改一下84,85.不从30,31读。然后再读出30和31,看看是不是也跟着变 ...

这个实验里面已经有答案,改了84,85,30和31还是不变的

使用特权

评论回复
18
chongdongchen|  楼主 | 2018-6-3 14:15 | 只看该作者
huangcunxiake 发表于 2018-6-3 11:34
发现了,这个例子当时看的我一愣一愣的。

就是啊,绕一圈去读,浪费代码空间,当时一看我就不愿意了,所以才有了此贴

使用特权

评论回复
19
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偏移量的任意频率范围。
根据这个情况,官方的例程很明显是最正宗的,虽然代码冗长了,但是不管你执行几次,目标唯一且正确。

使用特权

评论回复
20
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的结果”。这又是矛盾的。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

54

主题

1233

帖子

10

粉丝