一、实验目的
1、掌握A/D转换与单片机的接口方法;
2、掌握STC15系列单片机内部A/D转换器和实验板上的ADC与DAC编程方法;
3、掌握数据采集程序的设计方法;
二、实验内容
1、在PROTEUS软件仿真环境下,采用STC15系列单片机内部A/D转换器对电位器提供的模拟电压信号进行定时采样,结果送数码管模块显示;(仿真电路图如图5.1所示)
2、在PROTEUS软件仿真环境下,采用TLC5615做D/A转换器产生0-5V电压,输出电压在数码管显示,通过4个按键进行修改;(仿真电路图如图5.2所示)
3、在PROTEUS软件仿真环境下,用电位器产生0-5V电压,用MCP3201做A/D转换器读取电压,结果送数码管显示;(仿真电路图如图5.3所示)
三、实验线路
实验电路原理图如5.1图所示,所需元件为:STC15W4K32S4、7SEG-MPX4CC、MCP3201、TLC5615、POT-HG。
四、相关文件
任务一:片内 A/D 采集与显示※
- 功能:使用 STC15 内部 ADC (P1.7) 采集电位器电压,计算后在数码管显示(格式:X.XX V)。
- 仿真图:

main.c代码:
#define MAIN_Fosc 24000000L
#include "STC15Fxxxx.H"
#define ADC_RES ADC_RESH
// 注意:SEG4.H 中定义了 S1-S4 在 P3.2-P3.5,SEG 在 P0
#include "SEG4.H"
#include "ADC.H"
// 变量定义
u16 adc_value = 0;
u16 voltage = 0; // 单位:0.01V
// 定时器0初始化 (1ms @ 24MHz) - 用于数码管刷新
void Timer0_Init(void)
{
AUXR |= 0x80; // 定时器时钟1T模式
TMOD &= 0xF0; // 设置定时器模式
TL0 = 0x40; // 设置定时初始值 (24MHz, 1ms)
TH0 = 0xA2; // 设置定时初始值
TF0 = 0; // 清除TF0标志
TR0 = 1; // 定时器0开始计时
ET0 = 1; // 开启定时器中断
EA = 1; // 开启总中断
}
// 定时器中断服务函数 - 刷新数码管
void Timer0_Routine(void) interrupt 1
{
SEGDIS(); // 调用 SEG4.H 中的刷新函数
}
// 数据处理与显示缓冲更新
void Update_Display(u16 vol)
{
// vol 范围 0 - 500 (对应 0.00V - 5.00V)
u8 d0, d1, d2;
d0 = vol / 100; // 整数位 (个位)
d1 = (vol % 100) / 10; // 小数第一位
d2 = vol % 10; // 小数第二位
DIS[0] = disptab[d0] | 0x80; // 个位 + 小数点
DIS[1] = disptab[d1];
DIS[2] = disptab[d2];
DIS[3] = 0x00; // 第四位关闭
}
void main()
{
// 端口模式配置 (建议配置为推挽或准双向,此处沿用默认)
P0M0 = 0x00; P0M1 = 0x00;
P3M0 = 0x00; P3M1 = 0x00;
// 初始化外设
Timer0_Init();
ADC_init(0x80); // 初始化ADC,参数0x80对应 P1.7 (ADC7) 通道 [cite: 12]
while(1)
{
// 1. 获取ADC值 (10位精度 0-1023)
// 传入参数7表示通道7 (P1.7)
adc_value = ADC_Convert(7);
// 2. 转换为电压 (单位 0.01V)
// 计算公式:Voltage = (ADC * 500) / 1024
// 使用 long 强制转换防止乘法溢出
voltage = ((unsigned long)adc_value * 500) / 1024;
// 3. 更新显示
Update_Display(voltage);
delay_ms(100); // 延时,避免数字跳变过快
}
}任务二:TLC5615 D/A 输出与按键控制※
- 功能:通过按键调节数字量,驱动 TLC5615 输出 0-5V,并显示设定电压。
- 硬件连接 :
- CS: P1.4
- CLK: P1.5
- DIN: P1.6
- 按键: K1-K4 (P2.0-P2.3)
- 仿真图:

main.c代码:
#define MAIN_Fosc 24000000L
#include "STC15Fxxxx.H"
#include "SEG4.H"
#define ADC_RES ADC_RESH
// --- TLC5615 引脚定义 (必须在include TLC5615.H之前) ---
sbit CS = P1^4; // 根据仿真图 5-2 定义
sbit CLK = P1^5;
sbit DAT = P1^6; // DIN
//sbit CY = PSW^7; // TLC5615.H 中用到了 CY
#include "TLC5615.H"
// --- 按键定义 ---
#include "KEY.H"
// 变量定义
u16 dac_code = 0; // 发送给DAC的数值 (0-1023)
u16 voltage = 0; // 计算出的显示电压
void Timer0_Init(void) // 1ms
{
AUXR |= 0x80; TMOD &= 0xF0; TL0 = 0x40; TH0 = 0xA2;
TF0 = 0; TR0 = 1; ET0 = 1; EA = 1;
}
void Timer0_Routine(void) interrupt 1
{
SEGDIS();
}
void Update_Display(u16 vol)
{
u8 d0, d1, d2;
d0 = vol / 100;
d1 = (vol % 100) / 10;
d2 = vol % 10;
DIS[0] = disptab[d0] | 0x80;
DIS[1] = disptab[d1];
DIS[2] = disptab[d2];
DIS[3] = 0x00;
}
void main()
{
u8 key_val;
Timer0_Init();
dac_code = 512; // 初始输出 2.5V (1024的一半)
while(1)
{
key_val = GetKey();
// 按键处理
if(key_val == 1) // K1: 增加
{
if(dac_code < 1023) dac_code += 10; // 步进10
if(dac_code > 1023) dac_code = 1023;
}
if(key_val == 2) // K2: 减少
{
if(dac_code >= 10) dac_code -= 10;
else dac_code = 0;
}
if(key_val == 3) dac_code = 1023; // K3: 最大 (5V)
if(key_val == 4) dac_code = 0; // K4: 最小 (0V)
// 执行 DA 转换
TLC5615(dac_code);
// 计算理论电压显示
voltage = ((unsigned long)dac_code * 500) / 1024;
Update_Display(voltage);
delay_ms(20); // 按键消抖延时
}
}任务三:MCP3201 外部 A/D 采集※
- 功能:使用 MCP3201 (12位 ADC) 采集外部电位器电压。
- 硬件连接:
- CS: P1.4
- CLK: P1.5
- DOUT: P1.6 (注意:这里 MCU 是读取,所以 P1.6 是输入)
- 仿真图:

main.c代码:
#define MAIN_Fosc 24000000L
#include "STC15Fxxxx.H"
#include "SEG4.H"
// --- MCP3201 引脚定义 ---
// 根据仿真图 5-3
sbit CS = P1^4;
sbit CLK = P1^5;
sbit DAT = P1^6; // DOUT 接 MCU P1.6
#include "MCP3201.H"
u16 adc_res = 0;
u16 voltage = 0;
void Timer0_Init(void) // 1ms
{
AUXR |= 0x80; TMOD &= 0xF0; TL0 = 0x40; TH0 = 0xA2;
TF0 = 0; TR0 = 1; ET0 = 1; EA = 1;
}
void Timer0_Routine(void) interrupt 1
{
SEGDIS();
}
void Update_Display(u16 vol)
{
u8 d0, d1, d2;
d0 = vol / 100;
d1 = (vol % 100) / 10;
d2 = vol % 10;
DIS[0] = disptab[d0] | 0x80;
DIS[1] = disptab[d1];
DIS[2] = disptab[d2];
DIS[3] = 0x00;
}
void main()
{
// 配置 IO 口
// P1.6 (DAT) 必须配置为输入模式,或者准双向口并置1
// MCP3201.H 中的时序是模拟SPI,直接操作IO
Timer0_Init();
while(1)
{
// 1. 读取 MCP3201 (12位精度 0-4095)
adc_res = MCP3201();
// 2. 计算电压
// 12位ADC,基准电压5V
// Voltage = (Data * 500) / 4096
voltage = ((unsigned long)adc_res * 500) / 4096;
// 3. 显示
Update_Display(voltage);
delay_ms(100);
}
}