博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Proteus仿真—51单片机实现AC信号测频、显示、双机通信
阅读量:3953 次
发布时间:2019-05-24

本文共 7157 字,大约阅读时间需要 23 分钟。

文章目录

在Proteus仿真软件里面使用STC89C52实现指定频率的AC信号的测频、显示、双机通信。

一.原理图部分

整体的电路图如示:

在这里插入图片描述
DC-AC电路部分的输出就使用信号源直接模拟了。
原理图如下:
在这里插入图片描述

运行结果如下:

在这里插入图片描述

可以准确测量出结果,并在LCD上显示,单片机1测量到频率后通过串口发送给单片机2,然后在单片机2的LCD上再次显示。

二.源码部分

单片机1

/*单片机1功能: *1.测量AC的频率20Hz,T0检测上升沿、T1进行计时 *2.LED显示实时测量频率 *3.与单片机2串口通信,T2提供波特率 *晶振频率:11.0592MHz */ #include 
#include
#include
#include
#define uint unsigned int#define uchar unsigned charsfr 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还负责给DC-AC电路产生控制信号的,在这里我忽略了DC-AC电路部分,所以控制信号的代码可有可无。

/*单片机2功能: *1.与单片机1进行串口通讯,接收测量的AC频率 *2.LED显示实时单片机1传回的测量频率 *3.为DC-AC逆置电路提供信号 *晶振频率:11.0592MHz */#include 
#include
#include
#include
#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); }}

转载地址:http://kvwzi.baihongyu.com/

你可能感兴趣的文章
CoreLocation笔记 by STP
查看>>
Application Transport Security has blocked a cleartext HTTP (http://) 解决方案
查看>>
The identity used to sign the executable is no longer valid.解决方案
查看>>
Xcode增加pch文件
查看>>
CocoaPods安装和使用笔记 by STP
查看>>
Could not find developer disk image-解决方案
查看>>
升级Xcode之后VVDocumenter-Xcode不能用的解决办法
查看>>
iOS开发常见报错及解决方案 by STP
查看>>
SVN(Cornerstone)屏蔽/忽略不需要版本控制的UserInterfaceState.xcuserstate
查看>>
IOS 8 以上版本 设置applicationIconBadgeNumber和消息推送
查看>>
git常用命令
查看>>
Java 基本数据类型笔记by STP
查看>>
IDEA创建Maven项目时 loading archetype list转菊花转十年解决方案
查看>>
Mac启动tomcat
查看>>
报错: java.sql.SQLException: The server time zone value '�й�' is unrecognized or represents more ...
查看>>
使用xshell对服务器上的sql文件进行操作(mysql导入Linux)
查看>>
Spirngboot 后台操作一切正常并无报错,但是前端出现404错误
查看>>
java错误:java.lang.String can not be cast to java.math.BigDecimal
查看>>
Linux导出数据库文件mysql
查看>>
xshell查看程序代码后台的动态日志
查看>>