冰楓論壇

標題: PIC16F628 [打印本頁]

作者: 洪嵐峰    時間: 2023-4-26 06:42
標題: PIC16F628
製作變頻機需要的零件包括:

PIC16F628 微控制器
晶振(通常使用4MHz的晶振)
22pF環氧陶瓷電容(用於晶振的穩定)
10k歐姆電阻(用於重置電路)
10uF電解電容(用於供電電路的濾波)
100nF環氧陶瓷電容(用於降噪和穩定)
2個按鈕(用於調整頻率)
16x2液晶顯示器(用於顯示頻率和訊息)
10k歐姆可變電阻(用於調整頻率)
電源供應器(通常使用9V電池或直流電源)
PIC16F628的連結腳位如下:

VDD:供電腳,接5V或3.3V電源
VSS:接地腳,接地
RA0 - RA5:數位輸入/輸出腳,可設置為輸入或輸出模式
RB0 - RB7:數位輸入/輸出腳,可設置為輸入或輸出模式
OSC1:晶振輸入腳,連接到晶振的一端
OSC2:晶振輸出腳,連接到晶振的另一端
MCLR:重置腳,通常連接一個10k歐姆電阻到VDD

程式碼如下:(這只是基礎的程式碼,需要根據具體需求進行修改)


// PIC16F628 變頻機程式碼

#include <htc.h>
#include <stdio.h>

// 配置設定
__CONFIG(FOSC_HS & WDTE_OFF & PWRTE_OFF & MCLRE_ON & BOREN_OFF & LVP_OFF & CPD_OFF & CP_OFF);

// 定義變量和常量
#define _XTAL_FREQ 4000000 // 使用4MHz的晶振
#define LCD_RS RA0
#define LCD_EN RA1
#define LCD_D4 RA2
#define LCD_D5 RA3
#define LCD_D6 RA4
#define LCD_D7 RA5
#define BUTTON1 RB0
#define BUTTON2 RB1
#define POT RB2
#define LCD_LINE1 0x80
#define LCD_LINE2 0xC0

// 函數聲明
void LCD_Init(void);
void LCD_Write_Char(char);
void LCD_Write_String(char *);
void LCD_Cmd(char);
void LCD_Clear(void);
void LCD_Set_Cursor(char, char);
void ADCvoid ADC_Init(void);
unsigned int ADC_Read(unsigned char);

// 主函數
void main()
{
unsigned int adc_value;
char freq_str[16];
int freq = 1000; // 初始頻率為1kHz

TRISB0 = 1; // 設置按鈕為輸入模式
TRISB1 = 1;
TRISB2 = 1; // 設置可變電阻為輸入模式
ANSELH = 0; // 設置數位腳

LCD_Init(); // 初始化液晶顯示器
ADC_Init(); // 初始化ADC

while(1)
{
    // 讀取按鈕和可變電阻的值
    if(!BUTTON1)
    {
        freq -= 10;
        if(freq < 100) freq = 100;
        __delay_ms(200);
    }
    if(!BUTTON2)
    {
        freq += 10;
        if(freq > 10000) freq = 10000;
        __delay_ms(200);
    }
    adc_value = ADC_Read(2);

    // 計算頻率
    freq = 100 + adc_value * 39 / 1023;

    // 將頻率轉換為字符串
    sprintf(freq_str, "Freq: %d Hz", freq);

    // 在液晶顯示器上顯示頻率和訊息
    LCD_Set_Cursor(1, 1);
    LCD_Write_String(freq_str);
    LCD_Set_Cursor(2, 1);
    LCD_Write_String("Press button to adj.");

    // 延遲一段時間
    __delay_ms(100);
}
}

// 初始化液晶顯示器
void LCD_Init()
{
TRISA = 0x00;
TRISB = 0x00;
LCD_Cmd(0x02);
LCD_Cmd(0x28);
LCD_Cmd(0x0C);
LCD_Cmd(0x06);
LCD_Cmd(0x01);
}

// 寫入字符到液晶顯示器
void LCD_Write_Char(char data)
{
LCD_RS = 1;
PORTB = data;
LCD_EN = 1;
__delay_us(4);
LCD_EN = 0;
__delay_us(40);
}

// 寫入字符串到液晶顯示器
void LCD_Write_String(char *str)
{
while(*str)
{
LCD_Write_Char(*str++);
}
}

// 發送命令到液晶顯示器
void LCD_Cmd(char command)
{
LCD_RS = 0;
PORTB = command;
LCD_EN = 1;
__delay_us(4);
LCD_EN = 0;
__delay_us(40);
}

// 清空液晶顯示器
void LCD_Clear()
{
LCD_Cmd(0x01);
}

// 設置液晶顯示器游標位置
void LCD_Set_Cursor(char row, char column)
{
char address;
if(row == 1)
{
address = LCD_LINE1 + column - 1;
}
else
{
address = LCD_LINE2 + column - 1;
}

LCD_Cmd(0x80 | address);
}

// 初始化ADC
void ADC_Init(void)
{
ADCON0 = 0x81; // 設置ADC模塊
ADCON1 = 0x80; // 設置ADC輸入電壓範圍
__delay_us(20); // 等待模塊啟動
}

// 讀取ADC值
unsigned int ADC_Read(unsigned char channel)
{
ADCON0 &= 0xC7; // 清除ADC通道選擇
ADCON0 |= channel << 3; // 設置ADC通道
__delay_us(20); // 等待轉換完成
GO_nDONE = 1; // 啟動轉換
while(GO_nDONE); // 等待轉換完成
return (ADRESH << 8) + ADRESL; // 返回ADC值
}

// 設置PWM
void PWM_Init(void)
{
TRISC2 = 0; // 設置RC2為輸出模式
CCP1CON = 0x0C; // 設置PWM模式
PR2 = 124; // 設置TMR2的週期為4us
T2CON = 0x01; // 啟動TMR2
}

// 設置PWM頻率
void PWM_Set_Frequency(unsigned int frequency)
{
unsigned int pwm_period;
pwm_period = (_XTAL_FREQ / (4 * frequency)) - 1;
CCPR1L = pwm_period >> 2;
CCP1CON = (CCP1CON & 0xCF) | ((pwm_period & 0x03) << 4);
}

// 設置PWM佔空比
void PWM_Set_Duty_Cycle(unsigned char duty_cycle)
{
unsigned int pwm_duty_cycle;
pwm_duty_cycle = ((unsigned int)duty_cycle * PR2) / 100;
CCPR1L = pwm_duty_cycle >> 2;
CCP1CON = (CCP1CON & 0xCF) | ((pwm_duty_cycle & 0x03) << 4);
}

// 延遲一段時間
void __delay_ms(unsigned int ms)
{
unsigned int i, j;
for(i = 0; i < ms; i++)
{
for(j = 0; j < 165; j++);
}
}

void __delay_us(unsigned int us)
{
unsigned int i, j;
for(i = 0; i < us; i++)
{
for(j = 0; j < 2; j++);
}
}

// 腳位連接
// RA0 - 不使用
// RA1 - 不使用
// RA2 - 不使用
// RA3 - 不使用
// RA4 - 不使用
// RA5 - 不使用
// RA6 - 不使用
// RA7 - 不使用

// RB0 - 按鈕1,接VCC上拉
// RB1 - 按鈕2,接VCC上拉
// RB2 - 可變電阻,接GND和VCC之間,中間接ADC

// RC0 - 不使用
// RC1 - 不使用
// RC2 - PWM
// RC3 - LCD RS
// RC4 - LCD E
// RC5 - LCD D4
// RC6 - LCD D5
// RC7 - LCD D6

// 主程序
void main()
{
unsigned int frequency = 1000; // 初始頻率為1kHz
unsigned char duty_cycle = 50; // 初始佔空比為50%
unsigned int adc_value;
char lcd_buffer[16];

// 初始化
OSCCON = 0x72; // 設置FOSC為8MHz
TRISB = 0x03; // 設置RB0和RB1為輸入模式
ADC_Init(); // 初始化ADC
PWM_Init(); // 初始化PWM
PWM_Set_Frequency(frequency); // 設置PWM頻率
PWM_Set_Duty_Cycle(duty_cycle); // 設置PWM佔空比
LCD_Init(); // 初始化LCD

// 主循環
while(1)
{
    // 按鈕1按下,增加頻率
    if(!RB0)
    {
        frequency += 100;
        if(frequency > 10000) frequency = 10000;
        PWM_Set_Frequency(frequency);
        sprintf(lcd_buffer, "Freq: %4dHz", frequency);
        LCD_Write_String(lcd_buffer, 0x80);
        __delay_ms(200);
    }
    // 按鈕2按下,減少頻率
    if(!RB1)
    {
        frequency -= 100;
        if(frequency < 100) frequency = 100;
        PWM_Set_Frequency(frequency);
        sprintf(lcd_buffer, "Freq: %4dHz", frequency);
        LCD_Write_String(lcd_buffer, 0x80);
        __delay_ms(200);
    }
    // 讀取ADC值,設置佔空比
    adc_value = ADC_Read(2);
    duty_cycle = adc_value >> 6;
    PWM_Set_Duty_Cycle(duty_cycle);
    sprintf(lcd_buffer, "Duty: =%%", duty_cycle);
    LCD_Write_String(lcd_buffer, 0xC0);
    __delay_ms(20);
}
}

這是變頻機程序,可以根據按鈕和可變電阻的變化調整PWM的頻率和佔空比,並將頻率和佔空比顯示在LCD上。






歡迎光臨 冰楓論壇 (https://bingfong.com/) Powered by 冰楓