|
#include <msp430x14x.h>
#include "config.h"
uint k=0,flag=0,overflow = 0; //溢出次数
ulong fre,period_star=0,period=0,freH =0,temp=0;//频率值,中间变量
float freL;
float multi=0;
uchar unitL[]="Hz",unitH[]="kHz",a[]; //存放字符
uchar *x={'\0'},*unit={'\0'};
int i,point,len=0;
//*************************************************************************
// 初始化IO口子程序
//*************************************************************************
void Port_Init()
{
LCD_DATASEL = 0X00; //(P4)LCD的D7-D0端口普通IO模式,输出模式
LCD_DATADIR = 0XFF;
LCD_CONSEL = 0X00; //(P5)LCD的控制管脚普通IO模式
LCD_CONDIR |= BIT0 + BIT1 + BIT5 + BIT6 + BIT7; //(P5)LCD控制管脚0(PSB)、1(RST)、5(RS)、6(RW)、7(EC)置1输出模式
PSB_SET; //LCD串并脚PSB置高,并口方式
RST_SET; //LCD复位脚RST置高,复位
LED8DIR = 0xff; //设置LED指示灯
LED8 = 0xFF;
}
//***********************************************************************
// 显示屏命令写入函数
//***********************************************************************
void LCD_write_com(unsigned char com)
{
RS_CLR; //LCD的RS和RW置0,在EN下降沿时,指令从端口写入
RW_CLR;
EN_SET;
LCD_DATAPORT = com;
delay_ms(5);
EN_CLR;
}
//***********************************************************************
// 显示屏数据写入函数
//***********************************************************************
void LCD_write_data(unsigned char data)
{
RS_SET; //LCD的RS置1,RW置0,在EN下降沿时,数据从端口写入
RW_CLR;
EN_SET;
LCD_DATAPORT = data;
delay_ms(5);
EN_CLR;
}
//***********************************************************************
// 显示屏清空显示
//***********************************************************************
void LCD_clear(void)
{
LCD_write_com(0x01);
delay_ms(5);
}
//***********************************************************************
//函数名称:DisplayCgrom(uchar hz)显示CGROM里的汉字
//***********************************************************************
void DisplayCgrom(uchar addr,uchar *hz)
{
LCD_write_com(addr); //写入地址
delay_ms(5);
while(*hz != '\0')
{
LCD_write_data(*hz); //写入数据
hz++;
delay_ms(1);
}
}
//****************************************************************
//函数名称:Display()显示测试结果
//****************************************************************
void Display(void)
{
DisplayCgrom(0x80,"当前信号频率为:");
DisplayCgrom(0x88,x);
DisplayCgrom(0x8d,unit);
}
//***********************************************************************
// 显示屏初始化函数
//***********************************************************************
void LCD_init(void)
{
LCD_write_com(FUN_MODE); //工作模式:8位基本指令集
delay_ms(5);
LCD_write_com(DISPLAY_ON); //显示开,显示游标,且游标位置反白
delay_ms(5);
LCD_clear(); //清屏
delay_ms(5);
}
//***********************************************************************
// TIMERA初始化,用比较寄存器0,设置为增计数,阈值60000
//***********************************************************************
void TIMERA0_Init(void)
{
P1SEL |= BIT0; //计时器时钟为TACLK,在P1.0,将其设为第二功能,输入模式
P1DIR &= ~BIT0;
TACTL = TACLR;
TACCR0 = 60000-1; //寄存器0比较模式,阈值60000
TACCTL0 |= CCIE;
TACTL = MC0; //TACLK做时钟源,增计数模式
//P6OUT &= ~BIT0 ;
}
//***********************************************************************
// TIMERA初始化,用捕获寄存器1,设置为连续计数
//***********************************************************************
void TIMERA1_Init(void)
{
P1SEL |= BIT2; //捕获寄存器的捕获管脚在P1.2
P1DIR &= ~BIT2;
TACTL = TACLR;
TACCTL1 |= CM0 + SCS + CAP + CCIE; //寄存器1捕获模式,上升沿,CCIxA,同步
TACTL |=TASSEL0 + MC1 + TAIE;
}
//***********************************************************************
// 寄存器0中断服务程序,计数器达到60000将溢出次数+1
//***********************************************************************
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A0 (void)
{
overflow=overflow+1;
}
//***********************************************************************
// 寄存器1中断服务程序,达到捕获条件
//***********************************************************************
#pragma vector=TIMERA1_VECTOR
__interrupt void Timer_A1 (void)
{
switch(TAIV)
{
case 2:
{
k++;
if(k==1) period_star = 60000*overflow + TACCR1;
else if (k==2)
{
period = 60000*overflow + TACCR1-period_star;
freL=multi*32768/period;
temp=(ulong)freL; //计算长度
len=0;
while(temp)
{
len++;
temp/=10;
}
if (len<4) {len=4;point++;temp =(ulong)(10*freL);}
else {temp=(ulong)freL;}
for (i=len;i>=0;i--) //存入指针中
{
if(i!=(len-point))
{
a[i]=temp%10+48;
temp=temp/10;
}
else
{
a[i]='.';
}
}
a[len+1]='\0';
x=a;
}
}break;
case 4:break;
case 10:
{
overflow++;
break;
}
default:break;
}
}
//***********************************************************************
// WDT中断服务程序,1s时间到,计算频率,并转换成字符
//***********************************************************************
#pragma vector=WDT_VECTOR
__interrupt void watchdog_timer(void)
{
flag++;
if(flag==2)
{
WDT_Init(); //5s到,关看门狗
P6OUT &= ~BIT7; //LED8亮作为提示
P6OUT |= BIT0;
freH=TAR+overflow*60000; //计算频率(此时是5倍的值,因为看门狗走了五秒)
//判断频率的精度和位数
if (freH<20) { point=3;unit=unitL;multi=1000;} //频率在10Hz 以内
else if (freH<200) { point=2;unit=unitL;multi=100; } //频率在10-100Hz 之间
else if (freH<2000) { point=1;unit=unitL;multi=10; } //频率在100-1kHz 之间
else if (freH<4000) { point=3;unit=unitH;multi=1; } //频率在1k-2kHz 之间
else if (freH<20000) { point=4;unit=unitH; } //频率在2-10kHz 之间
else if (freH<200000) { point=4;unit=unitH; } //频率在10k-100k 之间
else if (freH<2000000) { point=4;unit=unitH; } //频率在100k-1MHz之间
//判断频率高低频,高频脉冲测量输出,低频重新用周期法捕获测量
if (freH>10000)
{
fre=5*freH; //得到10倍频率
//将测出来的数值转换成字符
temp=fre; //计算长度
len=0;
while(temp)
{
len++;
temp/=10;
}
for (i=len;i>=0;i--) //存入指针中
{
if(i!=(len-point))
{
a[i]=fre%10+48;
fre=fre/10;
}
else
{
a[i]='.';
}
}
a[len+1]='\0';
x=a;
}
else
{
TIMERA1_Init();
_EINT();
}
}
}
//***********************************************************************
// 主程序
//***********************************************************************
int main(void)
{
WDT_Init(); //关闭看门狗
Clock_Init_Ex32768(); //系统时钟设置8M
Port_Init(); //LCD端口初始化
delay_ms(100); //延时100ms
LCD_init(); //液晶参数初始化设置
LCD_clear(); //清屏
TIMERA0_Init(); //比较寄存器0初始化
IE1 |= WDTIE; //打开开门狗中断,全局中断
_EINT();
WDTCTL = WDT_ADLY_1000; //看门狗计时1s
DisplayCgrom(0x80,"信号频率测量中");
DisplayCgrom(0x88,"请稍等...");
delay_ms(3000);
LCD_clear();
delay_ms(200);
while(1)
{
Display(); //显示汉字
/*//重新启动
delay_ms(1000);
overflow = 0;
TIMERA0_Init();
IE1 |= WDTIE; //打开开门狗中断,全局中断
_EINT();
WDTCTL = WDT_ADLY_1000;*/
}
}
|
|