ATTiny1616-SNR频率测量/输入捕获

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

提示:本次使用ATTINY1616-SNR作为核心控制器,裸片测试

近期需要使用AT系列的一款单片机,用与特定频率信号的测量记录一下上手这款单片机的一个过程,主要使用了该单片机的串口功能、PWM波生成功能、定时器模块、事件管理系统以及实时定时器。
主流程为:使用pwm生成模块生成固定频率的方波,接入芯片的事件触发引脚,触发对应的事件中断,记录对应的定时器的计数值,利用计数器的记录值结合系统主频反推出信号的频率,在RTC模块中设置1s的定时器,通过串口将所测得的频率信息打印出来。
工程文件与芯片手册资源


提示:以下是本篇文章正文内容,思路仅供参考,有不足之处还望大家匹配指正

一、开发环境

使用Atmel公司的Microchip Studio作为本次的开发环境,芯片ATTINY1616-SNR,仿真器Atmel-ICE。

二、初始化

1.图形化初始化

图形化初始化网站
首页
点击create创建一个新的工程
选型
选择对应的型号,并选择对应的外设,本次使用到PWM1、Event System1、RTC1、Usart1、Timer*1配置完成之后点击右下角Create
配置
整个工程框架如下图所示
框架
主时钟树如下图所示
时钟树
配置波形生成模块作为本次测量频率的输入
PWM生成
生成波形的输出频率≈主时钟频率/(Value_Top)由引脚PB0输出–(本次主频20M按上图所配置的频率约为20KHz 占空比约50%)
对输入捕获定时器功能进行配置,选用其频率测量功能
定时器配置
事件系统的配置,首先需要配置对应的引脚
事件系统
内部链接
事件内部链接
配置串口
串口
配置实时时钟产生1s的定时中断,用于串口数据的打印
实时时钟配置
开启全局使能
全局使能
配置完成之后点击Export Project生成所配置的工程
生成工程
至此完成所有功能的配置

2.功能实现

中断服务函数application_isr.c:

/*
 * application_isr.c
 *
 * Created: 2022-04-07 17:00:23
 *  Author: dell
 */ 
#include <atmel_start.h>
#include "application_isr.h"

extern uint8_t  rtcFlag;
extern uint32_t periodSum;
extern uint32_t pulseWidthSum;
extern uint8_t  samplescount;

/**
 * **********************************************************
 *  ISR

    For every one second RTC interrupt is generated
 * **********************************************************
 **/
ISR(RTC_PIT_vect)
{
	/* Insert your PIT interrupt handling code here */

	rtcFlag = 1;

	/* The interrupt flag has to be cleared manually */
	RTC.PITINTFLAGS = RTC_PI_bm;
}

/**
 * *********************************************************************************
 *  ISR

    Capture Interrupt is generated for every one period measurement of the signal
 * *********************************************************************************
 **/

ISR(TCB0_INT_vect)
{

	if (samplescount < MAXSAMPLES_COUNT) {
		pulseWidthSum += TCB0.CCMP;

		periodSum += TCB0.CNT;

		samplescount = samplescount + 1;
	} else {
		// no operation
	}

	TCB0.INTFLAGS = TCB_CAPT_bm;
}

该函数中用于处理中断所产生的请求以及计数器值的捕获。
应用功能函数application.c

/*
 * application.c
 *
 * Created: 2022-04-07 16:57:22
 *  Author: Zxy
 */ 
/**
 * **********************************************************
 *  Macros definitions
 * **********************************************************
 **/

#include <atmel_start.h>
#include <stdio.h>
#include "application.h"

#define F_CPU 20000000

volatile uint8_t rtcFlag;
volatile uint8_t samplescount = 0;

volatile uint32_t periodAfterCapture        = 0;
volatile uint32_t pulseWidthAfterCapture    = 0;
volatile uint32_t periodAfterCaptureAvg     = 0;
volatile uint32_t pulseWidthAfterCaptureAvg = 0;
volatile uint32_t periodSum                 = 0;
volatile uint32_t pulseWidthSum             = 0;

volatile uint32_t captureDuty      = 0;
volatile uint32_t captureFrequency = 0;

uint8_t buffer[60];

/**
  @Param
  none
  @Returns
   none
  @Description
  function to transmit a data on terminal window
  **/
void SendString(const char *data)
{
	uint8_t i = 0;
	for (i = 0; data[i] != '\0'; i++) {
		// sending the data through EUSART2 peripheral
		USART_0_write(data[i]);
	}
}

/**
  @Param
  none
  @Returns
   none
  @Description
  This function measures Frequency and Duty cycle of the input signal given by signal measurement
  **/
void FrequencyAndDutycycleMeasurement(void)
{
	uint8_t decValue = 0;

	if (samplescount == MAXSAMPLES_COUNT) {
		// Sum of period and pulse width samples value of input signal
		// is copied to perioAfterCapture and pulseWidthAfterCature variable
		periodAfterCapture     = periodSum;
		pulseWidthAfterCapture = pulseWidthSum;

		// Averaging of the samples
		periodAfterCaptureAvg     = (periodAfterCapture / MAXSAMPLES_COUNT);
		pulseWidthAfterCaptureAvg = (pulseWidthAfterCapture / MAXSAMPLES_COUNT);

		// Using formula to calculate the Frequency and Duty cycle of the signal
		//captureDuty      = ((pulseWidthAfterCaptureAvg * 100L) / periodAfterCaptureAvg);
		captureFrequency = (F_CPU / pulseWidthAfterCaptureAvg);

		periodSum     = 0;
		pulseWidthSum = 0;
		samplescount  = 0;
	}

	// If condition is executed for every one second of the RTC interrupt
	if (rtcFlag == 1) {
		//decValue = (captureDuty % MAXSAMPLES_COUNT);
		// Prints measured Frequency and Duty cycle of the signal on terminal window.
		//sprintf(buffer, "Duty cycle=%lu.%d%% \r\nFrequency=%luHz\r\n\n", captureDuty, decValue, captureFrequency);
		sprintf(buffer, "Frequency=%luHz\r\n\n" ,captureFrequency);
		SendString(buffer);
		rtcFlag          = 0;
		captureDuty      = 0;
		captureFrequency = 0;
	}
}

主函数main.c

#include <atmel_start.h>
#include <stdio.h>
#include "application.h"
int main(void)
{
	/* Initializes MCU, drivers and middleware */
	atmel_start_init();

	/* Replace with your application code */
	while (1) {
		FrequencyAndDutycycleMeasurement();
	}
}

3.实验结果

首先看一下PWM模块所产生的波形
20K波形
对应的串口输出串口输出
可以看到串口打印为20khz
利用信号发生器更换频率
输入
信号发生器的输入
示波器显示
串口信息的反馈
反馈


总结

至此完成整个频率计的设计过程,随着频率的不断提高计算的频率精度会有一定程度的下降,可以进行一定的补偿来弥补。

  • 15
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 25
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 25
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱神的箭呵呵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值