|
技术交流 | 电路欣赏 | 工控天地 | 数字广电 | 通信技术 | 电源技术 | 测控之家 | EMC技术 | ARM技术 | EDA技术 | PCB技术 | 嵌入式系统 驱动编程 | 集成电路 | 器件替换 | 模拟技术 | 新手园地 | 单 片 机 | DSP技术 | MCU技术 | IC 设计 | IC 产业 | CAN-bus/DeviceNe |
在定时器1中断中为何必须写入TCNT1L??? |
作者:hotpower 栏目:单片机 |
一直用8MHZ晶振,今天由于产品需要定时准些,就改为7.3728MHZ.芯片M8L. 要求定时2.5mS,采用8分频(TCCR1B = 2),时间常数TCNT1H=0xf7,TCNT1L=0x00. #define DefTCNT1H 0xf7 #define DefTCNT1L 0x00 //2.5mS定时器 SIGNAL(SIG_OVERFLOW1) { TCNT1L = DefTCNT1L; TCNT1H = DefTCNT1H;//2.5mS //................................. } 为何不能: //2.5mS定时器 SIGNAL(SIG_OVERFLOW1) { // TCNT1L = DefTCNT1L; TCNT1H = DefTCNT1H;//2.5mS //................................. } TCNT1应该是加一器,那么定时到后TCNT1从0xffff到0,即TCNT1H = 0,TCNT1L = 0. 那么在中断中省略TCNT1L = DefTCNT1L;应该没问题. 就算TCNT1在0xffff时不归零,即TCNT1L = 0xff. 那么中断程序实际为TCNT1L = 0xff.而TCNT1H = DefTCNT1H给出了新值. 依据此判断,定时应该加快才是,但结果却相反!!! 问题即为: 在定时中断中,若不改写TCNT1L的值,定时将加长,实验结果至少数倍以上!!! 难道我又犯了一个低级错误??? 在51时这种省略时间常数低8位的写法可以提高定时精度而且可以少写一条指令. 不知在AVR上为何不行??? 郁闷...TCNT1L不就是一个0x00~0xff的数吗???不写应该也有值呀!!! |
2楼: | >>参与讨论 |
作者: ipman 于 2005/7/9 22:55:00 发布:
TCNT1=0xf7ff直接测试,如果没问题就是低级问题 |
3楼: | >>参与讨论 |
作者: hotpower 于 2005/7/9 23:16:00 发布:
不解... TCNT1=0xf700~TCNT1=0xf7ff无非差一点点... 我的郁闷在于为何非要在中断中重写TCNT1L... 难道访问TCNT1时,必须高低8位都要访问吗??? 估计是个低级错误.难道不访问TCNT1L,就是访问TCNT1H也不管用. 这样进入中断后虽然改写TCNT1H,但实际上TCNT1H不变(实际为0),故延时加长(0x100/(0x100-0xf7)) |
4楼: | >>参与讨论 |
作者: testcode 于 2005/7/10 4:23:00 发布:
必须写入TCNT1L,才能更新TCNT1H! datasheet: "Accessing 16-bit Registers" "TCNT1H is updated with the temporary register VALUE when TCNT1L is written. " * - 本贴最后修改时间:2005-7-10 6:52:55 修改者:testcode |
5楼: | >>参与讨论 |
作者: AVRx007 于 2005/7/10 10:35:00 发布:
呵呵! hotpower也犯了个AVR的基本错误。 |
6楼: | >>参与讨论 |
作者: hotpower 于 2005/7/10 12:00:00 发布:
基本错误犯多了有好处 "写16 位寄存器时,应先写入该寄存器的高位字节。而读16 位寄存器时应先读取该寄存器的低位字节。" "访问低字节会触发16位读或写操作。" "16 位计数器映射到两个8 位I/O存储器位置:TCNT1H为高8 位,TCNT1L 为低8 位。CPU只能间接访问TCNT1H 寄存器。CPU 访问TCNT1H 时,实际访问的是临时寄存器(TEMP)。读取TCNT1L时,临时寄存器的内容更新为TCNT1H的数值;而对TCNT1L执行写操作时,TCNT1H 被临时寄存器的内容所更新。" #define DefTCNT1H 0xf7 #define DefTCNT1L 0x00 void Timer1Init(void) { TCNT1H = DefTCNT1H;//2.5mS TCNT1L = DefTCNT1L; //............................. } //2.5mS定时器 SIGNAL(SIG_OVERFLOW1) { volatile unsigned CHAR TEMP; TCNT1H = DefTCNT1H;//2.5mS//是否写入TCNT1H的缓冲区???但并非改写TCNT1H // TCNT1L = DefTCNT1L;//假如其他中断使定时器1中断滞后使TCNT1L在此远远大于DefTCNT1L但小于0xff TEMP = TCNT1L;//读TCNT1L才真正写入TCNT1H??? //................................. } 为不改写TCNT1L且写入TCNT1H,以上指令不知对否??? TEMP变量实际没用,主要想读TCNT1L激活对TCNT1H的写入. 由于7.3728MHZ在定时2.5mS时理论误差为0,但由于定时中断由于某些原因而不能 及时响应中断,那么就会产生定时误差,选7.3728MHZ就无多大意义. 等有时间做个实验... |
7楼: | >>参与讨论 |
作者: testcode 于 2005/7/10 12:36:00 发布:
读TCNT1L才真正写入TCNT1H??? 应该为: 读取TCNT1L时, 临时寄存器的内容 = TCNT1H的数值; |
8楼: | >>参与讨论 |
作者: hotpower 于 2005/7/10 12:58:00 发布:
那么哪个次序对呢??? SIGNAL(SIG_OVERFLOW1) { volatile unsigned CHAR TEMP; TCNT1H = DefTCNT1H TEMP = TCNT1L;//读TCNT1L才真正写入TCNT1H??? //................................. } 还是: SIGNAL(SIG_OVERFLOW1) { volatile unsigned CHAR TEMP; TEMP = TCNT1L;//读TCNT1L才真正写入TCNT1H??? TCNT1H = DefTCNT1H //................................. } 周末没开发板无法论证...总之只想写TCNT1H不想写TCNT1L... 如何是好??? |
9楼: | >>参与讨论 |
作者: AVRx007 于 2005/7/10 16:55:00 发布:
用16位,无需担心。 在C语言里面用16位长度的变量(常量只写)对16位寄存器进行读写,AVR的C编译器会自动调整顺序。 |
10楼: | >>参与讨论 |
作者: hotpower 于 2005/7/10 17:33:00 发布:
关键是不想写TCNT1L而读TCNT1L是被逼无奈 |
11楼: | >>参与讨论 |
作者: 红日 于 2005/7/10 18:08:00 发布:
用8位计数器 7.3728MHZ.芯片M8L. 要求定时2.5mS,采用256分频,用8位计数器T/C0、T/C2,时间常数TCNT0=0xB8。 |
12楼: | >>参与讨论 |
作者: hotpower 于 2005/7/10 18:26:00 发布:
谢谢红日先生 我主要想搞清16位定时器的应用... 主要是想其他中断工作时且cli()时,则T1将无法及时响应中断. 如果延迟大于分频数且在0-TCNT1L的范围内时, TCNT1L的值此时应该是一个非0 的数. 当然不到0xff. 若此时其他中断结束后,由于T1中断标志早被触发,故应该补上中断响应. 如果再将TCNT1L初始为0,则肯定不对. 所以,TCNT1L应该做为"自由人"而不该改写它!!! 这样在一定时间内的中断延迟也不会影响整个定时的准确度... |
13楼: | >>参与讨论 |
作者: 红日 于 2005/7/10 18:53:00 发布:
用16位定时器,选用比效匹配方式。 用16位定时器,选用比效匹配方式(Auto Reload) 7.3728MHZ.芯片M8L. 要求定时2.5mS,采用1分频,用16位定时计数器T/C1,选用比效匹配方式(Auto Reload),时间常数TCNT1=0xB800,时间很准确。 |
14楼: | >>参与讨论 |
作者: hotpower 于 2005/7/10 19:00:00 发布:
再次感谢... 我知道AVR的定时方式很丰富,有很多方法解决... 可能我顶牛想不通吧... 再谢红日先生: 外晶振的问题解决了----原来是双龙的M8开发板插座接触不良所致... 而且双龙的ISP成功率太低...小马的100%. |
15楼: | >>参与讨论 |
作者: 红日 于 2005/7/10 21:46:00 发布:
双龙的ISP写入成功率太低 双龙的ISP写入成功率太低: 是选择ISP写入速度过高TURBO档问题,不成功。 选用FAST档或NORMAL档,成功率100%。 |
16楼: | >>参与讨论 |
作者: hotpower 于 2005/7/11 0:25:00 发布:
我选什么都不怎么样 选用FAST档或NORMAL档,成功率不敢说... |
17楼: | >>参与讨论 |
作者: testcode 于 2005/7/11 0:56:00 发布:
确实要开发板测试才可以 确实要用开发板转转,用avrstudio好像两种结果都一样。 不过datasheet要求必须写入TCNT1L,但TCNT1H倒是可以忽略,如果值不变时。 |
18楼: | >>参与讨论 |
作者: hotpower 于 2005/7/11 1:13:00 发布:
产品中写入了TCNT1L,我只是想不通 我昨天用TCNT1L++都不行...明天看有时间能测试一下... 学习嘛---郁闷多了不是坏事... |
19楼: | >>参与讨论 |
作者: athlon64fx 于 2005/7/11 9:05:00 发布:
软件重装似乎没有必要, AVR几乎所有定时器都有 CTC 工作模式(M8T0好像没有), 没有积累误差. SLISP软件经常校验失败是真的, 而且成功率与速度几乎没有关系, 即使你用Turbo Slow. 至少我用它对 M64 编程还没有一次成功过. |
20楼: | >>参与讨论 |
作者: madaha 于 2005/7/11 11:56:00 发布:
人非圣贤,孰能无过 看过不如做过,做过不如错过,错过不如错得多. |
21楼: | >>参与讨论 |
作者: zhiwei 于 2005/7/14 12:31:00 发布:
写TCNT1L才能更新TCNT1H 16位的计数值需要在一次操作中写入,但是实际上分开为H和L写,写H的时候并没有实际写入而是在TEMP里面,写L时,16位计数值同时更新。 |
22楼: | >>参与讨论 |
作者: qjy_dali 于 2005/7/14 22:36:00 发布:
这实际是硬件临界区保护,呵呵 |
|
|
Copyright © 1998-2006 tgdrjb.cn 浙ICP证030469号 |