#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();
}
}
|