ATMega8 Timer1 输入捕获(ICP)功能测试程序
来源: 芯艺工作室
本站广告
  ENC28J60+uIP DHCP动态获取IP及UDP广播服务端示例
  ENC28J60+uIP 基于TCP的MODBUS IO示例
  C720H5上实现MODBUS远程IO
  ENC28J60+uIP HTTP GET方式将温度数据上传到web服务器
  FM1702读写S50(也叫M1)卡相关资料

main.c文件:

/********************************
  ATMega8 T/C1 输入捕获(ICP)功能测试程序 
  文件名:main.c
  编译:WinAVR-20070122

  硬件环境:CA-M8X   打开的开关如下
            S6(1,2)   - 外部4MHz晶振
            另外用短路线连接PB0(ICP)和PB3(OC2)
  
  芯艺设计室 2004-2007  版权所有 
  转载请保留本注释在内的全部内容
  WEB: http://www.chipart.cn
  Email: changfutong@sina.com
*******************************/
/*
  功能描述:
    T/C2产生(从OC2口)不同的频率信号后用ICP引脚输入
    使用T/C1的输入捕获功能测其频率并发送到串行口
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdio.h>
#include <stdint.h>

uint16_t g_aTimerValue[2];    //记录两次输入捕获时的时间痕迹
uint8_t g_bTimer1Flag=0;    //timer1中断计数使能
volatile uint8_t g_bCaptureFlag=0;    //一次测量完成标记
uint8_t g_bTimer1Counter=0;  //记录两次输入捕获间定时器/计数器1产生的溢出中断次数 

//初始化标准I/O流函数,在debugprint.c中实现
extern void IoInit(void);

//延时一毫秒
void DelayMs(uint16_t t)
{
  uint16_t I;
  for(i=0;i<t;i++)
    _delay_loop_2(250*4);
}

//定时器/计数器1溢出中断
ISR(TIMER1_OVF_vect)    
{
  if(g_bTimer1Flag)
    g_bTimer1Counter++;
}

//定时器计数器输入捕获中断
//注:此版WINAVR中SIG_INPUT_CAPTURE1名字存在问题,请使用TIMER1_CAPT_vect
ISR(TIMER1_CAPT_vect)
{
  static uint8_t cnt=0;
  if(cnt==0)
  {
    g_aTimerValue[0]=ICR1;
    cnt++;
    g_bTimer1Flag=1;//timer1中断计数使能
  }
  else
  {
    cnt=0;
    g_aTimerValue[1]=ICR1;
    TIMSK &=~_BV(TICIE1);  //禁止中断
    g_bCaptureFlag=1;      //周期测量完成标记
  }
}

int main(void)
{
  uint8_t i=0;
  long  t1;
                
  PORTB = 0;          
  DDRB =  _BV(DDB3);
     
  TCCR1B = _BV(CS10);  //不分频           
  TIMSK =_BV(TOIE1);         
  IoInit();
  //t/c2从OC2(PB3)输出产生的频率, CTC模式,时钟源为系统时钟,比较匹配时OC2取反
  TCCR2=_BV(WGM21)|_BV(CS22)|_BV(COM20);  //64分频  
  IoInit();             
  sei();
  while(1) 
  {
    for(i=0;i<250;i+=5)
    {  
      OCR2=I;  //改变T/C2输出频率
      t1=(4000000/128)/(1+i);//输出频率的理论计算值
      
      printf("T/C2 输出频率为:%dHz   ",(int)t1);
      
      g_bTimer1Counter=0;      //t/c1中断次数记录值初始化
      g_bTimer1Flag=0;        //t/c1中断次数记录禁止
      
      TIMSK |=_BV(TICIE1);    //比较匹配中断使能,开始计时测量
      
      //等待两次个输入捕获中断发生
      while(g_bCaptureFlag==0);
      
      //通过中断将两次输入捕获中断时的定时器/计数器1值保存到了g_aTimerValue
      //g_bTimer1Counter为两次输入捕获中断间定时器/计数器1发生的溢出中断次数
      g_bCaptureFlag=0;
      
      if(g_bTimer1Counter==0)
      {
        t1=g_aTimerValue[1]-g_aTimerValue[0];
      }
      else
      {
        t1=0xffff * (g_bTimer1Counter-1);
        t1+=0xffff-g_aTimerValue[0];
        t1+=g_aTimerValue[1];
      }
      t1=4000000/t1;
      
      printf("ICP测量频率:%dHz\n",(int)t1);
      
      DelayMs(5000);
    }//for
  } //while          
}

debugprint.c文件:

/********************************
  UART初始化并设置标准I/O流
  文件名:debugprint.c
  编译:WinAVR-20070122

  硬件:CA-M8X  
  
  芯艺设计室 2004-2007  版权所有 
  转载请保留本注释在内的全部内容
  WEB: http://www.chipart.cn
  Email: changfutong@sina.com
*******************************/

#include <avr/io.h>
#include <stdio.h>

static int uart_putchar(char c, FILE *stream);
static int uart_getchar(FILE *stream);

static FILE mystd = FDEV_SETUP_STREAM(uart_putchar, uart_getchar,_FDEV_SETUP_RW);

static int uart_putchar(char c, FILE *stream)
{
  if (c == '\n')
    uart_putchar('\r', stream);
  loop_until_bit_is_set(UCSRA, UDRE);
  UDR = c;
  return 0;
}

static int uart_getchar( FILE *stream)
{
  loop_until_bit_is_set(UCSRA,RXC);
  return UDR;
}

//接口函数
void IoInit(void)
{
  //初始化uart,查询方式读写
  UCSRB=_BV(RXEN)|_BV(TXEN);/*(1<<RXCIE)|(1<<TXCIE)|*/
  UBRRL=25;  //9600 baud 4MHz:25  
  
  stdout=&mystd;
  stdin=&mystd;
}

执行效果:

连接图:



声明:芯艺工作室(http://www.chipart.cn)保留所有权力,转载请注明出处!

芯艺工作室    蒙ICP备06005492号

Copyright© 2004-2020 ChipArt Studio All Rights Reserved