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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

PIC單片機PWM電機速度控制源碼-實用C語言程序設計與典型實例

  [復制鏈接]
跳轉到指定樓層
樓主
與PIC單片機實用C語言程序設計與典型實例書籍配套的光盤實例,包括原理圖和C語言程序文件,希望對大家有所幫助!


單片機源程序如下:
  1. #include <p18cxxx.h>
  2. #include "16x2LCDDriver.h"

  3. unsigned char LCDBuffer_0[]={"STOP 00% DIR +"};
  4. unsigned char LCDBuffer_1[]={"Get Spd 0000 RPM"};

  5. struct TMR1COUNTER_STRUCT
  6. {
  7.   unsigned char HighCounter;
  8.   unsigned int LowCounter;       
  9.   unsigned char ChangeFlag;
  10. };
  11. struct TMR1COUNTER_STRUCT MyTMR1,MyTMR3,GetTMR1,GetTMR3;

  12. void OSCillator_Initize(void)
  13. {
  14.   OSCCON=0x70;//選擇內部8MHz的主振蕩器
  15.   OSCTUNE=0x40;//使能4xPLL--->Fosc=32MHz
  16. }

  17. void PIC_PortDir_Initize(void)
  18. {
  19.   ADCON1=0x0F;//RA和RE端口全為數字IO口
  20.   TRISD=0x00;//RD端口置輸出方向
  21.   TRISE=0x00;//RE端口置輸出方向
  22.   TRISCbits.TRISC1=0;
  23.   TRISCbits.TRISC2=0;
  24.   TRISCbits.TRISC3=0;
  25. }

  26. void PIC_TMR0_Initize(void)
  27. {
  28.   T0CONbits.TMR0ON=0;//TMR0停止工作
  29.   T0CONbits.T08BIT=0;//選擇16位的定時/計數器
  30.   T0CONbits.T0CS=0;//選擇內部CLKO時鐘源作為定時
  31.   T0CONbits.PSA=0;//選擇預分頻器
  32.   T0CONbits.T0PS2=1;//預分頻比為1:256
  33.   T0CONbits.T0PS1=1;
  34.   T0CONbits.T0PS0=1;
  35.   TMR0H=(65536-31250)/256;//先寫高字節
  36.   TMR0L=(65536-31250)%256;//再寫低字節
  37.   T0CONbits.TMR0ON=1;//開始定時工作  
  38. }

  39. void PIC_TMR1_Initize(void)
  40. {
  41.   //此處TMR1的預分頻比為1:1
  42.   T1CONbits.RD16=1;//允許一次性讀寫16位
  43.   T1CONbits.TMR1CS=1;//選擇外部時鐘源,TMR1用作外部計數
  44.   TMR1H=0;//TMR1數據寄存器清0
  45.   TMR1L=0;
  46.   T1CONbits.TMR1ON=1;//允許TMR1開始工作
  47. }

  48. void PIC_TMR3_Initize(void)
  49. {
  50.   //此處TMR1的預分頻比為1:8
  51.   T3CONbits.T3CKPS1=1;
  52.   T3CONbits.T3CKPS0=1;
  53.   T3CONbits.RD16=1;//允許一次性讀寫16位
  54.   T3CONbits.TMR3CS=0;//選擇內部時鐘源,TMR3用作內部計數
  55.   TMR3H=0;//TMR3數據寄存器清0
  56.   TMR3L=0;
  57.   T3CONbits.TMR3ON=1;//允許TMR3開始工作
  58. }

  59. void PIC_Interrupt_Initize(void)
  60. {
  61.   INTCONbits.TMR0IF=0;//TMR0溢出標志位清0
  62.   INTCONbits.TMR0IE=1;//TMR0溢出中斷允許
  63.   
  64.   PIR1bits.TMR1IF=0;//TMR1溢出標志位清0
  65.   PIE1bits.TMR1IE=1;//TMR1溢出中斷允許
  66.   IPR1bits.TMR1IP=0;//低優先級
  67.    
  68.   PIR2bits.TMR3IF=0;//TMR1溢出標志位清0
  69.   PIE2bits.TMR3IE=1;//TMR1溢出中斷允許
  70.   IPR2bits.TMR3IP=0;//低優先級
  71.   
  72.   INTCONbits.INT0IF=0;//清INT0中斷標志位
  73.   //INTCONbits.INT0IE=1;//INT0中斷允許
  74.   INTCON2bits.RBPU=0;//允許內部弱上拉
  75.   INTCON2bits.INTEDG0=1;//上邊沿觸發中斷
  76.   
  77.   RCONbits.IPEN=1;//允許中斷優先級位
  78.   INTCONbits.GIE=1;//CPU全局中斷使能允許
  79.   INTCONbits.PEIE=1;//CPU第二梯隊中斷使能允許
  80. }

  81. void PIC_CCPForPWM_Initize(void)
  82. {
  83.   TRISCbits.TRISC1=0;//RC1置輸出方向
  84.   TRISCbits.TRISC2=0;//RC2置輸出方向
  85.   LATCbits.LATC1=0;//RC1引腳輸出為0
  86.   LATCbits.LATC2=0;//RC2引腳輸出為0
  87.   CCP1CON=0x0F;//CCP1設置為PWM模式
  88.   CCP2CON=0x0F;//CCP2設置為PWM模式
  89.   T2CON=0x03;//TMR2的預分頻為1:16
  90.   T2CONbits.TMR2ON=1;//TMR2開始工作
  91.   PR2=249;//PWM周期為2000Hz,FOSC=32MHz
  92.   CCPR1L=0;//PWM1的占空比為0
  93.   CCPR2L=0;//PWM2的占空比為0         
  94. }

  95. unsigned char CycleFlag;
  96. unsigned char FreqFlag;

  97. #define RUNSTOPKEY PORTBbits.RB3
  98. #define PWMKEY PORTBbits.RB4
  99. #define DIRKEY PORTBbits.RB5

  100. unsigned char MotorRunStatus;
  101. unsigned char MotorDirection;
  102. unsigned char MotorPWMData;
  103. unsigned char RunStopKeyFlag;
  104. unsigned int RunStopKeyCounter;
  105. unsigned char DirKeyFlag;
  106. unsigned int DirKeyCounter;
  107. unsigned char PWMKeyFlag;
  108. unsigned int PWMKeyCounter;


  109. void SystemVariant_Initize(void)
  110. {
  111.   MotorPWMData=0;         
  112. }

  113. void Motor_Control(unsigned char Direction,
  114.                    unsigned char Speed)
  115. {
  116.   switch(Direction)
  117.     {
  118.           case 0:
  119.             CCPR1L=0;
  120.             CCPR2L=0;
  121.             CCPR1L=Speed;
  122.             break;
  123.           case 1:
  124.             CCPR2L=0;
  125.             CCPR1L=0;
  126.             CCPR2L=Speed;
  127.             break;
  128.         }       
  129. }

  130. //-------------------------------------------------------------------
  131. void PIC18F_High_isr(void);//高優先級中斷函數聲明
  132. #pragma code high_vector_section=0x8
  133. void high_vector (void)
  134. {
  135.   _asm goto PIC18F_High_isr _endasm
  136. }
  137. void SystemInterruptISR(void);//低優先級中斷函數聲明
  138. #pragma code low_vector=0x18//低中斷優先級
  139. void low_interrupt(void)
  140. {
  141.   _asm goto SystemInterruptISR _endasm       
  142. }
  143. #pragma code
  144. //-------------------------------------------------------------------


  145. void main(void)
  146. {
  147.   unsigned long temp;
  148.   unsigned char i;
  149.   
  150.   OSCillator_Initize();//CPU系統時鐘初始化內部時鐘源8MHz,經過4xPLL
  151.   PIC_PortDir_Initize();//PIC單片機的使用到的I/O口方向初始化
  152.   PIC_TMR0_Initize();//PIC單片機的TMR0定時器初始化為內部定時方式
  153.   PIC_TMR1_Initize();//PIC單片機的TMR1定時器初始化為外部計數方式
  154.   PIC_TMR3_Initize();
  155.   PIC_CCPForPWM_Initize();
  156.   PIC_Interrupt_Initize();
  157.   initize_lcd();
  158.   
  159.   while(1)
  160.     {
  161.           if(0==RUNSTOPKEY)//判斷啟動按鍵是否按下
  162.             {
  163.                   if(0==RunStopKeyFlag)//檢測啟動按鍵是否成功按下標志
  164.                     {
  165.                           RunStopKeyCounter++;//軟件計數器,用于按鍵去抖動
  166.                           if(4000==RunStopKeyCounter)//按鍵去抖動延時到
  167.                             {
  168.                                   RunStopKeyCounter=0;//清軟計數器為0
  169.                                   if(0==RUNSTOPKEY)//再判斷啟動按鍵是否真得按下
  170.                                     {
  171.                                           RunStopKeyFlag=1;//置啟動按鍵成功按下標志為1
  172.                                           if(0==MotorRunStatus)//如果電機是處理停止狀態
  173.                                             {//則啟動電機運轉
  174.                                                     MotorRunStatus=1;//同時置電機狀態為1                                                 
  175.                                                 LCDBuffer_0[0]='R';//LCD顯示屏上顯示"RUN"
  176.                                           LCDBuffer_0[1]='U';
  177.                                           LCDBuffer_0[2]='N';
  178.                                           LCDBuffer_0[3]=' ';
  179.                                           LCDBuffer_0[4]=' ';
  180.                                               temp=MotorPWMData;//讀取設置電機速度的變量
  181.                                               temp<<=1;//轉換成占空比送到LCD上顯示
  182.                                               temp/=5;
  183.                                               LCDBuffer_0[5]=(temp/10)+0x30;
  184.                                               LCDBuffer_0[6]=(temp%10)+0x30;
  185.                                               LCDBuffer_0[7]='%';
  186.                                               LCDBuffer_0[8]=' ';
  187.                                               LCDBuffer_0[9]='D';
  188.                                               LCDBuffer_0[10]='I';
  189.                                               LCDBuffer_0[11]='R';
  190.                                               LCDBuffer_0[12]=' ';
  191.                                                     if(0==MotorDirection)//根據電機運轉的方向
  192.                                                       {//來設置電機是正轉還是反轉,并在LCD上顯示
  193.                                                         CCPR1L=0;
  194.                                                         CCPR2L=0;
  195.                                                         CCPR1L=MotorPWMData;//使RC1引腳輸出PWM信號
  196.                                                         LCDBuffer_0[13]='+';//表示電機正轉
  197.                                                           }
  198.                                                           else
  199.                                                             {
  200.                                                           CCPR2L=0;
  201.                                                           CCPR1L=0;
  202.                                                           CCPR2L=MotorPWMData;//使RC2引腳輸出PWM信號
  203.                                                           LCDBuffer_0[13]='-';//表示電機反轉
  204.                                                         }                                                                                                   
  205.                                                   }
  206.                                                   else//如果電機是在運轉中,則這時按下該鍵可以停止電機運轉
  207.                                                     {
  208.                                                       MotorRunStatus=0;//置電機運動狀態為0
  209.                                                   LCDBuffer_0[0]='S';//LCD屏上顯示"STOP"
  210.                                             LCDBuffer_0[1]='T';
  211.                                             LCDBuffer_0[2]='O';
  212.                                             LCDBuffer_0[3]='P';
  213.                                             LCDBuffer_0[4]=' ';       
  214.                                             LCDBuffer_0[5]='0';
  215.                                             LCDBuffer_0[6]='0';            
  216.                                                       CCPR1L=0;//RC1和RC2引腳不輸出PWM信號
  217.                                                       CCPR2L=0;          
  218.                                                     }
  219.                                           lcd_displaystr(0,0,LCDBuffer_0);//將字符串送到LCD上顯示
  220.                                         }                                  
  221.                                 }  
  222.                         }
  223.                 }
  224.                 else
  225.                   {
  226.                         if(1==RUNSTOPKEY)//等待按鍵釋放處理過程
  227.                           {
  228.                                  if(1==RunStopKeyFlag)
  229.                                    {
  230.                                      RunStopKeyFlag=0;//清啟動按鍵上次成功按下標志
  231.                                      RunStopKeyCounter=0;//消抖動延時計數器清0
  232.                                    }
  233.                       }                                  
  234.               }   
  235.                
  236.           if(0==DIRKEY)//判斷電機運轉方向切換鍵是否按下
  237.             {
  238.                   if(0==DirKeyFlag)//判斷方向切換鍵的標志是否成功
  239.                     {
  240.                           DirKeyCounter++;//去抖動計數器加1
  241.                           if(4000==DirKeyCounter)//去抖動延時時間到
  242.                             {
  243.                                   DirKeyCounter=0;//計數器清0
  244.                                   if(0==DIRKEY)//判斷是否真得按下
  245.                                     {
  246.                                           DirKeyFlag=1;//置成功按下標志成立
  247.                                           if(0==MotorDirection)//電機是正轉方向嗎?
  248.                                             {
  249.                                                   MotorDirection=1;//置反向運轉方向狀態
  250.                                                   LCDBuffer_0[13]='-';//LCD顯示屏顯示"-"
  251.                                                   CCPR2L=0;
  252.                                                   CCPR1L=0;
  253.                                                   CCPR2L=MotorPWMData;//啟動RC2輸出PWM信號
  254.                                                 }
  255.                                             else
  256.                                               {
  257.                                                     MotorDirection=0;//置正向運轉方向狀態
  258.                                                     LCDBuffer_0[13]='+';//LCD顯示屏上顯示"+"
  259.                                                     CCPR1L=0;
  260.                                                     CCPR2L=0;
  261.                                                     CCPR1L=MotorPWMData;//啟運RC1輸出PWM信號
  262.                                                   }
  263.                                       lcd_displaystr(0,0,LCDBuffer_0);//將字符串送到LCD上顯示
  264.                                         }                                  
  265.                                 }
  266.                         }
  267.                 }
  268.                 else
  269.                   {
  270.                         if(1==DIRKEY)//等待按鍵釋放
  271.                           {
  272.                                 if(1==DirKeyFlag)//如果上次按鍵按下標志成功,則
  273.                                   {
  274.                                     DirKeyFlag=0;//清按鍵按下標志
  275.                                     DirKeyCounter=0;//清計數器為0
  276.                                   }
  277.                       }
  278.               }
  279.           
  280.           if(0==PWMKEY)//判斷電機速度調節鍵是否按下
  281.             {
  282.                   if(0==PWMKeyFlag)//判斷按鍵按下標志是否為0
  283.                     {
  284.                           PWMKeyCounter++;//去抖動計數器加1
  285.                           if(4000==PWMKeyCounter)//支抖動延時時間到
  286.                             {
  287.                                   PWMKeyCounter=0;//清計數器為0
  288.                                   if(0==PWMKEY)//再判斷電機速度調節鍵是否真得按下
  289.                                     {
  290.                                           PWMKeyFlag=1;//置本次按鍵按下標志成功
  291.                                           temp=MotorPWMData;//讀取PWM變量的內容
  292.                                           temp<<=1;//將其轉換成0-100之間的占空比
  293.                                           temp/5;
  294.                                           temp++;//占空比加1
  295.                                           if(100==temp)temp=0;//到100歸0
  296.                                           LCDBuffer_0[5]=(temp/10)+0x30;//送到LCD緩沖區
  297.                                           LCDBuffer_0[6]=(temp%10)+0x30;
  298.                                           temp*=5;//再將其轉換成0-250之間的PWM數據
  299.                                           temp>>=1;
  300.                                           MotorPWMData=temp;//裝入PWM變量中                                          
  301.                                           if(0==MotorDirection)//如果電機方向是正轉
  302.                                             {
  303.                                                   LCDBuffer_0[13]='+';//LCD上顯示"+"
  304.                                                   CCPR1L=0;
  305.                                                   CCPR2L=0;
  306.                                                   CCPR1L=MotorPWMData;//PWM變量內容送到CCP1
  307.                                                 }
  308.                                             else
  309.                                               {
  310.                                                     LCDBuffer_0[13]='-';
  311.                                                     CCPR2L=0;
  312.                                                     CCPR1L=0;
  313.                                                     CCPR2L=MotorPWMData;//PWM變量送到CCP2
  314.                                                   }
  315.                                           lcd_displaystr(0,0,LCDBuffer_0);//將字符串送到LCD上顯示
  316.                                         }
  317.                                 }                               
  318.                         }
  319.                 }
  320.                 else
  321.                   {
  322.                         if(1==PWMKeyFlag)//等待按鍵釋放
  323.                           {
  324.                                 PWMKeyFlag=0;//清按鍵按下標志
  325.                                 PWMKeyCounter=0;//計數器清0
  326.                       }
  327.               }
  328.           
  329.           if((1==FreqFlag)&&(0==CycleFlag))//1S的測頻標志成立
  330.             {
  331.                   FreqFlag=0;//清測頻標志
  332.           temp=MyTMR1.HighCounter;//讀取經過測頻的計數脈沖
  333.           temp<<=16;
  334.           temp|=MyTMR1.LowCounter;
  335.           //電機速度小于1000RPM,切換到測周法
  336.           if(temp<1000)
  337.             {             
  338.                   INTCONbits.INT0IE=1;//允許INT0中斷允許
  339.                   INTCONbits.INT0IF=0;//清INT0中斷標志位
  340.                   MyTMR3.ChangeFlag=0;//清測周所用變量標志位
  341.                 }
  342.                 else//否則就用測頻法計算電機速度
  343.                   {                        
  344.                         INTCONbits.INT0IE=0;//禁止INT0中斷允許
  345.                         INTCONbits.INT0IF=0;//清INT0中斷標志位
  346.                         //將測量的結果顯示在LCD顯示屏上
  347.                         for(i=8;i<12;i++)LCDBuffer_1[i]=0x30;
  348.                         i=11;
  349.                         while(temp)
  350.                           {
  351.                                 LCDBuffer_1[i]=(temp%10)+0x30;
  352.                                 temp/=10;
  353.                                 i--;
  354.                               }
  355.                         MyTMR1.HighCounter=0;//清TMR1使用的相關變量
  356.                         MyTMR1.LowCounter=0;
  357.                         T1CONbits.TMR1ON=1;
  358.                         lcd_displaystr(1,0,LCDBuffer_1);//將測量的結果送到LCD上顯示
  359.                       }                  
  360.                 }
  361.                
  362.           if((1==CycleFlag)&&(0==FreqFlag))
  363.             {
  364.                   CycleFlag=0;
  365.           temp=MyTMR3.HighCounter;
  366.           temp<<=16;
  367.           temp|=MyTMR3.LowCounter;
  368.           temp=1000000/temp;
  369.           //將測量的結果顯示在LCD顯示屏上
  370.               for(i=8;i<12;i++)LCDBuffer_1[i]=0x30;
  371.               i=11;
  372.               while(temp)
  373.                 {
  374.                   LCDBuffer_1[i]=(temp%10)+0x30;
  375.                   temp/=10;
  376.                   i--;
  377.                 }         
  378.                   MyTMR3.HighCounter=0;
  379.                   MyTMR3.LowCounter=0;
  380.                   T1CONbits.TMR1ON=1;
  381.                   lcd_displaystr(1,0,LCDBuffer_1);//將測量的結果送到LCD上顯示
  382.                 }
  383.         }
  384. }


  385. //-------------------------------------------------------------------
  386. #pragma interrupt PIC18F_High_isr
  387. void PIC18F_High_isr(void)
  388. {
  389.   unsigned long temp;
  390.   
  391.   if(1==INTCONbits.INT0IF)
  392.     {
  393.           INTCONbits.INT0IF=0;
  394.           if(MyTMR3.ChangeFlag)
  395.             {
  396.                   INTCONbits.INT0IE=0;
  397.                   MyTMR3.ChangeFlag=0;//如果標志為1,則置0
  398.                   MyTMR3.LowCounter=TMR3L;//讀取TMR3寄存器的內容
  399.                   MyTMR3.LowCounter=TMR3H;
  400.                   MyTMR3.LowCounter<<=8;
  401.                   MyTMR3.LowCounter|=TMR3L;
  402.                   FreqFlag=0;
  403.                   CycleFlag=1;                  
  404.                 }
  405.                 else
  406.                   {
  407.                         MyTMR3.ChangeFlag=1;//如果標志為0,則置1
  408.                         MyTMR3.HighCounter=0;//清相關變量
  409.                         MyTMR3.LowCounter=0;
  410.               }
  411.         }
  412.        
  413.   if(1==INTCONbits.TMR0IF)//定時1S時間到
  414.     {
  415.           INTCONbits.TMR0IF=0;//TMR0溢出標志位清0
  416.       TMR0H=(65536-31250)/256;//先寫高字節
  417.       TMR0L=(65536-31250)%256;//再寫低字節
  418.       
  419.       T1CONbits.TMR1ON=0;//TMR1計數器停止工作
  420.       MyTMR1.LowCounter=TMR1L;
  421.       MyTMR1.LowCounter=TMR1H;
  422.       MyTMR1.LowCounter<<=8;
  423.       MyTMR1.LowCounter|=TMR1L;
  424.       CycleFlag=0;
  425.       FreqFlag=1;
  426.         }
  427. }

  428. //-------------------------------------------------------------------
  429. //---低優先中斷服務程序函數
  430. #pragma interruptlow SystemInterruptISR
  431. void SystemInterruptISR(void)
  432. {
  433.   if(1==PIR1bits.TMR1IF)//如果TMR1溢出
  434.     {
  435.           PIR1bits.TMR1IF=0;//清TMR1溢出標志位
  436.           MyTMR1.HighCounter++;//TMR1軟計數器加1
  437.         }
  438.        
  439.   if(1==PIR2bits.TMR3IF)//如果TMR3溢出
  440.     {
  441.           PIR2bits.TMR3IF=0;//清TMR3溢出標志位
  442.           MyTMR3.HighCounter++;//TMR3軟計數器加1
  443.         }       
  444. }
復制代碼

所有資料51hei提供下載:
PIC單片機實用C語言程序設計與典型實例(光盤).rar (327.06 KB, 下載次數: 221)



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

使用道具 舉報

無效樓層,該帖已經被刪除
板凳
ID:242092 發表于 2019-6-18 14:56 | 只看該作者
感謝樓主分享!
回復

使用道具 舉報

無效樓層,該帖已經被刪除
5#
ID:339788 發表于 2019-8-23 21:50 | 只看該作者
感謝樓主分享!
回復

使用道具 舉報

6#
ID:339788 發表于 2019-8-23 21:51 | 只看該作者
感謝樓主分享!
回復

使用道具 舉報

7#
ID:140183 發表于 2019-12-22 10:37 | 只看該作者
太好啦謝謝分享!
回復

使用道具 舉報

8#
ID:116743 發表于 2020-4-7 11:21 | 只看該作者
謝謝 手下了
回復

使用道具 舉報

9#
ID:745141 發表于 2020-5-6 11:31 | 只看該作者
感謝樓主分享
回復

使用道具 舉報

10#
ID:606233 發表于 2020-6-4 15:39 | 只看該作者
感謝樓主分享!
回復

使用道具 舉報

11#
無效樓層,該帖已經被刪除
12#
ID:319585 發表于 2021-5-14 15:41 來自觸屏版 | 只看該作者
如果有pcb文件就完美了。
回復

使用道具 舉報

13#
ID:203380 發表于 2021-5-17 16:30 | 只看該作者
不錯 不錯   很好的資料   感謝分享!!!!!!!!!!!!
回復

使用道具 舉報

14#
無效樓層,該帖已經被刪除
15#
無效樓層,該帖已經被刪除
您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

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

Powered by 單片機教程網

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