功能:
0.本系统采用STC89C52作为单片机
1.LCD1602液晶实时显示温度,PWM档位值和当前转速
2.可通过按键控制电机启动,停止,正转,反转,加速,减速
3.温度超过50℃蜂鸣器报警,且电机停止转动
4.采用DC002作为电源接口可直接输入5V给整个系统供电
原理图:
PCB :
主程序:
#include <reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include <stdio.h>
#include "18b20.h"
#include "lcd1602.h"
#include "delay.h"
sbit L9110H_IN1 = P1^0; //引脚定义
sbit L9110H_IN2 = P1^1;
sbit BUZZER = P2^2;
sbit KEY_UP = P3^5; //按键引脚定义
sbit KEY_DOWN = P3^7;
sbit KEY_FORWORD = P3^6;
sbit KEY_BACK = P3^4;
sbit KEY_START = P1^6;
sbit KEY_STOP = P1^7;
sbit LED_RED = P2^1;
sbit LED_GREEN = P2^0;
bit ReadTempFlag; //定义读时间标志
int temp; //温度读取
float temperature; //实际温度
char dis0[16]; //定义显示区域临时存储数组
unsigned char levelValue = 5; //占空比调整
bit startFlag = 0; //启停标志
bit motorFlag = 1; //正反转标志
bit readRateFlag = 0; //读取速度标志
unsigned int rate; //速度值
unsigned long pulseNum; //脉冲计数
void Timer0_Init(void); //函数声明
void KeyProcess(void); //按键处理
void main(void)
{
L9110H_IN1 = 1;
L9110H_IN2 = 1;
Timer0_Init();
EX1 = 1; //外部中断1开
IT1 = 1; //边沿触发
EA = 1; //全局中断开
LCD_Init(); //初始化液晶
DelayMs(20); //延时有助于稳定
LCD_Clear(); //清屏
LCD_DispStr(0, 0, "Now: ");
LCD_DispOneChar(8, 0, 0xdf); //写入温度右上角点
LCD_DispOneChar(9, 0, 'C'); //写入字符C
LCD_DispStr(0, 1, "L: Rate: r/s");
LED_RED = 1;
LED_GREEN = 0;
while (1) //主循环
{
if (ReadTempFlag == 1)
{
EA = 0;
while(!DS18B20_GetTemp(&temp)); //读取温度
temperature = (float)temp * 0.0625; //温度转换
sprintf(dis0, "Now:%4.1f", temperature); //打印温度值
LCD_DispStr(0, 0, dis0);
LCD_DispOneChar(8, 0, 0xdf); //写入温度右上角点
LCD_DispOneChar(9, 0, 'C'); //写入字符C
EA = 1;
if (startFlag == 1)
{
LCD_DispStr(10, 0, " Start");
}
else
{
LCD_DispStr(10, 0, " Stop ");
}
sprintf(dis0, "L:%02d ", (int)levelValue); //打印等级
LCD_DispStr(0, 1, dis0);
if (temperature > 50) //高于报警温度
{
startFlag = 0; //电机停止
BUZZER = 0; //打开蜂鸣器
}
else
{
BUZZER = 1; //关闭蜂鸣器
}
ReadTempFlag = 0;
}
if (readRateFlag == 1)
{
readRateFlag = 0;
rate = pulseNum;
sprintf(dis0, "Rate:%03dr/s", rate); //打印速度
LCD_DispStr(5, 1, dis0);
EX1 = 1;
pulseNum = 0;
}
KeyProcess();
}
}
void KeyProcess(void)
{
if (!KEY_UP) //加速
{
DelayMs(20);
if(!KEY_UP)
{
if (levelValue <= 9)
levelValue++;
}
while(!KEY_UP);
}
if (!KEY_DOWN) //减速
{
DelayMs(20);
if(!KEY_DOWN)
{
if (levelValue > 1)
levelValue--;
}
while(!KEY_DOWN);
}
if (!KEY_FORWORD) //正转
{
DelayMs(20);
if(!KEY_FORWORD)
{
if (startFlag == 1)
{
startFlag = 0;
DelayMs(150);
startFlag = 1;
}
motorFlag = 1;
LED_RED = 1;
LED_GREEN = 0;
}
while(!KEY_FORWORD);
}
if (!KEY_BACK) //反转
{
DelayMs(20);
if(!KEY_BACK)
{
if (startFlag == 1)
{
startFlag = 0;
DelayMs(150);
startFlag = 1;
}
motorFlag = 0;
LED_RED = 0;
LED_GREEN = 1;
}
while(!KEY_BACK);
}
if (!KEY_START) //启动
{
DelayMs(20);
if(!KEY_START)
{
startFlag = 1;
}
while(!KEY_START);
}
if (!KEY_STOP) //停止
{
DelayMs(20);
if(!KEY_STOP)
{
startFlag = 0;
}
while(!KEY_STOP);
}
}
void Timer0_Init(void)
{
TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
TL0 = 0x33; //设置定时初始值
TH0 = 0xFE; //设置定时初始值 500us
PT0 = 1; //设置高优先级
EA = 1; //总中断打开
ET0 = 1; //定时器中断打开
TR0 = 1; //定时器开关打开
}
void Timer0_isr(void) interrupt 1
{
static unsigned char IN1Count = 0;
static unsigned int numCount = 0;
TL0 = 0x33; //设置定时初始值
TH0 = 0xFE; //设置定时初始值 500us
if (startFlag == 1)
{
IN1Count++;
if (IN1Count < levelValue+15) //占空比调节,+15是为了让电机处于可启动的占空比以上
{
if (motorFlag == 1) //正转
{
L9110H_IN1 = 1;
L9110H_IN2 = 0;
}
if (motorFlag == 0) //反转
{
L9110H_IN1 = 0;
L9110H_IN2 = 1;
}
}
else if ((IN1Count >= levelValue+15) && (IN1Count <= 11+15)) //关闭时间段
{
L9110H_IN1 = 1;
L9110H_IN2 = 1; //关闭
}
else
{
IN1Count = 0; //一个周期结束
}
}
else
{
L9110H_IN1 = 1;
L9110H_IN2 = 1; //关闭
}
numCount++;
if (numCount > 2000)
{
EX1 = 0;
readRateFlag = 1;
numCount = 0;
}
if (numCount % 1000 == 0)
{
ReadTempFlag = 1;
}
}
/*------------------------------------------------
外部中断程序
------------------------------------------------*/
void ISR_Key(void) interrupt 2
{
pulseNum++;
}