標(biāo)題:
基于MSP430G2553的直流電機(jī)調(diào)速測速裝置源程序
[打印本頁]
作者:
炫啦
時間:
2019-12-25 13:32
標(biāo)題:
基于MSP430G2553的直流電機(jī)調(diào)速測速裝置源程序
本設(shè)計(jì)基于MSP430G2553單片機(jī),主要用了PWM輸出和捕獲功能,控制算法是PID.
設(shè)置二級菜單,功能一:調(diào)速功能;通過按鍵加減占空比調(diào)速,
通過返回按鍵退出此功能。
功能二:定速功能:通過按鍵設(shè)置目標(biāo)轉(zhuǎn)速,確認(rèn)按鍵按下后,啟動電機(jī),自動調(diào)整到目標(biāo)轉(zhuǎn)速,通過返回按鍵退出此功能。
(附件限制了大小,能上傳的也就只有程序了,有相關(guān)視頻去B站搜索:飛檐走壁王不羈,即可觀看相關(guān)視頻)
IMG20191225124140.jpg
(2.12 MB, 下載次數(shù): 81)
下載附件
2019-12-25 13:31 上傳
單片機(jī)源程序如下:
#include <msp430G2553.h>
#include "Lcd1602.h"
unsigned int DUTY=1000; //PWM占空比 (DUTY/10000)%
#define uchar unsigned char
#define uint unsigned int
uchar flag=0,disp_table[6],cap_table[10],n=0;
volatile uint fre_num=0;
long sum=0;
uint Redge,frequence,key=4,count=0,speed=0,yes=0,fanhui=0;
uint Period[10];
volatile long AvgPeriod;
unsigned char distr[3];
//uint Real,Target;
/*------------------PID參數(shù)初始化----------------------*/
float kp=0.0457,ki=0.005,kd=0.1; //PI控制參數(shù)設(shè)置
float error=0,Last_error=0,Prev_error=0;
float IncremDuty;
/****************************增量式PI控制函數(shù)******************************/
float Incremental_PID(float Real,float Target)
{
error = Target - Real;
IncremDuty = kp*(2.45*error - 3.5*Last_error + 1.25*Prev_error) ;
Prev_error = Last_error;
Last_error = error;
return IncremDuty;
}
/****************************************字符類型轉(zhuǎn)換函數(shù)***********************************************/
char int_to_char(char x)
{
distr[0] = (x/10) + 0x30;
distr[1] = x%10 + 0x30;
distr[2] = '\0';
}
/*---------------------數(shù)字轉(zhuǎn)換成字符------------------------------------------------*/
void num_to_char(uint k)
{
uchar i=0;
// disp_table[0] = k/10000 + 0x30; //'0'的ASCII碼0x30
disp_table[0] = k%10000/1000 + 0x30;
disp_table[1] = k%1000/100 + 0x30;
disp_table[2] = k%100/10 + 0x30;
disp_table[3] = k%10 + 0x30;
disp_table[4] = 0x20;
disp_table[5] = '\0';
for(i=0;i<4;i++) //去掉無效的前導(dǎo)'0'字符
{
if(disp_table[i]==0x30)
disp_table[i] = 0x20; //0x20是空格的ASCII碼
else
break;
}
}
void long_to_char(long k)
{
uchar j=0;
cap_table[0] = k/100000000 + 0x30; //'0'的ASCII碼0x30
cap_table[1] = k%100000000/10000000 + 0x30;
cap_table[2] = k%10000000/1000000 + 0x30;
cap_table[3] = k%1000000/100000 + 0x30;
cap_table[4] = k%100000/10000 + 0x30;
cap_table[5] = k%10000/1000 + 0x30;
cap_table[6] = k%1000/100 + 0x30;
cap_table[7] = k%100/10 + 0x30;
cap_table[8] = k%10 + 0x30;
cap_table[9] = '\0';
for(j=0;j<8;j++) //去掉無效的前導(dǎo)'0'字符
{
if(cap_table[j]==0x30)
cap_table[j] = 0x20; //0x20是空格的ASCII碼
else
break;
}
}
/*****************************************系統(tǒng)時鐘源設(shè)置******************************************************/
void OSC_CLK_Init(void)
{
if (CALBC1_8MHZ == 0xFF || CALDCO_8MHZ == 0xFF)
{while(1);} // If calibration constants erased, trap CPU!!
BCSCTL1 = CALBC1_8MHZ; // Set range
DCOCTL = CALDCO_8MHZ; // Set DCO step + modulation
IFG1 &= ~OFIFG; // Clear OSCFault flag
BCSCTL2 |= SELM_1 + DIVS_3 ; // Set MCLK=8MHz, SMCLK/
}
/****************************************PWM設(shè)置函數(shù)(比較模塊)**************************************************/
void PWM()
{
TA1CTL=TASSEL_2+MC_1+TACLR; //(定時器A1控制寄存器 )SMCLK 1MHZ+不分頻+增計(jì)數(shù)+清零
TA1CCTL2=OUTMOD_7; //(定時器A1捕獲控制寄存器2)高電平 PWM
TA1CCR0=10000-1; //周期10000us==10ms 100HZ
TA1CCR2=DUTY; //高電平時間
}
/********************************************捕獲模塊寄存器設(shè)置*******************************************************/
//P1.2端口設(shè)置為捕獲功能,用于測量信號頻率 ,當(dāng)捕獲頻率f=1MHz時
//能捕獲到最大信號周期為65.536ms,頻率為15.26Hz(最低信號頻率)
void Timer_A0_1_CAP()
{
TACTL = TASSEL_2 + MC_2 + ID_3 + TACLR; //SMCLK=1MHz/8=0.125MHz,連續(xù)計(jì)數(shù)模式,清TAR
TACCTL1 = CAP + CCIS_0 + SCS + CM_1 + CCIE;//CCISxA,開捕獲,上升沿捕獲,使能,同步捕獲
}
/*******************************************GPIO設(shè)置*****************************************************/
void IO_RE()
{
P2DIR |=BIT4; //pwm輸出 P2.4
P2SEL |=BIT4; //
P1DIR&=~BIT2; //轉(zhuǎn)速捕獲 P1.2
P1SEL|=BIT2; //
//查詢方式
P1DIR&=~(BIT0+BIT1+BIT3+BIT4); //四個用戶按鍵 0加速 1減速 3加50 4減50
P1OUT|=BIT0+BIT1+BIT3+BIT4; //輸出高電平
P1REN|=BIT0+BIT1+BIT3+BIT4; //上拉(硬件有上拉)
P1DIR|=BIT7; //P1.7 LED指示燈 用于調(diào)試
}
/**************************************按鍵消抖延時函數(shù)*******************************************************/
void delay_Nms(unsigned int n)
{
unsigned int i;
unsigned int j;
for(i = n;i > 0;i--)
for(j = 100;j > 0;j--)
_NOP();
}
/****************************************主函數(shù)***************************************************/
void main(void)
{
WDTCTL = WDTPW | WDTHOLD; //
OSC_CLK_Init(); //SMCLK 1M
Timer_A0_1_CAP(); //定時器A
lcdinit();
IO_RE();
_EINT(); //開總中斷
while(1)
{
/**************************************一級菜單************************************************/
if(key==4) //主界面
{
disp_str(1,0," A: MODE 1 ");
disp_str(2,0," B: MODE 2 ");
DUTY=1000;
PWM();
}
//功能選項(xiàng)一
if(!(P1IN&BIT0))
{
delay_Nms(10);
if(!(P1IN&BIT0))
{
while(!(P1IN&BIT0));
{
key=1;
}
}
}
//功能選項(xiàng)二
if(!(P1IN&BIT1))
{
delay_Nms(10);
if(!(P1IN&BIT1))
{
while(!(P1IN&BIT1));
{
key=2;
}
}
}
/*******************************************對應(yīng)功能***************************************************/
switch(key)
{
/********************************************功能一***************************************************/
case 1:
while(1)
{
if(count==0) //清除主界面
{
count=1;
lcd_clr();
}
/********************功能一主頁面***********************/
disp_str(1,0,"DUTY=");
int_to_char(DUTY/100); //占空比數(shù)值顯示
disp_str(1,6," ");
disp_str(1,9,distr);
disp_str(1,11,"% ");
disp_str(2,0,"n="); //轉(zhuǎn)速
disp_str(2,6,"r/min ");
/*****************計(jì)算顯示頻率(轉(zhuǎn)速)*********************/
if(flag==1)
{
frequence = (uint)(125000/AvgPeriod)*30; //計(jì)算信號轉(zhuǎn)速
num_to_char(frequence);
disp_str(2,2,disp_table);
flag = 0;
}
/*********************************************加速按鍵1************************************************/
if(!(P1IN&BIT0)&&key==1)
{
delay_Nms(10);
if(!(P1IN&BIT0)&&key==1)
{
disp_str(1,5,"+1%");
while(!(P1IN&BIT0)&&key==1);
{
P1OUT^=BIT7;
DUTY+=100;
if(DUTY>9000)
{
DUTY=9000;
}
PWM();
disp_str(1,5," ");
}
}
}
/*********************************************減速按鍵2**************************************************/
if(!(P1IN&BIT1)&&key==1)
{
delay_Nms(10);
if(!(P1IN&BIT1)&&key==1)
{
disp_str(1,5,"-1%");
while(!(P1IN&BIT1)&&key==1);
{
P1OUT^=BIT7;
DUTY-=100;
if(DUTY<1000)
{
DUTY=1000;
}
PWM();
disp_str(1,5," ");
}
}
}
/*********************************************返回按鍵4*********************************************/
if(!(P1IN&BIT4))
{
delay_Nms(10);
if(!(P1IN&BIT4))
{
while(!(P1IN&BIT4));
{
key=4;
break;
}
}
}
}
;
break;
/********************************************功能二******************************************/
case 2:
while(1)
{
if(count==0) //清除主界面
{
count=1;
lcd_clr();
}
DUTY=0;
PWM();
disp_str(1,1,"Input:");
disp_str(2,1,"speed:");
/*****************計(jì)算顯示頻率(轉(zhuǎn)速)*********************/
if(flag==1)
{
frequence = (uint)(125000/AvgPeriod)*30; //計(jì)算信號轉(zhuǎn)速
num_to_char(frequence);
disp_str(2,7,disp_table);
flag = 0;
}
/*******************************************加按鍵1***********************************************/
if(!(P1IN&BIT0)&&key==2)
{
delay_Nms(10);
if(!(P1IN&BIT0)&&key==2)
{
while(!(P1IN&BIT0)&&key==2);
{
speed+=60;
if(speed>2400) speed = 2400;
}
}
}
/*******************************************減按鍵2***********************************************/
if(!(P1IN&BIT1)&&key==2)
{
delay_Nms(10);
if(!(P1IN&BIT1)&&key==2)
{
while(!(P1IN&BIT1)&&key==2);
{
speed-=60;
if(speed<900) speed = 900;
}
}
}
num_to_char(speed);
disp_str(1,7,disp_table);
/*********************************************確認(rèn)按鍵3*********************************************/
if(!(P1IN&BIT3)&&key==2)
{
delay_Nms(10);
if(!(P1IN&BIT3)&&key==2)
{
while(!(P1IN&BIT3)&&key==2);
{
yes=3;
}
}
}
if(yes==3)
{
DUTY=900;
PWM();
while(fanhui==0) //如果沒有按返回按鍵
{
delay_Nms(150);
if(flag==1) //檢測當(dāng)前風(fēng)扇轉(zhuǎn)速并顯示
{
frequence = (uint)(125000/AvgPeriod)*30; //計(jì)算信號轉(zhuǎn)速
num_to_char(frequence);
disp_str(2,7,disp_table); //顯示當(dāng)前轉(zhuǎn)速
flag = 0;
}
//根據(jù)設(shè)定轉(zhuǎn)速進(jìn)行PID調(diào)節(jié)
if(fabs(frequence-speed)>20)
{
DUTY = DUTY + (int)Incremental_PID(frequence,speed);
TA1CCR2 = DUTY;
}
if(!(P1IN&BIT4))
{
delay_Nms(10);
if(!(P1IN&BIT4))
{
while(!(P1IN&BIT4));
{
fanhui=1;
break;
}
}
}
}
if(!(P1IN&BIT4))
{
delay_Nms(10);
if(!(P1IN&BIT4))
{
while(!(P1IN&BIT4));
{
fanhui=0;speed=0;DUTY=0;yes=0;
key=4;
break;
}
}
}
}
/*********************************************返回按鍵4*********************************************/
}
break;
}
}
}
/******************************************************************
* TA0.1 P1.2捕獲中斷
* 捕獲測頻原理:分別記錄第1次和第2次捕獲到上升沿的時刻Redge1、Redge2,
* 則信號周期為:Period = Redge2 - Redge1
*******************************************************************/
#pragma vector = TIMER0_A1_VECTOR
__interrupt void TIMER0_A1_ISR(void)
{
switch(TAIV)
{
case 0x02: //Vector 2:TACCR1 CCIFG
if(fre_num == 0) // 捕獲上升沿信號
{
Redge = TACCR1;
fre_num++;
}
else
{
_DINT();
if(TACCR1 > Redge) //第二次捕獲上升沿
Period[n] = TACCR1 - Redge; //計(jì)算周期
else
Period[n] = 65536 + TACCR1 - Redge;
Redge = TACCR1; //保存上次捕獲值
sum += (long)Period[n];
n++;
if(n==10)
{flag=1;AvgPeriod = sum/10;n=0;sum=0;} //取10次捕獲值的平均
_EINT();
}
break;
case 0x0A:
//溢出次數(shù)計(jì)數(shù)
break;
default: break;
}
}
復(fù)制代碼
所有資料51hei提供下載:
test speed 程序.rar
(71.68 KB, 下載次數(shù): 34)
2019-12-25 13:28 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
作者:
luozhao
時間:
2019-12-26 08:39
感謝分享
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1