- UID
- 373967
- 帖子
- 8867
- 主題
- 2609
- 精華
- 0
- 積分
- 1000
- 楓幣
- 15
- 威望
- 977
- 存款
- 34822
- 贊助金額
- 0
- 推廣
- 0
- GP
- 1205
- 閱讀權限
- 70
- 在線時間
- 455 小時
- 註冊時間
- 2023-1-12
- 最後登入
- 2024-11-22
|
製作多通道示波器的零件清單:
PIC32MX440F256H 微控制器
128x64 黑白 OLED 顯示屏
AD9286-80 8 位 80 MSPS ADC
多路放大器
訊號開關
快速二極體
多路電位器
轉換器
滑動式電位器
電晶體
以下是 PIC32MX440F256H 微控制器腳位圖:
+----------------------------------------+
| PIC32MX440F256H 腳位圖 |
+----------------------------------------+
_______ _______
| \/ |
MCLR |1 64| VDD
ICSPDAT |2 63| VSS
ICSPCLK |3 62| PGED1
RB0 |4 61| PGEC1
RB1 |5 60| AN15/RB15
RB2 |6 59| AN14/RB14
RB3 |7 58| AN13/RB13
RB4 |8 57| AN12/RB12
RB5 |9 56| AN11/RB11
RB6 |10 55| AN10/RB10
RB7 |11 54| AN9/RB9
RB8 |12 53| AN8/RB8
RB9 |13 52| AN7/RB7
RB10 |14 51| AN6/RB6
RB11 |15 50| AN5/RB5
RB12 |16 49| AN4/RB4
RB13 |17 48| AN3/RB3
RB14 |18 47| AN2/RB2
RB15 |19 46| AN1/RB1
VUSB3V3 |20 45| AN0/RB0
VBUSON |21 44| AVDD
VDD |22 43| AVSS
VSS1 |23 42| RE5
RA0 |24 41| RE4
RA1 |25 40| RE3
RA2 |26 39| RE2
RA3 |27 38| RE1
RA4 |28 37| RE0
RA5 |29 36| VCAP
VSS2 |30 35| VSS
RD0 |31 34| RD7
RD1 |32 33| RD6
+---------------+
程式碼:
以下是 PIC32MX440F256H 微控制器的多通道示波器的程式碼
用於顯示 ADC 讀數的圖形:
#include <p32xxxx.h>
#include <plib.h>
#include <stdio.h>
#pragma config FNOSC = FRCPLL
#pragma config FPLLIDIV
#pragma config FPLLMUL = MUL_20
#pragma config FPLLODIV = DIV_2
#pragma config FPBDIV = DIV_1
#pragma config FWDTEN = OFF
#define SYS_FREQ (80000000L)
#define PB_DIV 1
#define PRESCALE 256
#define SAMPLING_RATE (SYS_FREQ/PB_DIV/PRESCALE)
#define OLED_CMD 0x00
#define OLED_DATA 0x40
void initADC(void);
void initOLED(void);
void plotWaveform(void);
unsigned char waveformBuffer[128];
int main(void)
{
initADC();
initOLED();
while (1)
{
plotWaveform();
}
return 0;
}
void initADC(void)
{
AD1PCFG = 0xFFFF; // All pins digital
AD1CON1 = 0x00E0; // Auto-convert mode
AD1CSSL = 0x0000; // No scanning required
AD1CON2 = 0x0000; // No scanning required
AD1CON3 = 0x1F00; // Tad = 32 PBCLK cycles
AD1CON1bits.ADON = 1; // Turn on ADC
}
void initOLED(void)
{
// Initialize SPI1 module
SPI1CONbits.ON = 0; // Disable SPI module
SPI1CONbits.MSTEN = 1; // Set as Master mode
SPI1CONbits.CKE = 1; // Clock edge select
SPI1CONbits.SMP = 0; // Input data sampled at middle of data output time
SPI1CONbits.MODE16 = 0; // 8-bit mode
SPI1CONbits.MODE32 = 0; // 8-bit mode
SPI1CONbits.DISSDI = 0; // Enable SDI pin
SPI1CONbits.DISSDO = 0; // Enable SDO pin
SPI1CONbits.SSEN = 0; // SS pin not used
SPI1CONbits.ENHBUF = 1; // Enable enhanced buffer mode
SPI1CONbits.MCLKSEL = 0;// Set PBCLK as SPI clock
SPI1BRG = 0; // Set clock divider to 1
SPI1CONbits.ON = 1; // Enable SPI module
// Initialize OLED module
TRISDbits.TRISD9 = 0; // Set RD9 as output (data/command pin)
TRISGbits.TRISG6 = 0; // Set RG6 as output (reset pin)
PORTGbits.RG6 = 1; // Set OLED reset pin high
DelayMs(1); // Wait for OLED to stabilize
PORTGbits.RG6 = 0; // Set OLED reset pin low
DelayMs(10); // Wait for OLED to reset
PORTGbits.RG6 = 1; // Set OLED reset pin high
// Initialize OLED display
WriteOLEDCommand(0xAE); // Display off
WriteOLEDCommand(0xA1); // Segment remap
WriteOLEDCommand(0xDA); // Common pads hardware: alternative
WriteOLEDCommand(0x12);
WriteOLEDCommand(0xC8); // Common output scan direction:com63~com0
WriteOLEDCommand(0D5,D4 display multiplex, D3 disable to display clock, D2~D0normal)
WriteOLEDCommand(0x81); // Contrast control
WriteOLEDCommand(0xCF);
WriteOLEDCommand(0xD9); // Set pre-charge period
WriteOLEDCommand(0xF1);
WriteOLEDCommand(0xDB); // VCOM deselect level mode
WriteOLEDCommand(0x40);
WriteOLEDCommand(0xA4); // Set display mode: Reset
WriteOLEDCommand(0xA6); // Set display mode: Normal display
WriteOLEDCommand(0xAF); // Display on
}
void plotWaveform(void)
{
int i;
// Sample analog inputs
AD1CON1bits.SAMP = 1; // Start sampling
DelayUs(10); // Wait for sampling to complete
AD1CON1bits.SAMP = 0; // Stop sampling and start conversion
while (!AD1CON1bits.DONE); // Wait for conversion to complete
int adcValues[4];
adcValues[0] = ADC1BUF0;
adcValues[1] = ADC1BUF1;
adcValues[2] = ADC1BUF2;
adcValues[3] = ADC1BUF3;
// Convert ADC values to waveform buffer
for (i = 0; i < 128; i++)
{
int sum = 0;
int j;
for (j = 0; j < 4; j++)
{
AD1CHSbits.CH0SA = j; // Select analog input channel
AD1CON1bits.SAMP = 1; // Start sampling
DelayUs(10); // Wait for sampling to complete
AD1CON1bits.SAMP = 0; // Stop sampling and start conversion
while (!AD1CON1bits.DONE); // Wait for conversion to complete
sum += ADC1BUF0;
}
waveformBuffer[i] = sum / 4;
}
// Display waveform on OLED
WriteOLEDCommand(0xAE); // Display off
WriteOLEDCommand(0x20); // Set memory addressing mode
WriteOLEDCommand(0x10); // Set horizontal addressing mode
WriteOLEDCommand(0xB0); // Set page start address
WriteOLEDCommand(0x00); // Set lower column address
WriteOLEDCommand(0x10); // Set higher column address
for (i = 0; i < 128; i++)
{
WriteOLEDData(waveformBuffer[i]);
}
WriteOLEDCommand(0xAF); // Display on
}
void WriteOLEDCommand(unsigned char command)
{
LATDbits.LATD9 = OLED_CMD;
while (SPI1STATbits.SPITBF); // Wait for TX buffer to be empty
SPI1BUF = command; // Send command
while (!SPI1STATbits.SPIRBF);// Wait for RX buffer to be full
char dummy = SPI1BUF; // Discard received data
}
void WriteOLEDData(unsigned char data)
{
LATDbits.LATD9 = OLED_DATA;
while (SPI1STATbits.SPITBF); // Wait for TX buffer to be empty
SPI1BUF = data;
while (!SPI1STATbits.SPIRBF);// Wait for RX buffer to be full
char dummy = SPI1BUF; // Discard received data
}
void DelayUs(unsigned int us)
{
// Convert us to timer ticks
us *= PBCLK / 1000000;
// Use Timer 2 to generate delay
T2CONbits.TCKPS = 0; // Set prescaler to 1
T2CONbits.T32 = 0; // Timer 2 operates as two 16-bit timers
T2CONbits.TCS = 0; // Use internal clock
TMR2 = 0; // Reset timer
PR2 = us; // Set period
T2CONbits.TON = 1; // Turn on timer
// Wait for timer to expire
while (!IFS0bits.T2IF);
T2CONbits.TON = 0; // Turn off timer
IFS0bits.T2IF = 0; // Clear interrupt flag
}
int main(void)
{
TRISB = 0xFFFF; // Set all PORTB pins as inputs
TRISD = 0; // Set all PORTD pins as outputs
LATD = 0; // Clear all PORTD outputs
// Configure SPI1 for OLED communication
SPI1CONbits.ON = 0; // Turn off SPI1
SPI1CONbits.MSTEN = 1; // Master mode
SPI1CONbits.CKP = 0; // Idle clock low
SPI1CONbits.CKE = 1; // Data changes on falling edge
SPI1CONbits.SMP = 0; // Sample data on rising edge
SPI1CONbits.MODE16 = 0; // 8-bit mode
SPI1CONbits.MODE32 = 0; // 8-bit mode
SPI1CONbits.DISSDO = 0; // SDO1 enabled
SPI1CONbits.DISSDI = 1; // SDI1 disabled
SPI1CONbits.SSEN = 0; // SS1 pin not used
SPI1CONbits.ENHBUF = 0; // Standard buffer mode
SPI1CONbits.MCLKSEL = 0; // PBCLK used as clock source
SPI1BRG = 0; // Maximum baud rate
SPI1CONbits.ON = 1; // Turn on SPI1
// Configure Timer 2 for delay function
T2CONbits.ON = 0; // Turn off Timer 2
T2CONbits.TCKPS = 0; // Set prescaler to 1
T2CONbits.T32 = 0; // Timer 2 operates as two 16-bit timers
T2CONbits.TCS = 0; // Use internal clock
TMR2 = 0; // Reset timer
PR2 = 0xFFFF; // Set period to maximum
T2CONbits.ON = 1; // Turn on Timer 2
// Configure analog inputs for ADC
AD1PCFG = 0xFFFF; // Set all pins as digital
AD1CON1bits.ADON = 0; // Turn off ADC1
AD1CON1bits.FORM = 0; // Integer format
AD1CON1bits.SSRC = 0b111; // Auto-
AD1CON1bits.ASAM = 1; // Auto-start sampling
AD1CON2bits.VCFG = 0; // Use AVDD and AVSS as reference
AD1CON2bits.CSCNA = 1; // Scan inputs
AD1CON2bits.SMPI = 3; // Interrupt after 4 conversions
AD1CON2bits.BUFM = 0; // Use 16-word buffer
AD1CON2bits.ALTS = 0; // Always use MUXA
AD1CON3bits.ADRC = 0; // Use PBCLK as clock source
AD1CON3bits.SAMC = 0b11111; // 31 Tad
AD1CON3bits.ADCS = 1; // Set Tad to 2x Tpb
AD1CHSbits.CH0NA = 0; // Use Vref- as negative input
AD1CON1bits.ADON = 1; // Turn on ADC1
// Configure Timer 3 for PWM output
T3CONbits.ON = 0; // Turn off Timer 3
T3CONbits.TCKPS = 0; // Set prescaler to 1
T3CONbits.TCS = 0; // Use internal clock
T3CONbits.TGATE = 0; // Disable gated mode
T3CONbits.TSIDL = 0; // Continue operation in idle mode
T3CONbits.TSYNC = 0; // Do not sync external clock input
TMR3 = 0; // Reset timer
PR3 = 3999; // Set period to 4ms
OC1R = 0; // Clear duty cycle
OC1RS = 2000; // Set initial duty cycle to 50%
OC1CONbits.OCTSEL = 1; // Use Timer 3 for output compare
OC1CONbits.OCM = 0b110; // PWM mode
T3CONbits.ON = 1; // Turn on Timer 3
while (1)
{
// Start ADC conversion
AD1CON1bits.SAMP = 1;
DelayUs(10);
AD1CON1bits.SAMP = 0;
// Wait for ADC conversion to complete
while (!IFS0bits.AD1IF);
// Read ADC result and display on OLED
int i;
for (i = 0; i < 4; i++)
{
char str[10];
sprintf(str, "%04d", ADC1BUF[i]);
DrawString(10 + i * 60, 20, str, WHITE, BLACK);
}
// Update PWM duty cycle based on ADC value
OC1RS = ADC1BUF[0] / 4;
// Clear ADC interrupt flag
IFS0bits.AD1IF = 0;
}
return 0;
}
程式碼主要功能是使用 PIC32MX440F256H 微控制器的 ADC 模塊和 PWM 模塊。
在這段程式碼中,首先使用 ADC 模塊來採樣四個通道的模擬信號,並使用 OLED 顯示每個通道的數值。
然後,根據其中一個通道的數值,更新 PWM 模塊的佔空比,以產生 PWM 輸出信號。
具體來說,以下是每個主要設置的解釋:
AD1CON1bits.ASAM = 1;:啟用自動採樣模式,讓 ADC 自動開始採樣。
AD1CON2bits.VCFG = 0;:將 AVDD 和 AVSS 設置為 ADC 參考電壓。
AD1CON2bits.CSCNA = 1;:啟用通道掃描模式,讓 ADC 自動掃描多個通道。
AD1CON2bits.SMPI = 3;:設置中斷標誌觸發時的掃描數量,此處設置為 4。
AD1CON2bits.BUFM = 0;:使用 16 個單詞緩存。
AD1CON2bits.ALTS = 0;:始終使用 MUXA。
AD1CON3bits.ADRC = 0;:使用 PBCLK 作為 ADC 時鐘源。
AD1CON3bits.SAMC = 0b11111;:設置採樣時間,此處為 31 Tad。
AD1CON3bits.ADCS = 1;:設置 ADC 時鐘分頻,此處設置為 2x Tpb。
AD1CHSbits.CH0NA = 0;:使用 Vref- 作為負輸入。
AD1CON1bits.ADON = 1;:啟用 ADC1。
以上設置將 ADC1 設置為掃描模式,自動採樣四個通道,並將採樣結果存儲在 ADC1BUF 中。
接下來,使用 Timer 3 和 Output Compare 模塊來生成 PWM 輸出信號。
具體來說:
T3CONbits.ON = 0;:關閉 Timer 3。
T3CONbits.TCKPS = 0;:設置計時器分頻器,此處設置為 1。
T3CONbits.TCS = 0;:使用內部時鐘源。
T3CONbits.TGATE = 0;:禁用門控模式。
T3CONbits.TSIDL = 0;:在空閒模式下 |
|