在Proteus仿真软件里面使用STC89C52实现指定频率的AC信号的测频、显示、双机通信。 整体的电路图如示: 运行结果如下: 可以准确测量出结果,并在LCD上显示,单片机1测量到频率后通过串口发送给单片机2,然后在单片机2的LCD上再次显示。 本来单片机2还负责给DC-AC电路产生控制信号的,在这里我忽略了DC-AC电路部分,所以控制信号的代码可有可无。一.原理图部分
 
 DC-AC电路部分的输出就使用信号源直接模拟了。
 原理图如下:
 
 
二.源码部分
单片机1
 /*单片机1功能:  *1.测量AC的频率20Hz,T0检测上升沿、T1进行计时  *2.LED显示实时测量频率  *3.与单片机2串口通信,T2提供波特率  *晶振频率:11.0592MHz  */ #include <reg52.h> #include <stdio.h> #include <intrins.h> #include <string.h> #define uint unsigned int #define uchar unsigned char   sfr T2MOD=0XC9; //寄存器T2MOD定义 /********************* LCD驱动 ************************************/ /* LCD引脚说明 */ sbit RS = P2^0; sbit RW = P2^1; sbit EN = P2^2; /*说明:延时函数  *参数:延时的ms数  */ void DelayMS(uint ms) {   uchar i; while(ms--) { for(i=0;i<120;i++); } } /*说明:LCD读  *参数:返回读取的值  */ uchar Read_LCD_State() {   uchar state;  RS=0;  RW=1;  EN=1; DelayMS(1);  state=P0;  EN = 0; DelayMS(1); return state; } /*说明:LCD忙判断  *参数:无  */ void LCD_Busy_Wait() { while((Read_LCD_State()&0x80)==0x80); DelayMS(5); } /*说明:向LCD写1Byte数据  *参数:写入的数据  */ void Write_LCD_Data(uchar dat) { LCD_Busy_Wait();  RS=1;  RW=0;  EN=0;  P0=dat;  EN=1; DelayMS(1);  EN=0; } /*说明:LCD写命令  *参数:cmd:写入的命令  */ void Write_LCD_Command(uchar cmd) { LCD_Busy_Wait();  RS=0;  RW=0;  EN=0;  P0=cmd;  EN=1; DelayMS(1);  EN=0; } /*说明:LCD初始化  *参数:无  */ void Init_LCD() { Write_LCD_Command(0x38); DelayMS(1); Write_LCD_Command(0x01); DelayMS(1); Write_LCD_Command(0x06); DelayMS(1); Write_LCD_Command(0x0c); DelayMS(1); } /*说明:LCD定位显示  *参数:0X00第一行  0X40第二行  */ void Set_LCD_POS(uchar p) { Write_LCD_Command(p|0x80); } /*说明:LCD显示函数  *参数:p:位置信息  *     *s:显示的字符串(一行只能显示16个字符)  */ void Display_LCD_String(uchar p,uchar *s) {   uchar i; Set_LCD_POS(p); for(i=0;i<16;i++) { /* 写数据 */ Write_LCD_Data(s[i]); DelayMS(1); } } /******************************* 测频驱动 *************************************************/ long uint pulse=0; //T0计数的方波的个数; long uint freq=0; //输入信号的频率 uchar temp=0; //临时变量 /*说明:定时器/计数器初始化函数  *T0的工作方式为16位计数器模式,用来记录上升沿   *T1的工作方式为16位定时器模式,用来计时  *  *参数:无  */ void Time_Init() {  EA=1; //打开全局中断  TMOD |= 0x15; //T0:16位计数器模式  T1:16位定时器模式     TH0 = 0xff; //计数器0的初值  TL0 = 0xff; //计数器0的初值  ET0=1; //允许计数器0中断  TR0=1; //打开计数器0,开始计数   TH1 = 0x4b; //定时器1的初值  TL1 = 0xff; //定时器1的初值  ET1=1; //允许定时器1中断  TR1 = 1; //打开定时器1,开始计数   } /*说明:T0的中断服务函数,用来计数脉冲数,每一个方波脉冲,计数器进入中断,脉冲数+1  *参数:无  */ void ISQ_timer0(void) interrupt 1 {  TR0 = 0;  pulse++;  TH0  = 0xff;  TL0  = 0xff;  TR0 = 1; } /*说明:T1的中断服务函数,每次中断代表50ms,测量20次中断(1s)的脉冲数就是频率  *参数:无  */ void ISQ_time1() interrupt 3 {  TH1  = 0x4b; //11.0592MHz,50ms定时的重装值  TL1  = 0xff;  temp++; if(temp==20) {   TR0 = 0; //进入处理时,关闭   TR1 = 0;   temp=0;   freq=pulse;   pulse=0; //将脉冲数清零,重新计数   TR0 = 1; //处理完毕,打开   TR1 = 1; } } /************************************ T2uart *************************************************/ /*说明:uart配置,T2作为波特率发生定时器  *参数:无  */ void uart_config(void) {    T2MOD = 0x01; //自动重载  T2CON = 0x30; //T2用做发送接收时钟  TH2 = 0xFF; //9600波特率,11.0592Mhz晶振  TL2 = 0xDC;   RCAP2H = 0xFF;   RCAP2L = 0xDC;   SCON = 0x50; //串口方式1,1个起始位,1个停止位,8位数据,可变波特率  PCON = 0X00; //波特率不加倍   TR2 = 1; //启动T2   ES = 1; //开串口中断    EA = 1; //开总中断 } /*说明:uart发送一个字符  *参数:byte:发送的字符  */ void uart_send_byte( uchar byte ) {  ES=0;  SBUF=byte; while(!TI);  TI=0;  ES=1; } /*说明:uart发送字符串,固定长度为16*uchar  *参数:*str:发送的字符串首地址  */ void uart_send_str( uchar *str ) {  uint i=0; for( i=0;i<16;i++ ) { uart_send_byte(str[i]); } } void main() {   uchar temp[16]; //定义字符显示缓存数组 Time_Init(); //T0、T1初始化 uart_config(); //uart初始化,主要是T2初始化波特率 Init_LCD(); //LCD初始化 while(1) { sprintf(temp,"FREQ:%08.0fHz",(float)freq); Display_LCD_String(0X40,temp); uart_send_str(temp); } } 单片机2
/*单片机2功能:  *1.与单片机1进行串口通讯,接收测量的AC频率  *2.LED显示实时单片机1传回的测量频率  *3.为DC-AC逆置电路提供信号  *晶振频率:11.0592MHz  */ #include <reg52.h> #include <stdio.h> #include <intrins.h> #include <string.h> #define uint unsigned int #define uchar unsigned char #define  uint8_t uint /********************* 控制信号发生 ************************************/ //为DC-AC电路提供稳定的20Hz脉冲信号 sbit O1_4 = P2^3 ; sbit O2_3 = P2^4;  sbit G1=P1^2; sbit G2=P1^3; sbit G3=P1^4; sbit G4=P1^5; sbit G5=P1^6; sbit G6=P1^7; unsigned int time1; unsigned int time2; /*说明:T0初始化,利用T0输出PWM脉冲信号  *参数:无  */ void Timer0_Init(void) //1毫秒@11.0592 {  TMOD |= 0x01;  TH0 = 0xfc;  TL0 = 0x66;  TF0 = 0;  EA = 1;  TR0 = 1;  ET0 = 1; } /*说明:T0中断服务函数,产生PWM脉冲信号  *参数:无  */ void time0() interrupt 1 { TH0=0xfc; TL0=0x66;  time1++;  time2++; /* 单相 */ if((time1>=0)&&(time1<=25)){O1_4=1;O2_3=0;} if((time1>25)&&(time1<=50)){O1_4=0;O2_3=1;} if(time1>50)time1=0; /* 三相 */ if(time2>0&&time2<=8){G1=1;G2=0;G3=0;G4=0;G5=1;G6=1;} if(time2>8&&time2<=16){G1=1;G2=1;G3=0;G4=0;G5=0;G6=1;} if(time2>16&&time2<=24){G1=1;G2=1;G3=1;G4=0;G5=0;G6=0;} if(time2>24&&time2<=32){G1=0;G2=1;G3=1;G4=1;G5=0;G6=0;} if(time2>32&&time2<=40){G1=0;G2=0;G3=1;G4=1;G5=1;G6=0;} if(time2>40&&time2<=48){G1=0;G2=0;G3=0;G4=1;G5=1;G6=1;} if(time2>48)time2=0; }//50ms的周期 /********************* LCD驱动 ************************************/ /* LCD引脚 */ sbit RS = P2^0; sbit RW = P2^1; sbit EN = P2^2; /*说明:延时函数  *参数:延时的ms数  */ void DelayMS(uint ms) {   uchar i; while(ms--) { for(i=0;i<120;i++); } } /*说明:LCD读  *参数:返回读取的值  */ uchar Read_LCD_State() {   uchar state;  RS=0;  RW=1;  EN=1; DelayMS(1);  state=P0;  EN = 0; DelayMS(1); return state; } /*说明:LCD忙判断  *参数:无  */ void LCD_Busy_Wait() { while((Read_LCD_State()&0x80)==0x80); DelayMS(5); } /*说明:向LCD写1Byte数据  *参数:写入的数据  */ void Write_LCD_Data(uchar dat) { LCD_Busy_Wait();  RS=1;  RW=0;  EN=0;  P0=dat;  EN=1; DelayMS(1);  EN=0; } /*说明:LCD写命令  *参数:cmd:写入的命令  */ void Write_LCD_Command(uchar cmd) { LCD_Busy_Wait();  RS=0;  RW=0;  EN=0;  P0=cmd;  EN=1; DelayMS(1);  EN=0; } /*说明:LCD初始化  *参数:无  */ void Init_LCD() { Write_LCD_Command(0x38); DelayMS(1); Write_LCD_Command(0x01); DelayMS(1); Write_LCD_Command(0x06); DelayMS(1); Write_LCD_Command(0x0c); DelayMS(1); } /*说明:LCD定位显示  *参数:0X00第一行  0X40第二行  */ void Set_LCD_POS(uchar p) { Write_LCD_Command(p|0x80); } /*说明:LCD显示函数  *参数:p:位置信息  *     *s:显示的字符串(一行只能显示16个字符)  */ void Display_LCD_String(uchar p,uchar *s) {   uchar i; Set_LCD_POS(p); for(i=0;i<16;i++) { /* 写数据 */ Write_LCD_Data(s[i]); DelayMS(1); } } /************************************ T1uart *************************************************/ /*说明:uart初始化函数,T1为uart提供9600波特率  *参数:无  */ void uart_config(void) {     TMOD |= 0x20; //设置定时器1的工作方式2---8位自动装填     SCON = 0x50;     TH1 = 0xfd; //设置初始值:使比特率为9600bps     TL1 = 0xfd;     PCON = 0x00; //SMOD=0,不加倍     EA = 1; //打开总中断     ES = 1; //打开串口通讯中断     TR1 = 1; //打开定时器中断开关 }   uchar Rx_Str[16]={0}; //接收缓存 uint state; //接收状态:1:正在接收   0:接收完毕 volatile uint i=0; /*说明:uart中断处理函数,进行解析数据帧  *参数:无  */ void uart_receive() interrupt 4 {  uchar num; if(1==RI) {   RI=0; //清除标志位   num=SBUF; //从计算机接收数据,赋给num if( num == 'F' ) //解析帧头 {    state = 1; } if( Rx_Str[i-1] == 'z' ) //解析帧尾 {    state = 0;    i=0; } if( 1 == state ) //缓存数据 {    Rx_Str[i++] = num; } } } void main() { Timer0_Init(); //T0初始化,产生脉冲信号 uart_config(); //uart初始化,接收串口数据 Init_LCD(); //LCD初始化,显示接收的数据帧 while(1) { Display_LCD_String(0X40,Rx_Str); } } 
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算
 官方软件产品操作指南 (170)
官方软件产品操作指南 (170)