欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136
標題:
一個單片機PWM調壓程序,怎么編寫PID函數調節電壓?
[打印本頁]
作者:
lern01
時間:
2018-12-14 19:11
標題:
一個單片機PWM調壓程序,怎么編寫PID函數調節電壓?
本帖最后由 lern01 于 2018-12-14 19:59 編輯
一個PWM調壓程序,怎么編寫PID函數來調節電壓?也望大老能指點,十分地感謝!
附單片機程序:
#include "stc12c5a60s2.h"
#include "intrins.h"
#define ADC_POWER 0x80 //ADC電源控制位,0-關閉,1-打開
#define ADC_FLAG 0x10 //ADC結束標志位
#define ADC_START 0x08 //ADC啟動控制位
#define ADC_SPEEDLL 0x00 //540 clocks--選擇轉換速度
unsigned char Lcd_Dis1_table[] = {"SetValue: "}; //第一行顯示框架
unsigned char Lcd_Dis2_table[] = {"Voltage : "}; //第二行顯示框架
float Show, NUM;
unsigned char volt = 0; //作為顯示的數據
bit flag300ms = 1; //300ms定時標志
unsigned char T0RH = 0; //T0重載值的高字節
unsigned char T0RL = 0; //T0重載值的低字節
//PID算法公式:
sbit key1 = P2^7; //定義按鍵1
sbit key2 = P2^6; //定義按鍵2
sbit key3 = P2^5; //定義按鍵3
sbit key4 = P2^4; //定義按鍵4
sbit key_gnd = P2^3; //定義接地
void ConfigTimer0(unsigned int ms);
void InitADC();
void InitPWM();
void PWM0_change(unsigned char type, unsigned char change);
void Delay(unsigned int n);
void KeyAction(unsigned char keycod);
void NumToString(unsigned char num);
void ValueToString(unsigned char *str, unsigned int val);
unsigned int GetADCResult(unsigned char ch); //讀取輸入電壓模數轉換函數
extern void KeyScan();
extern void KeyDriver();
extern void InitLcd1602();
extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
void main()
{
unsigned int val;
unsigned char str[10];
key_gnd = 0;
EA = 1; //開總中斷
ConfigTimer0(10); //配置T0定時10ms
InitADC();
InitPWM();
InitLcd1602();
LcdShowStr(0, 0, Lcd_Dis1_table);
LcdShowStr(0, 1, Lcd_Dis2_table);
while(1)
{
KeyDriver();
if(flag300ms)
{
flag300ms = 0;
val = GetADCResult(7);
ValueToString(str, val);
LcdShowStr(9, 1, str);
}
NumToString(volt);
/* NUM = 10 * NUM;
Show = ldata;
if((NUM < (Show - 0.1))||(NUM > (Show + 0.1)))
{
if(NUM < (Show - 0.1))
{
if((Show - 0.1) - NUM > 1)
{
PWM1_change(1, 0X05);
}
else
{
PWM1_change(1, 0X01);
}
}
else
{
if(NUM - (Show + 0.1) > 1)
{
PWM1_change(0, 0X05);
}
else
{
PWM1_change(0, 0X01);
}
}
Delay(500);
}
else
{
Delay(2000);
} */
}
}
void NumToString(unsigned char num)
{
unsigned char str[10];
str[0] = num/100 + '0';
str[1] = num/10%100 + '0';
str[2] = '.';
str[3] = num%10 + '0';
str[4] = 'V';
str[5] = '\0';
LcdShowStr(9, 0, str);
}
/*------------ADC 取值 --------------*/
unsigned int GetADCResult(unsigned char ch) //ch--AD輸入通道
{
unsigned int val = 0;
ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START |ch;
_nop_(); _nop_(); _nop_(); _nop_(); _nop_();
while(!(ADC_CONTR & ADC_FLAG)); //等待AD轉換完成
ADC_CONTR &= ~ADC_FLAG; //關閉ADC
val = ADC_RES;
val = (val << 2) | (0x03 & ADC_RESL);
return val; //返回A/D轉換結果
}
void InitADC()
{
P1ASF = 0x80; //設置P1.7為AD輸入通道
ADC_RES = 0; //清除高8位RES和低2位RESL
ADC_RESL = 0;
ADC_CONTR = ADC_POWER | ADC_SPEEDLL;
Delay(20); //打開ADC電源并延時
}
/* ADC轉換值轉為實際電壓值的字符串形式,str-字符串指針,val-AD轉換值 */
void ValueToString(unsigned char *str, unsigned int val)
{
NUM = (val * 5.03) / 1024.0;
str[0] = (unsigned int)NUM/10 + '0';
str[1] = (unsigned int)NUM%10 + '0';
str[2] = '.';
str[3] = (unsigned int)(NUM*10)%10 + '0';
str[4] = (unsigned int)(NUM*100)%10 + '0';
str[5] = 'V';
str[6] = '\0';
}
void InitPWM()
{
CCON = 0; //Initial PCA control register
//PCA timer stop runing
//Clear CF flag
//Clear all module interrupt flag
CL = CH = 0; //Reset PCA base timer
CMOD = 0x02; //Set PCA timer clock source as Fousc/2 0X00:以系統時鐘/12 為時鐘源,0X02:系統時鐘/2,0x08:系統時鐘
//Disable PCA timer overflow interrupt
CCAP0L = CCAP0H = 0xff; //起始占空比,0XC0:占空比為25%,0X80:占空比為50%,0X40:占空比為75%
PCA_PWM0 = 0x00;
CCAPM0 = 0x42;//0X42:8位PWM P1.4輸出,無中斷;0X53:8位PWM輸出,下降沿產生中斷;0X63:上升沿產生中斷;0X73:跳變沿產生中斷
CR = 1; //計時器開始工作
}
void PWM0_change(unsigned char type, unsigned char change) //type=0減占空比,1增加占空比 change: 0X0C約5%,0X05約2%
{
if(type == 0)
{
if(CCAP0L < 0xff) //占空比 < 90%
{
CCAP0L += change;
CCAP0H += change;
}
}
else
{
if(CCAP0L > 0x00) // > 10%
CCAP0L -= change;
CCAP0H -= change;
}
}
void KeyAction(unsigned char keycod)
{
switch(keycod)
{
case 0x26:
if(volt < 50);
{
volt++;
PWM0_change(1, 0x05);
}
break;
case 0x28:
if(volt > 0)
{
volt--;
PWM0_change(0, 0x05);
}
break;
case 0x27:
if(volt < 50)
{
volt += 10;
PWM0_change(1, 0x0C);
}
break;
case 0x25:
if(volt > 0)
{
volt -= 10;
PWM0_change(0, 0x0C);
}
break;
default: break;
}
}
void Delay(unsigned int n)
{
unsigned int x;
while (n--)
{
x = 500;
while (x--);
}
}
/*
void DelayMs(unsigned char ms) //延時程序
{
unsigned int i;
while(ms--)
{
for(i=0; i<850; i++)
;
}
}
*/
/* 配置并啟動T0,ms-T0定時時間 */
void ConfigTimer0(unsigned int ms)
{
unsigned long tmp; //臨時變量
tmp = 11059200 / 12; //定時器計數頻率
tmp = (tmp * ms) / 1000; //計算所需的計數值
tmp = 65536 - tmp; //計算定時器重載值
tmp = tmp + 12; //補償中斷響應延時造成的誤差
T0RH = (unsigned char)(tmp>>8); //定時器重載值拆分為高低字節
T0RL = (unsigned char)tmp;
TMOD &= 0xF0; //清零T0的控制位
TMOD |= 0x01; //配置T0為模式1
TH0 = T0RH; //加載T0重載值
TL0 = T0RL;
ET0 = 1; //使能T0中斷
TR0 = 1; //啟動T0
}
/* T0中斷服務函數,執行300ms定時 */
void InterruptTimer0() interrupt 1
{
static unsigned char tmr300ms = 0;
TH0 = T0RH; //重新加載重載值
TL0 = T0RL;
KeyScan();
tmr300ms++;
if (tmr300ms >= 30) //定時300ms
{
tmr300ms = 0;
flag300ms = 1;
}
}
復制代碼
作者:
瘋子本人
時間:
2018-12-18 13:57
pid函數網上都有的,你可以去網上找找,然后把pid函數返回來的值傳給所要控制的函數就可以了
歡迎光臨 (http://m.raoushi.com/bbs/)
Powered by Discuz! X3.1