蓝桥杯实验3 您所在的位置:网站首页 数码管显示屏 蓝桥杯实验3

蓝桥杯实验3

2024-06-24 03:44| 来源: 网络整理| 查看: 265

例程下载:https://github.com/xiaoengineer/lanqiano

首先得说说什么是数码管

数码管其实就是一堆发光二极管,将这些发光二极管封装在一起,每一个发光二极管做成字符的一个段,就组成了所谓的七段LED字符显示器。根据内部连接的不同,LED显示有共阴和共阳之分。共阴的适用于高电平驱动,共阳的适用于低电平驱动。由于集成电路的高电平输出电流小,而低电平输出电流相对比较大,所以集成电路直接驱动LED时,较多采用低电平的驱动方式。

知道了这些就可以控制数码管了:首先控制位选,指定数字是在哪一位数码管上显示,禁止位选使能,之后是段选,控制数码管显示什么,禁止段选使能。这样就完成任务了。

下面是静态显示,控制一个数字

#include typedef unsigned int u16; typedef unsigned char u8; void close() { P2 = (P2 & 0X1F) | 0XA0; P0 = 0XAF; P2 = 0x1f; //关闭蜂鸣器,继电器 } void main() { close(); P2 = (P2 & 0X1F) | 0XC0; //这个是位选使能,是不是感觉和普通的 //开发板不一样?那是由于开发板的设计决定的 //这样做是可以保证我可以修改我想要的位而保证 //其他位不变 P0 = 0X01; //位选,选第一个位 P2 = P2 & 0X1F; //禁止使能 P2 = (P2 & 0X1F) | 0XE0; //这个是段选,也不太一样,理由同上 P0 = 0xC0; //段选,显示一个数 P2 = 0X1F; while(1); }

下面这个是动态显示,何为动态显示?动态显示就是利用人眼的视觉暂留(这个仿真的不太好),闪动地播放数字。

先说一下共阳的段位表(0~F)

0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E

我将以两种方式来实现0 ~9999的数字显示(使用定时器)

方式一:

#include typedef unsigned int u16; typedef unsigned char u8; u8 seg_ment[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E}; //定义段位 u8 seg_bit[] = {0x80, 0x40, 0x20, 0x10}; //定义位选 u16 count, sec_flag; void close() { P2 = (P2 & 0X1F) | 0XA0; P0 = 0XAF; P2 = P2 & 0X1F; } void delay(u8 ms) { u8 i, j; for(i = ms; i > 0; i --) for(j = 114; j > 0; j --); } void led_show(u16 number) { /*这种处理数字的方法很简单,C语言课上老师应该都讲过*/ u16 kilobit = number / 1000; u16 hundreds_place = number % 1000 / 100; u16 decade = number % 1000 % 100 / 10; u16 unit = number - (kilobit * 1000 + hundreds_place * 100 + decade * 10); /*下面是显示函数*/ /*显示个位*/ P2 = (P2 & 0X1F) | 0XC0; P0 = seg_bit[0]; P2 = P2 & 0X1f; P2 = (P2 & 0X1F) | 0XE0; P0 = seg_ment[unit]; P2 = P2 & 0X1f; delay(10); /*显示十位*/ P2 = (P2 & 0X1F) | 0XC0; P0 = seg_bit[1]; P2 = P2 & 0X1f; P2 = (P2 & 0X1f) | 0XE0; P0 = seg_ment[decade]; P2 = P2 & 0X1f; delay(10); /*显示百位*/ P2 = (P2 & 0X1f) | 0XC0; P0 = seg_bit[2]; P2 = P2 & 0X1f; P2 = (P2 & 0X1F) | 0XE0; P0 = seg_ment[hundreds_place]; P2 = P2 & 0x1f; delay(10); /*显示千位*/ P2 = (P2 & 0X1F) | 0XC0; P0 = seg_bit[3]; P2 = P2 & 0X1f; P2 = (P2 & 0X1F) | 0XE0; P0 = seg_ment[kilobit]; P2 = P2 & 0X1f; delay(10); } void Timer0Init(void) //100微秒@12.000MHz { AUXR &= 0x7F; //定时器时钟12T模式 TMOD &= 0xF0; //设置定时器模式 TMOD |= 0x01; //设置定时器模式 TL0 = 0x9C; //设置定时初值 TH0 = 0xFF; //设置定时初值 TF0 = 0; //清除TF0标志 TR0 = 1; //定时器0开始计时 EA = 1; ET0 =1; } void main() { u16 sec; close(); Timer0Init(); while(1) { if(sec_flag) { sec_flag = 0; if(sec < 9999) { sec ++; led_show(sec); } else sec = 0; } } } void interruptTimer0() interrupt 1 { TL0 = 0x9C; //设置定时初值 TH0 = 0xFF; //设置定时初值 count ++; if(count > 100) { count = 0; sec_flag = 1; } }

方法二:

#include typedef unsigned int u16; typedef unsigned char u8; u8 seg_ment[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E}; //定义段位 u8 led_buff[] = {0xff, 0xff, 0xff, 0xff};//确保在上电的时候不亮 u16 count, sec_flag; void close() { P2 = (P2 & 0X1F) | 0XA0; P0 = 0XAF; P2 = P2 & 0X1F; } void delay(u8 ms) { u8 i, j; for(i = ms; i > 0; i --) for(j = 114; j > 0; j --); } void Timer0Init(void) //100微秒@12.000MHz { AUXR &= 0x7F; //定时器时钟12T模式 TMOD &= 0xF0; //设置定时器模式 TMOD |= 0x01; //设置定时器模式 TL0 = 0x9C; //设置定时初值 TH0 = 0xFF; //设置定时初值 TF0 = 0; //清除TF0标志 TR0 = 1; //定时器0开始计时 EA =1; ET0 =1; } /*这个函数使用来显示的*/ void led_scan() { static u8 index = 0; //这个静态变量使用来自动移位的 P2 = (P2 & 0x1f) | 0xe0; P0 = 0XFF; //这个是消影 P2 = P2 & 0X1F; delay(5); P2 = (P2 & 0X1F) | 0XC0; P0 = 0X80 >> index; //这个就实现了自动移位 P2 = 0x1f; P2 = (P2 &0x1f) | 0xe0; P0 = led_buff[index]; P2 = P2 & 0X1F; if(index < 3) index ++; else index = 0; } /*这个函数是用来处理数据的,用了缓存的思想*/ void show_number(u16 dat) { char i; u8 buf[4]; for(i = 0; i < 4; i ++) { buf[i] = dat % 10; dat = dat / 10; //将数字是各个位分离出来并存入缓存 } for(i = 3; i > 0; i --) { if(buf[i] == 0) //如果临时缓存区里代表高位的没有数字 led_buff[i] = 0xff; //那么就为0xff,否则就可以正式填入数据 else break; } for(; i >= 0; i --) { led_buff[i] = seg_ment[buf[i]]; } } void main() { u16 sec; close(); Timer0Init(); while(1) { if(sec_flag) { sec_flag = 0; if(sec < 9999) { sec ++; show_number(sec); led_scan(); } else sec = 0; } } } void T0_interrput() interrupt 1 { TL0 = 0x9C; //设置定时初值 TH0 = 0xFF; //设置定时初值 count ++; if(count > 100) { count = 0; sec_flag = 1; } }

两种方法各有好处,以自己而定。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有