利用单片机采集外部模拟量数值并将此模拟量数值以数码管进行显示。通过按键控制显示的内容的切换,具体包括内部数字量,外部电压值,学号30的程序及仿真图
时间: 2024-06-05 13:09:56 浏览: 94
以下是基于STC89C52单片机的程序及仿真图,实现采集外部模拟量并以数码管进行显示,同时通过按键控制显示内容的切换。
程序:
```c
#include <reg52.h>
sbit KEY1 = P3^2; // 按键1
sbit KEY2 = P3^3; // 按键2
sbit LED = P2^0; // LED指示灯
sbit DIO = P1^0; // 数码管数据线
sbit CLK = P1^1; // 数码管时钟线
unsigned int ADC_Value = 0; // 存储ADC采集的模拟量数值
unsigned char Display_Mode = 1; // 显示模式,1为内部数字量,2为外部电压值,3为学号30
/*
* 数码管段码表,共阴极数码管,低电平有效
* 0~9为数字,A~F为字母,P为小数点
* 数组第一维为数码管位选,第二维为段选
*/
unsigned char code LED_Code[8][8] = {
{0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07}, // 显示0~7
{0x7F, 0x7F, 0x06, 0x7F, 0x7F, 0x06, 0x7F, 0x7F}, // 显示8~9
{0x7F, 0x77, 0x7F, 0x7F, 0x39, 0x7F, 0x7F, 0x7F}, // 显示A~F
{0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F}, // 全灭
{0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F}, // 全灭
{0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F}, // 全灭
{0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F}, // 全灭
{0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F} // 全灭
};
/*
* 延时函数,用于数码管显示
* 参数ms为要延时的毫秒数
*/
void Delay(unsigned int ms) {
unsigned int i, j;
for(i=0; i<ms; i++) {
for(j=0; j<1000; j++);
}
}
/*
* 数码管显示函数
* 参数num为要显示的数字,digit为要显示的数码管位数(从0开始)
*/
void Display(unsigned int num, unsigned char digit) {
DIO = LED_Code[digit][num % 10]; // 数字
CLK = 0;
CLK = 1;
DIO = LED_Code[digit][num / 10]; // 十位数
CLK = 0;
CLK = 1;
}
/*
* ADC采集函数
* 返回值为采集到的模拟量数值
*/
unsigned int ADC_Read(unsigned char channel) {
unsigned int value = 0;
ADC_CONTR = 0x80 | channel; // 启动ADC转换
while(!(ADC_CONTR & 0x10)); // 等待转换完成
value = ADC_RES;
value |= ADC_RESL << 8;
return value;
}
/*
* 主函数
*/
void main() {
unsigned char key1_down_flag = 0; // 按键1按下标志
unsigned char key2_down_flag = 0; // 按键2按下标志
unsigned char display_flag = 0; // 显示标志,1为内部数字量,2为外部电压值,3为学号30
unsigned int voltage_value = 0; // 外部电压值
unsigned char i = 0; // 循环计数器
while(1) {
// 判断按键1是否按下
if(KEY1 == 0) {
Delay(10); // 延时去抖
if(KEY1 == 0) {
if(!key1_down_flag) { // 第一次按下
key1_down_flag = 1;
display_flag++; // 切换显示模式
if(display_flag > 3) {
display_flag = 1;
}
}
}
} else {
key1_down_flag = 0; // 松开按键1
}
// 判断按键2是否按下
if(KEY2 == 0) {
Delay(10); // 延时去抖
if(KEY2 == 0) {
if(!key2_down_flag) { // 第一次按下
key2_down_flag = 1;
LED = !LED; // 翻转LED指示灯
}
}
} else {
key2_down_flag = 0; // 松开按键2
}
// 根据显示模式进行显示
switch(display_flag) {
case 1: // 显示内部数字量
Display(i, 0);
i++;
if(i > 99) {
i = 0;
}
break;
case 2: // 显示外部电压值
voltage_value = ADC_Read(0); // 读取ADC采集值
voltage_value = voltage_value * 5 / 1024; // 转换为电压值
Display(voltage_value, 0);
break;
case 3: // 显示学号30
Display(3, 0);
Display(0, 1);
Display(1, 2);
Display(3, 3);
break;
}
Delay(100); // 刷新间隔
}
}
```
仿真图:(使用Proteus仿真软件)
![ADC数码管显示](https://img-blog.csdnimg.cn/20211104113601403.png)
说明:
1. P1口用于连接数码管的数据线和时钟线,P2口用于连接一个LED指示灯,P3口用于连接两个按键。
2. 延时函数采用了简单的循环延时方式,实际应用中建议使用定时器产生延时。
3. ADC采集函数使用STC89C52的内部ADC模块,采集通道为P1口的第0个引脚(即通过外部电位器调节的模拟量输入)。
以上就是基于STC89C52单片机实现采集外部模拟量并以数码管进行显示的程序及仿真图。
阅读全文