51单片机_频率计_1602
51单片机 1602液晶显示 TLC5615独立按键调频调幅
#include <reg52.h>#include <math.h>#define uint unsigned int#define uchar unsigned char#define PI 3.14sbit CS=P2^5; //定义片选信号IO口sbit SCLK=P2^4; //定义时钟信号IO口sbit DIN=P2^3; //定义数据输入IO口uint kk=1;sbit Aup=P1^4; //频率+sbit Adowm=P1^5;//频率-sbit Fup=P1^6; //幅度+sbit Fdowm=P1^7;//幅度-uint DataNum=128;//定义一个周期的点数uint AmNum=256; //定义一个周期的点数/*--------延时子程序----------*/void delay(unsigned char pp) //延迟时间等于k*8ms{while(pp--){unsigned char j;// P2=P2&0XF8;for(j = 0;j<123;j++); //j进行的内部循环,1次延迟8us,延迟1ms}}/*----------DA转换----------*/void DAConvert(uint Data){uchar i;Data<<=6;CS=0;SCLK=0;for (i=0;i<12;i++){DIN=(bit)(Data&0x8000);SCLK=1;Data<<=1;SCLK=0;}CS=1;SCLK=0;for (i=0;i<12;i++);}/*正弦波参数换算程序*/uint GetSinData(uchar x){uint SinData;SinData=((sin(2*PI*x/DataNum)+1)/2.0)*AmNum;return SinData;}/*----------主程序----------*/main(){uint i;while(1){for(i=0;i<DataNum;i++)DAConvert(GetSinData(i));//输出正弦波P1 = 0xFF; // 发全0行扫描码,列线输入if((P1&0xFF) != 0xFF) // 若有键按下{delay(1);// 延时去抖动if((P1&0xFF) != 0xFF)switch(AmNum){case 512: AmNum=256;break;case 32: AmNum=256; break;}switch(DataNum){case 256: DataNum=128;break;case 16: DataNum=128; break;}switch(P1){case 0x7f: AmNum=AmNum+32;break;//幅度+case 0xbf: AmNum=AmNum-32; break;//幅度-case 0xdf: DataNum=DataNum+16; break;//频率-case 0xef: DataNum=DataNum-16; break;//频率+}}}}。
基于51单片机的1602液晶频率计设计(Proteus仿真图和程序)
基于51单片机的1602液晶频率计设计一、Proteus仿真图:二、程序代码//最大测量65536Hz的频率计//原理:T0定时1S,T1计数#include <REG51.H>#include<INTRINS.H>#define uchar unsigned char#define uint unsigned intuint count=0;uint nm=0;uchar Fw,Fq,Fb,Fs,Fg;#define DataPort P0sbit LCM_RS=P2^0;sbit LCM_RW=P2^1;sbit LCM_EN=P2^2;uchar code str0[]={"-Test frequency-"};uchar code str1[]={"F=00000Hz "};//uchar code str2[]={" "};/*******************************/void delay(unsigned int k){unsigned int i,j;for(i=0;i<k;i++){for(j=0;j<121;j++){;}}}//=================================================///* 函数名:void WaitForEnable(void)作用:检测忙碌信号*///================================================//void WaitForEnable(void){DataPort=0xff;LCM_RS=0;LCM_RW=1;_nop_();LCM_EN=1;_nop_();_nop_();//while(DataPort&0x80);delay(5);LCM_EN=0;}//==========================================================// /* 函数名:void WriteCommandLCM(uchar CMD,uchar Attribc)作用:写命令到LCM *///==========================================================// void WriteCommandLCM(uchar CMD,uchar Attribc){if(Attribc)WaitForEnable();LCM_RS=0;LCM_RW=0;_nop_();DataPort=CMD;_nop_();LCM_EN=1;_nop_();_nop_();LCM_EN=0;}//=========================================================///* 函数名:void WriteDataLCM(uchar dataW)作用:写数据*///=========================================================// void WriteDataLCM(uchar dataW){WaitForEnable();LCM_RS=1;LCM_RW=0;_nop_();DataPort=dataW;_nop_();LCM_EN=1;_nop_();_nop_();LCM_EN=0;}//=========================================================///* 函数名:void InitLcd()作用:LCM初始化*///=========================================================// void InitLcd(){WriteCommandLCM(0x38,1);WriteCommandLCM(0x08,1);WriteCommandLCM(0x01,1);WriteCommandLCM(0x06,1);WriteCommandLCM(0x0c,1);}//=========================================================///*函数名:void DisplayOneChar(uchar X,uchar Y,uchar DData)作用:显示指定坐标的一个字符*///=========================================================// void DisplayOneChar(uchar X,uchar Y,uchar DData){Y&=1;X&=15;if(Y)X|=0x40;X|=0x80;WriteCommandLCM(X,0);WriteDataLCM(DData);}//============================================================// /*函数名:void DisplayListChar(uchar X,uchar Y,uchar code *DData作用:显示指定坐标的一串字符*///============================================================// void DisplayListChar(uchar X,uchar Y,uchar code *DData){uchar ListLength=0;Y&=0x1;X&=0xF;while(X<=15){DisplayOneChar(X,Y,DData[ListLength]);ListLength++;X++;}}//============================================================// /* 函数名:void main(void)作用:主函数*///============================================================////============================================================// /* 函数名:void display()作用:显示函数*///============================================================// void display(){Fw=count/10000+0x30;Fq=count/1000%10+0x30;Fb=count/100%10+0x30;Fs=count/10%10+0x30;Fg=count%10+0x30;DisplayOneChar(2,1,Fw);DisplayOneChar(3,1,Fq);DisplayOneChar(4,1,Fb);DisplayOneChar(5,1,Fs);DisplayOneChar(6,1,Fg);}void InitTime(void){TMOD=0x51;//T0为定时器工作于方式1,T1为计数器工作于方式1TH0=0x4C;//定时器50ms赋高8初值, 12M晶振TL0=0x00;//定时器50ms赋低8初值, 12M晶振TR0=1;//开定时器1TH1=0;//计数器赋高8初值初值TL1=0;//计数器赋低8初值TR1=1;//开计数器0ET0=1;EA=1;}void timeo(void) interrupt 1{TH0=0x4C;//定时器50ms赋高8初值TL0=0x00;//定时器50ms赋低8初值nm=nm+1;if(nm==10){TR1=0; //关闭T1定时器,定时1S完成TR0=0;//关闭T0}}//============================================================// /* 函数名:void main(void)作用:主函数*///============================================================// void main(void){char i;uint temp,temp1;delay(500);InitLcd(); //LCM初始化设置InitTime();for(i=15;i>=0;i--){DisplayListChar(i,0,str0);//显示第一行字符DisplayListChar(i,1,str1);//显示第二行字符delay(100);}while(1){if(nm==10)//定时10*50MS=500ms{temp=TL1;temp1=TH1;count=2*(temp1*256+temp);//定时2乘以500ms=1000ms display();TH1=0;//计数器赋高8初值初值TL1=0;//计数器赋低8初值nm=0;TR1=1;TR0=1;}}}。
基于51单片机数字温度计课设1602的设计和实现
基于51单片机数字温度计课设1602的设计和实现引言随着科技的发展和时代的进步,人们的生活水平日渐提高,对于环境的要求也越来越高。
其中,温度是一个非常重要的参数。
无论是日常生活还是科学实验,温度的测量都是至关重要的。
本文主要介绍了一个基于51单片机数字温度计课设1602的设计和实现,旨在方便人们测量温度、监测环境的变化。
系统设计设计要求本次的温度计设计需要满足以下要求:1、能够准确测量环境温度,并且实时监测环境的变化。
2、能够以数字的形式将温度值显示在1602液晶显示屏上。
3、具备温度过高或过低时进行声音提示和灯光警告的功能。
硬件选型本次设计采用了如下硬件:1、51单片机:主要负责数据的处理和控制。
2、DS18B20温度传感器:专门用来测量温度。
3、1602液晶显示器:用于显示温度值。
4、蜂鸣器:用来进行声音提示。
5、LED灯:用来进行灯光警告。
6、面包板、电源、杜邦线等。
系统原理DS18B20是一种数字温度传感器,它可以在一个单芯线上实现数字温度测量。
我们可以通过51单片机来对DS18B20进行一系列的控制和读取。
经过一定的计算,我们可以将测得的温度值以数字的形式显示在1602液晶显示器上。
在此基础上,通过对蜂鸣器和LED等的控制,可以进行声音和灯光的警告功能。
系统实现硬件连接根据硬件选型及系统原理,将各个器件以如下图的方式进行连接。
软件设计软件主要分为硬件初始化、温度计算、数码管显示、报警功能等几大部分。
1、硬件初始化:需要初始化IO口、定时器、串口等,将各个硬件初始化,以便后续的使用。
2、温度计算:读取DS18B20传感器寄存器中的数值,并进行一定的计算,将其转化为温度值。
3、数码管显示:将温度值按照规定的格式以数字的形式在1602液晶屏上进行显示。
4、报警功能:当温度过高或过低时,通过蜂鸣器和LED等进行声音和灯光警告。
系统测试经过一系列的硬件和软件设计,我们可以对整个系统进行测试。
首先,在正常温度下,我们可以看到液晶显示屏上显示的温度值以及蜂鸣器和LED等均未进行报警提示。
基于51单片机的频率计
TL0=0xfd;
EA=1; //开总中断
ET0=1; //开定时器0中断
TR0=1; //启动定时器0
TH1=0x00;//定时器1装初值
TL1=0x00;
ET1=1;//开定时器1中断
TR1=1;//启动定时器1
}
/*显示函数*/
void show1()
{
rate7=f/1000000;
write_sfm(0,rate7);
f1=f;
}
}
void show2()
{
if(f1!=0)
{
T=100000000/f1;
t7=T/1000000;
write_sfm(0,t7);
t6=(T%1000000)/10000;
write_sfm(2,t6);
t5=(T%10000)/100;
write_sfm(4,t5);
write_string(6,1,".");
}
void init_1602()//初始化
{
dx=0;wx=0;led_cs=0,c=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
TMOD=0x51;//设置定时器1计数工作模式1 定时器0计时工作模式1
TH0=0x4b;//定时器0装初值
2.2程序的设计
2.2.1程序设计思路
以T0计数器计数,程序主要完成对输入信号和标准号个数的测量、测量输入信号高电平和低电平。单片机主要完成对程序的控制、计算和显示相关信息及进行人机交互,并通过1602显示屏显示。
51单片机驱动LCM1602
功能;驱动LCM1602,LCM1602为深圳誉信公司的16*2液晶字符型显示模块,程序使用读写方式控制LCM1602,地址分别为:写指令口:80H; 读忙检查口:81H;写数据口:82H; 读数据口:83H;;子程序1:写控制指令子程序;子程序2:写CGRAM数据子程序;子程序3:写DDRAM子程序;子程序4:写数据子程序;子程序5:读忙子程序RG_DLY EQU 2HORG 0000HAJMP MAIORG 0030HMAI: MOV SP,#60HLP_MAI: NOPLCALL SB_WRIN;调用写控制指令子程序LCALL SB_WRCG;调用写CGRAMLP2_MAI:NOPLCALL SB_WRDR;调用写DDRAMRT_MAI: AJMP LP2_MAI;---------------------------------------------------------;---------子程序---开始------------------------------------;-1------写控制指令子程序----------SB_WRIN:PUSH ACCMOV R0,#80H ;写指令口MOV A,#01H ;(INSTR.1)LCALL SB_WAT ;清屏MOVX @R0,AMOV A,#02H ;(INSTR.2)LCALL SB_WAT ;A光标归位MOVX @R0,AMOV A,#06H ;(INSTR.3)LCALL SB_WAT ;AC自动加一,画面不动;MOVX @R0,AMOV A,#0CH ;(INSTR.4)0FH:显示开,关标开,闪烁开LCALL SB_WAT ;0CH 显示开,关标、闪烁关 MOVX @R0,A;MOV A,#18H ;(INSTR.5);LCALL SB_WAT ;光标或画面平移指令;MOVX @R0,AMOV A,#38H ;(INSTR.6)LCALL SB_WAT ;8位数据,2行显示,5-7点阵MOVX @R0,APOP ACCRET;-2----写CGRAM数据子程序------SB_WRCG:PUSH ACCMOV DPTR,#CGRMOV R1,#40H;=CGRAM的首地址MOV R2,#4;=4个字符LP_WG0: MOV R3,#8;=每个字符有8位数据即8行LP_WG1: MOV R0,#80HMOV A,R1LCALL SB_WATMOVX @R0,ACLR AMOVC A,@A+DPTRLCALL SB_WRTDINC R1INC DPTRDJNZ R3,LP_WG1DJNZ R2,LP_WG0NOPPOP ACCRET;-3-----写DDRAM子程序--------SB_WRDR:PUSH ACCMOV R0,#80HMOV A,#80H ; 写第一行DDRAM数据LCALL SB_WATMOVX @R0,AMOV A,#49H ; ILCALL SB_WRTDMOV A,#20H ; SPACELCALL SB_WRTDMOV A,#4CH ; LLCALL SB_WRTDMOV A,#4FH ; OLCALL SB_WRTDMOV A,#56H ; VLCALL SB_WRTDMOV A,#45H ; ELCALL SB_WRTDMOV A,#20H ; SPACELCALL SB_WRTDMOV A,#4DH ; MLCALL SB_WRTDMOV A,#59H ; YLCALL SB_WRTDMOV A,#20H ; SPACELCALL SB_WRTDMOV A,#42H ; BLCALL SB_WRTDMOV A,#41H ; ALCALL SB_WRTDMOV A,#42H ; BLCALL SB_WRTDMOV A,#59H ; YLCALL SB_WRTDMOV A,#20H ; EMPTYLCALL SB_WRTDMOV A,#20H ; EMPTYLCALL SB_WRTDMOV R0,#80HMOV A,#0C0H ;写第二行DDRAM LCALL SB_WATMOVX @R0,AMOV A,#49H ; ILCALL SB_WRTDMOV A,#20H ; SPACE LCALL SB_WRTDMOV A,#41H ; ALCALL SB_WRTDMOV A,#4CH ; LLCALL SB_WRTDMOV A,#53H ; SLCALL SB_WRTDMOV A,#4FH ; OLCALL SB_WRTDMOV A,#20H ; SPACELCALL SB_WRTDMOV A,#4DH ; MLCALL SB_WRTDMOV A,#49H ; ILCALL SB_WRTDMOV A,#53H ; SLCALL SB_WRTDMOV A,#53H ; SLCALL SB_WRTDMOV A,#20H ; SPACE LCALL SB_WRTDMOV A,#59H ; YLCALL SB_WRTDMOV A,#4FH ; OLCALL SB_WRTDMOV A,#55H ; ULCALL SB_WRTDMOV R2,#50 ;延时229ms ACALL SB_DLYPOP ACCRET;-4---写数据子程序---------SB_WRTD:MOV R0,#82H ; LCALL SB_WATMOVX @R0,A ;RET;-5---读忙子程序-----------SB_WAT: PUSH ACCPUSH 00HMOV R0,#81HLP_WAT: MOVX A,@R0RLC AJC LP_WATPOP 00HPOP ACCRET;---------子程序----结束----------------------------------- ;---------------------------------------------------------;------延时子程序-----------SB_DLY: PUSH RG_DLY ;LP1_DLY:PUSH RG_DLYLP2_DLY:PUSH RG_DLYDJNZ R2,$POP RG_DLYDJNZ R2,LP2_DLYPOP RG_DLYDJNZ R2,LP1_DLYPOP RG_DLYDJNZ R2,SB_DLYRET;----------CGRAM区---------- CGR:...................;(用户自编码字符区)END。
51单片机的1602计算器
51单片机的1602计算器一、51 单片机和 1602 液晶显示屏简介51 单片机是指英特尔公司生产的 8051 系列单片机,它具有丰富的资源,包括 I/O 端口、定时器、中断等。
通过编程,可以让 51 单片机完成各种复杂的任务。
1602 液晶显示屏是一种字符型液晶显示模块,它能够显示两行,每行 16 个字符。
1602 液晶显示屏的控制方式相对简单,通过发送特定的指令和数据,就可以实现字符的显示。
二、硬件设计要实现 51 单片机的 1602 计算器,首先需要进行硬件设计。
硬件部分主要包括 51 单片机最小系统、1602 液晶显示屏、按键等。
51 单片机最小系统通常包括单片机芯片、晶振电路和复位电路。
晶振电路为单片机提供时钟信号,复位电路则保证单片机能够正常启动。
1602 液晶显示屏与51 单片机的连接需要用到一些数据线和控制线。
数据线用于传输要显示的数据,控制线用于控制显示屏的工作状态。
按键用于输入数字和运算符,常见的按键有数字键 0 9 、运算符+、、、/以及等于号=等。
三、软件编程软件编程是实现 51 单片机 1602 计算器的关键。
在编程过程中,需要实现以下几个主要功能:1、初始化 1602 液晶显示屏在程序开始时,需要对 1602 液晶显示屏进行初始化,设置显示模式、光标显示等。
2、按键扫描通过不断扫描按键状态,获取用户输入的数字和运算符。
3、数据处理根据用户输入的数字和运算符,进行相应的计算,并将结果存储起来。
4、显示结果将计算结果显示在 1602 液晶显示屏上。
```cinclude <reg52h> //包含 51 单片机的头文件//定义 1602 液晶显示屏的控制引脚sbit RS = P2^0;sbit RW = P2^1;sbit EN = P2^2;//定义 1602 液晶显示屏的数据引脚sbit D0 = P0^0;sbit D1 = P0^1;sbit D2 = P0^2;sbit D3 = P0^3;sbit D4 = P0^4;sbit D5 = P0^5;sbit D6 = P0^6;sbit D7 = P0^7;//定义按键引脚sbit key0 = P1^0;sbit key1 = P1^1;sbit key2 = P1^2;sbit key3 = P1^3;sbit key4 = P1^4;sbit key5 = P1^5;sbit key6 = P1^6;sbit key7 = P1^7;sbit key8 = P3^0;sbit key9 = P3^1;sbit key_add = P3^2;sbit key_sub = P3^3;sbit key_mul = P3^4;sbit key_div = P3^5;sbit key_eq = P3^6;//定义变量unsigned char num1, num2, op, result;unsigned char flag = 0; //标志位,用于判断输入状态//写指令函数void write_command(unsigned char command){RS = 0;RW = 0;EN = 0;P0 = command;EN = 1;EN = 0;}//写数据函数void write_data(unsigned char data){RS = 1;RW = 0;EN = 0;P0 = data;EN = 1;EN = 0;}//初始化 1602 液晶显示屏函数void init_1602(){write_command(0x38);// 8 位数据,2 行显示,5x7 点阵write_command(0x0c);//显示开,光标关,闪烁关write_command(0x06);//字符右移,地址指针加 1 write_command(0x01);//清屏}//按键扫描函数void key_scan(){if (key0 == 0){delay_ms(10);//消抖if (key0 == 0){if (flag == 0){num1 = num1 10 + 0;write_data('0');}else{num2 = num2 10 + 0;write_data('0');}}while (!key0);//等待按键松开}//其他按键扫描类似}//计算函数void calculate(){switch (op){case '+':result = num1 + num2;break;case '':result = num1 num2;break;case '':result = num1 num2;break;case '/':if (num2!= 0)result = num1 / num2;elsewrite_data('E');//除数为 0 ,显示错误break;}}//主函数void main(){init_1602();while (1){key_scan();if (key_add == 0 || key_sub == 0 || key_mul == 0 ||key_div == 0){delay_ms(10);//消抖if (key_add == 0){op ='+';flag = 1;write_data('+');}//其他运算符处理类似}if (key_eq == 0){delay_ms(10);//消抖if (key_eq == 0){calculate();write_data(result);num1 = 0;num2 = 0;flag = 0;}}}}```上述代码只是一个简单的示例,实际应用中还需要进行更多的优化和完善,比如处理输入错误、添加更多的功能等。
51单片机 1602液晶显示 NE555频率计
#include<reg52.h>#define uint unsigned int#define uchar unsigned charsbit LCD_RS= P2^0;//定义LCD引脚sbit LCD_RW= P2^1;sbit LCD_E= P2^2;uchar code DIS[]={"NE555-------TEST"};//NE555 测试;uchar code dsptab[]={'0','1','2','3','4','5','6','7','8','9'};//字符代表码;uchar i,c[4],a[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; uint s;/*====================延时子程序====================*/ void delay(uint z){uchar m;for(;z>0;z--)for(m=124;m>0;m--);}void delay400ms(void)////400ms延时{ uchar z = 5;uint m;while(z--){ m=7269;while(m--);}}/*====================LCD1602子程序====================*/ /*-- 读状态--*///读状态子程序;有返回值;返回值类型为CHAR型;//读回的状态通过RETURN返回;uchar read_estate(void) //定义有返回值的函数;{ P0=0Xff; //把LCD端口全置1方便读取信号; LCD_RS=0; //RS置0;LCD_RW=1; //RW置1;LCD_E=0; //E端置0;delay(10); //短延时;LCD_E=1; //E端置1;以锁存数据; while(P0&0x80); //检测忙,则一直循环;return(P0); //返回读取的信号;}/*-- 写数据--*///写数据子程序;无返回值;输入变量I;//I为要写入LCD中的数据;//数据类型CHAR形;void write_data(uchar i) //定义输入变量值I;{read_estate(); //检测忙信号;P0=i; //把I中数据送到LCD数据端;LCD_RS=1; //RS置1;LCD_RW=0; //RW置0;LCD_E=0; //E置0;delay(10); //短延时;LCD_E=1; //E置1;以锁存数据;}/*-- 写指令--*///写指令子程序;无返回值;输入二个变量I和J.//I为要写入LCD的指令;J为判断要不要检测忙.//如果J为0则不判断检测忙;//如果J为1则判断检测忙;void write_dictate(uchar i,j) //定义二个变量;{if(j)read_estate(); //根据需要检测忙;P0=i; //把要写入的数据送到LCD数据端; LCD_RS=0; //RS置0;LCD_RW=0; //RW置0;LCD_E =1; //E端置0;delay(10); //延时;LCD_E =0; //E端置1;以锁存数据;}/*-- LCD初始化--*///LCD初始化程序;主要作用初始化LCD,对LCD进行复位以及设置;void initialization(void) //定义函数;{delay(50); //延时5MS;write_dictate(0x38,0); //写指令38H;不检测忙;delay(50); //延时5MS;write_dictate(0x38,0); //写指令38H;不检测忙;delay(50); //延时5MS;write_dictate(0x38,0); //写指令38H;不检测忙;delay(50);write_dictate(0x38,1); //显示模式设置;检测忙;write_dictate(0x08,1); //关闭显示;检测忙;write_dictate(0x01,1); //显示清屏;检测忙;write_dictate(0x06,1); //显示光标移动设置;检测忙;write_dictate(0x0C,1); //显示开及光标设置;检测忙;}/*-- 在指定位置显示一个字符--*/void displayonechar(uchar x, y,ddata){y &= 0x01;x &= 0x0f; //限制X不能大于15,Y不能大于1if (y) x+= 0x40; //当要显示第二行时地址码+0x40;x+= 0x80; //算出指令码write_dictate(x,0); //这里不检测忙信号,发送地址码write_data(ddata);}/*-- 在指定位置显示一串字符--*/void displaylistchar(uchar x,y,uchar code *ddata){uchar a=0;y&=0x01;x&=0xf;while(ddata[a]>0x20){ if(x<=0xff){displayonechar(x, y,ddata[a]);a++;x++;}}}/*====================MAIN主程序====================*/void main(){delay400ms();//延时400MSinitialization();//LCD复位;displaylistchar(0,0,DIS);//显示NE555 测试;displayonechar(0,1,'F'); //在LCD是显示F=____Hzdisplayonechar(1,1,'=');displayonechar(9,1,'H');displayonechar(10,1,'z');TMOD=0X51; //定义T0为方式一(十六位进制),T1为计数器(16位)TH0=0X3C; //50 msTL0=0XB0;TH1=0X00; //初始值TL1=0X00;TR0=1;TR1=1;ET0=1;ET1=0;EA=1;i=0;/* 显示*/ // 调用显示子程序(显示位,显示行,显示数据)注:显示行“0”为第一行,“1为第二行”while(1){if(s/10000>=1){displayonechar(2,1,dsptab[s/10000]); //万displayonechar(3,1,dsptab[s/1000%10]);//千displayonechar(4,1,'.'); //点displayonechar(5,1,dsptab[s/100%10]);//百displayonechar(6,1,dsptab[s/10%10]); //十displayonechar(7,1,dsptab[s%10]); //个displayonechar(8,1,'K');}else if(s/1000>=1){displayonechar(2,1,' ');displayonechar(3,1,dsptab[s/1000%10]);//千displayonechar(4,1,'.'); //点displayonechar(5,1,dsptab[s/100%10]);//百displayonechar(6,1,dsptab[s/10%10]); //十displayonechar(7,1,dsptab[s%10]); //个displayonechar(8,1,'K');}else if(s/100>=1){displayonechar(2,1,' ');displayonechar(3,1,' ');displayonechar(4,1,' '); //万displayonechar(5,1,' '); //千displayonechar(6,1,dsptab[s/100%10]);//百displayonechar(7,1,dsptab[s/10%10]); //十displayonechar(8,1,dsptab[s%10]); //个}else if(s/10>=1){displayonechar(2,1,' ');displayonechar(3,1,' ');displayonechar(4,1,' '); //万displayonechar(5,1,' '); //千displayonechar(6,1,' ');//百displayonechar(7,1,dsptab[s/10%10]); //十displayonechar(8,1,dsptab[s%10]); //个}else{displayonechar(2,1,' ');displayonechar(3,1,' ');displayonechar(4,1,' '); //万displayonechar(5,1,' '); //千displayonechar(6,1,' ');//百displayonechar(7,1,dsptab[s/10%10]); //十displayonechar(8,1,dsptab[s%10]); //个}}}/* 中断*/void t0()interrupt 1{TH0=0X3C;TL0=0XB0;i++;if(i==20) //1 s时间到时{s=TH1; //555信号发生器的输出口接P3.5(T1) 15脚s=s<<8;s=s+TL1;i=0; //清零TH1=0X00;TL1=0X00;}}/*----------------------------------------------------------------*//*----------------- 1602液晶数据读取子程序-----------------------*///读数据子程序;有返回值,返回值类型为CHAR型;/*uchar read_data(void) //定义有返回值的子函数; {LCD_DATA=0Xff; //LCD数据端口置1; LCD_RS=1; //RS置1;LCD_RW=1; //RW置1; LCD_E=0; //E置0;delay(10); //短延时;LCD_E=1; //E置1;以锁存数据; return(LCD_DATA); //返回读取的值;}/*----------------------------------------------------------------*/。
基于51单片机24小时可调时钟1602液晶显示程序
基于51单片机24小时可调时钟1602液晶显示程序#include<reg52.h>#define uchar unsigned char#define uint unsigned intsbit key1=P1^0;sbit key2=P1^1;sbit key3=P1^2;sbit key4=P1^3;sbit key5=P1^4;sbit key6=P1^5;sbit rs=P0^0; //液晶的第4端RS由开关独立s2 p3^5控制高电平写数据,低电平写命令。
sbit lecdn=P0^1; //使能端需控制LECDN,p3^6控制。
根据硬件电路而定uchar miao ,fen ,shi,num;uchar miao1,miao2,shi1,shi2,fen1,fen2;uchar table[]="0123456789";void delay(uint x){uint i,j;for(i=x;i>0;i--)for(j=10;j>0;j--);}void write_com(uchar com )//写指令{P2=com;//RW=0;写指令位定义一个io口控制lecdn=0; //起初为低电平时序图rs=0; //写指令rs为低delay(10); //简短延时lecdn=1; //给以高脉冲delay(5);lecdn=0;}void write_data(uchar shu ) //写数据{P2=shu; //将数据送给控制数据位的io口//RW=0;写指令位定义一个io口控制lecdn=0;rs=1; //写数据rs为低区别delay(10);lecdn=1;delay(5);lecdn=0;}void init() //初始化{write_com(0x38); //显示模式设置delay(20);write_com(0x0f); // 显示开关,和光标设置,开关必开,光标不开ox0c,开并闪烁0x0fdelay(20);write_com(0x06); //写完一个数据,数据地址指针自动往后移动一位delay(20);write_com(0x01); //清屏指令,按下复位键上次的结果变清掉。
基于51单片机的数字频率计
• 6、RESET/VPD(9脚):复位信号输入端/备用电源输入 端;
单片机执行程序都是从地址0000H开始的,所以在进入系 统时必须对CPU进行复位,有时候程序运行错误或操作错 误,系统会处于锁死的状态为了摆脱这样的状态也必须对 单片机进行复位。
复位的方法比较简单:只要在RESET脚上加一个持续时 间为24个振荡周期(两个机器周期)的高电平就可以了。
• 7、EA/VPP(31脚):内/外部ROM选择端; • 8、P0口(39-32脚):双向IO口P00-P07(P0口无上拉
电阻,作输出用需要接上拉电阻);
• 9、P1口(1-8脚):准双向通用IO口; • 10、P2口(21-28脚):准双向通用IO口; • 11、P3口(10-17脚):准双向通用IO口;
环境干扰等因素。经实际多次测试频率在 等于1000Hz的时候最大相对误差达到0.1%, 符合误差要求。
• 实物图
2.3 显示模块
• 2.3.1 LCD1602简介
LCD1602是一种专门用来显示字母、数字、 符号等的点阵型液晶模块,它由若干个5X7 或者5X11等点阵字符位组成,每个点阵字 符位都可以显示一个字符,每位之间有一 个点距的间隔,每行之间也有间隔,起到 了字符间距和行间距的作用。LCD1602是= 显示的内容为16X2,即可以显示两行,每 行16个字符液晶模块。
2.3.4 LCD1602地址
比如第二行第一个字符的地址是40H,那么是否直接 写入40H就可以将光标定位在第二行第一个字符的位置呢? 这样不行,因为写入显示地址时要求最高位D7恒定为高 电平1,所以实际写入的数据应该40H+80H=C0H
基于51单片机控制的1602液晶电子时钟显示程序
基于51单片机控制的1602液晶电子时钟显示程序[ 2007-05-31 13:31:45 | By: kevin ]刚写好的基于51单片机控制的1602液晶电子时钟显示程序,整理了一下,并尽量加上的注释,放出来大家共享及交流。
有兴趣的可以参考一下,各管脚定义都比较明显,有一定基础的可稍作修改即可进行实验。
//基于51单片机控制的1602液晶电子时钟显示程序#i nclude <intrins.h>#i nclude <at89x51.h>#define uchar unsigned char#define LCM_RS P2_2 //定义引脚#define LCM_RW P2_1#define LCM_E P2_0#define LCM_Data P0#define Busy 0x80 //用于检测LCM状态字中的Busy标识uchar i, j, k, second, tcount, minute, hour;void WriteDataLCM(unsigned char WDLCM);void WriteCommandLCM(unsigned char WCLCM,BuysC);unsigned char ReadDataLCM(void);unsigned char ReadStatusLCM(void);void LCMInit(void);void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData);void DisplayqListChar(unsigned char X, unsigned char Y, unsigned char code *DData);void Delay5Ms(void);void Delay400Ms(void);unsigned char code table[]={'0','1','2','3','4','5','6','7','8','9'};//数码管数字编码unsigned char code MyNo[] = {"NAME:Who_am_I?"};/*************************************************************************** ***************** 函数名称:delay()** 功能描述:延时子程序,大约延时n MS** 输入:** 输出:** 全局变量:** 调用模块:** 作者:kevin** 日期:2007年5月31日**************************************************************************** ****************/delay(uchar n){uchar i,j,k;for(i=2;i>0;i--)for(j=n;j>0;j--)for(k=125;k>0;k--);}/*************************************************************************** ***************** 函数名称:lcd()** 功能描述:液晶初始化,然后在液晶屏第二行显示提示信息** 输入:** 输出:** 全局变量:** 调用模块:Delay400Ms(),LCMInit(),DisplayListChar()** 作者:kevin** 日期:2007年5月31日**************************************************************************** ****************/void lcd(void){Delay400Ms(); //启动等待,等LCM讲入工作状态LCMInit(); //LCM初始化Delay5Ms(); //延时片刻(可不要)DisplayListChar(0, 1, MyNo);}/*************************************************************************** ***************** 函数名称:WriteDataLCM()** 功能描述:写数据** 输入:WDLCM** 输出:** 全局变量:** 调用模块:** 作者:kevin** 日期:2007年5月31日**************************************************************************** ****************/void WriteDataLCM(unsigned char WDLCM){ReadStatusLCM(); //检测忙LCM_Data = WDLCM;LCM_RS = 1;LCM_RW = 0;LCM_E = 0; //若晶振速度太高可以在这后加小的延时LCM_E = 0; //延时LCM_E = 1;}/*************************************************************************** ***************** 函数名称:WriteCommandLCM()** 功能描述:写指令** 输入:** 输出:** 全局变量:** 调用模块:** 作者:kevin** 日期:2007年5月31日**************************************************************************** ****************/void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC为0时忽略忙检测{if (BuysC) ReadStatusLCM(); //根据需要检测忙LCM_Data = WCLCM;LCM_RS = 0;LCM_RW = 0;LCM_E = 0;LCM_E = 0;LCM_E = 1;}/*************************************************************************** ***************** 函数名称:ReadDataLCM()** 功能描述:读数据** 输入:** 输出:** 全局变量:** 调用模块:** 作者:kevin** 日期:2007年5月31日**************************************************************************** ****************/unsigned char ReadDataLCM(void){LCM_RS = 1;LCM_E = 0;LCM_E = 0;LCM_E = 1;return(LCM_Data);}/*************************************************************************** ***************** 函数名称:ReadStatusLCM()** 功能描述:读状态** 输入:** 输出:** 全局变量:** 调用模块:** 作者:kevin** 日期:2007年5月31日**************************************************************************** ****************/unsigned char ReadStatusLCM(void){LCM_Data = 0xFF;LCM_RS = 0;LCM_E = 0;LCM_E = 0;LCM_E = 1;while (LCM_Data & Busy); //检测忙信号return(LCM_Data);}/*************************************************************************** ***************** 函数名称:LCMInit()** 功能描述:LCM初始化** 输入:** 输出:** 全局变量:** 调用模块:** 作者:kevin** 日期:2007年5月31日**************************************************************************** ****************/void LCMInit(void){LCM_Data = 0;WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号Delay5Ms();WriteCommandLCM(0x38,0);Delay5Ms();WriteCommandLCM(0x38,0);Delay5Ms();WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号WriteCommandLCM(0x08,1); //关闭显示WriteCommandLCM(0x01,1); //显示清屏WriteCommandLCM(0x06,1); // 显示光标移动设置WriteCommandLCM(0x0C,1); // 显示开及光标设置}/*************************************************************************** ***************** 函数名称:DisplayOneChar()** 功能描述:按指定位置显示一个字符** 输入:** 输出:** 全局变量:** 调用模块:** 作者:kevin** 日期:2007年5月31日**************************************************************************** ****************/void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData){Y &= 0x1;X &= 0xF; //限制X不能大于15,Y不能大于1if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;X |= 0x80; // 算出指令码WriteCommandLCM(X, 0); //这里不检测忙信号,发送地址码WriteDataLCM(DData);}/*************************************************************************** ***************** 函数名称:DisplayListChar()** 功能描述:按指定位置显示一串字符** 输入:** 输出:** 全局变量:** 调用模块:** 作者:kevin** 日期:2007年5月31日**************************************************************************** ****************/void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData){unsigned char ListLength;ListLength = 0;Y &= 0x1;X &= 0xF; //限制X不能大于15,Y不能大于1while (DData[ListLength]>0x20) //若到达字串尾则退出{if (X <= 0xF) //X坐标应小于0xF{DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符ListLength++;X++;}}}/*************************************************************************** ***************** 函数名称:Delay5Ms()** 功能描述:5ms延时** 输入:** 输出:** 全局变量:** 调用模块:** 作者:kevin** 日期:2007年5月31日**************************************************************************** ****************/void Delay5Ms(void){unsigned int TempCyc = 5552;while(TempCyc--);}/*************************************************************************** ***************** 函数名称:Delay400Ms()** 功能描述:400ms延时** 输入:** 全局变量:** 调用模块:** 作者:kevin** 日期:2007年5月31日**************************************************************************** ****************/void Delay400Ms(void){unsigned char TempCycA = 5;unsigned int TempCycB;while(TempCycA--){TempCycB=7269;while(TempCycB--);};}/*************************************************************************** ***************** 函数名称:timer0()** 功能描述:中断子程序,1秒重写一次液晶,以此实现60秒计数** 输入:** 全局变量:** 调用模块:** 作者:kevin** 日期:2007年5月31日**************************************************************************** ****************/void timer0() interrupt 1 using 0{int i;TH0=(65536-50000)/256*3; //中断设置初始化TL0=(65536-50000)%256*3;tcount++;if(tcount==60) //满1秒{ i=0;DisplayOneChar(i++, 0, 'T'); //在第1行第1个坐标显示DisplayOneChar(i++, 0, 'I'); //在第1行第2个坐标显示DisplayOneChar(i++, 0, 'M'); //在第1行第3个坐标显示DisplayOneChar(i++, 0, 'E'); //在第1行第4个坐标显示DisplayOneChar(i++, 0, ':'); //在第1行第5个坐标显示DisplayOneChar(i++, 0, table[hour/10]); //在第1行第6个坐标显示DisplayOneChar(i++, 0, table[hour%10]); //在第1行第7个坐标显示DisplayOneChar(i++, 0, ':'); //在第1行第1个坐标显示DisplayOneChar(i++, 0, table[minute/10]); //在第1行第8个坐标显示DisplayOneChar(i++, 0, table[minute%10]); //在第1行第9个坐标显示DisplayOneChar(i++, 0, ':'); //在第1行第10个坐标显示DisplayOneChar(i++, 0, table[second/10]); //在第1行第11个坐标显示DisplayOneChar(i++, 0, table[second%10]); //在第1行第12个坐标显示tcount=0;second++;if(second==60) //满1分{second=0;minute++; //分数加1,秒数归零if(minute==60) //满1小时{minute=0;hour++; //小时数加1,分数归零if(hour==24){hour=0;}}}}}/*************************************************************************** ***************** 函数名称:main()** 功能描述:主程序,设置初始时间,中断设置初始化,液晶显示,等待中断** 输入:** 输出:** 全局变量:** 调用模块:** 作者:kevin** 日期:2007年5月31日**************************************************************************** ****************/void main(){uchar i;second=0;minute=0;hour=0; //设置初始时间TH0=(65536-50000)/256; //中断设置初始化TL0=(65536-50000)%256;EA=1;ET0=1;TMOD=0x21;TR0=1;lcd();i=0;DisplayOneChar(i++, 0, 'T'); //在第1行第1个坐标显示DisplayOneChar(i++, 0, 'I'); //在第1行第2个坐标显示DisplayOneChar(i++, 0, 'M'); //在第1行第3个坐标显示DisplayOneChar(i++, 0, 'E'); //在第1行第4个坐标显示DisplayOneChar(i++, 0, ':'); //在第1行第5个坐标显示DisplayOneChar(i++, 0, table[hour/10]); //在第1行第6个坐标显示DisplayOneChar(i++, 0, table[hour%10]); //在第1行第7个坐标显示DisplayOneChar(i++, 0, ':'); //在第1行第1个坐标显示DisplayOneChar(i++, 0, table[minute/10]); //在第1行第8个坐标显示DisplayOneChar(i++, 0, table[minute%10]); //在第1行第9个坐标显示DisplayOneChar(i++, 0, ':'); //在第1行第10个坐标显示DisplayOneChar(i++, 0, table[second/10]); //在第1行第11个坐标显示DisplayOneChar(i++, 0, table[second%10]); //在第1行第12个坐标显示while(1); //等待中断}。
51单片机1602液晶显示频率计
摘要在电子领域内,频率是一种最根本的参数,并与其他许多电参量的测量方案和测量结果都有着十分密切的关系。
由于频率信号抗干扰能力强、易于传输,可以获得较高的测量精度。
因此,频率的测量就显得尤为重要,测频方法的研究越来越受到重视。
频率计作为测量仪器的一种,常称为电子计数器,它的根本功能是测量信号的频率和周期频率计的应用X围很广,它不仅应用于一般的简单仪器测量,而且还广泛应用于教学、科研、高精度仪器测量、工业控制等其它领域。
随着微电子技术和计算机技术的迅速开展,特别是单片机的出现和开展,使传统的电子侧量仪器在原理、功能、精度与自动化水平等方面都发生了巨大的变化,形成一种完全突破传统概念的新一代侧量仪器。
频率计广泛采用了高速集成电路和大规模集成电路,使仪器在小型化、耗电、可靠性等方面都发生了重大的变化。
目前,市场上有各种多功能、高精度、高频率的数字频率计,但价格不菲。
为适应实际工作的需要,本次设计给出了一种较小规模和单片机(AT89S52)相结合的频率计的设计方案,不但切实可行,而且体积小、某某性强、设计简单、本钱低、精度高、可测频带宽,大大降低了设计本钱和实现复杂度。
频率计的硬件电路是用Protel绘图软件绘制而成,软件局部的单片机控制程序,是以KeilC做为开发工具用C语言编写而成,而频率计的实现如此是选用Ptotues仿真软件来进展模拟和测试。
关键词:单片机;AT89S52;频率计;C语言ABSTRACTIn the electronic field, frequency is a kind of most basic parameter, and all there are close relations in the measurement schemes of many other electric parameters and result of measuring. Because the signal anti-interference ability of frequency is strong, easy to transmit, can obtain higher measurement precision. So, the measurement of frequency seems particularly important, the research of the method is being paid attention to.The Frequency meter, as one kind of the measuring instrument, often called the electronic counter, its basic function is that frequency and application of cycle Frequency meter of measuring the signal are in a very large range, it not only applies to general simple instrument measurement but also apply to otherfields such as teaching, scientific research, high-accuracy instrument measuring, industrial control extensively. With the rapid development of microelectric technique and puter technology, especially appearance and development of the one-chip puter, the instruments have all changed enormously in such aspects as principle, function, precision and automatic level to enable the traditional electronic side amount, form a kind of side amount instrument of new generation that totally broke through the traditional concept. The Frequency meter has adopted the high-speed integrated circuit and large scale integrated circuit extensively, make the instrument change greatly in such aspects as miniaturize, power consumptive, dependability. At present, there are various digital Frequency meter of multi-function, high precision, high frequency on the market, but the price is high.In order to meet the need of the real work, design and provide one this time The design plan of Frequency meter bining with one-chip puter (AT89S52) on a small scale, not only feasible, and small, of good security, design simply, with low costs, the precision is high, can examine the bandwidth frequently, have reduced the design cost and realized plexity greatly. The hardware circuit of the Frequency meter is drawing with Protel mapping software, the one-chip puter control procedure of the software part, regarded KeilC as the developing instrument to write in C language, but the realization of the Frequency meter was to select to carry on imitating and test with Protues artificial software.Key Words:single chip puter; AT89S52; frequency meter; C language目录1 绪论11.1 课题的引入11.2 产生背景11.3 国内外研究现状21.4 单片机频率计设计的目的与意义22 AT89S52单片机介绍与其开展概况32.1 单片机的介绍32.1.1 单片机概述32.1.2 单片机的开展42.1.3 单片机的特点与应用52.2 AT89S52系列单片机62.2.1 AT89系列单片机62.2.2 AT89S52系列单片机的根本结构73 频率计总体方案设计93.1 频率计设计原理93.1.1 频率检测实现方法103.1.2 频率计测频原理103.2 设计思路与方法113.2.1 频率计方案概述113.2.2 频率计的量程自动切换124 系统的硬件设计134.1 时钟信号发生器134.2 AT89S52 控制存放器144.2.1 AT89S52中断控制系统144.2.2 AT89S52定时/计数器的控制164.3 LCD1602显示电路174.3.1 LCD1602的主要技术参数与接口说明184.3.2 控制器接口与时序184.3.3 频率计硬件电路整体设计195 系统的软件设计215.1 Keil C简介225.2 频率计程序的建立过程225.3 软件功能模块设计265.3.1 LCD初始化设置模块275.3.2 浮点数到ASCII码转换模块275.3.3 定时/计数器初始化模块285.3.4 定时器中断服务模块子程序296 系统的模拟与仿真296.1 Proteus ISIS简介306.1.1 Proteus ISIS的概况简介与特点306.1.2 Proteus ISIS的运行概况306.1.3 用Proteus 软件虚拟单片机实验的优点31 6.2 系统的模拟与仿真过程326.3 频率计系统仿真分析36完毕语39致谢39参考文献401绪论1.1课题的引入在电子技术中,频率是一种计算单位时间内的信号变化的数值的仪器,是最根本的参数之一,由于频率信号抗干扰能力强、易于传输,可以获得较高的测量精度,并且与许多电参量的测量方案、测量结果都有十分密切的关系。
基于51单片机的数字频率计设计
基于51单片机的数字频率计一、设计说明1.数字频率计概述数字频率计是计算机、通讯设备、音频视频等科研生产领域不可缺少的测量仪器。
它是一种用十进制数字显示被测信号频率的数字测量仪器。
它的基本功能是测量正弦信号,方波信号及其他各种单位时间内变化的物理量。
在进行模拟、数字电路的设计、安装、调试过程中,由于其使用十进制数显示,测量迅速,精确度高,显示直观,经常要用到频率计。
本数字频率计将采用定时、计数的方法测量频率,采用一个1602A LCD显示器动态显示6位数。
测量范围从1Hz—10kHz的正弦波、方波、三角波,时基宽度为1us,10us,100us,1ms。
用单片机实现自动测量功能。
基本设计原理是直接用十进制数字显示被测信号频率的一种测量装置。
它以测量周期的方法对正弦波、方波、三角波的频率进行自动的测量。
2.频率测量仪的设计思路与频率的计算频率测量仪的设计思路主要是:对信号分频,测量一个或几个被测量信号周期中已知标准频率信号的周期个数,进而测量出该信号频率的大小,其原理如右图所示。
若被测量信号的周期为,分频数m1,分频后信号的周期为T,则:T=m1Tx。
由图可知:T=NTo(注:To为标准信号的周期,所以T为分频后信号的周期,则可以算出被测量信号的频率f。
)由于单片机系统的标准频率比较稳定,而是系统标准信号频率的误差,通常情况下很小;而系统的量化误差小于1,所以由式T=NTo可知,频率测量的误差主要取决于N值的大小,N值越大,误差越小,测量的精度越高。
3.设计原理及系统分析基本设计原理:直接用十进制数字显示被测信号频率的一种测量装置。
它以测量周期的方法对正弦波、方波、三角波的频率进行自动的测量。
若在一定时间间隔T内测得这个周期性信号的重复变化次数N,则其频率可表示为f=N/T。
其中脉冲形成电路的作用是将被测信号变成脉冲信号,其重复频率等于被测频率fx。
时间基准信号发生器提供标准的时间脉冲信号,若其周期为1s,则门控电路的输出信号持续时间亦准确地等于1s。
51单片机实现LCD1602显示定时计数器(自己整理的)
每隔一分钟,蜂鸣器响一次,按键按一下,计数器清0。
从新开始、#include<>#include<>#define uchar unsigned char#define uint unsigned intsbit RS=P2^0;sbit RW=P2^1;sbit EN=P2^2;uchar code dis2[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};uchar code p[]="-";//code 可以不加,加了之后就是固定了这个数组不能对其进行操作、、这个一定要注意。
uchar j,k,kk,miao,miao1,fen,fen1,shi,shi1;void delay_ms(int x)//延时程序,延时1ms{uint i;while(x--)for(i=0;i<120;i++);}uchar busy()//对LCD1602进行判断是否为忙{uchar status;RS=0;RW=1;EN=1;delay_ms(1);status=P1;EN=0;return status;}void write_cmd(uchar cmd)//写命令程序,首先对其进行判忙{while((busy()&0x80)==0x80);//对返回进行判断,如果为忙就进行等待RS=0;RW=0;EN=0;P1=cmd;EN=1;delay_ms(1);EN=0;}void write_data(uchar dat){while((busy()&0x80)==0x80);RS=1;RW=0;EN=0;P1=dat;EN=1;delay_ms(1);EN=0;}void canshu(){write_cmd(0x38);delay_ms(1);write_cmd(0x01);delay_ms(1);write_cmd(0x06);delay_ms(1);write_cmd(0x0c);delay_ms(1);}/*void xianshi(uchar x,uchar y,uchar *str){uint i=0;if(y==0)write_cmd(0x80|x);if(y==1)write_cmd(0xc0|x);for(i=0;i<16;i++){write_data(str[i]);if(p=='\0')break;}} */void aaa() interrupt 1{TH0=(65535-50000)/256;TL0=(65535-50000)%256;if(++kk==18){miao++;if(miao==10){if(miao1++==5){if(fen++==10){if(fen1++==5){if(shi++==10){if(shi1++==1){shi1=0;shi=0;}shi=0;}fen1=0;}fen=0;}miao1=0;}miao=0;}kk=0;}}void main(){canshu();//xianshi(0,0,p);//xianshi(0,1,p+16);EA=1;ET0=1;TMOD=0x01;TH0=(65535-50000)/256;//如果不准可对其进行修改,比如4000可能更准确TL0=(65535-50000)%256;TR0=1;while(1){write_cmd(0x80|1);write_data(dis2[shi]);write_cmd(0x80|2);write_data(dis2[shi1]);write_cmd(0x80|3);write_data(p[0]);write_cmd(0x80|4);write_data(dis2[fen1]);write_cmd(0x80|5);write_data(dis2[fen]);write_cmd(0x80|6);write_data(p[0]);write_cmd(0x80|7);write_data(dis2[miao]);write_cmd(0x80|8);write_data(dis2[miao1]);}}。
51单片机好学1602全过程C语言编程显示很全的哦(同名3209)
教你轻松学51所谓1602是指显示的内容为16*2,即可以显示两行,每行16个字符。
目前市面上字符液晶绝大多数是基于HD44780 液晶芯片的,控制原理是完全相同的,因此基于HD44780 写的控制程序可以很方便地应用于市面上大部分的字符型液晶。
1602液晶的正面(绿色背光,黑色字体)1602液晶背面(绿色背光,黑色字体)另一种1602液晶模块,显示屏是蓝色背光白色字体字符型LCD1602 通常有14条引脚线或16条引脚线的LCD,多出来的2条线是背光电源线VCC(15脚)和地线GND(16脚),其控制原理与14脚的LCD完全一样,引脚定义HD44780 内置了DDRAM、CGROM 和CGRAM。
DDRAM 就是显示数据RAM,用来寄存待显示的字符代码。
共80个字节,其地址和屏幕的对应关系如下表:也就是说想要在LCD1602 屏幕的第一行第一列显示一个"A"字,就要向DDRAM 的00H地址写入“ A字的代码就行了。
但具体的写入是要按LCD模块的指令格式来进行的,后面我会说到的。
那么一行可有40个地址呀?是的,在1602中我们就用前16个就行了。
第二行也一样用前16个地址。
对应如下:DDRAM地址与显示位置的对应关系f 1*I*S3H0UH眄H06H07H OSH佃H OAH ABH6CH flDU OEH■Hl!:朝H 41H42H43H44H45H46H i*7H48H却9H4AH却BH毗H却DH ikEH4FH1Ij (事实上我们往DDRAM 里的00H地址处送一个数据,譬如0x31(数字1的代码)并不能显示1出来。
这是一个令初学者很容易出错的地方,原因就是如果你要想在DDRAM的00H地址处显示数据,则必须将00H加上80H,即80H,若要在DDRAM 的01H处显示数据,则必须将01H加上80H即81H。
依次类推。
大家看一下控制指令的的8条:DDRAM地址的设定,即可以明白是怎么样的一回事了)1602 液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,如下表所示,这些字符有:阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等,每一个字符都有一个固定的代码,比如大写的英文字母“A'的代码是01000001B(41H ),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A”□RQH 中事科砂押曲宇料其贏对昭舂-wraa上表中的字符代码与我们 PC 中的字符代码是基本一致的。
51单片机频率计设计(LCD显示)[1]
51单片机频率计设计(LCD显示)[1]————————————————————————————————作者:————————————————————————————————日期://单片机89C51的数字频率计C程序:#include 〈AT89x51。
h>#include 〈stdio。
h〉#include <math.h>#include 〈intrins.h〉float f;//频率float p; //周期float sj;float mk; //脉宽char idata buff[20];char xs=0;//设置闸门时间结束后是否显示结果的标志位unsigned char m=0,n=0,yichu=0,fenpin;//m定时中断次数n计数中断次数yichu判断是定时器还是sbit B153=P2^4;sbit A153=P2^3;sbit P35=P3^5;unsigned char LCD_Wait(void);void LCD_Write(bit style,unsigned char input);void LCD_SetDisplay(unsigned char DisplayMode);void LCD_SetInput(unsigned char InputMode);void LCD_Initial();void GotoXY(unsigned char x, unsigned char y);void Print(unsigned char *str);void C51_Initial();void Delay(unsigned int t);void display(float f);void cepin();void panduan();void Mkdisplay(float mk);void ccpin();/***************************************** 模块名称:LCD1602显示程序*****************************************//***********************端口定义***********************************/sbit LcdRs= P2^0;sbit LcdRw= P2^1;sbit LcdEn= P2^2;sfr DBPort= 0x80;//P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.数据端口/************************内部等待函数********************************/unsigned char LCD_Wait(void){LcdRs=0;//寄存器选择输入端1:数据0:指令LcdRw=1;_nop_(); //RW:为0:写状态;为1:读状态;LcdEn=1; _nop_();//使能输入端,读状态,高电平有效;写状态,下降沿有效LcdEn=0;return DBPort;}/***********************向LCD写入命令或数据*********************************/#define LCD_COMMAND 0 // Command#define LCD_DATA 1 // Data#define LCD_CLEAR_SCREEN 0x01 // 清屏#define LCD_HOMING 0x02 // 光标返回原点void LCD_Write(bit style,unsigned char input){LcdEn=0;LcdRs=style;LcdRw=0;_nop_();DBPort=input; _nop_();//注意顺序LcdEn=1; _nop_();//注意顺序LcdEn=0;_nop_();LCD_Wait();}/********************设置显示模式****************************************/#define LCD_SHOW 0x04 //显示开#define LCD_HIDE 0x00 //显示关#define LCD_CURSOR 0x02 //显示光标#define LCD_NO_CURSOR 0x00 //无光标#define LCD_FLASH 0x01 //光标闪动#define LCD_NO_FLASH 0x00 //光标不闪动void LCD_SetDisplay(unsigned char DisplayMode){LCD_Write(LCD_COMMAND, 0x08|DisplayMode);}/*********************设置输入模式***************************************/#define LCD_AC_UP 0x02#define LCD_AC_DOWN 0x00 // default#define LCD_MOVE 0x01 // 画面可平移#define LCD_NO_MOVE 0x00 //defaultvoid LCD_SetInput(unsigned char InputMode){LCD_Write(LCD_COMMAND, 0x04|InputMode);}/******************初始化LCD******************************************/void LCD_Initial(){LcdEn=0;LCD_Write(LCD_COMMAND,0x38); //8位数据端口,2行显示,5*7点阵LCD_Write(LCD_COMMAND,0x38);LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR); //开启显示,无光标LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN);//清屏LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE); //AC递增,画面不动}/*****************************LCD**************************************/void GotoXY(unsigned char x, unsigned char y){if(y==0)LCD_Write(LCD_COMMAND,0x80|x);if(y==1)LCD_Write(LCD_COMMAND,0x80|(x-0x40));}void Print(unsigned char *str){while(*str!=’\0'){LCD_Write(LCD_DA TA,*str);str++;}}/***************************89c51初始化************************************/void C51_Initial(){sj=1000000.00;TMOD=0x51; // 01010001 T1为计数器,T0为定时器EA=1;ET0=1;ET1=1;EX0=1;PX0=1; //外部中断0设置为高优先级IT0=0; //电平触发方式}/**************************ms延时子程序***************************/void Delay(unsigned int t) //t随着数值越大,误差趋于平衡。
基于51单片机的循线测距测速及1602显示
#include<regx52.h> //器件配置文件#include <intrins.h>#define TX P1_2 //Trig#define RX P1_3 //Echo#define LCM_RS P2_5 //定义LCD引脚#define LCM_RW P2_6#define LCM_E P2_7#define LCM_Data P0#define Busy 0x80 //用于检测LCM状态字中的Busy标识#define uint unsigned int#define uchar unsigned charsbit P10=P2^1;//控制左电机前进sbit P11=P2^2;//控制左电机后退sbit P12=P2^3;//控制右电机前进sbit P13=P2^4;//控制右电机后退sbit P14=P1^4;//寻迹左sbit P15=P1^5;//寻迹中sbit P16=P1^6;//寻迹右sbit P17=P1^7;//避障void LCMInit(void);void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData); void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData); void Delay5Ms(void);void Delay400Ms(void);void Decode(unsigned char ScanCode);void WriteDataLCM(unsigned char WDLCM);void WriteCommandLCM(unsigned char WCLCM,BuysC);void fun2(void);void fun3(void);void fun4(void);void fun5(void);unsigned char ReadDataLCM(void);unsigned char ReadStatusLCM(void);unsigned char code mcustudio[] ={"…………. "};unsigned char code email[] = {"………… "};unsigned char code Cls[] = {"……………"};unsigned char code ASCII[15] = {'0','1','2','3','4','5','6','7','8','9','.','-','M'};static unsigned char DisNum = 0; //显示用指针unsigned int time=0;unsigned long S=0;bit flag =0;unsigned char disbuff[4] ={ 0,0,0,0,};bit Flg_5ms=0;unsigned char Counter_100ms=0;unsigned char buf[5]={0,0,0,0,0};unsigned int Speed;unsigned int speed_frequency; // frequencyunsigned int speed_catch1; //catch 1unsigned int speed_catch2; //catch 2unsigned char speed_t2_ovf_count_temp; //T1 overflow counter temp register unsigned char speed_t2_ovf_count; //T1 overflow counter register unsigned char speed_catch_p; //catch pointer//写数据void WriteDataLCM(unsigned char WDLCM){ReadStatusLCM(); //检测忙LCM_Data = WDLCM;LCM_RS = 1;LCM_RW = 0;LCM_E = 0; //若晶振速度太高可以在这后加小的延时LCM_E = 0; //延时LCM_E = 1;}//写指令void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC为0时忽略忙检测{if (BuysC) ReadStatusLCM(); //根据需要检测忙LCM_Data = WCLCM;LCM_RS = 0;LCM_RW = 0;LCM_E = 0;LCM_E = 0;LCM_E = 1;}//读数据unsigned char ReadDataLCM(void){LCM_RS = 1;LCM_RW = 1;LCM_E = 0;LCM_E = 0;LCM_E = 1;return(LCM_Data);}//读状态unsigned char ReadStatusLCM(void){LCM_Data = 0xFF;LCM_RS = 0;LCM_RW = 1;LCM_E = 0;LCM_E = 0;LCM_E = 1;while (LCM_Data & Busy); //检测忙信号return(LCM_Data);}void LCMInit(void) //LCM初始化{LCM_Data = 0;WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号Delay5Ms();WriteCommandLCM(0x38,0);Delay5Ms();WriteCommandLCM(0x38,0);Delay5Ms();WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号WriteCommandLCM(0x08,1); //关闭显示WriteCommandLCM(0x01,1); //显示清屏WriteCommandLCM(0x06,1); // 显示光标移动设置WriteCommandLCM(0x0F,1); // 显示开及光标设置}//按指定位置显示一个字符void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData) {Y &= 0x1;X &= 0xF; //限制X不能大于15,Y不能大于1if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;X |= 0x80; //算出指令码WriteCommandLCM(X, 1); //发命令字WriteDataLCM(DData); //发数据}//按指定位置显示一串字符void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData) {unsigned char ListLength;ListLength = 0;Y &= 0x1;X &= 0xF; //限制X不能大于15,Y不能大于1while (DData[ListLength]>0x19) //若到达字串尾则退出{if (X <= 0xF) //X坐标应小于0xF{DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符ListLength++;X++;}}}//5ms延时void Delay5Ms(void){unsigned int TempCyc = 5552;while(TempCyc--);}//400ms延时void Delay400Ms(void){unsigned char TempCycA = 5;unsigned int TempCycB;while(TempCycA--){TempCycB=7269;while(TempCycB--);};}/********************************************************/ void Conut(void){time=TH0*256+TL0;TH0=0;TL0=0;S=(time*1.7)/100; //算出来是CMif((S>=700)||flag==1) //超出测量范围显示"-"{flag=0;DisplayOneChar(0, 1, ASCII[11]);DisplayOneChar(1, 1, ASCII[10]); //显示点DisplayOneChar(2, 1, ASCII[11]);DisplayOneChar(3, 1, ASCII[11]);DisplayOneChar(4, 1, ASCII[12]); //显示M}else{disbuff[0]=S%1000/100;disbuff[1]=S%1000%100/10;disbuff[2]=S%1000%10 %10;DisplayOneChar(0, 1, ASCII[disbuff[0]]);DisplayOneChar(1, 1, ASCII[10]); //显示点DisplayOneChar(2, 1, ASCII[disbuff[1]]);DisplayOneChar(3, 1, ASCII[disbuff[2]]);DisplayOneChar(4, 1, ASCII[12]); //显示M}}/********************************************************/ void zd0() interrupt 1 //T0中断用来计数器溢出,超过测距范围{flag=1; //中断溢出标志}/********************************************************/ void StartModule() //启动模块{TX=1; //启动一次模块_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();TX=0;}//--------------------------------------------void fun2(void){ P10=1;P11=0;P12=1;P13=0;} //前进void fun3(void){ P10=0;P11=0;P12=1;P13=0;}//左转void fun4(void){ P10=1;P11=0;P12=0;P13=0;} //右转void fun5(void){ P10=0;P11=0;P12=0;P13=0;}//停止/********************************************************/void timer1() interrupt 3 //T0中断用来计数器溢出,超过测距范围{Flg_5ms=1;TH1=0xee;TL1=0;TF1=0;if(P14==1&&P15==0&&P16==1) fun2();if((P14==0&&P15==0&&P16==1)||(P14==0&&P15==1&&P16==1)) fun3();if((P14==1&&P15==0&&P16==0)||(P14==1&&P15==1&&P16==0)) fun4();if((P14==1&&P15==1&&P16==1)||(P14==0&&P15==0&&P16==0)||(P17==0)) fun5(); }//-------------------------------------------void Timer2() interrupt 5 //定时器2捕捉中断,溢出中断{if(TF2){if(speed_t2_ovf_count_temp < 2) speed_t2_ovf_count_temp++;else{speed_frequency = 0; // frequencyspeed_catch1 = 0; //catch 1speed_catch2 = 0; //catch 2speed_catch_p = 0; //catch pointerspeed_t2_ovf_count_temp = 0; //T2 overflow counter temp registerspeed_t2_ovf_count = 0; //T2 overflow counter registerSpeed=0;}TF2=0;}if(EXF2){switch(speed_catch_p){case 0:speed_catch1 = RCAP2H;speed_catch1 <<=8;speed_catch1 += RCAP2L;speed_catch_p++;break;case 1:speed_catch2 = RCAP2H;speed_catch2 <<=8;speed_catch2 += RCAP2L;speed_t2_ovf_count = speed_t2_ovf_count_temp;speed_catch_p++;break;default:break;}speed_t2_ovf_count_temp = 0;EXF2=0;}}/*********************************************************/void main(void){unsigned char TempCyc;unsigned long temp;Delay400Ms(); //启动等待,等LCM讲入工作状态LCMInit(); //LCM初始化Delay5Ms(); //延时片刻(可不要)DisplayListChar(0, 0, mcustudio);DisplayListChar(0, 1, email);ReadDataLCM();//测试用句无意义for (TempCyc=0; TempCyc<10; TempCyc++)Delay400Ms(); //延时DisplayListChar(0, 1, Cls);Speed=0;speed_frequency = 0; // frequencyspeed_catch1 = 0; //catch 1speed_catch2 = 0; //catch 2speed_catch_p = 0; //catch pointerspeed_t2_ovf_count_temp = 0; //T2 overflow counter temp registerspeed_t2_ovf_count = 0; //T2 overflow counter registerwhile(1){TMOD=0x11; //设T0为方式1,GATE=1;TH0=0;TL0=0;TH1=0xee;TL1=0;T2CON = 0x09; //捕捉模式ET0=1; //允许T0中断ET1=1; //允许T0中断ET2=1;EA=1; //开启总中断TR1=1; //开启计数TR2=1;while(1){if(Flg_5ms){Flg_5ms=0;if(Counter_100ms<39){Counter_100ms++;if(Counter_100ms==20){if(speed_catch_p > 1){temp =(unsigned long)(( 65536UL * speed_t2_ovf_count)+ speed_catch2 - speed_catch1); //calculate TSpeed= (unsigned int)(9584640UL / temp);speed_catch_p = 0;}if(Speed >9999U) Speed=9999U;buf[0]=Speed/1000;buf[1]=(Speed/100)%10;buf[2]=(Speed/10)%10;buf[3]=Speed %10;DisplayOneChar(8, 1, ASCII[buf[0]]);DisplayOneChar(9, 1, ASCII[buf[1]]);DisplayOneChar(10, 1, ASCII[buf[2]]);DisplayOneChar(11, 1, ASCII[buf[3]]);DisplayOneChar(12, 1, 'm'); //显示MDisplayOneChar(13,1, 'm'); //显示MDisplayOneChar(14,1, '/');DisplayOneChar(15,1, 's');}}else{Counter_100ms=0;StartModule();// DisplayOneChar(0, 1, ASCII[0]);TH0=0;TL0=0;while(!RX); //当RX为零时等待TR0=1; //开启计数while(RX); //当RX为1计数并等待TR0=0; //关闭计数Conut(); //计算}}}}}。
51单片机 频率计 1602
电子产品设计与开发结课论文题目:其于51单片机的频率计设计与仿真班级:电子1104班姓名:陈** (组员)学号:03 电话:1376******成员:曾* (组长)学号:29 电话:13726****** 成员:孙* (组员)学号:21 电话:137*******目录一、需求分析二、方案设计1设计基本原理 (4)1.1测量频率的原理 (4)1.2系统设计框图 (4)三、软件设计 (5)1资源分配表 (5)2程序流程框图 (6)四、系统硬件线路设计图 (7)1 单片机最小系统设计 (7)2 液晶LCD1602显示电路 (8)3 频率测量电路 (11)五.系统仿真、测试结果及性能分析 (12)1系统仿真、测试结果 (12)2性能分析 (13)六、心得与体会 (14)七、参考文献 (14)摘要本设计提出了一种基于AT89C51单片机开发的数字频率测量仪的设计。
系统以单片机AT89C51为核心,构成完备的测量系统。
可以对信号进行频率的精确测量,测频在1Hz至10kHZ。
采用液晶LCD1602显示被测信号的频率。
与传统的电路系统相比,其有处理速度快、稳定性高、性价比高、硬件结构简单的优点。
关键词:单片机;低频;绝对误差一、需求分析频率测量在科技研究和实际应用中的作用日益重要。
传统的频率计通采用组合电路和时序电路等大量的硬件电路构成,产品不但体积较大,运行速度慢,而且测量低频信号时不宜直接使用。
频率信号抗干扰性强、易于传输,可以获得较高的测量精度。
同时,频率测量方法的优化也越来越受到重视.并采用AT89C51 单片机和相关硬软件实现。
MCS—51系列单片机具有体积小,功能强,性能价格比较高等特点,因此被广泛应用于工业控制和智能化仪器,仪表等领域。
我们研制的频率计以89c51单片机为核心,具有性能优良,精度高,可靠性好等特点。
二、设计方案此次课程设计采用间接测量法来测量。
要用到GATE信号,GATE=1时,TR0=1,INTO=1才能启动计数器,而计数器0是通过外部中断INTO的下降沿开始触发的,计时器从0开始计时,计数器只能测高电平,因此测得的时间为半个周期。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
电子产品设计与开发结课论文题目:其于51单片机的频率计设计与仿真班级:电子1104班姓名:陈** (组员)学号:03 电话:1376******成员:曾* (组长)学号:29 电话:13726****** 成员:孙* (组员)学号:21 电话:137*******目录一、需求分析二、方案设计1设计基本原理 (4)1.1测量频率的原理 (4)1.2系统设计框图 (4)三、软件设计 (5)1资源分配表 (5)2程序流程框图 (6)四、系统硬件线路设计图 (7)1 单片机最小系统设计 (7)2 液晶LCD1602显示电路 (8)3 频率测量电路 (11)五.系统仿真、测试结果及性能分析 (12)1系统仿真、测试结果 (12)2性能分析 (13)六、心得与体会 (14)七、参考文献 (14)摘要本设计提出了一种基于AT89C51单片机开发的数字频率测量仪的设计。
系统以单片机AT89C51为核心,构成完备的测量系统。
可以对信号进行频率的精确测量,测频在1Hz至10kHZ。
采用液晶LCD1602显示被测信号的频率。
与传统的电路系统相比,其有处理速度快、稳定性高、性价比高、硬件结构简单的优点。
关键词:单片机;低频;绝对误差一、需求分析频率测量在科技研究和实际应用中的作用日益重要。
传统的频率计通采用组合电路和时序电路等大量的硬件电路构成,产品不但体积较大,运行速度慢,而且测量低频信号时不宜直接使用。
频率信号抗干扰性强、易于传输,可以获得较高的测量精度。
同时,频率测量方法的优化也越来越受到重视.并采用AT89C51 单片机和相关硬软件实现。
MCS—51系列单片机具有体积小,功能强,性能价格比较高等特点,因此被广泛应用于工业控制和智能化仪器,仪表等领域。
我们研制的频率计以89c51单片机为核心,具有性能优良,精度高,可靠性好等特点。
二、设计方案此次课程设计采用间接测量法来测量。
要用到GATE信号,GATE=1时,TR0=1,INTO=1才能启动计数器,而计数器0是通过外部中断INTO的下降沿开始触发的,计时器从0开始计时,计数器只能测高电平,因此测得的时间为半个周期。
当计数器0计时溢出,执行m加1的操作。
则测量时间为:t1=TH0*256+TL0+m*65536 ,所求频率F=1000000/(2*t1) 1设计基本原理1.1测量频率的原理定时/计数器工作在方式1,每产生一次定时器0中断,计数65536个脉冲,此时的脉冲来自振荡器的12分频后的脉冲,其周期为1uS。
根据产生外部中断0时,定时器0中断的次数u,以及此时定时/计数器0计数寄存器的数值X,即可求得待测方波的周期为:T=(65536*u+X)us ,取其倒数即可求得待测方波的频率,小数点后保留两位,即可使得频率精度为0.1HZ。
1.2系统设计框图经过方案论证和比较后,最终确定的系统框图如图1所示,主要由AT89C51单片机、异或器件、LCD1602、电源等组成。
图2 系统设计框图三、软件设计1资源分配表表5 资源分配表I/O口作用P0 LCD1602数据接口P1.6 LCD1602 RW接口P1.7 LCD1602 RS接口P2.4 LCD1602 E接口P3.2 频率测量接口2程序流程框图频率程序流程图如图9所示:图10 程序流程图四、系统硬件线路设计图1 单片机最小系统设计单片机最小系统是能补足单片机工作的最简单电路,它由单片机、电源、晶体振荡器、复位电路等构成。
它是本系统的处理单元也是控制单元,负责处理信号、外设的接口与控制,同时它也是所有软件的载体。
本系统采用AT89C51是美国Atmel公司生产的低电压、高性能CMOS 8位单片机,片内含4KB的可反复檫写的程序存储器和12B的随机存取数据存储器(RAM),器件采用Atmel 公司的高密度、非易失性存储技术生产,片内配置通用8位中央处理器(CPU)和Flash存储单元,功能强大的AT89C51单片机可灵活应用于各种控制领域。
与Intel公司的80C51在引脚排列、硬件组成、工作特点和指令系统等方面兼容。
主要管脚有:XTAL1(19 脚)和XTAL2(18 脚)为振荡器输入输出端口,外接12MHz 晶振。
RST/Vpd(9 脚)为复位输入端口,外接电阻电容组成的复位电路。
VCC(40 脚)和VSS(20 脚)为供电端口,分别接+5V电源的正负端。
P0~P3 为可编程通用I/O 脚,其功能用途由软件定义。
其管脚如下图所示:图3 AT89C51单片机管脚图本设计中,P0 端口(32~39 脚)被定义为N1 功能控制端口,分别与N1的相应功能管脚相连接。
单片机正常工作时,都需要有一个时钟电路和一个复位电路。
本设计中选择了内部时钟方式和按键电平复位电路,来构成单片机的最小电路。
如图3所示。
图4 单片机最小系统2液晶LCD1602显示电路字符型液晶显示模块是一种专门用于显示字母、数字、符号等点阵式LCD,目前常用16*1,16*2,20*2和40*2行等的模块。
LCD1602分为带背光和不带背光两种,基控制器大部分为HD44780,带背光的比不带背光的厚,是否带背光在应用中并无差别。
LCD1602采用标准的14脚(无背光)或16脚(带背光)接口,各引脚接口说明如下表1所示:表 1 LCD1602引脚接口说明编号符号引脚说明编号符号引脚说明1 VSS 电源地9 D2 数据2 VDD 电源正极10 D3 数据3 VL 液晶显示偏压11 D4 数据4 RS 数据/命令选择12 D5 数据5 R/W 读/写选择13 D6 数据6 E 使能信号14 D7 数据7 D0 数据15 BLA 背光源正极8 D1 数据16 BLK 背光源负极1602液晶模块的读写操作、屏幕和光标的操作都是通过指令编程来实现的。
1602液晶模块内部的控制器共有11条控制指令,如下表2所示,其中1为高电平、0为低电平。
表 2 LCD1602控制指令指令1:清显示,指令码01H,光标复位到地址00H位置。
指令2:光标复位,光标返回到地址00H。
指令3:光标和显示模式设置 I/D:光标移动方向,高电平右移,低电平左移 S:屏幕上所有文字是否左移或者右移。
高电平表示有效,低电平则无效。
指令4:显示开关控制。
D:控制整体显示的开与关,高电平表示开显示,低电平表示关显示 C:控制光标的开与关,高电平表示有光标,低电平表示无光标 B:控制光标是否闪烁,高电平闪烁,低电平不闪烁。
指令5:光标或显示移位 S/C:高电平时移动显示的文字,低电平时移动光标。
指令6:功能设置命令 DL:高电平时为4位总线,低电平时为8位总线 N:低电平时为单行显示,高电平时双行显示 F: 低电平时显示5x7的点阵字符,高电平时显示5x10的点阵字符。
指令7:字符发生器RAM地址设置。
指令8:DDRAM地址设置。
指令9:读忙信号和光标地址 BF:为忙标志位,高电平表示忙,此时模块不能接收命令或者数据,如果为低电平表示不忙。
指令10:写数据。
与HD44780相兼容的芯片时序如下表3所示:表 3 基本操作时序表读状态输入RS=L,R/W=H,E=H 输出D0—D7=状态字写指令输入RS=L,R/W=L,输出无D0—D7=指令码,E=高脉冲读数据输入RS=H,R/W=H,E=H 输出D0—D7=数据写数据输入RS=H,R/W=L,输出无D0—D7=数据,E=高脉冲其操作时序图如下所示:图5 读操作时序图图6 写操作时序图本设计中采用液晶LCD1602显示输入方波A的频率,其D0~D7与单片机的P0端口连接,使能端E、RS、RW分别与单片机P2.4、P1.7、P1.6连接,此电路原理简单,电路连接方便,如图7所示。
图7 液晶LCD1602显示电路3频率测量电路本设计中将方波A输入,采用定时中断测量其频率。
如图7所示。
图8 频率测量电路综上所述,频率的总体电路图如图9所示:图9 频率计的总体电路图五.系统仿真、测试结果及性能分析1系统仿真、测试结果在仿真软件PROTUES中按照电路图连接好电路。
输入待测方波信号波形,当测试频率时,先依次设置好方波A的频率,进行仿真测得数据;测试波形和结果如图11所示:图11 仿真波形输入频率/HZ 1 2 10 50 100 200 500测得频率/HZ 0.99 1.99 10.00 50.00 100.00 200.01 500.00输入频率/HZ 900 1000 1024 1234 2000 5000 10000测得频率/HZ 899.92 1000.64 1024.23 1234.20 2000.92 5000.48 10000.602性能分析根据表6测试所得结果可以看出:,频率范围为1Hz~3000HZ;频率误差少于1Hz.当输入频率大于4000HZ时,频率误差小于6HZ,并且随着输入频率增大,频率误差逐渐增大。
由此可得如下结论:本次所设计的频率适合测试低频信号,最佳频率范围为1-3000HZ,输入方波任意均可。
六、心得与体会刚刚拿到做频率计这个题目时,我们的感觉可以说是比较轻松的,在一开始的时候也不算太着急。
过了几天后,我和几个组员开始打算动手去做了,这时才感觉到频率计不是那么容易做的。
虽然心中有个大概的想法,但要实施起来时才觉得不知从哪里入手。
可是我们还是硬着头皮做了,我和组长曾潜,组员孙凯开始上网了解频率计的具体做法。
通过几个小时的讨论,终于大概定出了本次设计的思路、流程与分工。
在本次的设计中,我主要负责做PCB版和协助组长曾潜设计详细的程序。
通过好几天的努力,我们终于做出了最初的设计,但是程序在仿真图片中的显示不正常,误差也很大。
我们三人通过不断的修改,调试,终于,做出了基本符合要求的51单片机频率计。
这次的频率计设计,虽然在过程中也走了不少的弯路,但终究是学到许多知识,学到课堂上没有的知识,除了实践上的,理论上的知识也有。
除此之外,我还认识到了与人合作的重要性,这次设计如果只是我一个人做是很有可能做不出来的,在设计中往往会遇到一些个人弄很长时间都弄不明白的地方,但几个人一起讨论后就往往会害然开朗。
由于本次设计时间的安排还是不够合理,设计中还有很多不够完美的地方,系统中还有许多有待改进的地方。
最后,要感谢老师,给我们一个把理论应用到实践的机会,也感谢同学们在我困难的时候能伸出援手,谢谢。
七、参考文献【1】周美娟、肖来胜编著。
《单片机技术及系统设计》,清华大学出版社【2】谭浩强编著。
《C程序设计》,清华大学出版社附录一:仿真图附录二:原理图附录三:PCB图附录四:源程序#include<reg51.h>#include<math.h>#define uint unsigned int#define uchar unsigned charuchar m=0;uchar u;uint i;uint x;uint c; //相位数据结果保存float t0,f;uint a[]={70,61,48,48,48,48,48,46,48,48,72,90}; //频率数据结果保存//F,=,0,0,0,0,0,.,0,0,H,Zsbit lcdrw=P1^6;sbit lcdrs=P1^7;sbit lcden=P2^4;/////////////////LCD1602的设置////////////////////////////////// void delay(uint s)//延时1MS{uint r,g;for(r=s;r>0;r--)for(g=110;g>0;g--);}void write_com(uchar com) // 写指令{lcdrs=0;P0=com;delay(5);lcden=1;delay(5);lcden=0;}void write_data(uchar date) // 写数据{lcdrs=1;P0=date;delay(5);lcden=1;delay(5);lcden=0;}void initlcd()//初始化{lcdrw=0;lcden=0;//write_com(0x01);//显示清屏write_com(0x38);//显示模式设置write_com(0x0c); //显示开,开游标,不闪烁write_com(0x06); // 字符时整体不移动}////////////LCD1602设置//////////////////////////定时器的设置//////////////void CT_init() //定时计数器初始化{ TMOD=0x99; //GATE=1,T1、T0工作在方式1,定时方式TH0=0; //定时计数器初值清零TL0=0;// TH1=0;// TL1=0;TR0=1; //TR0,TR1置位,此时定时计数器的启动有INT0,INT1引脚电平决定// TR1=1;ET0=1; //开中断// ET1=1;}void ITC0() interrupt 0 //外部中断0服务程序{u=m; //读定时计数器0溢出次数m=0; //溢出次数清零x=TH0*256+TL0; //读定时计数器0当前值TH0=0; //定时计数器0清零TL0=0;}void TIME0() interrupt 1 //定时计数器0溢出中断{m++; //溢出次数加1}////////////定时器的设置//////////////void main(){initlcd(); //液晶显示初始化CT_init(); //定时计数器初始化EA=1; //开总中断EX0=1; //允许外部中断// EX1=1;IT0=1; //设置外部中断方式为下降沿触发// IT1=1;P3=0xff;while(1){t0=u*65536+x; //计算脉冲时间宽度f=1000000/(2*t0); //计算频率c=f*100; //计算结果逐位保存a[9]=c%10+48;a[8]=(c/10)%10+48;c=f;a[6]=c%10+48;a[5]=(c/10)%10+48;a[4]=(c/100)%10+48;a[3]=(c/1000)%10+48;a[2]=(c/10000)%10+48;write_com(0x80);for(i=0;i<=11;i++){write_data(a[i]);delay(10);}}}。