#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
/************************ 引腳定義(嚴格匹配仿真圖)************************/
// LCD1 控制引腳
sbit LCD_RES = P1^6; // RES -> P1.6
sbit LCD_DC = P1^5; // D/C -> P1.5
sbit LCD_CS = P1^4; // CS -> P1.4
sbit LCD_WR = P1^7; // WR -> P1.7
sbit LCD_RD = P1^3; // RD -> P1.3
#define LCD_DATA P0 // 數據總線 D0~D7 -> P0口(含P0.0蜂鳴器,不影響)
// ADC0832 引腳
sbit ADC_CS = P1^0; // CS -> P1.0
sbit ADC_CLK = P1^1; // CLK -> P1.1
sbit ADC_DI = P1^2; // DI -> P1.2
sbit ADC_DO = P1^2; // DO -> P1.2(ADC0832 DI/DO復用)
// 蜂鳴器
sbit BEEP = P0^0; // 蜂鳴器 -> P0.0
/************************ 基礎參數定義 ************************/
#define SCREEN_W 240 // LCD寬度
#define SCREEN_H 320 // LCD高度
#define BASE_Y 160 // 波形基準線(屏幕垂直中心)
#define SCALE 1 // 電壓縮放系數(適配ADC采樣值)
#define RED 0xF800// 基準線顏色
#define GREEN 0x07E0// 波形顏色
#define BLACK 0x0000// 背景色
/************************ 延時函數(12MHz晶振適配)************************/
void delay_ms(uint ms) {
uint i,j;
for(i=ms; i>0; i--)
for(j=110; j>0; j--);
}
void delay_us(uint us) {
while(us--);
}
/************************ LCD1(ILI9341)驅動函數 ************************/
// 寫指令
void lcd_write_cmd(uchar cmd) {
LCD_DC = 0; // 指令模式
LCD_CS = 0;
LCD_RD = 1; // 禁用讀
LCD_DATA = cmd;
LCD_WR = 0;
LCD_WR = 1; // 上升沿寫指令
LCD_CS = 1;
}
// 寫數據
void lcd_write_data(uchar dat) {
LCD_DC = 1; // 數據模式
LCD_CS = 0;
LCD_RD = 1;
LCD_DATA = dat;
LCD_WR = 0;
LCD_WR = 1; // 上升沿寫數據
LCD_CS = 1;
}
// 設置顯示窗口
void lcd_set_window(uint x1, uint y1, uint x2, uint y2) {
lcd_write_cmd(0x2A); // 列地址設置
lcd_write_data(x1>>8); lcd_write_data(x1&0xFF);
lcd_write_data(x2>>8); lcd_write_data(x2&0xFF);
lcd_write_cmd(0x2B); // 行地址設置
lcd_write_data(y1>>8); lcd_write_data(y1&0xFF);
lcd_write_data(y2>>8); lcd_write_data(y2&0xFF);
lcd_write_cmd(0x2C); // 寫GRAM
}
// 畫像素點
void lcd_draw_pixel(uint x, uint y, uint color) {
if(x >= SCREEN_W || y >= SCREEN_H) return; // 邊界保護
lcd_set_window(x, y, x, y);
lcd_write_data(color>>8); // 高8位
lcd_write_data(color&0xFF);// 低8位
}
// 清屏
void lcd_clear(uint color) {
uint x, y;
lcd_set_window(0, 0, SCREEN_W-1, SCREEN_H-1);
for(y=0; y<SCREEN_H; y++) {
for(x=0; x<SCREEN_W; x++) {
lcd_write_data(color>>8);
lcd_write_data(color&0xFF);
}
}
}
// LCD初始化(適配仿真圖接線)
void lcd_init(void) {
// LCD硬件復位
LCD_RES = 0;
delay_ms(20);
LCD_RES = 1;
delay_ms(50);
// ILI9341初始化時序
lcd_write_cmd(0xCF);
lcd_write_data(0x00); lcd_write_data(0xC1); lcd_write_data(0X30);
lcd_write_cmd(0xED);
lcd_write_data(0x64); lcd_write_data(0x03); lcd_write_data(0X12); lcd_write_data(0X81);
lcd_write_cmd(0xE8);
lcd_write_data(0x85); lcd_write_data(0x00); lcd_write_data(0x78);
lcd_write_cmd(0xCB);
lcd_write_data(0x39); lcd_write_data(0x2C); lcd_write_data(0x00); lcd_write_data(0x34); lcd_write_data(0x02);
lcd_write_cmd(0xF7); lcd_write_data(0x20);
lcd_write_cmd(0xEA); lcd_write_data(0x00); lcd_write_data(0x00);
lcd_write_cmd(0xC0); lcd_write_data(0x23);
lcd_write_cmd(0xC1); lcd_write_data(0x10);
lcd_write_cmd(0xC5); lcd_write_data(0x3E); lcd_write_data(0x28);
lcd_write_cmd(0xC7); lcd_write_data(0x86);
lcd_write_cmd(0x36); lcd_write_data(0x48);
lcd_write_cmd(0x3A); lcd_write_data(0x55);
lcd_write_cmd(0xB1); lcd_write_data(0x00); lcd_write_data(0x18);
lcd_write_cmd(0xB6); lcd_write_data(0x08); lcd_write_data(0x82); lcd_write_data(0x27);
lcd_write_cmd(0xF2); lcd_write_data(0x00);
lcd_write_cmd(0x26); lcd_write_data(0x01);
lcd_write_cmd(0xE0);
lcd_write_data(0x0F); lcd_write_data(0x31); lcd_write_data(0x2B); lcd_write_data(0x0C);
lcd_write_data(0x0E); lcd_write_data(0x08); lcd_write_data(0x4E); lcd_write_data(0xF1);
lcd_write_data(0x37); lcd_write_data(0x07); lcd_write_data(0x10); lcd_write_data(0x03);
lcd_write_data(0x0E); lcd_write_data(0x09); lcd_write_data(0x00);
lcd_write_cmd(0xE1);
lcd_write_data(0x00); lcd_write_data(0x0E); lcd_write_data(0x14); lcd_write_data(0x03);
lcd_write_data(0x11); lcd_write_data(0x07); lcd_write_data(0x31); lcd_write_data(0xC1);
lcd_write_data(0x48); lcd_write_data(0x08); lcd_write_data(0x0F); lcd_write_data(0x0C);
lcd_write_data(0x31); lcd_write_data(0x36); lcd_write_data(0x0F);
lcd_write_cmd(0x11); // 退出睡眠
delay_ms(120);
lcd_write_cmd(0x29); // 開啟顯示
lcd_clear(BLACK); // 清屏為黑色背景
}
/************************ ADC0832采樣函數 ************************/
uchar adc0832_read(uchar ch) {
uchar i, dat = 0, dat1 = 0;
ADC_CS = 0; // 選中ADC
ADC_CLK = 0; // 初始時鐘低電平
ADC_DI = 1; // 起始位
delay_us(1);
ADC_CLK = 1; // 時鐘上升沿
delay_us(1);
ADC_CLK = 0; // 時鐘下降沿
// 選擇通道(ch=0選CH0,ch=1選CH1)
ADC_DI = (ch == 0) ? 1 : 0;
delay_us(1);
ADC_CLK = 1;
delay_us(1);
ADC_CLK = 0;
ADC_DI = 1; // 通道選擇確認位
delay_us(1);
ADC_CLK = 1;
delay_us(1);
ADC_CLK = 0;
delay_us(1);
// 讀取8位采樣數據
for(i=0; i<8; i++) {
ADC_CLK = 1;
delay_us(1);
ADC_CLK = 0;
dat <<= 1;
if(ADC_DO) dat |= 0x01;
}
// 讀取反序數據(校驗,可省略)
for(i=0; i<8; i++) {
dat1 >>= 1;
if(ADC_DO) dat1 |= 0x80;
ADC_CLK = 1;
delay_us(1);
ADC_CLK = 0;
}
ADC_CS = 1; // 釋放ADC
return (dat == dat1) ? dat : 0; // 數據校驗
}
/************************ 示波器核心功能 ************************/
// 繪制基準線+網格(可選,增強可視化)
void draw_base_line(void) {
uchar x;
// 繪制垂直基準線(紅色)
for(x=0; x<SCREEN_W; x++) {
lcd_draw_pixel(x, BASE_Y, RED);
}
}
// 實時繪制波形(示波器核心)
void draw_wave(void) {
uchar x;
uchar adc_val;
int y_curr, y_prev = BASE_Y;
// 從左到右逐點繪制波形
for(x=0; x<SCREEN_W; x++) {
adc_val = adc0832_read(0); // 讀取CH0采樣值(仿真圖中ADC接CH0)
// 轉換采樣值為屏幕坐標(適配0~255采樣值到屏幕高度)
y_curr = BASE_Y - (adc_val - 128) * SCALE;
// 邊界保護(防止超出屏幕)
if(y_curr < 0) y_curr = 0;
if(y_curr >= SCREEN_H) y_curr = SCREEN_H - 1;
// 清除上一幀對應位置(實現“滾動波形”效果)
lcd_draw_pixel(x, y_prev, BLACK);
// 繪制當前采樣點
lcd_draw_pixel(x, y_curr, GREEN);
y_prev = y_curr;
delay_us(50); // 調整采樣速度(值越小,波形越密)
}
}
/************************ 主函數 ************************/
void main(void) {
BEEP = 1; // 關閉蜂鳴器
lcd_init(); // 初始化LCD
draw_base_line(); // 繪制基準線
// 循環采集+繪制波形(示波器持續工作)
while(1) {
draw_wave();
}
}
|