久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4399|回復(fù): 1
打印 上一主題 下一主題
收起左側(cè)

基于51單片機實現(xiàn)的電機PWM控制及測速(Proteus仿真)

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:351566 發(fā)表于 2018-6-14 08:44 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
#include <reg52.h>
#include <string.h>
typedef unsigned char uchar;
typedef unsigned int uint;
sbit m1 = P2^0;                //pwm信號1
sbit m2 = P2^1;                //pwm信號2
sbit key0 = P3^3;                //反接制動
sbit key1 = P3^4;                //方向切換及啟動
sbit key2 = P3^5;                //能耗制動
sbit key3 = P3^6;                //加速
sbit key4 = P3^7;                //減速
sbit BUTTON0 = P3^2;        //外部中斷0
//sbit BUTTON1 = P3^3;        //外部中斷1
sbit RS = P0^2;
sbit RW = P0^1;
sbit EN = P0^0;
sbit relay = P0^3;
sbit led  = P2^7;
unsigned char flag=1,sflag=0;                //flag:轉(zhuǎn)向標(biāo)志,1為正轉(zhuǎn)、0為翻轉(zhuǎn)
                                                                        //sflag:啟動標(biāo)志,1為轉(zhuǎn)動狀態(tài)、0為停止?fàn)顟B(tài)
unsigned int t1=0;                                        //t1:定時器中斷計數(shù)
int time=10;                                                //time:占空比(0~10)
int freq,num;                                                // num是外部中斷計數(shù)值,freq保存外部中斷的次數(shù)
char cnt=0;                                                        // 定時器0 1s計數(shù)值
uint pp;                                                         // 定時器0 1s計數(shù)值,根據(jù)程序修改,本程序取pp=20時定時滿1s
void delayms(unsigned int xms);         //微秒級延時函數(shù)
void key();                                                        //按鍵功能函數(shù)
void Initial();                                                   //初始化函數(shù),包括定時器0(中斷),定時器1,外部中斷
void Read_Busy();                                         //讀寫檢查函數(shù)
void Write_Cmd(uchar cmd);                  //寫指令函數(shù)
void Write_Dat(uchar dat);                  //寫入數(shù)據(jù)
void LCD1602_Init();                                //LCD初始化
void PrintStr(char *str);                        // LCD輸出字符串
void DisplayNum(int m);                                // LCD顯示數(shù)值
void delay(unsigned int x);
/*****************主函數(shù)***********************/
void main()
{
   m1=1;
   m2=1;
   Initial();                // 初始化定時器0,1,外部中斷
   LCD1602_Init();          // 初始化LCD1602
   relay = 0;                // 正常工作情況下繼電器不能得電
   led = 0;
   while(1)
   {
      key();
      Write_Cmd(0x80 | 0x00);        // 顯示第1行
      PrintStr("Speed:");
      DisplayNum(freq);
      PrintStr(" rpm");
      Write_Cmd(0xc0| 0x00);        // 顯示第二行
      PrintStr("Duty:");
      DisplayNum(time*10);
      Write_Dat('%');
   }
}
/************初始化函數(shù)****************
*
* 功能描述:實現(xiàn)對定時器0,定時器1,外部中斷1中斷
*
************************************/
void Initial()
{
   TMOD=0X11;        //設(shè)置定時器0 和 定時器1,工作方式1,16為定時
   TH1 = 0XFC;        //定時器0初值1ms
   TL1 = 0X66;
   IP = 0X00;        // 中斷優(yōu)先級控制
   //定時器1初值50ms
   TH0 = 0x4c;        //高8位
   TL0 = 0X00;        //低8位
   EX0 = 1;                // 開啟外部中斷0,默認中斷優(yōu)先級為0
   EX1 = 1;                // 開啟外部中斷0,默認中斷優(yōu)先級為2
   IT0 = 1;                // 外部中斷觸發(fā)方式為脈沖觸發(fā)
   TR0 = 1;                // 定時器0啟動由后面啟動
   //TR1 = 1;                // 定時器1用來參數(shù)PWM波,按下啟動按鈕后才啟動
   ET0 = 1;                // 開定時器0中斷
   ET1 = 1;                // 開定時器1中斷
   EA=1;                // 開總中斷
}
/********************************************
*
* 函數(shù)描述:定時器1中斷函數(shù),默認中斷編號3
*
*            t1                        PWM波
      |-----|                |-----|
      |            |                |     |
      |     |                |     |
----- |     |-----------|     |---------
      |<--------------->|
                 time
********************************************/
void timer1() interrupt 3
{
        TH1=0XFC;
        TL1=0X66;
        t1++;
        if(t1<=time)
        {
                if(flag==1)                //正轉(zhuǎn),P2^0 輸出PWM
                {
                        m1=1;
                        m2=0;
                }
                else                        //反轉(zhuǎn),P2^1 輸出PWM
                {
                        m1=0;
                        m2=1;
                }
        }
        else
        {
                m1=1;
                m2=1;
        }
        if(t1==10)                //定時滿 1ms
        {
                t1=0;
        }
}
/**
*
* 函數(shù)描述:定時器0中斷函數(shù),默認中斷編號1,處理
*                 外部中斷的數(shù)值
*
*/
void timer0() interrupt 1
{
   TH0 = 0x4C;        //定時器1初值50ms
   TL0 = 0X00;
   pp++;
   if(pp ==20)        //計時滿 1s
   {
     freq = num/6-25;        //獲取1s內(nèi)中斷計數(shù)的值num,并進行數(shù)值處理,這個根據(jù)個人不同需求修改
      if(freq<=0)
         freq=0;
     num = 0;
     //cnt++;
     //led = ~led;
     pp = 0;
   }
}
/**
* @brief        外部中斷0,P3^2口每來一次脈沖就計數(shù)值加1
               記錄特定時間內(nèi)的脈沖數(shù),可用作頻率計
*
*/
void extern_int0(void) interrupt 0         //外部中斷0
{
   //led = ~led;
   num ++;        // 外部中斷計數(shù)
}
/**
* @brief        外部中斷1,控制反接制動,反接約2s(軟件延時)
*
*/
void extern_int1(void) interrupt 2        //外部中斷1
{
      TR1 = 0;                //關(guān)閉定時器1,即關(guān)閉PWM輸出
      if(flag)                //判斷是由正轉(zhuǎn)停止還是由反轉(zhuǎn)狀態(tài)下停止,
      {
         m1 = 0;
         m2 = 1;        //反接制動
         delayms(2000);        //延時2s
         m1 = 1;        //停止時m1,m2都輸出高電平
         sflag=0;
      }
      else if(!flag)
      {
         m1 = 1;
         m2 = 0;
         delayms(2000);
         m2 = 1;
         sflag=0;
      }
}
/*
//判斷液晶忙,如果忙則等待,因為1602也是一個CPU,要處理原來的指令,如果不判斷會導(dǎo)致數(shù)據(jù)紊亂
void Read_Busy() //讀寫檢查函數(shù)
{
    uchar busy;
    P1 = 0xFF;   //P0口作為數(shù)據(jù)端
    RS = 0;         
    RW = 1;             //讀狀態(tài)的操作時序為 RS=L,RW=H,E=H,D0~D7輸出狀態(tài)字
    do
    {
        EN = 1;
        busy = P1;
        EN = 0;
    }while(busy & 0x80);
    //狀態(tài)字為busy(8位2進制數(shù))的最高位,
    //若為1則禁止讀寫,為0則允許讀寫,該狀態(tài)用busy&0x80的結(jié)果表示
}
*/
/*******************************************
*
* 函數(shù)描述:寫指令函數(shù)
*
*******************************************/
void Write_Cmd(uchar cmd)  //寫指令函數(shù)
{
    //Read_Busy();        //對控制器每次進行讀寫操作都要判斷是否正忙,即要進行讀寫檢測
   P1 = cmd;           //寫入十六進制形式的指令(command)
   RS = 0;
   EN = 0;
   delay(10);
   EN = 1;             //寫指令的操作時序:RS=0,RW=0,EN=高脈沖
   delay(10);
   EN = 0;                 //獲得高脈沖后使能端重新置零
}
void Write_Dat(uchar dat)  //寫入數(shù)據(jù)
{
   // Read_Busy();         //寫入數(shù)據(jù)前進行讀寫檢測
   P1 = dat;            //P0口寫入數(shù)據(jù)
   RS = 1;
   EN = 0;
   delay(10);
   EN = 1;                  //寫數(shù)據(jù)操作時序:RS=0,RW=0,EN=高脈沖
   delay(10);
   EN = 0;                  //獲得高脈沖后使能端重新置零
}
void LCD1602_Init()
{
   RW = 0;
   Write_Cmd(0x38);//設(shè)置16*2顯示
   delay(8);
   Write_Cmd(0x0f);//開顯示 顯示光標(biāo),光標(biāo)閃爍
   delay(8);
   Write_Cmd(0x01);//清屏
   delay(8);
   Write_Cmd(0x06);//地址指針移位命令
   delay(8);
    //Write_Cmd(0x80 | 0x00);//顯示地址,0x80是第一行的的首地址。0x80|0x06表示數(shù)據(jù)從第一行第7個字符位置開始顯示
}
/**
* @brief        LCD1602打印字符串的函數(shù),使用到了strlen函數(shù),需要引入string.h頭文件
*
*/
void PrintStr(char *str)        // LCD輸出字符串
{
   char i,len;
   len = strlen(str);                 // 獲取字符串長度
   for(i=0;i<len;i++)
   {
      Write_Dat(*str);
      str++;
   }
}
/**
* @brief        LCD1602顯示整數(shù),顯示4位數(shù)
* @note       
*            希望補充顯示浮點型數(shù)值,未完成功能
*/
void DisplayNum(int m)                // LCD顯示數(shù)值
{
   int disdata[4];                // 顯示占空比的數(shù)值,存到此數(shù)組
   disdata[0] = m/1000+0x30;
   disdata[1] = m%1000/100+0x30;
   disdata[2] = m%100/10+0x30;
   disdata[3] = m%10+0x30;
   if(disdata[0]==0x30)                //如果千位為0,讓LCD不顯示,0x30和0x20可以查詢ACSII碼表
   {
      disdata[0]=0x20;
      if( disdata[1]==0x30)                //如果百位為0,讓LCD不顯示,0x30和0x20可以查詢ACSII碼表
      {
         disdata[1]=0x20;
         if( disdata[2]==0x30)                //如果百位為0,讓LCD不顯示,0x30和0x20可以查詢ACSII碼表
         {
            disdata[2]=0x20;
         }
      }
   }
   Write_Dat(disdata[0]);
   delay(4);
   Write_Dat(disdata[1]);
   delay(4);
   Write_Dat(disdata[2]);
   delay(4);
   Write_Dat(disdata[3]);
   delay(4);
}
/**
*
* @brief        按鍵功能函數(shù),包括啟動/反轉(zhuǎn),能耗制動,加速,減速
*
*/
void key()
{
        if(key1==0)                //轉(zhuǎn)向及啟動
        {
                delayms(5);
                if(key1==0)
                {
                        while(key1==0);
                        if(sflag==1)                //為了實現(xiàn)停止后再啟動保持之前的轉(zhuǎn)向
                        {
                                flag=!flag;
                                TR1=1;                //開啟定時器1,即開始PWM波輸出
                        }
                        else
                        {
                                TR1=1;
                                sflag=1;
                        }
                }
        }
        else if(key2==0)                //停止
        {
                delayms(5);
                if(key2==0)
                {
                        while(key2==0);
                        relay=1;        //能耗制動
                        TR1=0;                //關(guān)閉定時器1,即關(guān)閉PWM輸出
                        m1=1;
                        m2=1;
                        sflag=0;
                }
        }
        else if(key3==0)                //加速
        {
                delayms(5);
                if(key3==0)
                {
                        while(key3==0);
                        if(time>=10)
                                time=10;
                        else
                                time++;
                }
        }
        else if(key4==0)                //減速
        {
                delayms(5);
                if(key4==0)
                {
                        while(key4==0);
                        if(time==0)
                                time=0;
                        else
                                time--;
                }
        }
        /*
        else if(key0==0)        // 按下反接制動
        {
           delayms(5);                //軟件消抖
           if(key0==0)                //再次檢測到按下
           {
              while(key0==0);
              TR1 = 0;                //關(guān)閉定時器1,即關(guān)閉PWM輸出
             
              if(flag)                //判斷 是由正轉(zhuǎn)停止還是由反轉(zhuǎn)狀態(tài)下停止
              {
                 m1 = 0;
                 m2 = 1;        //反接制動
                // delayms(10);        //延時1.5s
                 m1 = 1;        //停止時m1,m2都輸出高電平
                 sflag=0;
              }
              else if(!flag)
              {
                 m1 = 1;
                 m2 = 0;
                // delayms(150);
                 m2 = 1;
              }
           }
        }
        */
}
/**
* @brief        軟件延時函數(shù)
*
*/
void delayms(unsigned int xms)
{
        unsigned int i,j;
        for(i=xms;i>0;i--)
                for(j=110;j>0;j--);
}
/**
* @brief        軟件延時函數(shù)
*
*/
void delay(unsigned int x)
{
        unsigned int a,b;
        for(a=x;a>0;a--)
                for(b=10;b>0;b--);
}

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂 踩
回復(fù)

使用道具 舉報

沙發(fā)
ID:634862 發(fā)表于 2019-11-23 18:14 | 只看該作者
怎么沒有電路圖呢
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 免费在线观看成人av | 日日草夜夜草 | 精品久久一区 | 久久久久久成人 | 中文字幕高清视频 | 国产精品免费一区二区三区四区 | 久久美国 | 久久亚洲一区二区三区四区 | 午夜视频一区 | 乳色吐息在线观看 | 久久久精品一区 | 精品无码久久久久国产 | 欧美综合一区 | 男人天堂社区 | 毛片久久久 | 精品99久久久久久 | 欧美在线视频一区二区 | 欧美一级片免费看 | 天天拍天天操 | 国产精品一区二区三区在线播放 | 国产精品色综合 | 亚洲福利网 | aa级毛片毛片免费观看久 | 欧美在线观看免费观看视频 | 久草免费视 | 91精品久久久久久久久99蜜臂 | 日韩电影中文字幕在线观看 | 精品久久ai电影 | 奇色影视 | 国产精品久久久久久一区二区三区 | 日韩中文在线观看 | 午夜精品久久 | 成人午夜视频在线观看 | 欧美一级做a爰片免费视频 国产美女特级嫩嫩嫩bbb片 | 成人亚洲精品 | 久久国产精99精产国高潮 | 视频一区在线 | h视频在线免费 | 91精品久久久久久久久久入口 | 日韩影院在线观看 | 日本不卡一区二区三区在线观看 |