周末把单片机的开发环境理顺了,开始模块化编程的实践,先从外围模块开始,先从独立的模块,然后构建复杂一些的综合应用,条件所限,以protues的仿真为主。
1、单片机内置ADC采样与显示电路
2、电路原理简介
该电路主要由单片机(PIC16F877A)、74HC573锁存器和四位七段数码管组成,下面是它的工作原理详细介绍:
1. 系统整体结构
- 单片机 (U1):负责控制整个电路的工作,读取输入信号并控制输出。
- 锁存器 (U2, U3):使用74HC573作为数据锁存器,可以缓冲单片机发出的数据,确保稳定输出到数码管。
- 七段数码管:用于显示数字或字母,通过控制相应的段点亮来显示信息。
2. 电源和基础元件
- 电源:电路通过提供+5V的电源来工作,接地是重要的参考点。
- 电阻器 (R2, R5, R8, R9, R10):电阻的作用包括偏置电流、限流等,确保整个电路工作在合理范围内。
- 电容器 (C3):用来滤波,稳定电源电压,减少干扰。
3. 工作流程
-
初始化:
- 单片机启动后,进行自检和初始化,配置I/O端口及其他工作参数。
-
数据处理:
- 单片机从外部传感器或其他输入源获取数据,并进行处理。
- 数据经过逻辑运算后,由单片机控制锁存器(74HC573)的使能端(LE)。
-
数据锁存:
- 当使能信号(LE)为高时,锁存器将单片机的数据输入锁存,即使得数据输入保持不变。
- 锁存器的输出将连接至七段数码管相应的段,从而控制其显示。
-
显示输出:
- 七段数码管的各个段通过锁存器的输出控制,显示所需的数字或字母。每个数码管的各个段由相应的输出信号控制,形成完整的显示结果。
3、软件代码
//********************************************************************
//* 文件名:main.c
//* 文件描述:基于PIC单片机的数码管显示A/D转换结果程序
//* 编译环境: Windows XP + MPLAB IDE 8.83 + Picc 9.60
//* 编程者: bianjingyuan
//* 编程日期: 2024-10-30
//* 版本号:1.0
//* 修改记录:无
//* 硬件资源分配表:
//* 端口: RC0 - DUAN
//* RC1 - WEI
//********************************************************************
#include "pic.h"// 定义数据引脚
#define DUAN RC0 // 数码管的十位引脚
#define WEI RC1 // 数码管的位选引脚// 配置字设置
__CONFIG (0X3B31);// 函数声明
void delay(unsigned int x); // 延时函数
void display(unsigned char duan, unsigned char wei); // 显示数字
int get_advalue(); // 获取A/D转换值
void inital(); // 初始化系统配置// 数码管编码表
const char dua_table[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90}; // 不带点数码管编码 0~9
const char ddua_table[] = {0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78, 0x00, 0x10}; // 带点数码管编码 0~9
const char wei_array[] = {0x01, 0x02, 0x04, 0x08}; // 位选编码// 中断标志
bit AD_FLAG;void main()
{volatile long int tmp; // 用于存储A/D转换的临时值int advalue;unsigned char digits[4]; // 存储千位、百位、十位和个位unsigned char i;inital(); // 初始化系统ADIE = 1; // 使能A/D中断PEIE = 1; // 使能外围中断GIE = 1; // 使能全局中断ADGO = 1; // 开始A/D转换// 等待中断标志AD_FLAG被置位while (!AD_FLAG); // 等待A/D转换完成tmp = get_advalue(); // 读取A/D转换结果advalue = (tmp * 500) >> 10; // 将AD值转换为相应值// 按位分离,存储到digits数组中digits[0] = advalue / 1000; // 千位digits[1] = (advalue / 100) % 10; // 百位digits[2] = (advalue / 10) % 10; // 十位digits[3] = advalue % 10; // 个位// 显示结果for ( i = 0; i < 4; i++) {display(digits[i], i + 1); // 显示各位数}
}/********************************************************************** 函 数 名: delay* 功能描述: 控制延时函数* 函数说明: 通过嵌套循环实现延时* 调用函数: 无* 全局变量: 无* 输 入: unsigned int x - 延时循环次数* 返 回: 无* 设 计 者:bianjingyuan 日期:2024-10-30* 修 改 者:bianjingyuan 日期:2024-10-30* 版 本:**********************************************************************/
void delay(unsigned int x)
{unsigned char b; while(x--){for (b = 0; b < 18; b++); // 控制延时}
}/********************************************************************** 函 数 名: display* 功能描述: 显示数字到数码管* 函数说明: 选择带点或不带点的数码管进行显示* 调用函数: delay()* 全局变量: DUAN, WEI* 输 入: unsigned char duan - 数码管要显示的数字* unsigned char wei - 数码管的位选* 返 回: 无* 设 计 者:bianjingyuan 日期:2024-10-30* 修 改 者:bianjingyuan 日期:2024-10-30* 版 本:**********************************************************************/
void display(unsigned char duan, unsigned char wei)
{if (wei == 2)PORTB = ddua_table[duan]; // 显示带点数码管elsePORTB = dua_table[duan]; // 显示不带点数码管 DUAN = 1; // 使能DUADUAN = 0; // 关闭DUAPORTB = wei_array[wei - 1]; // 设置当前位选WEI = 1; // 使能WEIWEI = 0; // 关闭WEIdelay(40); // 延时PORTB = 0; // 关闭数码管显示WEI = 1; // 使能WEIWEI = 0; // 关闭WEI
}/********************************************************************** 函 数 名: get_advalue* 功能描述: 读取A/D转换结果* 函数说明: 从高位和低位合并读取A/D值* 调用函数: 无* 全局变量: AD_FLAG* 输 入: 无* 返 回: int - 返回读取的A/D值* 设 计 者:bianjingyuan 日期:2024-10-30* 修 改 者:bianjingyuan 日期:2024-10-30* 版 本:**********************************************************************/
int get_advalue()
{unsigned char low;int temp;temp = ADRESH; // 读取高位low = ADRESL; // 读取低位AD_FLAG = 0; // 清除A/D标志return (temp << 8) | low; // 返回合并的A/D值
}/********************************************************************** 函 数 名: get_ad* 功能描述: A/D转换中断服务程序* 函数说明: 检查A/D中断标志并清除标志* 调用函数: 无* 全局变量: AD_FLAG* 输 入: 无* 返 回: 无* 设 计 者:bianjingyuan 日期:2024-10-30* 修 改 者:bianjingyuan 日期:2024-10-30* 版 本:**********************************************************************/
void interrupt get_ad()
{if (ADIF) // 检查A/D中断标志{ ADIF = 0; // 清除中断标志AD_FLAG = 1; // 设置A/D标志}
}/********************************************************************** 函 数 名: inital* 功能描述: 初始化系统设置* 函数说明: 设置各个端口的输入输出状态等初始化操作* 调用函数: 无* 全局变量: 无* 输 入: 无* 返 回: 无* 设 计 者:bianjingyuan 日期:2024-10-30* 修 改 者:bianjingyuan 日期:2024-10-30* 版 本:**********************************************************************/
void inital()
{TRISA |= 0x01; // 设置RA0为输入TRISB = 0x00; // 设置PORTB为输出TRISC = 0x00; // 设置PORTC为输出PORTB = 0; // 清空PORTBPORTC = 0; // 清空PORTC INTCON = 0; // 清除中断控制寄存器PIE1 = 0; // 清除外部中断ADCON1 = 0x8E; // 配置ADC参考电压和通道ADCON0 = 0x41; // 使能A/D转换
}
4、代码解析
该程序的主要功能是基于PIC单片机进行A/D转换,并将转换结果通过数码管显示出来。代码实现了以下主要功能:
- 初始化PIC单片机的相关外设和端口。
- 通过A/D转换功能采集模拟量输入。
- 执行A/D转换操作,并在转换完成后通过中断获取转换结果。
- 将A/D转换的结果进行数值处理,转换为实际数值。
- 将处理后的数值分离为千位、百位、十位和个位,通过数码管显示出来。
软件流程图:
+------------------------+
| Start |
+------------------------+
|
+------------------------+
| Initialize |
+------------------------+
|
+------------------------+
| Enable A/D Interrupts |
+------------------------+
|
+------------------------+
| Start A/D Convert |
+------------------------+
|
+------------------------+
| Wait for A/D Flag |
+------------------------+
|
+------------------------+
| Read A/D Result |
+------------------------+
|
+------------------------+
| Convert Result to Digits |
+------------------------+
|
+------------------------+
| Display on 7-Seg |
+------------------------+
|
+------------------------+
| End |
+------------------------+
5、硬件资源分配表
序号 | 单片机引脚 | 功能定义 | 字符串替代定义 | 功能内容 | 备注 |
---|---|---|---|---|---|
1 | RC0 | DUAN | - | 数码管的十位引脚 | 连接数码管 |
2 | RC1 | WEI | - | 数码管的位选引脚 | 连接数码管 |
3 | PORTB | - | - | 数码管显示数据总线 | 连接数码管输出 |
基于上述硬件资源分配表,该程序实现了以下主要功能:
- 通过A/D转换采集模拟量。
- 将A/D转换结果转换为实际数值。
- 通过数码管显示转换后的数值。
6、仿真运行结果
相关资料:
时钟芯片DS1302及其在数据记录中的应用.pdf
https://pan.baidu.com/s/1uEe3L3PMw6rt3lIgTAqL0A?pwd=88c8
DS1302时钟.ppt
百度网盘 请输入提取码
基于STC89C52单片机DS1302时钟芯片定时开关的设计与仿真.pdf
百度网盘 请输入提取码