[AVR单片机] T0 输出的频率咋不准了呢

[复制链接]
2827|5
 楼主| jsll86 发表于 2013-5-7 23:28 | 显示全部楼层 |阅读模式
目的:通过PA1输出0.993KHz方波,用PD6采集该输出方波频率。
问题:当注释掉T1计频中断timer1_capt_isr后,PA1口可以产生0.993KHz的信号;当启用timer1_capt_isr中断后,PA1口只有0.224KHz,这咋回事呢:dizzy:
  1. /*
  2. LCD12864液晶屏显示实验。
  3. PA1输出0.993KHz方波,通过PD6采集,并显示
  4. */

  5. #include <iom16v.h>
  6. #include "font.h"
  7. #include "lcd12864.h"
  8. #include <macros.h>
  9. int contN;
  10. unsigned char flow_flag=0; //用于标记定时器溢出,如果溢出了,只记录到TCNT的值就不对了哦,需要进行处理,应该是TOP*flow_flag+TCNT
  11. unsigned int icpnum=0; //记录每次采集的TCNT差值,注意整个过程中不要操作TCNT,以免引入误差
  12. unsigned char timerover_error=0;
  13. unsigned int last_icrvalue=0; //记录上次的ICR值
  14. unsigned int value;
  15. void timer1_init(void)
  16. {
  17. TCCR1B = 0x00; //stop
  18. TCNT1H = 0x00;
  19. TCNT1L = 0x00;
  20. ICR1H = 0x00;
  21. ICR1L = 0x00;
  22. TCCR1A = 0x00;
  23. TCCR1B|=(1<<ICNC1)|(1<<ICES1)|(1<<CS11)|(1<<CS10);
  24. }

  25. #pragma interrupt_handler timer1_capt_isr:12
  26. void timer1_capt_isr(void)
  27. {
  28. PORTA|=(1<<7);
  29. //CLI();
  30. value=ICR1L;
  31. value|=(int)ICR1H << 8;

  32. if(flow_flag==0)
  33. {
  34. icpnum=value-last_icrvalue;
  35. }
  36. else
  37. {
  38. if(flow_flag==1)
  39. {
  40. flow_flag=0;
  41. icpnum=0xFFFF-last_icrvalue+value;
  42. }
  43. else
  44. {
  45. timerover_error=1;
  46. flow_flag=0;
  47. }
  48. }
  49. last_icrvalue=value;
  50. SEI();
  51. }

  52. void timer0_init(void)
  53. {

  54. TCCR0 = 0x00;
  55. TCNT0 = 0xc6;
  56. OCR0 = 0xc6;

  57. TIMSK |= 0x03;

  58. TCCR0 |=0B00011;
  59. }


  60. void init_devices(void)
  61. {
  62. CLI();
  63. MCUCR = 0x00;
  64. MCUCSR = 0x80;//禁止JTAG
  65. GICR = 0x00;

  66. DDRA |= (1<<PA1);
  67. DDRD &=~ (1<<PD6);
  68. PORTD |= (1<<PD6);

  69. timer0_init();
  70. timer1_init(); //定时器1初始化
  71. SEI();//开全局中断
  72. }

  73. //T0比较中断服务程序
  74. #pragma interrupt_handler timer0_comp_isr:20
  75. void timer0_comp_isr(void)
  76. {
  77. TCNT0 = 0xc6;
  78. PORTA^=BIT(1);//
  79. PORTD^=BIT(0);//
  80. contN++;
  81. }

  82. //led show
  83. void LCD_init(void)
  84. {
  85. DDRB = 0xFF;
  86. DDRC |= (1<<PC7)|(1<<PC6);//0xC0;
  87. DDRD |= (1<<PD7)|(1<<PD6);//0xD0;

  88. PORTC |=(1<< PC6);// 0x40;
  89. PORTD |= (1<< PD6);//0x40;
  90. PORTD &= ~(1<<PD7);//~0x80;
  91. }
  92. void displaynum(unsigned char row,int aa)
  93. { int at;
  94. unsigned char asi1,n;

  95. at=aa;n=1;
  96. while(at>0)
  97. {
  98. asi1=at%10+48;
  99. at/=10;
  100. disp_charNum((16-n)*8+1,row,asi1);
  101. n=n+1;
  102. }
  103. }

  104. void main(void)
  105. {
  106. unsigned int showN;
  107. float Freque_value=0.00,T=0.00;//带小数位,精确度高
  108. unsigned int Freque=0,t=0; //只显示整数,精确度低
  109. unsigned int temp=0;

  110. init_devices();
  111. disp_init();
  112. DDRA |=(1<<7) ;
  113. PORTA &=~(1<< PA7);
  114. DDRD |=(1<<0) ;
  115. //PORTD &=~(1<< PA0);

  116. disp_clear(0, 128, 0);
  117. disp_clear(0, 128, 2);
  118. disp_clear(0, 128, 4);
  119. disp_clear(0, 128, 6);

  120. while (1)
  121. {
  122. if(timerover_error==1)
  123. {
  124. //错误处理程序
  125. }
  126. temp = icpnum;
  127. Freque_value=(float)((float)1000000/(float)temp);
  128. //Freque=1000000/temp;
  129. T = (float)((float)temp/(float)1000);
  130. //t=temp/1000;
  131. displaynum(5,Freque_value);//LCD 显示数值
  132. }


  133. }

qin552011373 发表于 2013-5-9 09:41 | 显示全部楼层
好奇怪
 楼主| jsll86 发表于 2013-5-9 22:09 | 显示全部楼层
qin552011373 发表于 2013-5-9 09:41
好奇怪

是内,注释掉timer1_capt_isr就没事了
qin552011373 发表于 2013-5-10 09:43 | 显示全部楼层
jsll86 发表于 2013-5-9 22:09
是内,注释掉timer1_capt_isr就没事了

好奇怪  感觉是什么原因
 楼主| jsll86 发表于 2013-5-11 00:35 | 显示全部楼层
感觉T1的频率采集,影响了,T0的频率输出,按理说系统晶振为7.3728MHz,T0口输出1KHz的频率,应该不止于的呀
qin552011373 发表于 2013-5-11 21:34 | 显示全部楼层
jsll86 发表于 2013-5-11 00:35
感觉T1的频率采集,影响了,T0的频率输出,按理说系统晶振为7.3728MHz,T0口输出1KHz的频率,应该不止于的 ...

您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

89

帖子

0

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