1、主函数部分:
/*
* Author: 余裕鑫
* function:测量信号的频率和占空比,信号输入管脚为P2.1.串口打印输出信息。
* 串口:9600,无校验位,8位数据位,1位停止位
* Created on: 2018年5月2日
*注意:测频率和占空比采用分别是测量一个周期和高电平期间的时钟个数,故适合于低频部分的频率和占空比的测量
* 当频率高于100Hz时,误差逐渐增大,
* 100Hz时,误差约为1%,1Hz
* 1000Hz时,误差约为1.5%,15Hz
* 10000Hz时,误差约为0.37%,37Hz
* 20000Hz时,误差约为2%,199Hz
* 30000Hz时,误差约为6.5%,650Hz
*/
#include <msp430g2553.h>
#include "stdio.h"
#include "pwminput.h"
#include "uart.h"
#include "datatype.h"
extern volatile u16 Frequency;
extern volatile u8 Duty;
extern volatile u16 PeakValue;
float PeakValueF;
/**
* main.c
*/
void main(void)
{
unsigned char str[20];
WDTCTL = WDTPW + WDTHOLD; // stop watchdog timer
// 将MCLK 和 SMCLK 设置为16MHZ,ACLK默认为32.768KHz
DCOCTL = CALDCO_16MHZ;
BCSCTL1 = CALBC1_16MHZ; //使用高频时钟而减小误差
_EINT();
UART_Init();
sprintf(str,"frequency and duty:\n");
UARTSendString(str);
while(1)
{
Measure_Frequency_Duty();
sprintf(str,"Frequency : %d \n",Frequency);
UARTSendString(str);
sprintf(str,"Duty : %d \n",Duty);
UARTSendString(str);
// Measure_Peak_Value();
// PeakValueF = PeakValue*3.6/1024;
// sprintf(str,"Peak Value : %0.2f \n",PeakValueF);
// UARTSendString(str);
__delay_cycles(50000000);
}
}
2、C文件部分:
/*
* pwminput.c
*
* Created on: 2018年4月23日
* Author: yyx
*/
#include "pwminput.h"
#include "adc.h"
#define T0C1A P1DIR&=~BIT2;P1SEL|=BIT2;P1SEL2&=~BIT2
#define T1C0A P2DIR&=~BIT0;P2SEL|=BIT0;P2SEL2&=~BIT0
#define T1C1A P2DIR&=~BIT1;P2SEL|=BIT1;P2SEL2&=~BIT1
#define SAMPLETIMES 10 //测峰峰值中一个周期采样的次数
#define SAMPLEPERIODS 5 //测一次峰峰值中采样的周期个数
u8 FreqFlag = 0;
u16 PwmStart;//初始时间
u16 PwmHighEnd,PwmLowEnd;//高电平和低电平的结束时间
u16 HighOverFlow,AllOverFlow; //高电平和一个周期的翻转个数
u32 HighClockSteps,AllClockSteps;
u16 PeakIntervalSteps;
volatile u16 Frequency;
volatile u8 Duty;
volatile u16 PeakValue;
extern volatile u16 ADC10_Result;
u8 SampleStatus;
//频率占空比测量函数
void Measure_Frequency_Duty(void)
{
T1C1A; //管脚配置p2.1
FreqFlag=1; //频率测量中断标志
TA1CCTL1 = CAP+CM_1+CCIS_0+SCS+CCIE; // 输入捕捉,上升沿触发(upCM_1,downCM_2,updownCM_3),同步捕捉,CCI0A 中断使能
TA1CTL = TASSEL_2 + MC_2 + TAIE + TACLR; // 选择SMCLK为时钟,连续计数模式 ,溢出中断使能
while(FreqFlag);
if(PwmHighEnd>PwmStart)
{
HighClockSteps=(HighOverFlow-1)*65536+PwmHighEnd-PwmStart;
}else
{
HighClockSteps=(HighOverFlow-1)*65536+PwmHighEnd+65536-PwmStart;
}
if(PwmLowEnd>PwmStart)
{
AllClockSteps=(AllOverFlow-1)*65536+PwmLowEnd-PwmStart;
}else
{
AllClockSteps=(AllOverFlow-1)*65536+PwmLowEnd+65536-PwmStart;
}
if(AllClockSteps)
{
PeakIntervalSteps = (u16)AllClockSteps/SAMPLETIMES; //测峰峰值中以10倍频率进行采样
}
Frequency = 16000000/AllClockSteps;
Duty = HighClockSteps*100.0/AllClockSteps;
}
/*
* 功能:测P1.3管脚信号的峰峰值
* */
void Measure_Peak_Value(void)
{
if(PeakIntervalSteps) //如果采样间隔不为0
{
//使用TimerA1的计数模式,
TA1CTL |= TACLR; //定时器清零
TA1CTL |= TASSEL_2+ MC_1+ID_0; //SMCLK(16MHz),1分频,上数模式
//定时器开始计数从0到CCR0
TA1CCR0 = PeakIntervalSteps; //十分之一个周期中断一次
TA1CCTL0=CCIE; //使能中断
ADC10_Init(3); // 初始化ADC
SampleStatus = SAMPLEPERIODS;
while(SampleStatus);
}
}
#pragma vector = TIMER1_A0_VECTOR
__interrupt void TimerA1_ISR(void)
{
_DINT();
static u16 PeriodValue[2*SAMPLETIMES],MaxValue[SAMPLEPERIODS+1],MinValue[SAMPLEPERIODS+1];
u32 MaxSum,MinSum;
static u8 i;
u8 j;
if(SampleStatus)
{
if(i<2*SAMPLETIMES)
{
ADC10_Start_Convey();
PeriodValue[i++] = ADC10_Result;
}
if(i==2*SAMPLETIMES)
{
i=0;
MaxValue[SampleStatus]=MinValue[SampleStatus]=PeriodValue[0];//初始化最值
for(j=0;j<2*SAMPLETIMES;j++)
{
if(PeriodValue[j]>MaxValue[SampleStatus])MaxValue[SampleStatus]=PeriodValue[j];
if(PeriodValue[j]<MinValue[SampleStatus])MinValue[SampleStatus]=PeriodValue[j];
}
SampleStatus--; //测量的周期次数减1
if(SampleStatus==0)//如果采样完成
{
for(j=1;j<=SAMPLEPERIODS;j++)
{
MaxSum+=MaxValue[j];
MinSum+=MinValue[j];
}
PeakValue=(u16)(MaxSum-MinSum)/SAMPLEPERIODS;
MaxSum=MinSum=0;
}
}
}
_EINT();
}
#pragma vector = TIMER1_A1_VECTOR
__interrupt void TimerA1_Capture_ISR(void)
{
_DINT(); //关闭中断,
switch(TA1IV)//向量查询
{
case 2: //捕获中断,CCR1
if(FreqFlag)
{
static u8 index;
if((TA1CCTL1&CM0)&&(index==0)) //第一次上升沿
{
TA1CCTL1|=CM_2;//更变为下降沿触发
PwmStart=TA1R;//记录初始时间
HighOverFlow = AllOverFlow = 0; //溢出计数变量复位
PwmHighEnd=PwmLowEnd=0;
index=(index+1)%3;
}
else if((TA1CCTL1&CM1)&&(index==1))//下降沿
{
TA1CCTL1|=CM_1;//更改设置为上升沿触发
HighOverFlow = AllOverFlow;
PwmHighEnd = TA1R; //记录高电平结束时间
index=(index+1)%3;
}else if((TA1CCTL1&CM0)&&(index==2)) //第二次上升沿
{
//测完一个周期,等待下一个上升沿
PwmLowEnd = TA1R;
FreqFlag = 0;
index=(index+1)%3;
}
}
break;
case 4:break;//CCR2
case 10:
{
if(FreqFlag)
{
AllOverFlow++;
TA1CTL &= ~TAIFG;
}
break;
}
default: break;
}
_EINT(); //打开中断
}
3、头文件部分:
/*
* pwminput.h
*
* Created on: 2018年4月23日
* Author: yyx
*/
#ifndef PWMINPUT_H_
#define PWMINPUT_H_
#include <msp430g2553.h>
#include "datatype.h"
void Measure_Frequency_Duty(void);
void Measure_Peak_Value(void);
#endif /* SRC_PWMINPUT_H_ */
4、其中涉及的相关辅助型文件
①、ADC
/* * adc.c * * Created on: 2018年5月2日 * Author: yyx */ #include "adc.h" volatile u16 ADC10_Result; /** * 功能:ADC10初始化函数 * 参数: * pin:选择模拟输入的管脚,取值为0-7,对应P1.0到P1.7 * */ void ADC10_Init(u8 pin) { ADC10CTL0 |= ADC10SHT_2 + ADC10ON; //打开ADC10,并设置为16个ADC时钟 ADC10CTL0 |= ADC10IE; ADC10CTL1 |= ADC10SSEL_3; switch(pin) { case 3: ADC10CTL1 |= INCH_3; ADC10AE0 |= BIT3; P1DIR &= ~BIT3; break; default:break; } } /* * adc.h * * Created on: 2018年5月2日 * Author: yyx */ #ifndef SRC_ADC_H_ #define SRC_ADC_H_ #include "msp430g2553.h" #include "datatype.h" void ADC10_Init(u8 pin); void ADC10_Start_Convey(void); #endif /* ADC_H_ */ void ADC10_Start_Convey(void) { ADC10CTL0 |=ENC + ADC10SC; //开始转换 } #pragma vector = ADC10_VECTOR __interrupt void ADC10_ISR(void) { _DINT(); //关总中断 ADC10_Result = ADC10MEM; ADC10CTL0 &= ~ADC10SC; //结束转换 _EINT(); //开总中断 }
②、uart
/*
* uart.c
*
* Created on: 2018年4月22日
* Author: yyx
*/
#include "uart.h"
void UART_Init()
{
P1SEL |= BIT1 + BIT2;
P1SEL2 |= BIT1 + BIT2; //将p1.1和p1.2选为UART模式
P1DIR &= ~BIT1;
P1DIR |= BIT2;
UCA0CTL1 |= UCSSEL_2; //SMCLK
UCA0BR1 = 1666/256; //高8位
UCA0BR0 = 1666%256;
UCA0MCTL |= UCBRS_6 + UCBRF_0; //设置波特率为9600
UCA0CTL1 &= ~UCSWRST; //开始运行
// IE2 |= UCA0RXIE+UCA0TXIE; //使能中断
}
/********************************************************************
*
*******************************************************************/
void UARTSendChar(char ch)
{
if(ch == '\n')
{
while(UCA0STAT & UCBUSY);
UCA0TXBUF = '\r';
}
while(UCA0STAT & UCBUSY);
UCA0TXBUF = ch;
}
/********************************************************************
*
*******************************************************************/
void UARTSendString(char *pt)
{
UART_Init();
while(UCA0STAT & UCBUSY);
while(*pt)
{
UARTSendChar(*pt++);
}
}
/*
* uart.h
*
* Created on: 2018年4月22日
* Author: yyx
*/
#ifndef SRC_UART_H_
#define SRC_UART_H_
#include <msp430g2553.h>
void UART_Init(void);
void UARTSendChar(char ch);
void UARTSendString(char *pt);
#endif /* SRC_UART_H_ */
③、数据类型的重定义
/*
* datatype.h
*
* Created on: 2018年5月1日
* Author: yyx
*/
#ifndef SRC_DATATYPE_H_
#define SRC_DATATYPE_H_
typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;
#endif /* DATATYPE_H_ */