如何把从DS1302中读出的数据用51单片机用动态扫描方式显示在数码管

合集下载

51单片机动态数码管实验报告

51单片机动态数码管实验报告

51单片机动态数码管实验报告一、背景动态数码管是一种常见的显示装置,它由多个LED组成,可以显示数字、字母和符号等信息。

在嵌入式系统中,动态数码管常用于显示各种信息,如温度、湿度、时间等。

本次实验旨在通过学习51单片机动态数码管的使用方法,了解动态数码管的工作原理和使用技巧。

二、分析动态数码管由多个共阴极或共阳极LED组成,每个LED都可用于显示一个数字或字符。

动态数码管的显示是通过快速切换数码管的管脚电平实现的,每个数码管显示部分的亮度和显示时间取决于刷新速度。

本次实验涉及到四位数码管,所以需要控制四个共阳极或共阴极数码管,通过快速切换显示四个数码管的方式实现动态显示效果。

实验所需要的材料有:51单片机开发板、数码管模块、面包板、杜邦线等。

以下是步骤:1.将数码管模块的共阳极或共阴极连接到51单片机开发板的IO口。

根据数码管模块的引脚连接方式,选择合适的IO口。

2.在51单片机开发板上搭建实验电路。

首先将开发板的VCC引脚连接到面包板的正电源线上,GND引脚连接到面包板的地线上。

然后将数码管模块的VCC引脚连接到面包板的正电源线上,GND引脚连接到面包板的地线上。

最后将数码管模块的信号引脚连接到51单片机开发板选择的IO口上。

3.编写程序。

使用C语言编写代码,通过控制IO口的电平和延时实现数码管的动态显示功能。

根据所需显示的数字和字符,选择合适的代码逻辑。

4.将编写好的程序下载到51单片机开发板上。

使用USB转串口工具将开发板与电脑连接,使用相应的下载软件将程序下载到开发板。

5.执行程序。

将开发板上的动态数码管模块打开,观察数码管的显示效果。

根据实际需求,调整程序中的显示内容和显示速度。

三、结果经过以上步骤,可以成功实现51单片机动态数码管的显示功能。

根据编写的程序和韦氏编码表,可以显示各种数字、字母和符号等信息。

通过调整程序中的显示内容和显示速度,可以实现不同的显示效果。

四、建议在进行实验过程中,需要注意以下几点:1.确保电路连接正确。

ds1302数码管显示

ds1302数码管显示

DS1302应用刚学单片机,好多好奇,所以想做个简单的时钟。

下面是PROTEUS仿真电路和电路图,简单易懂。

文笔不好,说了多余。

下面是程序。

#include<reg52.h>#include<intrins.h>#include<ds1302.h>#define uint unsigned int#define uchar unsigned char#define BCDTUAN(str) (str/10*16+str%10) //定义宏,将要写入DS1302的时间转化为BCD码#define Write_Sec 0x80#define Write_Min 0x82#define Write_Hou 0x84#define Write_Dat 0x86#define Write_Mon 0x88#define Write_day 0x8a#define Write_Yea 0x8c#define Write_WP 0x8e //写保护位#define Write_TCR 0x90#define Read_Sec 0x81#define Read_Min 0x83#define Read_Hou 0x85#define Read_Dat0x87#define Read_Mon 0x89#define Read_Day 0x8b#define Read_Yea 0x8d#define CLK_BurstW 0xbf //时钟突发模式写#define CLK_BurstR 0xbf //时钟突发模式读#define Write_RAM_Begin 0xc0 //RAM第一个字节写指令#define Read_RAM_Begin 0xc1 //RAM第一个字节读指令#define RAM_BurstW 0xfe //突发模式写RAM#define RAM_BurstR 0xff //突发模式读RAMsbit _74hc154_A = P1^0;sbit _74hc154_B = P1^1;sbit _74hc154_C = P1^2;sbit _74hc154_D = P1^3;sbit CE =P1^6;sbit SCLK=P1^5;sbit IO =P1^4;uchar code scan[][4]={{0,0,0,0},{0,0,0,1},{0,0,1,0},{0,0,1,1},{0,1,0,0},{0,1,0,1},{0,1,1,0},{0,1,1,1},{1,0,0,0},{1,0,0,1},{1,0,1,0},{1,0,1,1},{1,1,0,0},{1,1,0,1},{1,1,1,0},{1,1,1,1}};uchar scanbuff[]={0,0,0,0,0,0,0,0,0,0,0,0};uchar code dispdate[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};void WriteDS1302(void); //向DS1302写入时间。

ds1302与单片机的连接,51单片机操作ds1302流程展示

ds1302与单片机的连接,51单片机操作ds1302流程展示

ds1302 与单片机的连接,51 单片机操作ds1302 流程
展示
在许多单片机系统中常需要一些与时间有关的控制这就有需要使用实时时钟,因为在测控系统中需要做一些特殊数据的记录及其出现时间的记
录。

那幺实时时钟就能够很好的解决这个问题,今天我们就来谈谈ds1302 与单片机之间是如何作用联系的,单片机又是如何对时钟芯片进行操作的,一
起来了解一下。

51 单片机操作ds1302 流程展示
DS1302 通过3 根线与MCU 连接串行数据发送,接收时钟信号由MCU 发送,可外接备用电池以便主电源断电后不丢失数据,并可编程对备用电源充电。

DS1302 的结构如下:。

ds1302工作原理

ds1302工作原理

ds1302工作原理DS1302是一款常用的实时时钟芯片,它具有精准的时间计数和存储功能,广泛应用于各种电子设备中。

本文将介绍DS1302的工作原理,帮助大家更好地理解这款芯片的工作方式。

DS1302芯片主要由时钟计数部分、RAM部分、控制逻辑部分和串行接口部分组成。

它采用了静态存储器和CMOS技术,具有低功耗、高稳定性和高精度的特点。

在DS1302中,时钟计数部分用于实时计数和存储时间,RAM部分用于存储控制寄存器和时钟/日历信息,控制逻辑部分用于控制整个芯片的工作,串行接口部分用于与微处理器进行通信。

DS1302的工作原理主要分为时钟计数和数据存储两个部分。

在时钟计数部分,DS1302通过外接的晶体振荡器产生稳定的时钟信号,并通过分频器将时钟信号分频为1Hz的脉冲信号,然后将脉冲信号送入计数器进行计数。

计数器将计数结果存储在时钟/日历寄存器中,以实现对时间的精准计数。

在数据存储部分,DS1302将时钟/日历信息存储在RAM中,并通过控制逻辑部分实现对RAM的读写操作,从而实现对时间和日期信息的存储和更新。

在实际应用中,DS1302通常与微处理器或单片机相结合,通过串行接口进行通信。

微处理器可以通过串行接口向DS1302发送读写命令和数据,从而实现对DS1302的配置和控制。

DS1302可以通过串行接口向微处理器发送当前的时间和日期信息,从而实现对时间的显示和记录。

总的来说,DS1302的工作原理是通过时钟计数和数据存储实现对时间和日期的精准计数和存储。

它具有精准、稳定、低功耗的特点,广泛应用于各种电子设备中。

通过了解DS1302的工作原理,可以更好地应用和设计相关的电子设备,从而提高设备的性能和稳定性。

希望本文能够帮助大家更好地理解DS1302的工作原理,为相关电子设备的设计和应用提供参考和帮助。

感谢大家的阅读!。

跟我学51单片机5单片机动态扫描驱动数码管

跟我学51单片机5单片机动态扫描驱动数码管

跟我学51单片机(五):单片机动态扫描驱动数码管一、本文内容提要本刊第四期介绍了单片机外接键盘的原理,并给出了应用实例。

本期将介绍单片机动态驱动段式数码管。

通过该讲,读者可以掌握段式数码管的工作原理和如何通过动态驱动的方法设计电路以及程序。

二、原理简介常用的段式数码管有七段式和八段式,八段比七段多了一个小数点,其他的基本相同。

所谓的几段就是指数码管里有相应的几个小LED 发光二极管,通过控制不同的LED 的亮灭来显示出不同的字形(见图1(a))。

从各发光二极管的电极连接方式又可以分为共阳极和共阴极两种类型。

共阴极则是所有的二极管的阴极连接在一起,而阳极是分离的(见图1(b));而共阳极就是所有二极管的阳极是公共相连,而阴极则是分离的(见图1(c))。

本学习板采用的是八段共阴极数码管,型号为LG3641AH。

图1 数码管内部结构图前文所述,数码管与发光二极管的工作原理相同,共阳极时,所有正端接电源正极,当负端有低电平时,该段有电流流过,发光管亮,当负端为高电平时,该段无电流流过,发光管不亮。

要显示什么数字,就使对应的段为低电平(见表1)。

共阴极与共阳极的电平变化状态相反。

当每个段的驱动电流为2~20mA,电流越大,发光越亮。

表1 显示的数字和七段码各位的对应关系表常用的七段式数码管的硬件驱动设计方法有:静态驱动与动态驱动。

静态驱动即指每个数码管的数据线都有一个单独的数据锁存器,数据锁存器输入的数据由使能端控制,当使能端为高电平时,数据线上的数据(要显示的七段码)进入显示器,使能端与地址译码器的输出相连,要显示那位,则选通那位的地址,在软件设计上不要求程序循环,也不存在显示数字发生闪烁。

但是这样会占用很多口线。

动态显示是将所有位数码管的段选线并联在一起,由位选线控制是哪一位数码管有效。

这样一来,就没有必要每一位数码管配一个锁存器,从而节省了口线,地简化了硬件电路。

所谓动态扫描显示即轮流向各位数码管送出字形码和相应的位选,利用发光管的余辉和人眼视觉暂留作用,使人的感觉好像各位数码管同时都在显示。

51单片机数码管动态显示(延时扫描)

51单片机数码管动态显示(延时扫描)
/*
*函数名:Display
*功 能:可预置显示首地址和显示位数的LED显示函数
*参 数:无符号字符型指针类型,无符号字符型数字
*返回值:无
*/
void Display(uint8 *buf,uint8 n)
{
uint8 i;
for(i=0;i<n;i++)
{
DUAN = 0xFF;
DUAN = DuanMa[*(buf+i)];
#define _DISPLAY_H_
#define DUAN P0
#define WEI P2
extern void Display(uint8 *buf,uint8 n);
#endif
//display.c文件
#include "global.h"
#include "display.h"
#include "delay.h"
WEI = WeiMa[i];
DelayMs(1);
}
}
//main.c文件
#include "global.h"
#include "display.h"
uint8 data DisBuf[] = {0,0,0,0,0,0,0,0,0};
//主函数
void main(void)
{
while(1)
{
Display(DisBuf,4);
typedef unsigned char uint8;
extern uint8 DisBuf[];
#endif
//delay.h文件
#ifndef _DELAY_H_

DS1302和51单片机设计电子钟数码管显示

DS1302和51单片机设计电子钟数码管显示

DS1302和51单片机设计电子钟数码管显示2010-09-03 10:39DS1302和51单片机设计电子钟数码管显示(未作出防真)#include<reg51.h>#define uchar unsigned char#define uint unsigned intuchar dis[16]={0,0,0,0,10,10,0,0,7,2,9,0,9,0,0,2};uchar P2_scan[4]={0xf7,0xfb,0xfd,0xfe}; //位选择显示扫描ucharP0_scan[11]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff}; //数字显示不带小数点ucharP0_scan1[11]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0x7f} ;//数字显示带小数点char clock[7]={4,0,15,10,27,9,9};uchar tiao,m=0,n=8,S;bit time=0,p=0;sbit CLK = P1^0;sbit IO = P1^1;sbit RST = P1^2;sbit P32 = P3^2;sbit P33 = P3^3;sbit P34 = P3^4;sbit P35 = P3^5;/**************************** 延时函数 **************************/ void delay(uchar time)//延时0.1ms{uchar i,j;do{for(i=0;i<10;i++)for(j=0;j<20;j++);time--;}while (time>0);}/***************************** 复位函数******************************/void reset(){CLK = 0;RST = 0;RST = 1;}/****************************** 字节写入函数***************************/void wbyte(uchar W_Byte){uchar i;for(i =0;i<8;++i){IO=0;if(W_Byte&0x01)IO=1;CLK=0;CLK=1; //一次上升沿写一位,zwj注 W_Byte>>=1;}}/****************************** 字节读取函数****************************/uchar rbyte(){uchar i;uchar R_Byte;uchar TmpByte;R_Byte=0x00;IO=1;for(i=0;i<8;++i){CLK=1;CLK=0;TmpByte=(uchar)IO; //读IO口TmpByte<<=7;R_Byte>>=1 ;R_Byte|=TmpByte;}return R_Byte;}/**************************** DS1302初始化函数**************************/void initialize_DS1302(void){reset();wbyte(0x8e); // 写保护控制寄存器wbyte(0); // 允许写入reset();wbyte(0x90); // 涓流充电控制寄存器wbyte(0xab); // 允许充电, 双二极管, 8K 电阻reset();wbyte(0xbe); // 以多字节突发方式写入时钟数据(8个字节)wbyte(clock[1]); //秒wbyte(clock[2]); //分wbyte(clock[3]); //时wbyte(clock[4]); //日wbyte(clock[5]); //月wbyte(clock[0]); //星期wbyte(clock[6]); //年wbyte(0x00); // 以多字节突发方式写入时钟数据时,必须对写保护控制寄存器写入0值reset();}/**************************** 显示函数 **************************/ void scan(void)//显示函数{uchar k;for (k=0;k<4;k++){if(S>4) P0=~P0_scan[dis[k+S]];else P0=~P0_scan[dis[k+S]];P2=P2_scan[k];delay(5);P0=0x00;P2=0xff;}}/**************************** BCD-非BCD **************************/ void transform(void){uchar k;for(k=0;k<7;++k){clock[k]=(((clock[k] >> 4) * 10) + (clock[k] & 0xf));}}/**************************** 非BCD-BCD **************************/ void transform_1(void){uchar k;for(k=0;k<7;++k){clock[k]=(((clock[k] / 10) << 4) | (clock[k] % 10));}}/**************************** 定时器中断0 **************************/ void timer0(void) interrupt 1{TR0=0 ;if(p==0){reset();wbyte(0xbf); // 以多字节突发方式从DS1302读取时钟数据 clock[1] = rbyte(); // 秒clock[2] = rbyte(); // 分clock[3] = rbyte(); // 小时clock[4] = rbyte(); // 日期clock[5] = rbyte(); // 月份clock[0] = rbyte(); // 星期此程序不用clock[6] = rbyte(); // 年reset();transform();}dis[0]=clock[1]%10;dis[1]=clock[1]/10;dis[2]=clock[2]%10;dis[3]=clock[2]/10;dis[6]=clock[3]%10;dis[7]=clock[3]/10;dis[8]=clock[4]%10;dis[9]=clock[4]/10;dis[10]=clock[5]%10;dis[11]=clock[5]/10;dis[12]=clock[6]%10;dis[13]=clock[6]/10;scan();TH0=0xff ; TL0=0x38 ; TR0=1 ;}/**************************** 主函数 **************************/void main(void){TMOD=0x01 ; TH0=0xff ; TL0=0x38 ; ET0=1 ; EA=1 ; transform_1();initialize_DS1302();TR0=1 ;while(1){if(!P32) //K0键被按下{delay(1); //按键消抖if(!P32){S+=4;if(S == 16) S = 0;while(!P32); //等待按键弹起delay(1);}}}}。

51单片机综合学习系统之 DS1302时钟应用篇

51单片机综合学习系统之 DS1302时钟应用篇

51单片机综合学习系统之DS1302时钟应用篇大家好,通过以前的学习,我们已经对51单片机综合学习系统的使用方法及学习方式有所了解与熟悉,学会了使用AD模数转换的基本知识,体会到了综合学习系统的易用性与易学性,这一期我们将一起学习DS1302时钟的基本原理与应用实例。

先看一下我们将要使用的51单片机综合学习系统能完成哪些实验与产品开发工作:分别有流水灯,数码管显示,液晶显示,按键开关,蜂鸣器奏乐,继电器控制,IIC总线,SPI总线,PS/2实验,AD模数转换,光耦实验,串口通信,红外线遥控,无线遥控,温度传感,步进电机控制等等。

主体系统如图1所示,其配套书本教程《单片机快速入门》如图2所示。

图151单片机综合学习系统主机部分图片图251单片机综合学习系统配套书本教程——《单片机快速入门》上图是我们将要使用的51单片机综合学习系统硬件平台,如图1所示,本期实验我们用到了综合系统主机、板载的DS1302时钟芯片,综合系统其它功能模块原理与使用详见前几期《电子制作》杂志及后期连载教程介绍。

在很多单片机系统中都要求带有实时时钟电路,如最常见的数字钟、钟控设备、数据记录仪表,这些仪表往往需要采集带时标的数据,同时一般它们也会有一些需要保存起来的重要数据,有了这些数据,便于用户后期对数据进行观察、分析。

本小节就介绍市面上常见的时钟芯片DS1302的应用。

DS1302是美国DALLAS公司推出的一款高性能、低功耗、带内部RAM的实时时钟芯片(RTC),也就是一种能够为单片机系统提供日期和时间的芯片。

通过本小节的学习,我们将会把RTC相关的一些技术粗略介绍一下,然后介绍DS1302与单片机之间的软硬件应用。

DS1302时钟芯片简介DS1302是DALLAS公司推出的涓流充电时钟芯片,内含一个实时时钟/日历和31字节静态RAM,可以通过串行接口与单片机进行通信。

实时时钟/日历电路提供秒、分、时、日、星期、月、年的信息,每个月的天数和闰年的天数可自动调整,时钟操作可通过AM/PM标志位决定采用24或12小时时间格式。

实时时钟芯片DS1302 的C51 编程

实时时钟芯片DS1302 的C51 编程

实时时钟芯片DS1302的C51编程作者:刘健永Email:ts_jianyong@1.将数据写入DS1302// 名称: v_RTInputByte// 说明:// 功能: 往DS1302写入1Byte数据// 调用:// 输入: dat 写入的数据// 返回值: 无void v_RTInputByte(unsigned char ucdat){unsigned char i;for(i=8;i>0;i--){DS1302_IO = (bit)(ucdat & 0x01); /*相当于汇编中的 RRC */ DS1302_SCLK = 1;_nop_();DS1302_SCLK = 0;ucdat >>= 1;}return;}2.读取DS1302中的数据// 名称: uchar uc_RTOutputByte// 说明:// 功能: 从DS1302读取1Byte数据// 调用:// 输入:// 返回值: datunsigned char uc_RTOutputByte(void){unsigned char i;unsigned char ucdat=0;for(i=8;i>0;i--){DS1302_IO=1;ucdat >>= 1; /*相当于汇编中的 RRC */if(DS1302_IO)ucdat|=0x80;DS1302_SCLK = 1;_nop_();DS1302_SCLK = 0;}return(ucdat);}3.往DS1302写入数据// 名称: v_W1302// 说明: 先写地址,后写命令/数据// 功能: 往DS1302写入数据// 调用: v_RTInputByte()// 输入: address: DS1302地址, dat: 要写的数据// 返回值: 无void v_W1302(unsigned char address, unsigned char ucdat) {DS1302_RST = 0;DS1302_SCLK = 0;DS1302_RST = 1;v_RTInputByte(address); /* 地址,命令 */v_RTInputByte(ucdat); /* 写1Byte数据*/DS1302_SCLK = 1;DS1302_RST =0;return;}4.读取DS1302某地址的数据// 名称: uc_R1302// 说明: 先写地址,后读命令/数据// 功能: 读取DS1302某地址的数据// 调用: v_RTInputByte() , uc_RTOutputByte()// 输入: ucAddress: DS1302地址// 返回值: ucData :读取的数据unsigned char uc_R1302(unsigned char address){unsigned char ucdat;DS1302_RST=0;DS1302_SCLK=0;DS1302_RST=1;v_RTInputByte(address); /* 地址,命令 */ucdat = uc_RTOutputByte(); /* 读1Byte数据 */DS1302_SCLK = 1;DS1302_RST =0;return(ucdat);}5.设置初始时间// 名称: v_Set1302// 说明:// 功能: 设置初始时间// 调用: v_W1302()// 输入: pSecDa: 初始时间地址。

51单片机的数码管动态显示技术

51单片机的数码管动态显示技术
当测量的数据按权位展开所得的十进制数 不是我们所需要的十进制数,就必须按照测量 的要求,找出实际的数据与测量的数据之间的 对应关系来进行转换。如在电压测量系统中,测 量范围为 0-5V,测量精度为 0.02V,这样通过 ADC0809 转换后的数据就是 8 位二进制测量数 据。这个数据就包含了十进制电压值得个位、十 分位和百分位,必须从这 8 位二进制数据中拆 出个位、十分位和百分位的电压值,每一位用一 个数码管显示,这样才能直观的读出当前测量 的电压值是几点几几伏。
在信息时代的今天,单片机技术应用越来 越广泛,涉及各行各业,也渗透到人们的日常生 活之中,如洗衣机、空调、冰箱等的控制系统,就 可以用单片机实现。为了让人们很直观的了解 相关设备当前的工作状态,很多时候需要将当 前的时间、温度、工作程序等状态通过数码管显 示出来,这就涉及到单片机的数码管显示技术。
1 单片机与 LED 数码管动态显示接口电路 动态显示方式是将所有数码管的 8 段按同 名端连在一起,另外为每个数码管的公共极 COM 增加位选通控制电路,位选通由各自独立 的 I/O 线控制,显示数码同时传到每个数码管, 但每个瞬时由位选通信号选通一个数码管,即 在某一瞬时只有一个数码管显示数据,且显示 时间不能太长,一般为 1-10MS,依次循环扫描, 轮流显示,由于人的视觉滞留效应,人们看到的 是多位同时稳定显示。占用 I/O 端线少,电路较 简单,编程较复杂,CPU 要定时扫描刷新显示, 一般适用于显示位数较多的场合。 由于动态显示情况下,CPU 要定时扫描刷 新显示,数码管的信号在不停的通断变化,为了 保证显示效果,一般会在数据端口接一个缓冲 驱动芯片(如 74HC244、74LS244 等),而在位选 通端接一个 PNP 三极管作驱动 (如 9012、8550 等)。(如图 1)

DS1302时钟芯片51单片机c语言程序

DS1302时钟芯片51单片机c语言程序

DS1302时钟芯片51单片机c语言程序#ifndef __DS1302_H__#define __DS1302_H__#define uchar unsigned char#define uint unsigned int#includesbit SCLK = P3^2;sbit IO = P2^4;sbit RST = P3^3;#define R_Second 0x81#define W_Second 0x80#define R_Minute 0x83#define W_Minute 0x82#define R_Hour 0x85#define W_Hour 0x84#define R_Day 0x87#define W_Day 0x86#define R_Month 0x89#define W_Month 0x88#define R_Week 0x8B#define W_Week 0x8A#define R_Year 0x8D#define W_Year 0x8C#define R_Control 0x8F#define W_Control 0x8Evoid DS1302_Write_Byte(uchar Date); uchar DS1302_Read_Byte();void Write_DS1302(uchar Adr,uchar Date); uchar Read_DS1302(uchar Adr);void Init_DS1302();#endif#include "ds1302.h"/************************************************************** 函數名稱:DS1302_Write_Byte(uchar Date)函數功能:单字节写輸入參數:写的字节輸出參數:无備注:**************************************************************/ void DS1302_Write_Byte(uchar Date){uchar i;for(i = 0;i < 8;i++){if(Date & 0x01)IO = 1;elseIO = 0;SCLK = 1;Date = Date >> 1;SCLK = 0;}}/************************************************************** 函數名稱:uchar DS1302_Read_Byte()函數功能:单字节读輸入參數:无輸出參數:读出的数据備注:uchar DS1302_Read_Byte(){uchar i,Temp = 0;for(i = 0;i < 8;i++){Temp = Temp >> 1;SCLK = 0;if(IO == 1)Temp = Temp | 0x80;SCLK = 1;}return Temp;}/************************************************************** 函數名稱:Write_DS1302(uchar Adr,uchar Date)函數功能:写数据輸入參數:写的寄存器地址和数据輸出參數:无備注:**************************************************************/ void Write_DS1302(uchar Adr,uchar Date){RST = 0;SCLK = 0;RST = 1;DS1302_Write_Byte(Adr);DS1302_Write_Byte(Date);RST = 0;}函數名稱:uchar Read_DS1302(uchar Adr)函數功能:读数据輸入參數:写的寄存器地址輸出參數:读出的数据備注:**************************************************************/ uchar Read_DS1302(uchar Adr){uchar Temp = 0;RST = 0;SCLK = 0;RST = 1;DS1302_Write_Byte(Adr);Temp = DS1302_Read_Byte();RST = 0;Temp = Temp / 16 * 10 + Temp % 16;return Temp;}/************************************************************** 函數名稱:Init_DS1302()函數功能:初始化DS1302輸入參數:无輸出參數:无備注:**************************************************************/ void Init_DS1302(){Write_DS1302(W_Control,0x00);Write_DS1302(W_Year,0x11);Write_DS1302(W_Week,0x06); Write_DS1302(W_Month,0x09); Write_DS1302(W_Day,0x10); Write_DS1302(W_Hour,0x16); Write_DS1302(W_Minute,0x11); Write_DS1302(W_Second,0x23); Write_DS1302(W_Control,0x80); }。

DS1302时钟芯片C51驱动程序

DS1302时钟芯片C51驱动程序

DS1302时钟芯片C51驱动程序/**********************************************程序名称:DS1302时钟芯片C51驱动程序简要说明:read_clockS函数为读取时钟数据调用Set_time即可调整时间并写入DS1302sel为调整标志,可通过外部按键来更改其值来源:整理杜洋程序文档所得**********************************************///定义头文件#include/************************************************************** ****///定义DS1302时钟接口sbit clock_clk = P1 ^ 0; //ds1302_clk(时钟线)sbit clock_dat = P1 ^ 1; //ds1302_dat(数据线)sbit clock_Rst = P1 ^ 2; //ds1302_Rst(复位线)/************************************************************** ****///定义累加器A中的各位sbit a0 = ACC ^ 0;sbit a1 = ACC ^ 1;sbit a2 = ACC ^ 2;sbit a3 = ACC ^ 3;sbit a4 = ACC ^ 4;sbit a5 = ACC ^ 5;sbit a6 = ACC ^ 6;sbit a7 = ACC ^ 7;/************************************************************** ****///定义全局变量unsigned char yy,mo,dd,xq,hh,mm,ss; //定义时间映射全局变量/************************************************************** ****///声明unsigned char clock_in(void);void clock_out(unsigned char dd);void Init_1302(void);unsigned char read_clock(unsigned char ord);void read_clockS(void);void Set_time(unsigned char sel);void write_clock(unsigned char ord, unsigned char dd);/************************************************************** ****///常用时钟数据读取void read_clockS(void){ss = read_clock(0x81); //读取秒数据mm = read_clock(0x83); //读取分钟数据hh = read_clock(0x85); //小时dd = read_clock(0x87); //日mo = read_clock(0x89); //月xq = read_clock(0x8b); //星期yy = read_clock(0x8d); //年}/************************************************************** ****///调时用加1或减1程序void Set_time(unsigned char sel){//根据选择调整的相应项目加1或减1并写入DS1302,sel为调整项标志,通过外部程序来影响它signed char address,item;signed char max,mini;if(sel==6) {address=0x80; max=0;mini=0;} //秒7if(sel==5) {address=0x82; max=59;mini=0;} //分钟6if(sel==4) {address=0x84; max=23;mini=0;} //小时5if(sel==3) {address=0x8a; max=7;mini=1;} //星期4if(sel==2) {address=0x86; max=31;mini=1;} //日3if(sel==1) {address=0x88; max=12;mini=1;} //月2if(sel==0) {address=0x8c; max=99; mini=0;} //年1//读取1302某地址上的数值转换成10进制赋给itemitem=((read_clock(address+1))/16)*10 + (read_clock(address+1))%16;if(ADD_KEY == 0){item++;} //增加键(ADD_KEY)按下,数加1if(DEC_KEY == 0){item--;} //减少键(DEC_KEY)按下,数减 1 if(item>max) item=mini; //查看数值有效范围if(itemwrite_clock(0x8e,0x00); //允许写操作write_clock(address,(item/10)*16+item%10);//转换成16进制写入1302write_clock(0x8e,0x80); //写保护,禁止写操作}/************************************************************** ****///设置1302的初始时间void Init_1302(void)//(2009年1月1日00时00分00秒星期一){write_clock(0x8e,0x00); //允许写操作write_clock(0x8c,0x09); //年write_clock(0x8a,0x01); //星期write_clock(0x88,0x01); //月write_clock(0x86,0x01); //日write_clock(0x84,0x00); //小时write_clock(0x82,0x00); //分钟write_clock(0x80,0x00); //秒write_clock(0x90,0xa5); //充电write_clock(0x8e,0x80); //禁止写操作}/************************************************************** ****///DS1302写数据(底层协议)void write_clock(unsigned char ord, unsigned char dd){clock_clk=0;clock_Rst=0;clock_Rst=1;clock_out(ord);clock_out(dd);clock_Rst=0;clock_clk=1;}/************************************************************** ****///1302驱动程序(底层协议)void clock_out(unsigned char dd){ACC=dd;clock_dat=a0; clock_clk=1; clock_clk=0;clock_dat=a1; clock_clk=1; clock_clk=0;clock_dat=a2; clock_clk=1; clock_clk=0;clock_dat=a3; clock_clk=1; clock_clk=0;clock_dat=a4; clock_clk=1; clock_clk=0;clock_dat=a5; clock_clk=1; clock_clk=0;clock_dat=a6; clock_clk=1; clock_clk=0;clock_dat=a7; clock_clk=1; clock_clk=0;}/************************************************************** ****///DS1302写入字节(底层协议)unsigned char clock_in(void){clock_dat=1;a0=clock_dat;clock_clk=1; clock_clk=0; a1=clock_dat;clock_clk=1; clock_clk=0; a2=clock_dat;clock_clk=1; clock_clk=0; a3=clock_dat;clock_clk=1; clock_clk=0; a4=clock_dat;clock_clk=1; clock_clk=0; a5=clock_dat;clock_clk=1; clock_clk=0; a6=clock_dat;clock_clk=1; clock_clk=0; a7=clock_dat;return(ACC);}/************************************************************** ****///DS1302读数据(底层协议)unsigned char read_clock(unsigned char ord){unsigned char dd=0;clock_clk=0;clock_Rst=0;clock_Rst=1;clock_out(ord);dd=clock_in();clock_Rst=0;clock_clk=1;return(dd);}/************************************************************** ****/。

51单片机数码管动态显示分析

51单片机数码管动态显示分析

51单片机数码管动态显示分析51单片机数码管动态显示是一种常见的数字显示方式,其主要通过控制不同位数的数码管,使其依次显示数字,从而实现数字动态显示的效果。

以下将从原理和实现两个方面对51单片机数码管动态显示进行分析。

一、原理分析51单片机数码管动态显示的原理主要分为两部分,分别为定时器控制和位选控制。

定时器控制:在51单片机中使用定时器是为了保证数字动态显示的稳定性。

通过定时器中断的方式来控制数码管的显示时间,使得每个数字都有足够的时间显示,并且切换速度平稳。

位选控制:在数码管动态显示过程中,需要依次控制不同位数的数码管显示数字。

这是通过位选控制器实现的,它会依次选中各位数码管,并显示出要显示的数字。

这个过程会不停地重复,从而实现数字的动态显示。

二、实现分析51单片机数码管动态显示的实现需要以下几个步骤:1. 确定使用的数码管数量及其接口:需要确定使用几个数码管以及它们的引脚分别对应的单片机IO口。

2. 编写显示函数:编写一个函数来控制数码管的动态显示,其中需要实现定时器中断以及位选控制的功能。

3. 循环调用显示函数:将编写好的显示函数放到主函数中进行调用,并不断地循环执行,从而实现数字的动态显示。

需要注意的是,在编写显示函数的过程中,需要确定定时器中断的时间间隔、位选控制的顺序以及每个数码管对应的IO口。

这些因素会直接影响到数字的显示效果,因此需要仔细调试以达到最佳的显示效果。

在实现过程中,还需要考虑到如何读取用户输入并将其显示在数码管上。

一种常见的方式是通过外部按键来读取用户输入,然后通过数码管动态显示的方式,将输入的数字依次显示出来。

总之,51单片机数码管动态显示是一种常见的数字显示方式,其实现原理和步骤相对比较简单。

需要注意的是,在实际应用中还需要结合实际需求进行相应的调整,以达到最佳的显示效果。

超详细的ds1302使用说明及其例程

超详细的ds1302使用说明及其例程
先看一下我们将要使用的51单片机综合学习系统能完成哪些实验与产品开发工作:分别 有流水灯,数码管显示,液晶显示,按键开关,蜂鸣器奏乐,继电器控制,IIC 总线,SPI 总线,PS/2实验,AD 模数转换,光耦实验,串口通信,红外线遥控,无线遥控,温度传感, 步进电机控制等等。主体系统如图1所示,其配套书本教程《单片机快速入门》如图2所示。
图1 DS1302的外部引脚分配
图2 DS1302的内部结构 各引脚的功能为:
Vcc1:主电源;Vcc2:备份电源。当 Vcc2>Vcc1+0.2V 时, 由 Vcc2向 DS1302供电,当 Vcc2< Vcc1时,由 Vcc1向 DS1302供电。
SCLK:串行时钟,输入,控制数据的输入与输出; I/O:三线接口时的双向数据线; CE:输入信号,在读、写数据期间,必须为高。该引脚有两 个功能:第一,CE 开始控制字访问移位寄存器的控制逻辑;其次,
在很多单片机系统中都要求带有实时时钟电路,如最常见的数字钟、钟控设备、数据记 录仪表,这些仪表往往需要采集带时标的数据,同时一般它们也会有一些需要保存起来的重 要数据,有了这些数据,便于用户后期对数据进行观察、分析。本小节就介绍市面上常见的 时钟芯片 DS1302的应用。DS1302是美国 DALLAS 公司推出的一款高性能、低功耗、带内 部 RAM 的实时时钟芯片(RTC),也就是一种能够为单片机系统提供日期和时间的芯片。通 过本小节的学习,我们将会把 RTC 相关的一些技术粗略介绍一下,然后介绍 DS1302与单片 机之间的软硬件应用。
图1 51单片机综合学习系统主机部分图片
图2 51单片机综合学习系统配套书本教程——《单片机快速入门》
上图是我们将要使用的51单片机综合学习系统硬件平台,如图1所示,本期实验我们用 到了综合系统主机、板载的 DS1302时钟芯片,综合系统其它功能模块原理与使用详见前几 期《电子制作》杂志及后期连载教程介绍。

简述单片机控制数码管动态显示的工作原理

简述单片机控制数码管动态显示的工作原理

简述单片机控制数码管动态显示的工作原理一、概述数码管动态显示是一种常见的技术,它通过单片机控制多个数码管以实现同时显示多路数据。

这种技术广泛应用于各种电子设备中,如数字仪表、电子时钟、智能仪表等。

单片机作为一种低功耗、低成本、高集成度的芯片,成为了实现数码管动态显示的核心器件。

二、工作原理1.硬件连接数码管动态显示通常需要连接多个数码管和单片机。

每个数码管需要一个行驱动器,用于控制数码管的亮灭。

单片机通过串行接口与行驱动器相连,以控制多个数码管的显示。

同时,单片机还需要连接一个时钟电路,以实现定时刷新数码管的数据。

在实际应用中,行驱动器通常采用共阳极接法,而单片机则采用串行数据传输方式与行驱动器进行通信。

此外,为了实现数码管的动态显示,通常还需要连接多个限流电阻和限位电阻等元器件。

2.显示方式数码管动态显示主要有静态显示和动态显示两种方式。

静态显示是指每个数码管轮流显示,实现多路数据的依次显示,但由于需要为每个数码管分配单独的接口,因此适用于数据量较小的场景。

而动态显示则是通过控制数码管的行驱动器轮流导通,实现多个数码管的依次显示,从而适用于数据量较大的场景。

行驱动器通常采用轮流导通的方式控制多个数码管,以达到同时显示多路数据的目的。

3.控制方式单片机通过串行接口向行驱动器发送控制信号,包括数据信号和时钟信号。

数据信号用于传输要显示的数据,时钟信号则用于定时刷新数据。

此外,单片机还可以通过中断控制方式,根据需要实时更新显示内容。

在实际应用中,为了提高刷新速度和显示效果,通常需要优化单片机的处理速度和行驱动器的驱动能力。

此外,单片机还可以通过PWM(脉宽调制)控制行驱动器的电流大小,以实现更好的亮度调节和动态效果。

4.刷新速度数码管动态显示的刷新速度取决于单片机的处理速度和行驱动器的驱动能力。

为了获得更好的显示效果和更长的使用寿命,通常需要较高的刷新速度和适当的行驱动器驱动电流。

此外,可以通过优化软件算法和代码来实现更高的刷新速度和更好的显示效果。

DS1302时钟芯片单片机控制操作步骤

DS1302时钟芯片单片机控制操作步骤

DS1302 是美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周日、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V~5.5V。

采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。

DS1302内部有一个31×8的用于临时性存放数据的RAM寄存器。

DS1302是DS1202的升级产品,与DS1202兼容,但增加了主电源/后备电源双电源引脚,同时提供了对后备电源进行涓细电流充电的能力.RST是复位/片选线,通过把RST输入驱动置高电平来启动所有的数据传送。

RST输入有两种功能:首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,RST提供终止单字节或多字节数据的传送手段。

当RST为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。

如果在传送过程中RST置为低电平,则会终止此次数据传送,I/O引脚变为高阻态。

上电运行时,在Vcc>2.0V之前,RST必须保持低电平。

只有在SCLK 为低电平时,才能将RST置为高电平。

时钟相关寄存器:时钟数据为BCD码格式,秒寄存器的CH位:时钟暂停位,为1是,振荡器停止工作,进入低功耗。

小时寄存器:最高位12/24:为1时表示12小时模式,0表示24小时模式。

第5位A/P,1表示下午,0表示上午。

DS1302命令控制字:DS1302的RAM共31个,寄存器地址范围:C0H~FDH,其中奇数为读操作,偶数为写操作DS1302的读写时序:通过控制RST端为高电平启动读写操作,首先发送8位命令控制字,指明读操作还是写操作,及读写的地址。

数据从低到高位顺序传输。

上电时,RST脚必须为低电平,当把RST置为高电平前,SCLK必须为低电平。

写过程:一、启动准备:RST为低电平,SCLK为低电平--PORTB&=~(1<<PB2); PORTB&=~(1<<PB0);二、启动读写开始信号:将RST置为高电平--- PORTB|=(1<<PB2);三、发送要写入地址的命令字节数据,如写秒寄存器,命令字节为80H,write_byte(0x80);四、延时10ms,SCLK 置低电平,----delay(10);PORTB&=~(1<<PB0);五、发送要写入秒寄存器的数据; write_byte(0x02);六、结束写入过程:SCLK清0,RST置为低电平。

51单片机数码管动态显示程序

51单片机数码管动态显示程序

单片机数码管动态显示程序实验,数码管显示一般分静态显示及动态显示两种驱动方式,静态显示占用口线比较多,本文介绍的是如何实现数码管动态显示,应该说数码管动态显示是单片机外部指令输出的重要途径,因此如何设计数码管以及数码管的工作原理、数码管显示的方法、数码管显示的抗干扰设计等在单片机系统设计中占有重要地位。

这个例子在系统硬件的基础上设计了软件查询程序、软件延时程序(防止干扰),大致讲述了一种数码管动态显示的工作原理与读取方式。

s1 bit p0.0 ;数码管位定义s2 bit p0.1s3 bit p0.2s4 bit p0.3s5 bit p0.4s6 bit p0.5s7 bit p0.6s8 bit p0.7led_data equ p2 ;数码管数据定义org 00h ;程序开始jmp main ;主程序开始处org 030h ;主程序从30H开始main: MOV sp,#30h ;设置堆栈lcall rest ;调用初始化程序lcall pro_8led ;调用数码管显示程序jmp main ;返回********* 初始化程序 **************rest:MOV a,#00h ;清寄存器MOV b,#00h ;清寄存器MOV p0,#0 ;禁止数码管显示MOV p2,#255 ;MOV p1,0ffh ;禁止LED显示clr beep ;禁止蜂鸣器ret ;返回******** 数码管显示程序 *************** pro_8led:MOV b,#32 ;一共显示32个数字clr psw.3 ;重新设置寄存器组setb psw.4 ;MOV r0,#00h ;数据显示从0开始MOV r1,#01h ;数码管从第1个开始loop:MOV p0,r1 ;点亮当前数码管MOV a,r0 ;准备第一个数据MOV dptr,#tab_nu ;获得表头MOVc a,@a+dptr ;得到第一个数据MOV led_data,a ;输出到显示数据口lcall delay ;500 ms 延时lcall delay ;1 s 延时inc r0 ;准备下一个数据MOV a,r1 ;准备下一位数码管rlc a ;设置下一个数码管jc c1 ;8位全部显示,转移MOV r1,a ;否则,设置下一位djnz b,loop ;32个数没有显示完,返回显示ret ;否则返回主程序c1: MOV r1,#1 ;8位显示完,重新开始循环clr c ;设置显示位djnz b,loop ;32位显示完则返回重新显示ret ;否则返回到主程序************* 数码管显示 ******************************* ************* 软件延时 500ms ***************************** delay: push psw ;保存原来的寄存器内容clr psw.3 ;clr psw.4 ;设置新的寄存器组MOV r0,#2 ;延时参数1MOV r1,#250 ;延时参数2MOV r2,#2 ;延时参数3dl1:djnz r0,dl1 ;延时循环1MOV r0,#250 ;dl2:djnz r1,dl1 ;延时循环2MOV r0,#240 ;MOV r1,#248 ;dl3:djnz r2,dl1 ;延时循环3nop ;定时精度调整pop psw ;恢复原来的寄存器ret ;返回********************************************************************************************************************这是数字显示表格,其中带小数点的数字比不带小数点的数字大16比如 0 的显示代码为 0;那么 0.的显示代码为 16;如此类推tab_nu:db 0c0h, 0f9h, 0a4h, 0b0h, 99h , 92h , 82h, 0f8h ;数字0-7 不带小数点代码db 80h , 90h, 88h , 83h , 0c6h, 0a1h, 86h, 8eh ;数字8-f 不带小数点代码db 40h , 79h, 24h , 30h , 19h , 12h , 02h, 78h ;数字0-7 带小数点代码db 00h , 10h, 08h , 03h , 46h , 21h , 06h, 0eh ;数字8-f 带小数点代码。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
sbit clock_rst=P2^5;
sbit wei1=P2^0;
sbit wei2=P2^1;
sbit wei3=P2^2;
sbit wei4=P2^3;
sbit wei5=P2^4;
sbit wei6=P3^3;
sbit a0 = ACC ^ 0;//为了编程方便定义的位变量
clock_clk=0;clock_dat=a5; clock_clk=1;
clock_clk=0;clock_dat=a6; clock_clk=1;
clock_clk=0;clock_dat=a7; clock_clk=1;
}
unsigned char clock_read(void) //读出一个字节,时序
delay(250);
write_clock(0x8c,0x08);//year 08年
delay(250);
write_clock(0x88,0x6);//month 06
delay(250);
write_clock(0x86,0x25);//date 25
delay(250);
clock_rst=1;
clock_write(reg2);
clock_write(date);
clock_rst=0;
}
void show(void)//显示和闪烁函数
{
unsigned char d, e;
unsigned int i;
for(i=0;i<1000;i++)
wei3=1;
delay(250);
wei3=0;
d=read_clock(0x85);//读小时
e=d;
d=d>>4;
e=e&0x0f;
P0 = Tab_Num[ d ];//小时十位
wei6=1;
delay(250);
wei6=0;
write_clock(0x84,0x8);//hour 8
delay(250);
write_clock(0x82,0x28);//minute 28
delay(250);
write_clock(0x80,0x29);//second 40
delay(250);
write_clock(0x8a,0x03);//week_day 3
wei1=0;
d=read_clock(0x83);//读分钟
e=d;
d=d>>4;
e=e&0x0f;
P0 = Tab_Num[ d ];//分十位
wei4=1;
delay(250);
wei4=0;
P0 = Tab_Num[ e ];//分各位
}
}
/*--------------------时钟的初始化---------------------------*/
void Init_1302(void)//如果不满意现在的表,可以初始化调整,写入程序之后,再把初始化屏蔽掉
{
write_clock(0x8e,0x00);//close_protect
delay(2000);
Init_1302();//DS1302寄存器初始化
P2=0x00;
while(1)
{
show();
}
}
{
clock_clk=1; clock_clk=0; a0=clock_dat;
clock_clk=1; clock_clk=0; a1=clock_dat;
clock_clk=1; clock_clk=0; a2=clock_dat;
clock_clk=1; clock_clk=0; a3=clock_dat;
wei4=1;
delay(250);
wei4=0;
P0 = Tab_Num[ e ];//月各位
wei3=1;
delay(250);
wei3=0;
d=read_clock(0x8d);//读年
e=d;
d=d>>4;
e=e&0xf;
P0 = Tab_Num[ d ];//年十位
wei2=1;
delay(250);
wei2=0;
P0 = Tab_Num[ e ];//日各位
wei1=1;
delay(250);
wei1=0;
d=read_clock(0x89);//读月
e=d;
d=d>>4;
e=e&0x0f;
P0 = Tab_Num[ d ];//月十位
dd=clock_read();
clock_rst=0;
return(dd);
}
void write_clock(unsigned char reg2, unsigned char date)//向reg2写入date数据
{
clock_clk=0;
clock_rst=0;
如何把从DS1302中读出的数据用51单片机用动态扫描方式显示在数码管.txt花前月下,不如花钱“日”下。叶子的离开,是因为风的追求还是树的不挽留?干掉熊猫,我就是国宝!别和我谈理想,戒了!
#include<reg52.h>
sbit clock_clk=P2^7;
sbit clock_dat=P2^6;
clock_clk=1; clock_clk=0; a4=clock_dat;
clock_clk=1; clock_clk=0; a5=clock_dat;
clock_clk=1; clock_clk=0; a6=clock_dat;
clock_clk=1; clock_clk=0; a7=clock_dat;
wei6=1;
delay(250);
wei6=0;
P0 = Tab_Num[ e ];//年各位
wei5=1;
delay(250);
wei5=0;
}
for(i=0;i<200;i++) //间隔显示
{
d=read_clock(0x8b);//读年
return(ACC);
}
unsigned char read_clock(unsigned char reg1)//从reg1寄存器读数据
{
unsigned char dd=0;
clock_clk=0;
clock_rst=0;
clock_rst=1;
clock_write(reg1);
P0 = Tab_Num[ e ];//小时各位
wei5=1;
delay(250);
wei5=0;
}
for(i=0;i<400;i++) //间隔显示

d=read_clock(0x87);//读日
e=d;
d=d>>4;
e=e&0x0f;
P0 = Tab_Num[ d ];//日十位
e=d;
d=d>>4;
e=e&0xf;
P0 = Tab_Num[ d ];//年十位
wei2=1;
delay(250);
wei2=0;
P0 = Tab_Num[ e ];//年各位
wei1=1;
delay(250);
wei1=0;
{
d=read_clock(0x81);//读秒
e=d;
d=d>>4;
e=e&0x0f;
P0 = Tab_Num[ d ];//秒十位
wei2=1;
delay(250);
wei2=0;
P0 = Tab_Num[ e ];//秒各位
wei1=1;
delay(250);
delay(250);
write_clock(0x90,0xa0);//supply_power
delay(250);
write_clock(0x8e,0x80);//protect
delay(250);
}
void main(void)
{
int i;
for(i=0;i<2;i++)
void delay(int num)//延时函数
{
while(num--) ;
}
void clock_write(unsigned char dd) //写入一个字节,DS1302时序
{
ACC=dd;
clock_clk=0;clock_dat=a0; clock_clk=1;
clock_clk=0;clock_dat=a1; clock_clk=1;
clock_clk=0;clock_dat=a2; clock_clk=1;
clock_clk=0;clock_dat=a3; clock_clk=1;
clock_clk=0;clock_dat=a4; clock_clk=1;
sbit a1 = ACC ^ 1;
sbit a2 = ACC ^ 2;
sbit a3 = ACC ^ 3;
sbit a4 = ACC ^ 4;
sbit a5 = ACC ^ 5;
sbit a6 = ACC ^ 6;
相关文档
最新文档