单片机的课程设计NO.1
项目功能
测量正弦信号源的信号频率,并用LCD1062显示
项目代码
#include<reg51.h>
#include<intrins.h>
#include<string.h>
#define uchar unsigned char
#define uint unsigned int
#define correct 1950 //计时器修正值
sbit TEXT = P1^0;
uchar TimeH = (65536 - 50000 +correct)/256; //数码管刷新间隔
uchar TimeL = (65536 - 50000 +correct)%256;
unsigned long int Frequency=0; //Frequency频率,Counter计数器
uchar a[]="0,000,000",b[]="Ready!",c[]="Frequency:",m[]="Measureing...",z[]="0,000,000";
bit renovate_frequency_flag=0; //刷新频率值的标志位
bit show_m_flag=0;
void send(uchar *s);
/*LCD显示函数*/
#define out P2
sbit RS = P1^5; //LCD1602寄存器选择
sbit RW = P1^6; //LCD1602读写操作选择
sbit E = P1^7; //LCD1602使能信号
void lcd_initial(void); //LCD初始化函数
void check_busy(void); //检查忙标志函数
void write_command(uchar com); //写命令函数
void write_data(uchar dat); //写数据函数
void string(uchar ad,uchar *s); //显示字符串函数
void delay(uint j);
/*以上*/
void main( )
{
lcd_initial();
TMOD = 0X21;
TH1 = 0XFD; //波特率9600
TL1 = 0XFD;
SCON = 0X50;
PCON = 0X00;
TR1 = 1; //接通T1
EA = 1; //总中断开
ET0 = 1; //T0中断开
EX1 = 1; //外部中断1开
IT0 = 1; //外部中断0下降沿触发
IT1 = 1; //外部中断1下降沿触发
ES = 1; //串口中断开
string(0x80,b);
while(1)
{
if(show_m_flag)
{
write_command(0x01); //清屏
string(0x80,m);
show_m_flag=0;
}
if(renovate_frequency_flag)
{
Frequency *= 10;
strcpy(a,z);
a[0] += (Frequency/1000000)%10;
a[2] += (Frequency/100000)%10;
a[3] += (Frequency/10000)%10;
a[4] += (Frequency/1000)%10;
a[6] += (Frequency/100)%10;
a[7] += (Frequency/10)%10;
renovate_frequency_flag=0;
write_command(0x01); //清屏
string(0x80,c);
string(0xc0,a);
TI=1;
} //对频率按位分解
}
}
void INT0_Interrupt() interrupt 0 //外部中断0,统计待测信号的脉冲数量
{
Frequency++;
}
void INT2_Interrupt() interrupt 2 //重启测量程序,由外部按钮控制
{
Frequency=0; //重置频率计
TH0 = TimeH; //重置计时器
TL0 = TimeL;
show_m_flag=1;
EX0=1; //开启外部中断,开始脉冲计数
TR0=1; //开启计时器
}
void T0_Interrupt() interrupt 1
{
static uint cnt = 0;
TH0 = TimeH;
TL0 = TimeL;
cnt++;
if(cnt==20) //计时50ms*20=1s,计时完成
{
EX0=0; //关闭外部中断,结束测量
cnt=0;
renovate_frequency_flag=1;
TR0=0;
}
}
void TRX_Interrupt() interrupt 4 //串口通信
{
if(RI)
{
RI = 0;
}
if(TI)
{
TI = 0;
send(a);
}
}
void send(uchar *s) //串口发送函数
{
static uchar i=0;
if(i<strlen(s))
{
SBUF=*(s+i);
i++;
}
else
{
i=0;
}
}
/* ---------------------------
LCD1602显示函数
----------------------------*/
void delay(uint j) //延时函数
{
uchar i = 250;
for(;j>0;j--)
{
while(--i);
i=249;
while(--i);
i=250;
}
}
void check_busy(void) //检查忙标志函数
{
uchar dt;
do
{
dt = 0xff;
E = 0;
RS = 0;
RW = 1;
E = 1;
dt = out;
}while(dt&0x80);
E = 0;
}
void write_command(uchar com) //写命令函数
{
check_busy();
E = 0;
RS = 0;
RW = 0;
out = com;
E = 1;
_nop_();
E = 0;
delay(1);
}
void write_data(uchar dat) //写显示数据函数
{
check_busy();
E = 0;
RS = 1;
RW = 0;
out = dat;
E = 1;
_nop_();
E = 0;
}
void lcd_initial(void) //LCD初始化函数
{
write_command(0x38); //写入命令0x38:8位两行显示,5*7点阵字符
write_command(0x0c); //写入命令0x0c:开整体显示,光标关,无闪烁
write_command(0x06); //写入命令0x06:光标右移
write_command(0x01); //写入命令0x01:清屏
delay(1);
}
void string (uchar ad,uchar *s) //输出显示字符串的函数
{
write_command(ad);
while(*s>0)
{
write_data(*s++);
}
}