四位数码管(动态) - C51程序详解
- 格式:docx
- 大小:19.85 KB
- 文档页数:4
单片机动态数码管小数输出要实现单片机动态数码管小数输出,需要进行以下步骤:1. 读取小数的整数部分和小数部分。
2. 将整数部分和小数部分转换成字符串。
3. 分别输出整数部分和小数部分到数码管,在数码管上显示小数点。
4. 通过动态扫描数码管的方式,将整数部分和小数部分输出到数码管的对应位置上,实现小数输出。
示例代码:c#include<reg52.h>动态扫描数码管时使用的数码段表unsigned char code LED_Table[] ={0xc0, 00xf9, 10xa4, 20xb0, 30x99, 40x92, 50x82, 60xf8, 70x80, 80x90 9};void delay(unsigned int x){while(x);}将整数转换成字符串void intToString(int num, char* str) {int i = 0;while(num > 0){str[i++] = num % 10 + '0';num /= 10;}str[i] = '\0';反转字符串for(int j = 0; j < i / 2; j++){char temp = str[j];str[j] = str[i - j - 1];str[i - j - 1] = temp;}}将小数转换成字符串void floatToString(float num, char* str){取小数点后两位int temp = (int)(num * 100);intToString(temp, str);}在数码管上显示小数点void displayDecimalPoint(unsigned char* LED, unsigned char pos)把小数点位置的LED值改为0x7f即可LED[pos] = 0x7f;}void main(){unsigned char LED[8] = {0}; 数码管各个位的LED值char intStr[4] = {0}; 整数部分转换后的字符串char floatStr[4] = {0}; 小数部分转换后的字符串float num = 12.34; 要输出的小数int intPart = (int)num; 小数的整数部分float floatPart = num - intPart; 小数部分将整数部分转换成字符串intToString(intPart, intStr);将小数部分转换成字符串floatToString(floatPart, floatStr);在数码管上显示小数点displayDecimalPoint(LED, 2);while(1){动态扫描数码管for(int i = 0; i < 8; i++){每隔一段时间扫描下一位数码管的LED值P2 = 1 << i;P0 = LED[i];delay(200);}根据当前扫描的位置输出整数部分或小数部分if(P2 == 0xfe) 第0位数码管{P0 = LED_Table[intStr[0] - '0'];}else if(P2 == 0xfd) 第1位数码管{P0 = LED_Table[intStr[1] - '0'];}else if(P2 == 0xfb) 第2位数码管(小数点后一位){P0 = LED_Table[floatStr[0] - '0'];}else if(P2 == 0xf7) 第3位数码管(小数点后两位){P0 = LED_Table[floatStr[1] - '0'];}else 其他数码管{P0 = 0;}}}在代码中,我们首先将要输出的小数分别转换成整数部分和小数部分的字符串,然后将整数部分和小数部分分别输出到数码管,其中要特别处理小数点的显示。
四位数码管单独显示1. 引言数码管是一种常见的数字显示设备,常用于电子时钟、电子测量仪器等场合。
四位数码管单独显示是指将四个数码管分别控制,使其能够独立显示不同的数字。
本文将介绍如何使用Arduino控制四位数码管实现单独显示的功能。
2. 器件准备在开始之前,我们需要准备以下器件: - Arduino主控板 - 四位共阳数码管 - 适配器电源 - 杜邦线若干3. 电路连接将四位数码管接线连接到Arduino主控板上,具体的接线方式如下: - 将数码管的A、B、C、D、E、F、G引脚分别连接到Arduino的引脚2、3、4、5、6、7、8; - 将数码管的COM1、COM2、COM3、COM4引脚分别连接到Arduino的引脚9、10、11、12。
4. 程序编写以下是使用Arduino语言编写的程序,实现四位数码管单独显示的功能:// 四位数码管单独显示// 数码管引脚定义int segPins[] = {2, 3, 4, 5, 6, 7, 8};int comPins[] = {9, 10, 11, 12};void setup() {// 设置数码管引脚为输出模式for (int i = 0; i < 7; i++) {pinMode(segPins[i], OUTPUT);}for (int i = 0; i < 4; i++) {pinMode(comPins[i], OUTPUT);}}void loop() {// 数字0-9的编码,对应数码管的a-g引脚状态int numCode[] = {B1111110, B0110000, B1101101, B1111001, B0110011, B1 011011, B1011111, B1110000, B1111111, B1110011};for (int i = 0; i < 4; i++) {// 在COM1-COM4引脚依次输出低电平,其他引脚输出高电平for (int j = 0; j < 4; j++) {if (j == i) {digitalWrite(comPins[j], LOW);} else {digitalWrite(comPins[j], HIGH);}}// 控制数码管显示对应数字for (int j = 0; j < 7; j++) {digitalWrite(segPins[j], (numCode[i] >> j) & 1);}// 设置显示间隔delay(10);}}5. 程序说明上述程序中,我们首先定义了数码管的引脚,然后在setup()函数中,设置数码管引脚为输出模式。
/******************************************************************************************* **/#include<STC12C2052AD.H>//STC头文件/******************************************************************************************* ***///“程序开发调试设置项”#define DY_LI 9 //设置LED显示的亮度(值域:~9)#define DY_DELAY 12 //设置每一个点显示的时间长度(~20)/******************************************************************************************* ***/sbit DY_LED1_H1 =P3 ^ 0; //设置LED点阵屏连接的I/O口sbit DY_LED1_H2 =P3 ^ 1; //设置LED点阵屏连接的I/O口sbit DY_LED1_H3 =P3 ^ 2; //设置LED点阵屏连接的I/O口sbit DY_LED1_H4 =P3 ^ 3; //设置LED点阵屏连接的I/O口sbit DY_LED1_L1 =P1 ^ 0; //设置LED点阵屏连接的I/O口sbit DY_LED1_L2 =P1 ^ 1; //设置LED点阵屏连接的I/O口sbit DY_LED1_L3 =P1 ^ 2; //设置LED点阵屏连接的I/O口sbit DY_LED1_L4 =P1 ^ 3; //设置LED点阵屏连接的I/O口sbit DY_LED1_L5 =P1 ^ 4; //设置LED点阵屏连接的I/O口sbit DY_LED1_L6 =P1 ^ 5; //设置LED点阵屏连接的I/O口sbit DY_LED1_L7 =P1 ^ 6; //设置LED点阵屏连接的I/O口sbit DY_LED1_L8 =P1 ^ 7; //设置LED点阵屏连接的I/O口//sbit DY_BEEP =P2 ^ 2; //扬声器//sbit DY_KEY1 =P0 ^ 2; //按键(M键)(连接在P1.3和P0.2,读P0.2为低时表示有按键动作)//sbit DY_KEY2 =P3 ^ 0; //按键(+键)(连接在P4.6和P3.0,读P3.0为低时表示有按键动作)//sbit DY_KEY3 =P3 ^ 6; //按键(-键)(连接在P2.4和P3.6,读P3.6为低时表示有按键动作)#define DY_P1M0SET 0x00 //设置I/O口工作方式//00000000(左到右,高到低位)#define DY_P1M1SET 0x00 //设置I/O口工作方式//00101000#define DY_P3M0SET 0x00 //设置I/O口工作方式//00000000#define DY_P3M1SET 0xff //设置I/O口工作方式//10010100data unsigned char TIME_DD,TIME_MO,TIME_YY,TIME_WW,TIME_HH,TIME_MM,TIME_SS,ty;//设置日、月、年、周、时、分、秒和温度存放区data unsigned char cou = 0; // 软计数器,对ms时基信号累加到sdata unsigned char bn;//扫描映射全局变量data unsigned char KEY_BIT = 0;//按键值data unsigned char DY_PWM;//显示亮度data unsigned char DY_PWM2;//显示暂存unsigned char code disdata[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f //无小数点数码管段码表(0~9)};/******************************************************************************************* **/void delay (unsigned int a){ // 用于点扫描的延时unsigned int i;while( --a != 0){for(i = 0; i < DY_DELAY; i++);}}/******************************************************************************************* **/void delay1ms (unsigned int a){ // 1ms延时程序(MHz 10倍于单片机速度时)unsigned int i;while( --a != 0){for(i = 0; i < 600; i++);}}/******************************************************************************************* **/void dis_off (void){P1 = ~DY_P1M1SET; //关所有显示P3 = ~DY_P3M1SET;delay(10-DY_PWM);}/******************************************************************************************* **/void displayHH1 (unsigned char d){ //第列横向显示程序unsigned char i;i = d & 0x01;if(i == 0x01){DY_LED1_H1 = 1;DY_LED1_L1 = 0;}delay(DY_PWM);dis_off();i = d & 0x02;if(i == 0x02){DY_LED1_H1 = 1;DY_LED1_L2 = 0;}delay(DY_PWM);dis_off();i = d & 0x04;if(i == 0x04){DY_LED1_H1 = 1;DY_LED1_L3 = 0;}delay(DY_PWM);dis_off();i = d & 0x08;if(i == 0x08){DY_LED1_H1 = 1;DY_LED1_L4 = 0;}delay(DY_PWM);dis_off();i = d & 0x10;if(i == 0x10){DY_LED1_H1 = 1;DY_LED1_L5 = 0;}delay(DY_PWM);dis_off();i = d & 0x20;if(i == 0x20){DY_LED1_H1 = 1;DY_LED1_L6 = 0;}delay(DY_PWM);dis_off();i = d & 0x40;if(i == 0x40){DY_LED1_H1 = 1;DY_LED1_L7 = 0;}delay(DY_PWM);dis_off();i = d & 0x80;if(i == 0x80){DY_LED1_H1 = 1;DY_LED1_L8 = 0;}delay(DY_PWM);dis_off();}/******************************************************************************************* **/void displayHH2 (unsigned char d){ //第列横向显示程序unsigned char i;i = d & 0x01;if(i == 0x01){DY_LED1_H2 = 1;DY_LED1_L1 = 0;}delay(DY_PWM);dis_off();i = d & 0x02;if(i == 0x02){DY_LED1_H2 = 1;DY_LED1_L2 = 0;}delay(DY_PWM);dis_off();i = d & 0x04;if(i == 0x04){DY_LED1_H2 = 1;DY_LED1_L3 = 0;}delay(DY_PWM);dis_off();i = d & 0x08;if(i == 0x08){DY_LED1_H2 = 1;DY_LED1_L4 = 0;}delay(DY_PWM);dis_off();i = d & 0x10;if(i == 0x10){DY_LED1_H2 = 1;DY_LED1_L5 = 0;}delay(DY_PWM);dis_off();i = d & 0x20;if(i == 0x20){DY_LED1_H2 = 1;DY_LED1_L6 = 0;}delay(DY_PWM);dis_off();i = d & 0x40;if(i == 0x40){DY_LED1_H2 = 1;DY_LED1_L7 = 0;}delay(DY_PWM);dis_off();i = d & 0x80;if(i == 0x80){DY_LED1_H2 = 1;DY_LED1_L8 = 0;}delay(DY_PWM);dis_off();}/******************************************************************************************* **/void displayHH3 (unsigned char d){ //第列横向显示程序unsigned char i;i = d & 0x01;if(i == 0x01){DY_LED1_H3 = 1;DY_LED1_L1 = 0;}delay(DY_PWM);dis_off();i = d & 0x02;if(i == 0x02){DY_LED1_H3 = 1;DY_LED1_L2 = 0;}delay(DY_PWM);dis_off();i = d & 0x04;if(i == 0x04){DY_LED1_H3 = 1;DY_LED1_L3 = 0;}delay(DY_PWM);dis_off();i = d & 0x08;if(i == 0x08){DY_LED1_H3 = 1;DY_LED1_L4 = 0;}delay(DY_PWM);dis_off();i = d & 0x10;if(i == 0x10){DY_LED1_H3 = 1;DY_LED1_L5 = 0;}delay(DY_PWM);dis_off();i = d & 0x20;if(i == 0x20){DY_LED1_H3 = 1;DY_LED1_L6 = 0;}delay(DY_PWM);dis_off();i = d & 0x40;if(i == 0x40){DY_LED1_H3 = 1;DY_LED1_L7 = 0;}delay(DY_PWM);dis_off();i = d & 0x80;if(i == 0x80){DY_LED1_H3 = 1;DY_LED1_L8 = 0;}delay(DY_PWM);dis_off();}/******************************************************************************************* **/void displayHH4 (unsigned char d){ //第列横向显示程序unsigned char i;i = d & 0x01;if(i == 0x01){DY_LED1_H4 = 1;DY_LED1_L1 = 0;}delay(DY_PWM);dis_off();i = d & 0x02;if(i == 0x02){DY_LED1_H4 = 1;DY_LED1_L2 = 0;}delay(DY_PWM);dis_off();i = d & 0x04;if(i == 0x04){DY_LED1_H4 = 1;DY_LED1_L3 = 0;}delay(DY_PWM);dis_off();i = d & 0x08;if(i == 0x08){DY_LED1_H4 = 1;DY_LED1_L4 = 0;}delay(DY_PWM);dis_off();if(i == 0x10){DY_LED1_H4 = 1;DY_LED1_L5 = 0;}delay(DY_PWM);dis_off();i = d & 0x20;if(i == 0x20){DY_LED1_H4 = 1;DY_LED1_L6 = 0;}delay(DY_PWM);dis_off();i = d & 0x40;if(i == 0x40){DY_LED1_H4 = 1;DY_LED1_L7 = 0;}delay(DY_PWM);dis_off();i = d & 0x80;if(i == 0x80){DY_LED1_H4 = 1;DY_LED1_L8 = 0;}delay(DY_PWM);dis_off();}/******************************************************************************************* **/void diplay_data (unsigned char l,unsigned char d){switch (l){//显示的列位置case 1://displayHH1(d); //将显示数据送入break;//case 2://displayHH2(d); //将显示数据送入break;//case 3://displayHH3(d); //将显示数据送入break;//case 4://displayHH4(d); //将显示数据送入break;//}}/******************************************************************************************* **/void init (void){ //上电初始化P1M0 = DY_P1M0SET;P1M1 = DY_P1M1SET;P3M0 = DY_P3M0SET;P3M1 = DY_P3M1SET;////dis_off();DY_PWM = DY_LI;////TMOD = 0x11; // 定时/计数器,1工作于方式TH0 = 0x3c; // 预置产生ms时基信号EA = 1; // 开总中断ET0 = 1; // 定时/计数器允许中断TR0 = 1; // 开闭定时/计数器//////TIME_DD = 18; //时间在首次使用的值,之后会在EEPROM自动记录上一天的值//TIME_MO = 5; //初始时间:年月日周一,时分秒//TIME_YY = 9;//TIME_WW = 1;//TIME_HH = 22;//TIME_MM = 13;//TIME_SS = 40;}/******************************************************************************************* **/void main (void){ //主程序init();while (1){diplay_data (1,disdata[TIME_MM/10]);diplay_data (2,disdata[TIME_MM%10]);diplay_data (3,disdata[TIME_SS/10]+0x80);diplay_data (4,disdata[TIME_SS%10]+0x80);}}/******************************************************************************************* ***/void tiem0(void) interrupt 1{ // T/C0中断服务程序(产生ms时基信号)cou++; // 软计数器加if(cou > 19){ // 计数值到(1s)cou = 0; // 软计数器清零TIME_SS++; // 秒计数器加(进位ms*100=1s)if(TIME_SS > 59){ // 秒计数值到TIME_SS = 0; // 秒计数器清零TIME_MM++; // 分计数器加(进位s=1m)if(TIME_MM > 59){ // 分计数到TIME_MM = 0; // 分计数器清零TIME_HH++; // 时计数器加(进位m=1h)if(TIME_HH > 23){ // 时计数到TIME_HH = 0; // 时计数器清零}}}}TH0 = 0x3c; // 重置定时常数TL0 = 0xb0;}/******************************************************************************************* ***//*************************************************************/*************************************************************/。
arduino4位数码管倒计时程序逻辑【Arduino 4位数码管倒计时程序逻辑】引言:Arduino是一款开源的电子开发平台,可以利用其强大的功能来实现各种实时控制的项目。
本文将介绍如何使用Arduino搭建一个4位数码管的倒计时程序,帮助读者更好地理解和掌握Arduino的编程逻辑。
一、准备工作:首先,我们需要准备以下材料:1. Arduino主控板2. 4位数码管(带有共阳极或共阴极)3. 4个220欧姆的电阻4. 面包板、杜邦线等连接材料二、电路连接:将Arduino主控板与4位数码管通过杜邦线连接起来,并根据数码管的类型选择合适的连接方式。
如果是共阳极数码管,将将数码管的数字空脚连接到Arduino的数字引脚上;如果是共阴极数码管,将数字引脚连接到Arduino的数字引脚上,而将汇流脚连接到Arduino的地(GND)引脚上。
连接完成后,通过电阻将Arduino的供电引脚和数码管的供电引脚连接起来,以确保电流稳定。
三、编程逻辑:接下来,我们将使用Arduino IDE来编写倒计时程序。
打开Arduino IDE,创建一个新的空白文件,并编写如下代码:引入数码管库#include <SevSeg.h>定义数码管引脚SevSeg sevseg;初始化倒计时时间unsigned long countdownTime = 5; 倒计时时间为5秒unsigned long targetTime;int seconds;void setup() {设置数码管引脚sevseg.Begin(COMMON_ANODE, 4, 2, 3, 5, 6, 7, 8); 数码管引脚分别连接到Arduino的数字引脚4、2、3、5、6、7、8设置数码管亮度sevseg.setBrightness(50); 设置亮度为50,可以根据需要进行调整初始化目标时间targetTime = millis() + countdownTime * 1000;}void loop() {获取剩余时间unsigned long remainingTime = targetTime - millis();判断倒计时是否结束if (remainingTime > 0) {计算剩余秒数seconds = remainingTime / 1000;显示剩余秒数sevseg.setNumber(seconds, 0); 显示数字sevseg.refreshDisplay(); 刷新显示} else {倒计时结束sevseg.setNumber(0, 0); 显示0sevseg.refreshDisplay(); 刷新显示}}四、程序解析:1. 首先,我们引入了SevSeg库来操作数码管。
数码管动态扫描函数51 单片机数码管动态扫描显示函数设计。
在学单片机的过程中,数码管动态扫描可是个挺重要的知识点。
就好比要让数码管显示出各种各样的数字、字母啥的,这时候动态扫描函数就派上用场。
数码管动态扫描是咋回事。
打个比方哈,数码管就像一排小窗户,每个窗户能显示不同数字。
但有时候,没办法同时让所有窗户都显示想要的东西,这就得一个一个来。
动态扫描就是按照一定顺序,快速轮流点亮每个数码管,由于人眼有视觉暂留,看着就好像所有数码管同时亮起来显示不同内容。
设计动态扫描函数前的准备。
得先了解数码管的硬件连接。
一般来说,数码管有共阴极和共阳极之分。
共阴极就是把所有发光二极管的阴极连在一起接地,要让哪个亮就给对应的阳极高电平;共阳极相反,阳极连一起接高电平,给阴极低电平就亮。
比如用的是共阴极数码管,那就得按照这个规则来设计电路和函数。
动态扫描函数的设计步骤。
1. 初始化部分:要先设置好单片机的端口,让它们能正确控制数码管。
比如说,把 P0 口用来控制数码管显示的段码,P2 口控制数码管的位选。
那就得在函数开头设置 P0 和 P2 口为输出模式。
就像这样:c.#include <reg51.h>.sbit LSA = P2^2;sbit LSB = P2^3;sbit LSC = P2^4;void main(){// 设置端口为输出模式。
P0 = 0x00;P2 = 0x00;// 其他初始化代码。
}2. 段码和位码设置:得准备好段码表,就是告诉数码管怎么显示 0 9 这些数字。
比如数字 0 的段码是 0x3F。
位码,就是控制哪个数码管亮。
要是有 4 个数码管,第一位的位码就是 0xFE,第二位是 0xFD,第三位是 0xFB,第四位是 0xF7。
像这样:c.unsigned char code SEG_TABLE[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D,0x7D, 0x07, 0x7F, 0x6F};// 显示 0 9 的段码表。
一、实验目的1.掌握Keil软件的基本使用2.学习和掌握C语言编写程序的一般格式3.了解数码管与单片机的接口方法;4.了解数码管性能及动态显示编程方法;5.了解并掌握单片机系统中定时器中断控制的基本方法;二、实验内容用定时器中断实现四位数码管动态显示从1234-9999。
三、实验原理3.1基础知识介绍A.数码管是LED的升级,每位数码管里面继承了8个LED,点亮数码管就是点亮数码管里面的LED。
要在数码管上面显示相应的值,就是点亮不同位置的LED。
数码管有共阴和共阳两种,共阴数码管公共端是所有LED的负极连接在一起,相反共阳数码管公共端是所有LED的正极连接在一起。
一般公共端称作“位选”,控制每一个LED的称为“段选”。
数码管主要是利用视觉暂留的效果,通过快速循环点亮数码管方式,将数据呈现出来。
数码管如图1.2所示1.2数码管1.3数码管实物图/B.定时器定时器也可看作是对计算机机器周期的计数器。
因为每个机器周期包含12个振荡周期,故每一个机器周期定时器加1,可以把输入的时钟脉冲看成机器周期信号。
故其频率为晶振频率的1/12。
如果晶振频率为12MHz,则定时器每接收一个输入脉冲的时间刚好为1μs。
定时器有两种工作模式,分别为计数模式和定时模式。
对Px,y 的输入脉冲进行计数为计数模式。
定时模式,则是对MCU的主时钟经过12分频后计数。
因为主时钟是相对稳定的,所以可以通过计数值推算出计数所经过的时间。
计数器的计数值存放于特殊功能寄存器中。
T0(TL0-0x8A, TH0-0x8C), T1(TL1-0x8B, TH1-0x8D)定时器工作原理如下图由上图可见与定时器相关的寄存器主要有下面这几个:TMOD、TCON、TL0、TH0、TL1、TH1。
下面介绍一下这几个寄存器16位加法计数器:是定时计数器的核心,其中TL0、TH0、是定时计数器0的底八位和高八位;TL1、TH1是定时计数器1的底八位和高八位;并且高八位和底八位可单独使用。
4位共阴数码管显示代码共阴数码管是一种常见的数码显示器件,它由4位7段数码管组成,每个数码管由7个LED组成,可以显示0-9的数字以及一些字母。
在控制4位共阴数码管显示数字的代码中,通常会使用单片机或者其他微控制器来实现。
下面是一个简单的示例代码,使用Arduino来控制4位共阴数码管显示数字:c.int digitPins[] = {2, 3, 4, 5}; // 数码管的位选引脚。
int segmentPins[] = {6, 7, 8, 9, 10, 11, 12}; // 数码管的段选引脚。
// 数码管显示的数字0-9的编码。
int numbers[10][7] = {。
{1, 1, 1, 1, 1, 1, 0}, // 0。
{0, 1, 1, 0, 0, 0, 0}, // 1。
{1, 1, 0, 1, 1, 0, 1}, // 2。
{1, 1, 1, 1, 0, 0, 1}, // 3。
{0, 1, 1, 0, 0, 1, 1}, // 4。
{1, 0, 1, 1, 0, 1, 1}, // 5。
{1, 0, 1, 1, 1, 1, 1}, // 6。
{1, 1, 1, 0, 0, 0, 0}, // 7。
{1, 1, 1, 1, 1, 1, 1}, // 8。
{1, 1, 1, 1, 0, 1, 1} // 9。
};void setup() {。
for (int i = 0; i < 4; i++) {。
pinMode(digitPins[i], OUTPUT); }。
for (int i = 0; i < 7; i++) {。
pinMode(segmentPins[i], OUTPUT); }。
}。
void loop() {。
for (int i = 0; i < 10; i++) {。
displayNumber(i);delay(1000);}。
/*-----------------------------------------------------
方案要求:上电一个LED一直闪,四位数码管9999循环正计数
思路:用两个定时器分别控制LED和数码管
----------------------------------------------------------*/
#include
#define Uchar unsigned char //宏定义,用Uchar来代表关键词 unsigned char(无符号字符型数据)
#define Uint unsigned int //宏定义,用Uchar来代表关键词 unsigned int(无符号整型数据)
sbit seg = P2^6; //位声明,声明该位用于控制数码管的笔画.
sbit com = P2^7; //位声明,声明该位用于控制数码管的公共端.
sbit LED = P1^0; //位声明,声明该位用于控制一个LED亮灭.
Uchar displ[]= //声明数组,displ是自定义数组名,[]是叫下标的,里面本应填元素个数,但可以不填.
{0x3f,0x06,0x5b,0x4f, //这些都是叫数组的元素,按顺序排放,从左到右,从上到下.
0x66,0x6d,0x7d,0x07,
0x7f,0x6f, //这是共阴数码管,ox7f=01111111 ,如果该数(8字)是10000000则是共阳.
};
Uint number, number1, number2, qian, bai, shi, ge; //定义多个全局变量,以便后面要用到
void delay_mS (Uint k) //延时子程序,k为形参,在显示子程序里会传递实参来进行计算
{
Uint i,j; //定义两个局部变量
for(i=k; i>0; i--) //k接到实参后,如果i大于0,那么让i自减1,再执行{ }内的for语句,然后再判断i是否大于0,
{
for(j=110; j>0; j--);
} //直到i=0(不大于0),该延时子程序才算执行完成,跳出。
}
void display (Uchar digital_4, digital_3, digital_2, Uchar digital_1) //显示子程序, digital_2 和 digital_1 是形参,程序跑第二遍以后凡是调用该子程序的都会有实参传来
{
seg = 1; //笔画使能,74HC573的锁存控制端LE, 1(高电平)为输出跟随输入端变化而变化,0(低电平)为输出状态被锁存,不受输入端影
响。
P0 = displ[digital_1]; //调用数组,[shi]数组元素的下标,将十位数的笔画显示数据送出
seg = 0; //将刚送出的笔画数据锁存输出。
P0 = 0xff; //该指令的作用是消影(隐),因为P0口本身也是锁存型输出,这里等于清零,让P0口全高电平(数码管全黑)
com = 1; //共阴端使能,
P0 = 0xf7; //第一个数码管地接通点亮的数据。
com = 0; //将刚送出的共阴控制数据锁存输出。
delay_mS(5); //调用延时子程序,将以上送出的笔画和共阴控制数据延时显示。(5)是实参,传递给延时子程序的形参。
seg = 1; //下面这些指令功能同上面,只不过它送的是个位数的数据(送的是个位数数码管的显示内容)。
P0 = displ[digital_2];
seg = 0;
P0 = 0xff;
com = 1;
P0 = 0xfb;
com = 0;
delay_mS(5); //这个延时时间也就是数码管的刷新间隔时间,可换算成刷新率Hz,如果该时间太长会有闪烁感.
seg = 1;
P0 = displ[digital_3];
seg = 0;
P0 = 0xff;
com = 1;
P0 = 0xfd;
com = 0;
delay_mS(5);
seg = 1;
P0 = displ[digital_4]; //这些digital可以不分先后的,因为刷新很快,人眼分辨不出哪个先后显示.
seg = 0;
P0 = 0xff;
com = 1;
P0 = 0xfe;
com = 0;
delay_mS(5);
}
void main (void) //主程序 (函数即程序即代码)
{
TMOD = 0x01; //定义定时器的工作方式,TMOD是一个8位特功能寄存器,0x01=0000001,(方式1,16位定时器)
TH0 = 0X4c; //给定时器0装初值,高八位
TL0 = 0Xd0; //给定时器0装初值,低八位
TH1 = 0X4c; //给定时器1装初值
TL1 = 0Xd0;
EA = 1; //打开中断总允许开关,这样定时器溢出后才会进入中断服务程序
ET0 = 1; //打开定时器0中断允许,这样定时器溢出后才会进入中断服务程序
ET1 = 1; //打开定时器1中断允许,这样定时器溢出后才会进入中断服务程序
TR0 = 1; //启动定时器0 (中断入口号为1)
TR1 = 1; //启动定时器1 (中断入口号为3);两个定时器开始"同时"跑动了(实际上是TR0先跑,哪条指令在先就先执行哪条嘛)
//两个定时器进入的中断程序是不一样的,规定有对应的入口号
while(1) //主程序循环...
{ //不断调用display子程序.
display(qian, bai, shi, ge); //shi 和ge是变量,是实参,该实参是由中断程序传递过来,然后再传递给display子程序中的形参digital_2 和 digital_1.
} //也就是不断地循环重复运行display程序,display程序中的延时时间就构成了显示刷新率.
}
void T0_time (void) interrupt 1 // 中断服务程序,服务号(中断入口号)为1 (也叫中断函数)
{
TH0 = 0X4c; //进入中断后首要任务给它重装下一次要跑的时间值(所谓重装初值)
TL0 = 0Xd0; //严格来讲装初值也是要花费时间来装的,所以该方式的定时并不是很准确,如果要很准确需要用自动装初值的定时器工作方式.
number1++; //每溢出进入中断一次就进行变量number1++
if(number1 == 10) //如果加到4,说明到了所需要的延时时间,那么
{
number1 = 0; //给number赋0(清零)
LED = ~LED; //给LED状态取反, 不断重复这个中断程序就得到了LED闪的效果.
}
}
void T1_time (void) interrupt 3 // 中断服务程序,服务号(中断入口号)为3
{
TH1 = 0X4c; //初值的计算公式:例如需要20mS的定时:12X(65536-x)/11059200=0.02S;(即20mS)12是机器周期;11059200是晶振频率;0.02是要定时的时间;65536
是16位定时器最大值.
TL1 = 0Xd0; //0.02x11059200/12=18432 ; 65536-18432=47104 ; 47104转成十六进制=B800
number2++; // 那么就可写成TH1=0xB8; TL1=0x00; 提示0xB8是C51编译器里16进制的写法,不分大小写.
if(number2 == 20) //如果加到20,说明到了所需要的延时时间,(即0到59递增的速度)那么number++
{
number2 = 0; //将其清零,以便跑第二遍程序时再重新加同样的数(定同样的时间)
number++; //0-59的显示数加一
if(number == 9999) //显示的数(0-99),如果显示到99,那么 (两位数最多只能99了,再多就出错了)
{
number = 0; //清零,也就是转为显示0(从头再来),如果这里填TR0=0; TR1=0;(关闭定时器)那么到9999停止不动.
}
qian = number/1000; //千位数对1000求模
bai = number%1000/100; //百位数需对1000求余再对100求模
shi = number%100/10; //十位数,对number这个变量的当时值求模得出的数作为实参赋给主程序(68行)中的shi作为实参 (十位数)
ge = number%10; //个位数,对number这个变量的当时值求余得出的数作为实参赋给主程序中的ge作为实参 (个位数)
}
}
/***********************************
作业:
请将上面的正计数改为倒计数
************************************/