欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4529|回復: 1
打印 上一主題 下一主題
收起左側

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

[復制鏈接]
跳轉到指定樓層
樓主
ID:351566 發表于 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:轉向標志,1為正轉、0為翻轉
                                                                        //sflag:啟動標志,1為轉動狀態、0為停止狀態
unsigned int t1=0;                                        //t1:定時器中斷計數
int time=10;                                                //time:占空比(0~10)
int freq,num;                                                // num是外部中斷計數值,freq保存外部中斷的次數
char cnt=0;                                                        // 定時器0 1s計數值
uint pp;                                                         // 定時器0 1s計數值,根據程序修改,本程序取pp=20時定時滿1s
void delayms(unsigned int xms);         //微秒級延時函數
void key();                                                        //按鍵功能函數
void Initial();                                                   //初始化函數,包括定時器0(中斷),定時器1,外部中斷
void Read_Busy();                                         //讀寫檢查函數
void Write_Cmd(uchar cmd);                  //寫指令函數
void Write_Dat(uchar dat);                  //寫入數據
void LCD1602_Init();                                //LCD初始化
void PrintStr(char *str);                        // LCD輸出字符串
void DisplayNum(int m);                                // LCD顯示數值
void delay(unsigned int x);
/*****************主函數***********************/
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('%');
   }
}
/************初始化函數****************
*
* 功能描述:實現對定時器0,定時器1,外部中斷1中斷
*
************************************/
void Initial()
{
   TMOD=0X11;        //設置定時器0 和 定時器1,工作方式1,16為定時
   TH1 = 0XFC;        //定時器0初值1ms
   TL1 = 0X66;
   IP = 0X00;        // 中斷優先級控制
   //定時器1初值50ms
   TH0 = 0x4c;        //高8位
   TL0 = 0X00;        //低8位
   EX0 = 1;                // 開啟外部中斷0,默認中斷優先級為0
   EX1 = 1;                // 開啟外部中斷0,默認中斷優先級為2
   IT0 = 1;                // 外部中斷觸發方式為脈沖觸發
   TR0 = 1;                // 定時器0啟動由后面啟動
   //TR1 = 1;                // 定時器1用來參數PWM波,按下啟動按鈕后才啟動
   ET0 = 1;                // 開定時器0中斷
   ET1 = 1;                // 開定時器1中斷
   EA=1;                // 開總中斷
}
/********************************************
*
* 函數描述:定時器1中斷函數,默認中斷編號3
*
*            t1                        PWM波
      |-----|                |-----|
      |            |                |     |
      |     |                |     |
----- |     |-----------|     |---------
      |<--------------->|
                 time
********************************************/
void timer1() interrupt 3
{
        TH1=0XFC;
        TL1=0X66;
        t1++;
        if(t1<=time)
        {
                if(flag==1)                //正轉,P2^0 輸出PWM
                {
                        m1=1;
                        m2=0;
                }
                else                        //反轉,P2^1 輸出PWM
                {
                        m1=0;
                        m2=1;
                }
        }
        else
        {
                m1=1;
                m2=1;
        }
        if(t1==10)                //定時滿 1ms
        {
                t1=0;
        }
}
/**
*
* 函數描述:定時器0中斷函數,默認中斷編號1,處理
*                 外部中斷的數值
*
*/
void timer0() interrupt 1
{
   TH0 = 0x4C;        //定時器1初值50ms
   TL0 = 0X00;
   pp++;
   if(pp ==20)        //計時滿 1s
   {
     freq = num/6-25;        //獲取1s內中斷計數的值num,并進行數值處理,這個根據個人不同需求修改
      if(freq<=0)
         freq=0;
     num = 0;
     //cnt++;
     //led = ~led;
     pp = 0;
   }
}
/**
* @brief        外部中斷0,P3^2口每來一次脈沖就計數值加1
               記錄特定時間內的脈沖數,可用作頻率計
*
*/
void extern_int0(void) interrupt 0         //外部中斷0
{
   //led = ~led;
   num ++;        // 外部中斷計數
}
/**
* @brief        外部中斷1,控制反接制動,反接約2s(軟件延時)
*
*/
void extern_int1(void) interrupt 2        //外部中斷1
{
      TR1 = 0;                //關閉定時器1,即關閉PWM輸出
      if(flag)                //判斷是由正轉停止還是由反轉狀態下停止,
      {
         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,要處理原來的指令,如果不判斷會導致數據紊亂
void Read_Busy() //讀寫檢查函數
{
    uchar busy;
    P1 = 0xFF;   //P0口作為數據端
    RS = 0;         
    RW = 1;             //讀狀態的操作時序為 RS=L,RW=H,E=H,D0~D7輸出狀態字
    do
    {
        EN = 1;
        busy = P1;
        EN = 0;
    }while(busy & 0x80);
    //狀態字為busy(8位2進制數)的最高位,
    //若為1則禁止讀寫,為0則允許讀寫,該狀態用busy&0x80的結果表示
}
*/
/*******************************************
*
* 函數描述:寫指令函數
*
*******************************************/
void Write_Cmd(uchar cmd)  //寫指令函數
{
    //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)  //寫入數據
{
   // Read_Busy();         //寫入數據前進行讀寫檢測
   P1 = dat;            //P0口寫入數據
   RS = 1;
   EN = 0;
   delay(10);
   EN = 1;                  //寫數據操作時序:RS=0,RW=0,EN=高脈沖
   delay(10);
   EN = 0;                  //獲得高脈沖后使能端重新置零
}
void LCD1602_Init()
{
   RW = 0;
   Write_Cmd(0x38);//設置16*2顯示
   delay(8);
   Write_Cmd(0x0f);//開顯示 顯示光標,光標閃爍
   delay(8);
   Write_Cmd(0x01);//清屏
   delay(8);
   Write_Cmd(0x06);//地址指針移位命令
   delay(8);
    //Write_Cmd(0x80 | 0x00);//顯示地址,0x80是第一行的的首地址。0x80|0x06表示數據從第一行第7個字符位置開始顯示
}
/**
* @brief        LCD1602打印字符串的函數,使用到了strlen函數,需要引入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顯示整數,顯示4位數
* @note       
*            希望補充顯示浮點型數值,未完成功能
*/
void DisplayNum(int m)                // LCD顯示數值
{
   int disdata[4];                // 顯示占空比的數值,存到此數組
   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        按鍵功能函數,包括啟動/反轉,能耗制動,加速,減速
*
*/
void key()
{
        if(key1==0)                //轉向及啟動
        {
                delayms(5);
                if(key1==0)
                {
                        while(key1==0);
                        if(sflag==1)                //為了實現停止后再啟動保持之前的轉向
                        {
                                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;                //關閉定時器1,即關閉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;                //關閉定時器1,即關閉PWM輸出
             
              if(flag)                //判斷 是由正轉停止還是由反轉狀態下停止
              {
                 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        軟件延時函數
*
*/
void delayms(unsigned int xms)
{
        unsigned int i,j;
        for(i=xms;i>0;i--)
                for(j=110;j>0;j--);
}
/**
* @brief        軟件延時函數
*
*/
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 分享淘帖 頂 踩
回復

使用道具 舉報

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

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表