单片机控制数码管显示的秘密:原理、方法和应用
发布时间: 2024-07-13 07:04:51 阅读量: 96 订阅数: 30
![单片机控制数码管显示的秘密:原理、方法和应用](https://img-blog.csdnimg.cn/direct/641fe6e097aa4a86ba1e96af2e6bc230.png)
# 1. 单片机控制数码管显示原理
数码管是一种电子显示器件,广泛应用于各种电子设备中,用于显示数字或字符信息。单片机是一种小型计算机,具有强大的控制能力,可以控制数码管显示各种信息。
单片机控制数码管显示的原理是通过单片机的输出端口向数码管发送控制信号,控制数码管的各个段位亮灭,从而显示不同的数字或字符。数码管的每一段位对应一个数字或字符,通过组合不同的段位亮灭状态,可以显示不同的信息。
# 2. 单片机控制数码管显示方法
### 2.1 硬件连接原理
#### 2.1.1 数码管的管脚定义
数码管是一种电子显示器件,由七个发光二极管(LED)组成,分别对应于数字 0 到 9 的显示。每个数码管有 8 个管脚,定义如下:
| 管脚 | 名称 | 功能 |
|---|---|---|
| 1 | a | 第一位发光二极管的阴极 |
| 2 | b | 第二位发光二极管的阴极 |
| 3 | c | 第三位发光二极管的阴极 |
| 4 | d | 第四位发光二极管的阴极 |
| 5 | e | 第五位发光二极管的阴极 |
| 6 | f | 第六位发光二极管的阴极 |
| 7 | g | 第七位发光二极管的阴极 |
| 8 | DP | 小数点发光二极管的阴极 |
#### 2.1.2 单片机与数码管的连接方式
单片机与数码管的连接方式有两种:共阴极连接和共阳极连接。
**共阴极连接**:
* 数码管的阴极端(管脚 1-7)连接到单片机的低电平端口。
* 数码管的阳极端(管脚 8)连接到电源的正极。
* 当单片机端口输出低电平时,对应的发光二极管点亮。
**共阳极连接**:
* 数码管的阳极端(管脚 8)连接到单片机的低电平端口。
* 数码管的阴极端(管脚 1-7)连接到电源的负极。
* 当单片机端口输出低电平时,对应的发光二极管熄灭。
### 2.2 软件编程方法
#### 2.2.1 数码管显示字符编码
为了控制数码管显示不同的字符,需要使用字符编码。每个字符都有一个对应的编码,如下表所示:
| 字符 | 编码 |
|---|---|
| 0 | 0x3F |
| 1 | 0x06 |
| 2 | 0x5B |
| 3 | 0x4F |
| 4 | 0x66 |
| 5 | 0x6D |
| 6 | 0x7D |
| 7 | 0x07 |
| 8 | 0x7F |
| 9 | 0x6F |
#### 2.2.2 单片机控制数码管显示流程
单片机控制数码管显示的流程如下:
1. **初始化数码管**:设置单片机端口为输出模式,并输出低电平。
2. **设置显示字符编码**:将要显示的字符编码写入到单片机的端口寄存器中。
3. **点亮数码管**:将数码管的阳极端(共阳极连接)或阴极端(共阴极连接)连接到电源的正极或负极。
4. **延时**:等待一段时间,以确保数码管正常显示。
5. **关闭数码管**:断开数码管与电源的连接。
```c
// 数码管显示字符编码
const uint8_t num_code[] = {
0x3F, // 0
0x06, // 1
0x5B, // 2
0x4F, // 3
0x66, // 4
0x6D, // 5
0x7D, // 6
0x07, // 7
0x7F, // 8
0x6F // 9
};
// 单片机控制数码管显示流程
void display_num(uint8_t num) {
// 初始化数码管
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pin = GPIO_PIN_ALL;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// 设置显示字符编码
GPIOA->ODR = num_code[num];
// 点亮数码管
GPIOA->ODR |= GPIO_PIN_ALL;
// 延时
HAL_Delay(10);
// 关闭数码管
GPIOA->ODR &= ~GPIO_PIN_ALL;
}
```
# 3.1 实验材料和环境搭建
#### 3.1.1 所需硬件和软件
- **硬件:**
- 单片机开发板(如 Arduino Uno)
- 数码管(如共阳极七段数码管)
- 电阻(100Ω)
- 面包板
- 连接线
- **软件:**
- Arduino IDE
- Arduino 程序代码
#### 3.1.2 实验环境搭建步骤
1. **连接硬件:**
- 将数码管的正极(长脚)连接到单片机的数字输出引脚。
- 将数码管的负极(短脚)通过 100Ω 电阻连接到地线。
- 将多个数码管并联连接,形成显示位数。
2. **安装 Arduino IDE:**
- 从 Arduino 官网下载并安装 Arduino IDE。
3. **导入程序代码:**
- 打开 Arduino IDE,新建一个草图。
- 将准备好的程序代码复制粘贴到草图中。
4. **编译并上传程序:**
- 点击 IDE 上的“编译”按钮,编译程序。
- 点击“上传”按钮,将程序上传到单片机开发板。
### 3.2 实验程序设计和实现
#### 3.2.1 程序设计思路
实验程序的思路如下:
- 初始化单片机数字输出引脚,用于控制数码管显示。
- 定义一个数组,存储要显示的数字的编码。
- 循环遍历数组,依次显示每个数字。
- 延时一段时间,保持数字显示稳定。
#### 3.2.2 程序代码实现
```c++
// 定义数码管显示字符编码
const byte numCode[] = {
0b01111110, // 0
0b00110000, // 1
0b01101101, // 2
0b01111001, // 3
0b00110011, // 4
0b01011011, // 5
0b01011111, // 6
0b01110000, // 7
0b01111111, // 8
0b01111011 // 9
};
void setup() {
// 初始化数字输出引脚
for (int i = 2; i <= 7; i++) {
pinMode(i, OUTPUT);
}
}
void loop() {
// 循环显示数字
for (int i = 0; i < 10; i++) {
// 显示数字
displayNum(i);
// 延时
delay(500);
}
}
// 显示数字
void displayNum(int num) {
// 获取数字编码
byte code = numCode[num];
// 依次控制数码管显示
for (int i = 2; i <= 7; i++) {
digitalWrite(i, (code >> (i - 2)) & 0x01);
}
}
```
**代码逻辑分析:**
- `setup()` 函数中,初始化单片机的数字输出引脚,用于控制数码管显示。
- `loop()` 函数中,循环遍历数字 0-9,依次显示每个数字。
- `displayNum()` 函数中,根据要显示的数字,获取对应的编码,并依次控制数码管显示。
# 4. 单片机控制数码管显示应用
### 4.1 电子时钟设计
#### 4.1.1 时钟电路原理
电子时钟由时钟电路和显示电路两部分组成。时钟电路负责产生时基信号,显示电路负责将时基信号转换成时间显示。
时钟电路一般采用石英晶体振荡器,石英晶体振荡器具有很高的精度和稳定性,可以产生频率非常稳定的时基信号。时基信号经过分频器分频后,得到秒、分、时等不同频率的时基信号。
#### 4.1.2 单片机控制时钟显示程序
单片机控制时钟显示程序主要包括以下几个部分:
- 初始化时钟电路,设置时钟频率和分频系数。
- 定时中断服务程序,每秒中断一次,更新时钟显示。
- 数码管显示程序,将时间信息转换成数码管显示码,并控制数码管显示。
### 4.2 数字温度计设计
#### 4.2.1 温度传感器原理
温度传感器是一种将温度转换成电信号的器件。常用的温度传感器有热敏电阻、热电偶和集成温度传感器。
热敏电阻是一种随着温度变化而改变电阻值的电阻器。热电偶是一种由两种不同金属材料制成的电偶,当两种金属材料的连接点温度发生变化时,电偶两端会产生电压。集成温度传感器是一种将温度传感器和信号调理电路集成在一起的芯片。
#### 4.2.2 单片机控制温度显示程序
单片机控制温度显示程序主要包括以下几个部分:
- 初始化温度传感器,设置采样频率和精度。
- 定时中断服务程序,每秒中断一次,采集温度数据。
- 温度转换程序,将温度数据转换成温度值。
- 数码管显示程序,将温度值转换成数码管显示码,并控制数码管显示。
# 5. 单片机控制数码管显示进阶
### 5.1 动态显示效果实现
#### 5.1.1 数码管动态显示原理
动态显示效果是指数码管上的数字或字符以动态的方式显示,例如逐个点亮或熄灭。实现动态显示效果需要使用单片机的定时器功能,通过周期性地控制数码管的管脚状态来实现。
#### 5.1.2 单片机控制数码管动态显示程序
```c
#include <reg51.h>
sbit SEG_A = P2^0;
sbit SEG_B = P2^1;
sbit SEG_C = P2^2;
sbit SEG_D = P2^3;
sbit SEG_E = P2^4;
sbit SEG_F = P2^5;
sbit SEG_G = P2^6;
sbit SEG_DP = P2^7;
void delay(unsigned int ms) {
unsigned int i, j;
for (i = 0; i < ms; i++) {
for (j = 0; j < 120; j++);
}
}
void display_digit(unsigned char digit) {
switch (digit) {
case 0:
SEG_A = 0; SEG_B = 1; SEG_C = 1; SEG_D = 1; SEG_E = 1; SEG_F = 1; SEG_G = 0; SEG_DP = 0; break;
case 1:
SEG_A = 0; SEG_B = 1; SEG_C = 1; SEG_D = 0; SEG_E = 0; SEG_F = 0; SEG_G = 0; SEG_DP = 0; break;
case 2:
SEG_A = 1; SEG_B = 1; SEG_C = 0; SEG_D = 1; SEG_E = 1; SEG_F = 0; SEG_G = 1; SEG_DP = 0; break;
case 3:
SEG_A = 1; SEG_B = 1; SEG_C = 1; SEG_D = 1; SEG_E = 0; SEG_F = 0; SEG_G = 1; SEG_DP = 0; break;
case 4:
SEG_A = 0; SEG_B = 1; SEG_C = 1; SEG_D = 0; SEG_E = 0; SEG_F = 1; SEG_G = 1; SEG_DP = 0; break;
case 5:
SEG_A = 1; SEG_B = 0; SEG_C = 1; SEG_D = 1; SEG_E = 0; SEG_F = 1; SEG_G = 1; SEG_DP = 0; break;
case 6:
SEG_A = 1; SEG_B = 0; SEG_C = 1; SEG_D = 1; SEG_E = 1; SEG_F = 1; SEG_G = 1; SEG_DP = 0; break;
case 7:
SEG_A = 1; SEG_B = 1; SEG_C = 1; SEG_D = 0; SEG_E = 0; SEG_F = 0; SEG_G = 0; SEG_DP = 0; break;
case 8:
SEG_A = 1; SEG_B = 1; SEG_C = 1; SEG_D = 1; SEG_E = 1; SEG_F = 1; SEG_G = 1; SEG_DP = 0; break;
case 9:
SEG_A = 1; SEG_B = 1; SEG_C = 1; SEG_D = 1; SEG_E = 0; SEG_F = 1; SEG_G = 1; SEG_DP = 0; break;
}
}
void main() {
unsigned char i;
while (1) {
for (i = 0; i < 10; i++) {
display_digit(i);
delay(100);
}
}
}
```
### 5.2 多路数码管显示控制
#### 5.2.1 多路数码管显示原理
多路数码管显示是指使用一个单片机控制多个数码管,实现多位数字或字符的显示。实现多路数码管显示需要使用单片机的IO扩展功能,通过时分复用技术来控制多个数码管的显示。
#### 5.2.2 单片机控制多路数码管显示程序
```c
#include <reg51.h>
sbit SEG_A = P2^0;
sbit SEG_B = P2^1;
sbit SEG_C = P2^2;
sbit SEG_D = P2^3;
sbit SEG_E = P2^4;
sbit SEG_F = P2^5;
sbit SEG_G = P2^6;
sbit SEG_DP = P2^7;
sbit SEG_SEL0 = P1^0;
sbit SEG_SEL1 = P1^1;
sbit SEG_SEL2 = P1^2;
void delay(unsigned int ms) {
unsigned int i, j;
for (i = 0; i < ms; i++) {
for (j = 0; j < 120; j++);
}
}
void display_digit(unsigned char digit, unsigned char sel) {
switch (digit) {
case 0:
SEG_A = 0; SEG_B = 1; SEG_C = 1; SEG_D = 1; SEG_E = 1; SEG_F = 1; SEG_G = 0; SEG_DP = 0; break;
case 1:
SEG_A = 0; SEG_B = 1; SEG_C = 1; SEG_D = 0; SEG_E = 0; SEG_F = 0; SEG_G = 0; SEG_DP = 0; break;
case 2:
SEG_A = 1; SEG_B = 1; SEG_C = 0; SEG_D = 1; SEG_E = 1; SEG_F = 0; SEG_G = 1; SEG_DP = 0; break;
case 3:
SEG_A = 1; SEG_B = 1; SEG_C = 1; SEG_D = 1; SEG_E = 0; SEG_F = 0; SEG_G = 1; SEG_DP = 0; break;
case 4:
SEG_A = 0; SEG_B = 1; SEG_C = 1; SEG_D = 0; SEG_E = 0; SEG_F = 1; SEG_G = 1; SEG_DP = 0; break;
case 5:
SEG_A = 1; SEG_B = 0; SEG_C = 1; SEG_D = 1; SEG_E = 0; SEG_F = 1; SEG_G = 1; SEG_DP = 0; break;
case 6:
SEG_A = 1; SEG_B = 0; SEG_C = 1; SEG_D = 1; SEG_E = 1; SEG_F = 1; SEG_G = 1; SEG_DP = 0; break;
case 7:
SEG_A = 1; SEG_B = 1; SEG_C = 1; SEG_D = 0; SEG_E = 0; SEG_F = 0; SEG_G = 0; SEG_DP = 0; break;
case 8:
SEG_A = 1; SEG_B = 1; SEG_C = 1; SEG_D = 1; SEG_E = 1; SEG_F = 1; SEG_G = 1; SEG_DP = 0; break;
case 9:
SEG_A = 1; SEG_B = 1; SEG_C = 1; SEG_D = 1; SEG_E = 0; SEG_F = 1; SEG_G = 1; SEG_DP = 0; break;
}
SEG_SEL0 = (sel & 0x01) != 0;
SEG_SEL1 = (sel & 0x
0
0