//频率记范围:
//外部晶振 时钟间隔 周期 频率
// (4M) 1/1--0.25us 0.25us~16384us 61HZ~4MHZ
// 1/2--0.5us 0.5us~32768us 30HZ~2MHZ
// 1/4--1us 1us~65535us 15HZ~1MHZ
// 1/8--2us 2us~131070us 8HZ~0.5MHZ
//程序分类:用户电路板功能模块
//程序功能:信号周期测量,定时法
//待测试信号从 P1.0 管脚引入
//测量结果用 lcd1602显示
//显示格式:5 位有效数字( 10 进制,单位 us )
//待测信号的幅度(峰峰值)必须是4V以上
//待测信号的周期范围是 65535us--1us 频率范围是 15HZ---1MHZ
#include <msp430x14x.h>
typedef unsigned char uchar;
typedef unsigned int uint;
uchar ShuZi[10]={'0','1','2','3','4','5','6','7','8','9'};
uchar function; //声明功能变量
uchar fun_0,fun_1,fun_2,fun_3; //声明功能参数变量
//分别存储输出信号周期从个位到千位的 4 位数值
#define DataDir P4DIR
#define DataPort P4OUT
#define Busy 0x80
#define CtrlDir P3DIR
#define CLR_RS P3OUT&=~BIT0; //RS=P3.0
#define SET_RS P3OUT|=BIT0;
#define CLR_RW P3OUT&=~BIT1; //RW=P3.1
#define SET_RW P3OUT|=BIT1;
#define CLR_EN P3OUT&=~BIT2; //EN=P3.2
#define SET_EN P3OUT|=BIT2;
void DispNChar(uchar x,uchar y,uchar n,uchar *ptr);
void DispStr(uchar x,uchar y,uchar *ptr);
void LocateXY(uchar x,uchar y);
void Disp1Char(uchar x,uchar y,uchar data);
void LcdReset();
void LcdWriteCommand(uchar cmd,uchar chk);
void LcdWriteData(uchar data);
void WaitForEnable();
void Delay5ms(void);
void delay_1s(void); //声明延时 1s 函数
void int_clk(void);
//*************************
//功能:让液晶从某个位置起连续显示一个字符串
//x--位置列坐标,y--位置行坐标,ptr--指向字符串存放位置指针
void DispStr(uchar x,uchar y,uchar *ptr)
{
uchar *temp;
uchar i,n=0;
temp=ptr;
while(*ptr++!='\0') //计算字符串有效字符的个数
n++;
for(i=0;i<n;i++)
{
Disp1Char(x++,y,temp[i]);
if(x==0x0f)
{
x=0;
y^=1;
}
}
}
//*************************
//功能:让液晶从某个位置起连续显示N个字符
//x--位置列坐标,y--位置行坐标,ptr--指向字符串存放位置指针,n--字符个数
void DispNChar(uchar x,uchar y,uchar n,uchar *ptr)
{
uchar i;
for(i=0;i<n;i++)
{
Disp1Char(x++,y,ptr[i]);
if(x==0x0f)
{
x=0;
y^=1;
}
}
}
//*************************
//功能:向液晶输入显示字符位置的坐标信息
void LocateXY(uchar x,uchar y)
{
uchar temp;
temp=x&0x0f;
y&=0x01;
if(y) //如果在第二行
temp|=0x40;
temp|=0x80;
LcdWriteCommand(temp,1);
}
//*************************
//功能:在某个位置显示一个字符
void Disp1Char(uchar x,uchar y,uchar data)
{
LocateXY(x,y);
LcdWriteData(data);
}
//*************************
//功能:对液晶模块进行复位操作
void LcdReset(void)
{
CtrlDir|=0x07;
DataDir =0xFF;
LcdWriteCommand(0x38,0);//规定复位操作
Delay5ms();
LcdWriteCommand(0x38,0);
Delay5ms();
LcdWriteCommand(0x38,0);
Delay5ms();
LcdWriteCommand(0x38,1);//显示模式设置
LcdWriteCommand(0x08,1);//显示关闭
LcdWriteCommand(0x01,1);//显示清屏
LcdWriteCommand(0x06,1);//写字符时整体不移动
LcdWriteCommand(0x0c,1);//显示开,不开游标,不闪烁
}
//*************************
//功能:向液晶写入命令 cma--命令,chk__是否判忙标志1:判忙,0:不判
void LcdWriteCommand(uchar cmd,uchar chk)
{
if(chk)
WaitForEnable();
CLR_RS ;
CLR_RW;
_NOP();
DataPort=cmd;//将命令写入数据端
_NOP();
SET_EN;
_NOP();
_NOP();
CLR_EN;
}
//*************************
//功能:向液晶显示的当前地址写入数据
void LcdWriteData(uchar data)
{
WaitForEnable();//等待液晶不忙
SET_RS;
CLR_RW;
_NOP();
DataPort=data;
_NOP();
SET_EN;
_NOP();
_NOP();
CLR_EN;
}
//*************************
//功能:等待液晶完成内部操作
void WaitForEnable(void)
{
P4DIR &= 0X00;//将p4口切换为输入状态
CLR_RS;
SET_RW;
_NOP();
SET_EN;
_NOP();
_NOP();
while ((P4IN&Busy)!=0);//检测忙标志
CLR_EN;
P4DIR |= 0XFF;//将p4口切换为输出状态
}
void Delay5ms(void)
{
uint i=40000;
while(i!=0)
{
i--;
}
}
void Lcd1602(uchar flag,uchar fun_4,uchar fun_3,uchar fun_2,uchar fun_1,uchar fun_0)
{
WDTCTL = WDT_ADLY_250;
LcdReset();
if(flag)
{
DispStr(0,0,"ZhouQi:");
Disp1Char(0x08,0x00,ShuZi[fun_4]);
Disp1Char(0x09,0x00,ShuZi[fun_3]);
Disp1Char(0x0a,0x00,ShuZi[fun_2]);
Disp1Char(0x0b,0x00,ShuZi[fun_1]);
Disp1Char(0x0c,0x00,ShuZi[fun_0]);
DispStr(0x0d,0x00,"us");
}
else
{
DispStr(0,1,"Function:");
Disp1Char(0x0a,0x01,ShuZi[fun_4]);
Disp1Char(0x0b,0x01,ShuZi[fun_3]);
Disp1Char(0x0c,0x01,ShuZi[fun_2]);
Disp1Char(0x0d,0x01,ShuZi[fun_1]);
Disp1Char(0x0e,0x01,ShuZi[fun_0]);
}
}
void main(void) //主函数
{
uint data,wanwei,thousand,hundred,ten,zero;
WDTCTL=WDTPW+WDTHOLD; //关闭看门狗
//看门狗控制寄存器 WDTCTL 地址以及密码位 WDTPW 内容和
//使能位 WDTHOLD 内容在头函数 MSP430x16x.h 定义
// WDTPW 内容加 WDTHOLD 内容向 WDTCTL 赋值
int_clk( ); //系统时钟初始化
P1SEL&=~BIT0; // P4.0 设置为 IO 管脚,作为待测信号输入管脚
P1DIR&=~BIT0; // P4.0 设置为输入管脚
P3SEL=0x00; //设置 P3 端口为数字输入 / 输出口
P3DIR=0xff; //设置 P3 端口为输出口
Lcd1602(1,0x00,0x00,0x00,0x00,0x00);
delay_1s( ); //延时 1s,保证结果显示稳定
while(1) //重复执行
{
//开始信号周期测量
TACTL|=TACLR; //定时计数器 TAR 清零,定时控制寄存器 TACTL 清零
TACTL|=TASSEL1+ID1; //定时器时钟:SMCLK,参见 int_clk,系统时钟 XT2,SMCLK 时钟源为 XT2,分频比 1
//时钟分频:4,使得当 SMCLK 频率为 4MHz 时计数周期为 1us
//停止模式
TACCR0=0xfffe; //计数器计数周期 0xffff,
//当计数周期为 1us,在保证测量结果为 4 位 10 进制有效数字情况下
//测量信号周期范围为 1000us 到 9999us
// 频率范围为 100Hz 到 1000Hz
while((P1IN&0x01)!=0) //当 P1.0 待测信号输入管脚为高电平,等待信号前沿
{
}
while((P1IN&0x01)==0) //当 P1.0 待测信号输入管脚为低电平,等待信号前沿
{
}
TACTL|=MC0; //信号前沿到来,启动定时器,工作在增加模式
while((P1IN&0x01)!=0) //当 P1.0 待测信号输入管脚为高电平
{
//定时器继续计数,完成信号高电平持续时间测量
}
while((P1IN&0x01)==0) //当 P1.0 待测信号输入管脚为低电平
{
//定时器继续计数,完成信号低电平持续时间测量
}
TACTL&=~MC0; //工作模式由增加模式转换为停止模式,关闭定时器
data=TAR;
wanwei=data/10000; //读取定时器计数结果
thousand=data%10000/1000; //信号周期数据位分解
hundred=data%1000/100;
ten=data%100/10;
zero=data%10;
Lcd1602(1,wanwei,thousand,hundred,ten,zero);
//显示格式:4 位有效数字( 10 进制,单位 us )
delay_1s( ); //延时 1s,保证结果显示稳定
}