基于51单片机的4路交流电机电流监测系统Protues仿真

功能:
0.本项目采用STC89C52作为单片机系统的控制MCU
1.系统实时显示当前监测的4路电流,当检测的电流超过阈值时,蜂鸣器报警,并串口上报过流通道电流信息,
用户可通过串口发送命令的方式控制对应通道的继电器,同时关闭报警
2.按键可更改电流阈值,电流阈值掉电不丢失
控制命令:*Cx# 闭合继电器(x对应1/2/3/4/A) *Bx# 断开继电器(x对应1/2/3/4/A) A代表全部
3.采用DC002作为电源接口可直接输入5V给整个系统供电

仿真图:
在这里插入图片描述

主程序:

#include "main.h"
#include "math.h"

bit refreshFlag = 1;
bit isNewFlag = 1;

enum _MODE_DF_ dispMode;
xdata float f_cur[4]; //单位A
float f_curVolt = 0.0; //单位V
int curMax[4]; //过流阈值单位mA

unsigned char setIndex = 0; //设定位置
unsigned char setChannel = 0; //设定通道
unsigned char cnt = 0;
unsigned char channel = 0;
unsigned char sendDelay = 0; //串口发送数据延时

xdata char dis0[16]; //定义显示区域临时存储数组

void main(void)
{

    EEPROM_Init();
    ReadData();
    // isNewFlag = 1;
    if (isNewFlag != 0) //新芯片
    {
        EEPROM_WriteByte(ISNEW_ADDRESS, 0);
        //给出初始值
        curMax[0] = 1000;
        curMax[1] = 1100;
        curMax[2] = 1200;
        curMax[3] = 1300;
        WriteData();
    }

    LCD_Init();   //初始化液晶
    DelayMs(200); //延时有助于稳定
    UART_Init(); //初始化串口
    LCD_DispStr(0, 0, "    Welcome!    ");
    DelayS(1);

    DelayS(1);
    
    Timer0_Init();
    
    RELAY1 = CLOSE;
    RELAY2 = CLOSE;
    RELAY3 = CLOSE;
    RELAY4 = CLOSE;
    BUZZER = OFF;
    
    while (1) //主循环
    {
        
        if (refreshFlag == 1) //500ms获取数据并发送
        {
            refreshFlag = 0;
            
            CD5051_SelChannel(channel);

            for (cnt = 0; cnt < 50; cnt++) //采集50次数据
            {
                f_curVolt = f_curVolt + 5 * (ReadADC(AIN0_GND)-1) / 255; //转换电流 ReadADC(AIN0_GND)-1仿真需要减1,因protues中最小输出code值为1
                DelayUs10x(10);
            }
            
            f_cur[channel] = f_curVolt / 50 * 2000 / 150; //求平均后计算电流,电阻150欧姆 I = U * 2000 / R (A)
            f_curVolt = 0;

            if ((f_cur[channel]*1000) > curMax[channel]) //电流超过阈值范围
            {
                BUZZER =  ON;
                SendData(channel); //发送错误通道电流及阈值电流
            }

            //液晶显示
            if (dispMode == NORMAL)
            {
                DispNormal();
            }
            channel++;
            if (channel > 3)
            {
                channel = 0;
            }
        }

        KeyProcess();
    }
}

/************************* 正常显示 *************************/
void DispNormal()
{
    sprintf(dis0, "1:%4.1fA  2:%4.1fA", (float)f_cur[0], (float)f_cur[1]);
    LCD_DispStr(0, 0, dis0);
    sprintf(dis0, "3:%4.1fA  4:%4.1fA", (float)f_cur[2], (float)f_cur[3]);
    LCD_DispStr(0, 1, dis0);
}

/************************* 显示电流阈值 *************************/
void DispSetCurrentLimit(unsigned char channel, unsigned char setIndex)
{
    sprintf(dis0, "  Max Current %1d ", (int)channel+1); //打印
    LCD_DispStr(0, 0, dis0);

    sprintf(dis0, "      %4.1f A    ", (float)curMax[channel]/1000); //打印
    LCD_DispStr(0, 1, dis0);

    switch (setIndex)
    {
        case 1: LCD_SetCursor(9, 1, 1); break;
        default:;
    }
}

/************************* 串口发送数据 *************************/
void SendData(unsigned char channel)
{
    sprintf(dis0, "Current %1d:%4.1fA\r\n", (int)channel+1, f_cur[channel]); //串口发送
    UART_SendStr(dis0, 16); //发送数据
    DelayMs(10);
    sprintf(dis0, "Max %1d: %4.1fA\r\n", (int)channel+1, (float)curMax[channel] / 1000); //串口发送
    UART_SendStr(dis0, 13); //发送数据
    DelayMs(10);
}

/************************* 读取数据 *************************/
void ReadData(void)
{
    unsigned char i;

    isNewFlag = EEPROM_ReadByte(ISNEW_ADDRESS);

    for (i = 0; i < 4; i++)
    {
        curMax[i] = EEPROM_ReadByte(BASE_ADDRESS + 2*i);
        curMax[i] = (curMax[i] << 8) | EEPROM_ReadByte(BASE_ADDRESS + 2*i + 1);
    }
}

/************************* 写入数据 *************************/
void WriteData(void)
{
    unsigned char i;

    for (i = 0; i < 4; i++)
    {
        EEPROM_WriteByte(BASE_ADDRESS + 2*i, ((curMax[i] & 0xFF00) >> 8));
        EEPROM_WriteByte(BASE_ADDRESS + 2*i + 1, (curMax[i] & 0x00FF));
    }
}

/*------------------------------------------------
                    定时器初始化子程序
------------------------------------------------*/
void Timer0_Init(void)
{
    TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
    TH0 = (65536 - 10000) / 256; //重新赋值 10ms
    TL0 = (65536 - 10000) % 256;
    EA = 1;  //总中断打开
    PT0 = 1;
    ET0 = 1; //定时器中断打开
    TR0 = 1; //定时器开关打开
}

/*------------------------------------------------
                定时器中断子程序
------------------------------------------------*/
void Timer0_Interrupt(void) interrupt 1
{
    static unsigned char time10ms = 0;
    
    TH0 = (65536 - 10000) / 256; //重新赋值 10ms
    TL0 = (65536 - 10000) % 256;

    time10ms++;
    if (time10ms > 50) // 0.5s
    {
        refreshFlag = 1;
        time10ms = 0; 
    }
    
}


/************************* 串口配置 *************************/
void UART_Init(void)
{
	SCON = 0x50;
	TH2 = 0xFF;
	TL2 = 0xFD;
	RCAP2H = 0xFF;  //(65536-(FOSC/32/BAUD))   BAUD = 115200 FOSC = 11059200
	RCAP2L = 0xFD;

	/*****************/
	TCLK = 1;
	RCLK = 1;
	C_T2 = 0;
	EXEN2 = 0;

	/*****************/
	TR2 = 1;
	ES   = 1; //关闭串口中断
	EA   = 1; //打开总中断

}

/************************* 串口发送字节 *************************/
void UART_SendByte(unsigned char dat) //串口发送单字节数据
{
	unsigned char time_out;
    
	time_out = 0;
	SBUF = dat;						  //将数据放入SBUF中
	while ((!TI) && (time_out < 100)) //检测是否发送出去
	{
		time_out++;
		DelayUs10x(2);
	}		//未发送出去 进行短暂延时
	TI = 0; //清除ti标志
}

/************************* 串口发送字符串 *************************/
void UART_SendStr(unsigned char *s, unsigned char length)
{
	unsigned char num;
	num = 0x00;
	while (num < length) //发送长度对比
	{
		UART_SendByte(*s); //放松单字节数据
		s++;			  //指针++
		num++;			  //下一个++
	}
}


/************************* 串口中断 *************************/
void UART_Interrupt(void) interrupt 4 //串行中断服务程序
{
    static unsigned char i = 0;
    static unsigned char firstBit = 0;
    static unsigned char R_buf[4];
    
    if (RI)//判断是接收中断产生
    {
        RI = 0; //标志位清零
        SBUF = SBUF;
        if (SBUF == '*')
        {
            firstBit = 1; //接收标志成功
            i = 0;
            R_buf[1] = 0;
            R_buf[2] = 0;
            R_buf[3] = 0;
        }
        if (firstBit == 1)
        {
            R_buf[i] = SBUF;
            
            i++;
            if (i >= 4)
            {
                i = 0;
                if (R_buf[0] == '*' && R_buf[3] == '#')
                {
                    if (R_buf[1] == 'C') //继电器闭合命令
                    {
                        switch (R_buf[2])
                        {
                            case '1': RELAY1 = CLOSE; break;
                            case '2': RELAY2 = CLOSE; break;
                            case '3': RELAY3 = CLOSE; break;
                            case '4': RELAY4 = CLOSE; break;
                            case 'A': RELAY1 = CLOSE; RELAY2 = CLOSE; RELAY3 = CLOSE; RELAY4 = CLOSE; break;
                            default:break;
                        }
                        BUZZER = OFF;
                    }
                    else if (R_buf[1] == 'B') //继电器断开命令
                    {
                        switch (R_buf[2])
                        {
                            case '1': RELAY1 = BREAK; break;
                            case '2': RELAY2 = BREAK; break;
                            case '3': RELAY3 = BREAK; break;
                            case '4': RELAY4 = BREAK; break;
                            case 'A': RELAY1 = BREAK; RELAY2 = BREAK; RELAY3 = BREAK; RELAY4 = BREAK; break;
                            default:break;
                        }
                        BUZZER = OFF;
                    }
                }
                firstBit = 0;
            }
        }
    }
    if (TI)//判断是中断产生
    {
        TI = 0; //标志位清零
    }
}

仿真演示视频:
https://www.bilibili.com/video/BV1c44y1Q7JX/

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 基于51单片机的电子时钟项目需要通过Keil编写程序,并使用Proteus进行仿真搭建。该项目主要包括以下几个步骤: 1. 硬件搭建:按照电子时钟的设计需求,连接51单片机和相关的电子元件,如晶体振荡器、数码管、按键等。通过Proteus软件,可以将这些元件连接起来,搭建出完整的电。 2. Keil程序编写:使用Keil软件,编写51单片机的C语言程序。该程序需要实现时钟的功能,包括时、分、秒的显示和计时、调整时间、闹钟功能等。通过编程,可以控制数码管的显示,以及对按键进行响应。 3. Proteus仿真:将编写好的程序通过Proteus软件连接至搭建好的电。进行仿真测试时,可以通过模拟时钟的不同状态,调试和验证编写的程序的正确性和稳定性。仿真过程中,可以检查数码管的显示情况,以及程序对按键输入的响应。 4. 优化和调试:根据仿真过程中的结果,对程序进行优化和调试。可能需要根据具体的需求,修改程序中的一些逻辑或代码,确保电子时钟的功能正常运行,并符合设计要求。 总的来说,基于51单片机的电子时钟项目需要通过Keil编写程序,并结合Proteus进行仿真搭建和测试。通过这样的开发流程,可以实现一个功能完善、稳定可靠的电子时钟。 ### 回答2: 基于51单片机的电子时钟keil程序和protues仿真组成了一个完整的设计方案。 首先,keil程序是用于开发51单片机的集成开发环境,它提供了编译、调试和仿真等功能,能够帮助程序员快速开发出51单片机的应用程序。在电子时钟的设计中,我们可以使用keil来编写单片机的程序代码,实现时钟的各种功能。 其次,protues是一款电子设计自动化软件,它提供了电子电仿真和PCB布局设计等功能,能够帮助我们快速验证电的正确性。在电子时钟的设计中,我们可以使用protues来建立电子时钟的仿真,验证单片机代码的正确性和稳定性。 基于51单片机的电子时钟设计,我们可以使用keil来编写单片机的程序代码,实现时钟的各种功能,包括时间显示、报时功能、闹钟功能等。通过keil的编译、调试和仿真功能,我们可以验证代码的正确性和稳定性。 在电设计方面,我们可以使用protues来建立电子时钟的仿真,通过仿真可以验证电的正确性和稳定性,包括时钟电、数码管驱动电、按钮输入电等。通过protues的电仿真功能,我们可以检查电设计的错误和漏洞,提前解决电问题。 基于51单片机电子时钟keil程序和protues仿真的组合,我们可以全面验证电子时钟的功能和性能,确保设计的准确性和可靠性,为最终实现一个完整的电子时钟设计提供了有力的支持。 ### 回答3: 基于51单片机的电子时钟keil程序和protues仿真可以实现以下功能: 1. 显示当前时间:我们可以使用数码管或LCD显示模块来显示当前的时、分和秒。通过编写相应的程序,我们可以从单片机的时钟源获取当前时间,并将其转换为可以在数码管或LCD上显示的格式。 2. 时间调整功能:可以通过按钮或旋钮等输入设备来调整电子时钟的时间。当用户按下或旋转输入设备时,我们可以响应用户的操作,并对时钟的时间进行相应的调整。 3. 闹钟功能:我们可以设置闹钟功能,让电子时钟在特定的时间点发出警报声。通过在程序中设置闹钟时间和警报声的播放方式,我们可以实现这一功能。 4. 温湿度监测:如果我们希望电子时钟能够同时监测室内的温度和湿度,我们可以连接温湿度传感器,并在程序中读取传感器的数据。然后,我们可以将这些数据显示在数码管或LCD上。 程序开发过程中,我们可以使用keil来编写51单片机的程序,通过keil提供的调试工具来测试和调试程序的正确性。同时,我们可以在protues中设计和仿真电子时钟的电,包括单片机、显示模块、输入设备和传感器等所有的硬件组件。这样,我们可以在protues中验证电的功能和效果,并进行性能优化和调试。当电和程序都满足我们的要求后,我们就可以将程序烧录到实际的硬件上,并使用它作为一台完整的电子时钟了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值