找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4422|回复: 1
打印 上一主题 下一主题
收起左侧

基于51单片机的温度控制直流电机的转动Proteus仿真+程序

[复制链接]
跳转到指定楼层
楼主
0度到24度电机不运行,25开始运行,50度全速运行,0度以下反转

电路原理图如下:


代码如下:
#include<reg51.h>                                         //预处理命令,定义SFR的头文件
#include <math.h>
#define uchar unsigned char                              //定义缩写字符uchar
#define uint  unsigned int                             //定义缩写字符uint
#define lcd_data P0                                      //定义LCD1602接口 P0
sbit DQ =P1^7;                                           //将DQ位定义为P1.7引脚
sbit lcd_RS=P2^0;                                        //将RS位定义为P2.0引脚
sbit lcd_RW=P2^1;                                       //将RW位定义为P2.1引脚
sbit lcd_EN=P2^2;                                        //将EN位定义为P2.2引脚
sbit PWM=P3^7;                                      //将PWM定义为P3.7引脚
sbit D=P3^6;                                  //将d定义为P3.6引脚,转向选择位
uchar t[2],speed,temperature;  //用来存放温度值,测温程序就是通过这个数组与主函数通信的
uchar DS18B20_is_ok;
ucharTempBuffer1[12]={0x20,0x20,0x20,0x20,0xdf,0x43,'\0'};
uchartab[16]={0x20,0x20,0x20,0x54,0x20,0x4d,0x6f,0x6e,0x69,0x74,0x6f,0x72,'\0'};
                                                                      //显示"T Monitor"
/**********lcd显示子程序************/
voiddelay_20ms(void)                         /*延时20ms函数*/
{
uchar i,temp;                               //声明变量i,temp
for(i = 20;i > 0;i--)                              //循环
{
temp = 248;                         //给temp赋值248
while(--temp);                        //temp减1是否等于0,否则继续执行该行
temp = 248;                         //给temp赋值248
while(--temp);                        //temp减1是否等于0,否则继续执行该行
}
}
void delay_38us(void)                                    /*延时38us函数*/
{   
uchar temp;                                //声明变量temp
temp = 18;                                 //给temp赋值
while(--temp);                               //temp减1是否等于0,否则继续执行该行
}
void delay_1520us(void)                         /*延时1520us函数*/
{  
uchar i,temp;                                     //声明变量i,temp
for(i = 3;i > 0;i--)                               //循环
{
temp = 252;                               //给temp赋值
while(--temp);                        //temp减1是否等于0,否则继续执行该行
}
}
uchar lcd_rd_status( )                                   /*读取lcd1602的状态,主要用于判断忙*/
{
uchar tmp_sts;                                  //声明变量tmp_sts
lcd_data = 0xff;                                   //初始化P3口
lcd_RW = 1;                             //RW =1  读      
lcd_RS = 0;                              //RS =0  命令,合起来表示读命令(状态)
lcd_EN = 1;    //EN=1,打开EN,LCD1602开始输出命令数据,100nS之后命令数据
//100nS之后命令数据有效
tmp_sts = lcd_data;                               //读取命令到tmp_sts
lcd_EN = 0;                              //关掉LCD1602
lcd_RW = 0;                             //把LCD1602设置成写
return tmp_sts;                                  //函数返回值tmp_sts
}
void lcd_wr_com(uchar command )                    /*写一个命令到LCD1602*/
{
while(0x80&lcd_rd_status()); //先判断LCD1602是否忙,看读出的命令的最高位是否为1,
//为1表示忙,继续读,直到不忙
lcd_RW = 0;
lcd_RS = 0;                                       //W=0,RS=0 写命令
lcd_data = command;                             //需要写的命令写到数据线上
lcd_EN = 1;
lcd_EN = 0;                                       //EN输出高电平脉冲,命令写入
}
void lcd_wr_data(uchar sjdata )                          /*写一个显示数据到lcd1602*/
{      while(0x80&lcd_rd_status());  //判断1602是否忙,最高位为1表示忙,继续读,直到不忙
lcd_RW = 0;
lcd_RS = 1;                                      //RW=0,RS=1 写显示数据
lcd_data = sjdata ;                                //把需要写的显示数据写到数据线上
lcd_EN = 1;
lcd_EN = 0;                               //EN输出高电平脉冲,命令写入
lcd_RS = 0;                 
}
void Init_lcd(void)                                  /*初始化lcd1602*/
{
delay_20ms();                                    //调用延时
lcd_wr_com(0x38);                               //设置16*2格式,5*8点阵,8位数据接口
delay_38us();                                     //调用延时
lcd_wr_com(0x0c);                                //开显示,不显示光标
delay_38us();                                     //调用延时
lcd_wr_com(0x01);                               //清屏
delay_1520us();                                  //调用延时
lcd_wr_com(0x06);                               //显示一个数据后光标自动+1
}      
void GotoXY(uchar x, uchar y)                            //设定位置,x为行,y为列
{
              if(y==0)                                          //如果y=0,则显示位置为第一行
              lcd_wr_com(0x80|x);
              if(y==1)
              lcd_wr_com(0xc0|x);                             //如果y=1,则显示位置为第二行
}
void Print(uchar *str)                                   //显示字符串函数
{
              while(*str!='\0')                                     //判断字符串是否显示完
              {
                     lcd_wr_data(*str);                    //写数据
                     str++;                             
              }
}
void LCD_Print(uchar x, uchar y, uchar*str)        //x为行值,y为列值,str是要显示的字符串
{
GotoXY(x,y);                                    //设定显示位置
Print(str);                                              //显示字符串
}
       /*****************系统显示子函数*****************/
void covert1()                                     //温度转化程序
{
uchar x=0x00;                                       //变量初始化
if(t[1]>0x07)                                 //判断正负温度
{
TempBuffer1[0]=0x2d;                          //0x2d为"-"的ASCII码
                     t[1]=~t[1];                                    //负数的补码
                     t[0]=~t[0];                                  //换算成绝对值
                     x=t[0]+1;                                        //加1
                     t[0]=x;                                     //把x的值送入t[0]
                     if(x>255)                             //如果x大于255
                     t[1]++;                                     //t[1]加1
              }
      else
             TempBuffer1[0]=0x2b;                          //0xfe为变"+"的ASCII码
      t[1]<<=4;                                         //将高字节左移4位
     t[1]=t[1]&0x70;                                   //取出高字节的3个有效数字位
     x=t[0];                                            //将t[0]暂存到X,因为取小数部分还要用到它
           x>>=4;                                          //右移4位
           x=x&0x0f;                                              //和前面两句就是取出t[0]的高四位   
           t[1]=t[1]|x;                                             //将高低字节有效值的整数部分拼成一个字节
           temperature=t[1];
           TempBuffer1[1]=t[1]/100+0x30;                     //加0x30为变 0~9 ASCII码
           if(TempBuffer1[1]==0x30)                            //如果百位为0
           TempBuffer1[1]=0xfe;                             //百位数消隐
           TempBuffer1[2]=(t[1]%100)/10+0x30;           //分离出十位
           TempBuffer1[3]=(t[1]%100)%10+0x30;         //分离出个位
}                    
/*******************DS18B20函数**********************/
void delay_18B20(uint i)                                //延时程序
{
              while(i--);
}
void Init_DS18B20(void)                               //ds18b20初始化函数
{
             ucharx=0;
             DQ =1;                                           //DQ复位
             delay_18B20(8);                                    //稍做延时
             DQ =0;                                           //单片机将DQ拉低
             delay_18B20(80);                                 //精确延时大于480us
             DQ =1;                                           //拉高总线
             delay_18B20(14);
             x=DQ;                                            //延时后如果x=0则初始化成功 x=1则失败
               delay_18B20(20);
}
uchar ReadOneChar(void)                                  //ds18b20读一个字节函数
{
              unsignedchar i=0;
              unsignedchar dat0 = 0;
              for(i=8;i>0;i--)
             {
                     DQ= 0;                             //读前总线保持为低
                     dat0>>=1;
                     DQ= 1;                             //开始读总线释放
                     if(DQ)                                       //从DS18B20总线读得一位
                     dat0|=0x80;
                     delay_18B20(4);                             //延时一段时间
             }
      return(dat0);                                //返回数据
}
void WriteOneChar(uchar dat1)                          //ds18b20写一个字节函数
{
              uchari=0;
              for(i=8; i>0; i--)
              {
                     DQ= 0;                                     //开始写DS18B20总线要处于复位(低)状态
                     DQ= dat1&0x01;                      //写入下一位
                  delay_18B20(5);
             DQ = 1;                                     //重新释放总线
                  dat1>>=1;                                       //把一个字节分成8个BIT环移给DQ
      }
}
void ReadTemperature()                                   //读取ds18b20当前温度
{      
              delay_18B20(80);                              //延时一段时间
              Init_DS18B20();   
              WriteOneChar(0xCC);                                    //跳过读序号列号的操作
              WriteOneChar(0x44);                            //启动温度转换
              delay_18B20(80);                                //延时一段时间
              Init_DS18B20();                                      //DS18B20初始化
              WriteOneChar(0xCC);                           //跳过读序号列号的操作
              WriteOneChar(0xBE);                            //读取温度寄存器等(共可读9个寄存器)                          delay_18B20(80);                                       //延时一段时间
t[0]=ReadOneChar();                               //读取温度值低位
              t[1]=ReadOneChar();                               //读取温度值高位
}
void delay_motor(uchar i)                             //延时函数
{
              ucharj,k;                                  //变量i、k为无符号字符数据类型
              for(j=i;j>0;j--)                                 //循环延时
                     for(k=200;k>0;k--);                    //循环延时
}
/*******************电机转动程序*******************/
void motor(uchar tmp)            
{    uchar x;
     if(TempBuffer1[0]==0x2b)                      //温度为正数
              {
                         if(tmp<25)                                            //温度小于25度
                     {
                           D=0;                                          //电机停止转动
                           PWM=0;
                     }
                     else if(tmp>50)                                 //温度大于50度,全速转动
                            {
                                   D=0;                                  //D置0
                                   PWM=1;             //正转,PWM=1
                        x=250;                              //时间常数为x
                        delay_motor(x);                        //调延时函数
                                  PWM=0;                    //PWM=0
                        x=5;                                    //时间常数为x
                                delay_motor(x);                 //调延时函数
                            }
                            else
                            {
                                   D=0;                                  //D置0
                                  PWM=1;             //正转,PWM=1
                       x=5*tmp;                           //时间常数为x
                       delay_motor(x);                  //调延时函数
                                  PWM=0;                    //PWM=0
                       x=255-5*tmp;                       //时间常数为255-x
                               delay_motor(x);            //调延时函数
                         }
                     }
else if (TempBuffer1[0]==0x2d)                   //温度小于0,反转
                     {
                           D=1;                                          
                    PWM=0;                           //PWM=0
                 x=5*tmp;                                 //时间常数为tmp
                            delay_motor(x);                  //调延时函数
                            PWM=1;                           //PWM=1
                 x=255-5*tmp;                              //时间常数为255- tmp
                            delay_motor(x);                  //调延时函数
                    }
}      
void delay(unsigned int x)                                 //延时函数名
{
unsigned char i;                            //定义变量i的类型
while(x--)                                    //x自减1
{
for(i=0;i<123;i++){;}                       //控制延时的循环
}
}
/*************************main主程序*********************/
void main(void)
{
delay_20ms();                                         //系统延时20ms启动
              ReadTemperature();                              //启动DS18B20
     Init_lcd();                                      //调用LCD初始化函数
              LCD_Print(0,0,tab);                                //液晶初始显示
              delay(1000);                                   //延时一段时间
              while(1)
{      
                    ReadTemperature();                      //读取温度并存放在一个两个字节的数组中
                         delay_18B20(100);
                         covert1();                                        //数据转化
                         LCD_Print(4,1,TempBuffer1);               //显示温度
                     motor(temperature);                     //电机转动
              }
}

全部资料51hei下载地址:
基于51单片机的温度控制直流电机的转动.rar (73.85 KB, 下载次数: 132)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏4 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:734734 发表于 2020-4-25 12:17 | 只看该作者
源程序呢,下载的啥都没有
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表