冰楓論壇

 找回密碼
 立即註冊
搜索
查看: 738|回覆: 0
打印 上一主題 下一主題

[討論] PIC16F887

[複製鏈接]

2609

主題

0

好友

1009

積分

金牌會員

Rank: 6Rank: 6

UID
373967
帖子
9026
主題
2609
精華
0
積分
1009
楓幣
0
威望
986
存款
35994
贊助金額
0
推廣
0
GP
1205
閱讀權限
70
在線時間
461 小時
註冊時間
2023-1-12
最後登入
2024-12-25

2023端午節紀念勳章 2023中秋節紀念勳章 2023聖誕節紀念勳章

跳轉到指定樓層
1
發表於 2023-4-27 06:19:26 |只看該作者 |倒序瀏覽
PIC16F887是一款8位元微控制器,支援多種通訊介面和多種週邊裝置,如計時器、計數器和類比數位轉換器等。
下面是使用PIC16F887製作PID控制器所需的零件和相關連結腳位:

PIC16F887微控制器
LCD 16x2顯示器
電位計
電位計電路
電源供應器
USB TTL轉換器

以下是PID控制器的程式碼,您可以根據自己的需要進行修改:


#include <xc.h>

// 設定運算時脈頻率
#pragma config FOSC = INTOSCIO // 內部振盪器
#pragma config WDTE = OFF // 監看狗定時器關閉
#pragma config PWRTE = ON // 延時器啟動
#pragma config BOREN = OFF // 失壓檢測關閉
#pragma config LVP = OFF // 能量驅動程式關閉

// 設定顯示器腳位
#define RS RB0
#define EN RB1
#define D4 RB2
#define D5 RB3
#define D6 RB4
#define D7 RB5

// 設定PID參數
#define Kp 1.0
#define Ki 0.5
#define Kd 0.2

// 宣告變數
int set_point, current_point, error, last_error, integral, derivative, output;

// 設定計時器初值
void timer_init() {
    T1CONbits.T1CKPS = 0b11; // 設定計時器時脈頻率為1/8
    T1CONbits.TMR1ON = 1; // 啟動計時器
}

// 讀取電位計數值
int read_pot() {
    ADCON0bits.ADON = 1; // 啟動類比轉換器
    ADCON0bits.CHS = 0b0000; // 選擇AN0通道
    __delay_us(5); // 等待轉換完成
    ADCON0bits.GO_nDONE = 1; // 開始進行轉換
    while (ADCON0bits.GO_nDONE); // 等待轉換完成
    return ADRESH << 8 | ADRESL; // 返回轉換結果
}

// 初始化LCD顯示器
void lcd_init() {
    TRISB = 0x00; // 設定RB0-RB5腳位為輸出模式
    __delay_ms(100); // 等待LCD初始化完成
    LCD_command(0x02); // 將光標移至左上角
    LCD_command(0x28); // 選擇16x2顯示模
    LCD_command(0x0C); // 顯示器開啟,光標隱藏
    LCD_command(0x06); // 光標自動右移
    LCD_command(0x01); // 清除顯示器內容
}

// 傳送命令給LCD顯示器
void LCD_command(unsigned char cmd) {
RS = 0; // 選擇命令模式
PORTB = (cmd >> 4) & 0x0F; // 傳送高4位元
EN = 1; // 啟動顯示器
__delay_us(1); // 延時1微秒
EN = 0; // 關閉顯示器
PORTB = cmd & 0x0F; // 傳送低4位元
EN = 1; // 啟動顯示器
__delay_us(1); // 延時1微秒
EN = 0; // 關閉顯示器
__delay_us(100); // 延時100微秒
}

// 傳送資料給LCD顯示器
void LCD_data(unsigned char data) {
RS = 1; // 選擇資料模式
PORTB = (data >> 4) & 0x0F; // 傳送高4位元
EN = 1; // 啟動顯示器
__delay_us(1); // 延時1微秒
EN = 0; // 關閉顯示器
PORTB = data & 0x0F; // 傳送低4位元
EN = 1; // 啟動顯示器
__delay_us(1); // 延時1微秒
EN = 0; // 關閉顯示器
__delay_us(100); // 延時100微秒
}

// 將整數轉換為字串
void int_to_string(int num, char* str) {
int i, sign;
if ((sign = num) < 0) // 處理負數
num = -num;
i = 0;
do {
str[i++] = num % 10 + '0'; // 取最後一位數字
} while ((num /= 10) > 0); // 移除最後一位數字
if (sign < 0) // 如果是負數,加上負號
str[i++] = '-';
str[i] = '\0'; // 加上結束符號
// 反轉字串
int j = 0, k = i - 1;
while (j < k) {
char temp = str[j];
str[j] = str[k];
str[k] = temp;
j++;
k--;
}
}

// 主程式
void main() {
OSCCON = 0b01110010; // 設定內部振盪器頻率為8MHz
ANSEL = 0b00000001; // 設定AN
TRISA = 0b00000001; // 設定RA0為輸入
TRISB = 0b00000000; // 設定RB為輸出
TRISC = 0b00000000; // 設定RC為輸出
PORTB = 0b00000000; // 初始值為0
PORTC = 0b00000000; // 初始值為0

// 初始化LCD顯示器
LCD_init();

// 設定PID控制器參數
double Kp = 1.0, Ki = 0.5, Kd = 0.2;
double setpoint = 25.0; // 目標溫度
double dt = 0.1; // 取樣時間
double error, last_error, integral = 0, derivative, output;
double temp, voltage;
int adc_value;
char str[16];

// 設定ADC模組
ADCON0 = 0b00000001; // 選擇AN0輸入,啟動ADC模組
ADCON1 = 0b00000000; // 右對齊,選擇Vref+為VDD,Vref-為VSS
__delay_us(10); // 等待ADC模組啟動完成

while (1) {
    // 讀取溫度值
    ADCON0bits.GO = 1; // 啟動ADC轉換
    while (ADCON0bits.GO); // 等待ADC轉換完成
    adc_value = ADRESH << 8 | ADRESL; // 組合ADC轉換結果
    voltage = adc_value * 5.0 / 1024.0; // 轉換為電壓
    temp = (voltage - 0.5) * 100.0; // 轉換為溫度
    error = setpoint - temp; // 計算誤差
    integral += error * dt; // 累計積分
    derivative = (error - last_error) / dt; // 計算微分
    output = Kp * error + Ki * integral + Kd * derivative; // 計算控制輸出
    last_error = error; // 儲存上一次誤差值

    // 限制控制輸出在0到5V之間
    if (output > 5.0)
        output = 5.0;
    else if (output < 0)
        output = 0;

    // 設定PWM
    CCP1CONbits.DC1B = ((int)(output / 0.0195)) & 0x03;
    CCPR1L = (int)(output / 0.0195) >> 2;

    // 顯示溫度和控制輸出值
    LCD_command(0x80); // 設定顯示器光標位置
    LCD_data('T');
    LCD_data('e');
    LCD_data('m');
    LCD_data('p');
    LCD_data(':');
    sprintf(str, "%3.1f", temp);
    LCD_string(str);
    LCD_data(0xDF); // 顯示溫度符號
    LCD_data('C');

    LCD_command(0xC0); // 設定顯示器光標位置
    LCD_data('O');
    LCD_data('u');
    LCD_data('t');
    LCD_data('p');
    LCD_data('u');
    LCD_data('t');
    LCD_data(':');
    sprintf(str, "%3.1f", output);
    LCD_string(str);
    LCD_data('V');

    __delay_ms(100); // 等待100ms
}
}

以上是一個簡單的PID控制器的範例,使用PIC16F887微控制器控制一個PWM輸出,用於控制加熱器的溫度。

程式碼中包含了設定IO腳位、LCD顯示器、ADC模組和PID控制器參數的部分,以及控制輸出和顯示溫度和控制輸出值的主要部分。

建議使用相關的開發板或模擬器進行實際的測試和調試。
收藏收藏0 推0 噓0


把本文推薦給朋友或其他網站上,每次被點擊增加您在本站積分: 1鑰匙
複製連結並發給好友,以賺取推廣點數
簡單兩步驟,註冊、分享網址,即可獲得獎勵! 一起推廣文章換商品、賺$$
高級模式
B Color Image Link Quote Code Smilies |上傳

廣告刊登意見回饋關於我們管群招募本站規範DMCA隱私權政策

Copyright © 2011-2024 冰楓論壇, All rights reserved

免責聲明:本網站是以即時上載留言的方式運作,本站對所有留言的真實性、完整性及立場等,不負任何法律責任。

而一切留言之言論只代表留言者個人意見,並非本網站之立場,用戶不應信賴內容,並應自行判斷內容之真實性。

小黑屋|手機版|冰楓論壇

GMT+8, 2024-12-26 02:28

回頂部