十天学会单片机Day1点亮数码管(数码管、外部中断、定时器中断)
1.引脚定义
标号 | 引脚 | 第二功能 | 说明 |
P3.0 | 10 | RXD | 串行输入口 |
P3.1 | 11 | TXD | 串行输出口 |
P3.2 | 12 | INT0(上划线) | 外部中断0 |
P3.3 | 13 | INT1(上划线) | 外部中断1 |
P3.4 | 14 | T0 | 定时器/计数器0 外部输入端 |
P3.5 | 15 | T1 | 定时器/计数器1 外部输入端 |
P3.6 | 16 | WR(上划线) | 外部数据存储器写脉冲 |
P3.7 | 17 | RD(上划线) | 外部数据存储器读脉冲 |
XTAL1(19脚) XTAL2(18脚):外接时钟引脚。XTAL1为片内震荡电路的输入端,XTAL2为片内震荡电路的输出端。
8051时钟两种方式:①片内时钟震荡,两引脚外接晶振和震荡电容。
②外部时钟方式,XTAL1接地,外部时钟信号从XTAL2脚输入。
RST(9脚):单片机复位引脚。当输入连续两个机器周期以上高电平时为有效。复位后程序计数器PC=0000H,读取第一条指令码。即从头开始执行程序。
ALE(30脚):在没有外部存储器期间,ALE以1/6振荡周期频率输出(6分频),当访问外部存储器时,以1/12振荡周期输出(12分频)。
EA(上划线)(31脚):接高电平时,单片机读取内部程序存储器。接低电平,单片机直接读取外部(ROM)。(板子上直接接高)
P0口(39~32脚):双向8位三态I/O口,早期51芯片内部无上拉电阻,为高阻态,需外部接上拉电阻。
P1口(1~8脚):准双向8位I/O口,之所以称它为"准双向",是因为改口作为输入使用前,要先向该口进行写1操作,有个"准"备过程,称为准双向口。
P2口(21~28脚):准双向8位I/O口。
P3口(10~17脚):准双向8位I/O口。
2.复位电路
按键按下,RST=5V,按键时长大于两个时钟周期,则复位。
上电自动复位:上电瞬间,电容充电,之后电容放电,τ = √(RC) >两个时钟周期 ,自动复位。
3.晶振
非极性电容,上电帮助晶振起振。12M左右 30pf,6M左右20pf。具体参考厂家提供的晶振要求负载电容选值。(Day0有详细介绍)
4.数码管
开发板中用的为共阴极。即WE选信号给低,则导通(WE提供一个GND作用)。
利用74HC573锁存器的锁存功能。(详细见Day0 ⑤锁存器),先控制位选信号P2.7口高,选定哪个数码管,后P2.7低锁存。再控制段选信号P2.6高,亮什么数字后,P2.6低锁存。
//共阴极数码管静态显示1
#include <reg52.h>
sbit DUAN = P2^;
sbit WE = P2^; int main()
{
WE = ; //打开WE选信号
P0 = 0xDF; //选WE6的数码管,给低,其余给高
WE = ; //关闭WE选信号
DUAN = ; //打开段选信号
P0 = 0x06; //亮1,即bc接高,其余低
DUAN = ; //关闭段选信号 return ;
}
超级亮,但是别的数码管有淡淡的光,以下进行改进
//共阴极数码管静态显示1 防干扰
#include <reg52.h>
sbit DUAN = P2^;
sbit WE = P2^; int main()
{
WE = ;
P0 = 0xDF;
WE = ;
P0 = 0xFF; //关闭所有显示,防止打开段选后发生混乱
DUAN = ;
P0 = 0x06;
DUAN = ;
P0 = 0xFF; //关闭所有显示,防止打开位选后发生混乱 return ;
}
接下来是数码管的动态扫描,其实是一个个显示,由于频率太快,人眼无法识别,达到目的。
//共阴极数码管动态显示
#include <reg52.h>
sbit DUAN = P2^;
sbit WE = P2^;
unsigned char DuanTable[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,
0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
unsigned char WeTable[] = {0xFE,0xFD,0xFB,0xF7,0xEF,0xDF};
void delayms(unsigned int n);
int main()
{
unsigned int i = ;
while()
{
for(i = ; i < ; i++) {
DUAN = ;
P0 = DuanTable[i+];
DUAN = ;
P0 = 0xFF;
WE = ;
P0 = WeTable[i];
WE = ;
P0 = 0xFF;
delayms();
}
}
return ;
} void delayms(unsigned int n) //误差 -0.651041666667us
{
unsigned char a,b;
unsigned int i;
for(i = ; i < n; i++) {
for(b=;b>;b--)
for(a=;a>;a--);
}
}
5.中断
52单片机共有6个中断源
INT0:外部中断0.由P3.2端口线引入,低电平或下降沿引起。
INT1:外部中断1.由P3.3端口线引入,低电平或下降沿引起。
T0:定时器/计数器0中断,由T0计数器计满回零引起。
T1:定时器/计数器1中断,由T1计数器计满回零引起。
T2:定时器/计数器2中断,由T2计数器计满回零引起。
TI/RI:串行口中断,串行端口完成一帧字符发送/接收后引起。
中断源 | 默认中断级别 | 序号(C语言用) | 入口地址(汇编语言用) |
INT0 外部中断0 | 最高 | 0 | 0003H |
T0 定时器/计数器0中断 | 第2 | 1 | 000BH |
INT1 外部中断1 | 第3 | 2 | 0013H |
T1 定时器/计数器1中断 | 第4 | 3 | 001BH |
TI/RI 串行口中断 | 第5 | 4 | 0023H |
T2 定时器/计数器2中断 | 最低 | 5 | 002BH |
位序号
|
D7
|
D6
|
D5
|
D4
|
D3
|
D2
|
D1
|
D0
|
说明
|
全局中断位
|
无效位
|
定时/计数2
(52单片机)
|
串行口中断
|
定时/计数1
|
外部中断1
|
定时/计数0
|
外部中断0
|
位符号(写程序时可直接引用)
|
EA
|
--
|
ET2
|
ES
|
ET1
|
EX1
|
ET0
|
EX0
|
位地址
|
AFH
|
--
|
ADH
|
ACH
|
ABH
|
AAH
|
A9H
|
A8H
|
位序号 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
说明 | 无效位 | 无效位 | 无效位 | 串行口中断优先级控制位 | 定时器/计数器1中断优先级控制位 | 外部中断1中断优先级控制位 | 定时器/计数器0中断优先级控制位 | 外部中断0中断优先级控制位 |
位符号 | -- | -- | -- | PS | PT1 | PX1 | PT0 | PX0 |
位地址 | -- | -- | -- | BCH | BBH | BAH | B9H | B8H |
位序号 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
位符号 | GATE | C/T(上划线) | M1 | M0 | GATE | C/T(上划线) | M1 | M0 |
定时器1 | 定时器0 |
单片机复位时全部清零。不可进行位寻址。
GATE:
GATE = 0 定时器/计数器启动与停止仅受TCON寄存器中TRX(X=0,1)来控制。
C/T(上划线):定时器模式和计数器模式选择位
C/T=0时为定时模式: 加1计数器对脉冲f进行计数,每来一个脉冲,计数器加1,直到计时器TFx满溢出。
C/T=1时为计数模式: 加1计数器对来自输入引脚T0(P3.4)和T1(P3.5)的外信号脉冲进行计数,每来一个脉冲,计数器加1,直到计时器TFx满溢出。
M1
|
M0
|
工作方式
|
功能说明
|
0
|
0
|
方式0
|
13位定时器/计数器
|
0
|
1
|
方式1
|
16位定时器/计数器
|
1
|
0
|
方式2
|
自动重载8位定时器/计数器
|
1
|
1
|
方式3
|
T0分为2个8位独立计数器,T1无方式3
|
位序号 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
位符号 | TF1 | TR1 | TF0 | TR0 | IE1 | IT1 | IE0 | IT0 |
位地址 | 8FH | 8EH | 8DH | 8CH | 8BH | 8AH | 89H | 88H |
定时器/计数器控制 | 外部中断控制 |
//外部中断0 低电平触发
#include <reg52.h>
sbit DUAN = P2^;
sbit WE = P2^;
unsigned char DuanTable[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,
0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
unsigned char WeTable[] = {0xFE,0xFD,0xFB,0xF7,0xEF,0xDF};
void delayms(unsigned int n);
int main()
{
unsigned int i = ;
EA = ;//打开总中断
EX0 = ;//打开外部中断0中断
//IT0 = 0; 电平触发 由于TCON在复位时自动清零,所以可以省略
while()
{
for(i = ; i < ; i++) {
DUAN = ;
P0 = DuanTable[i+];
DUAN = ;
P0 = 0xFF;
WE = ;
P0 = WeTable[i];
WE = ;
P0 = 0xFF;
delayms();
}
}
return ;
} void delayms(unsigned int n) //误差 -0.651041666667us
{
unsigned char a,b;
unsigned int i;
for(i = ; i < n; i++) {
for(b=;b>;b--)
for(a=;a>;a--);
}
} void exter0() interrupt //中断函数无需在main前声明 中断全部显示0 P3,2口INT0
{
int i = ;
for(i = ; i < ; i++) {
DUAN = ;
P0 = DuanTable[];
DUAN = ;
P0 = 0xFF;
WE = ;
P0 = WeTable[i];
WE = ;
P0 = 0xFF;
delayms();
}
}
中断ing
//定时器0中断 方式1 中断显示0
#include <reg52.h>
sbit DUAN = P2^;
sbit WE = P2^;
unsigned char DuanTable[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,
0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
unsigned char WeTable[] = {0xFE,0xFD,0xFB,0xF7,0xEF,0xDF};
unsigned int t = ;
void delayms(unsigned int n);
int main()
{
unsigned int i = ;
TMOD = 0x01; //TMOD不能位寻址 定时器0工作方式1
TH0 = ( - ) / ;
TL0 = ( - ) % ;
EA = ;//打开总中断
ET0 = ;//打开定时器0中断
TR0 = ;
while()
{
for(i = ; i < ; i++) {
DUAN = ;
P0 = DuanTable[i+];
DUAN = ;
P0 = 0xFF;
WE = ;
P0 = WeTable[i];
WE = ;
P0 = 0xFF;
delayms();
}
if(t >= ) {
for(i = ; i < ; i++) {
DUAN = ;
P0 = DuanTable[];
DUAN = ;
P0 = 0xFF;
WE = ;
P0 = WeTable[i];
WE = ;
P0 = 0xFF;
delayms();
}
if(t >= )
t = ;
}
}
return ;
} void delayms(unsigned int n) //误差 -0.651041666667us
{
unsigned char a,b;
unsigned int i;
for(i = ; i < n; i++) {
for(b=;b>;b--)
for(a=;a>;a--);
}
} void T0_Time() interrupt //中断函数无需在main前声明 中断全部显示0 P3,2口INT0
{
TH0 = ( - ) / ;
TL0 = ( - ) % ;
t++;
}
practice:
59s循环计时。
//60s倒计时 定时器0中断+数码管显示
#include <reg52.h>
sbit DUAN = P2^;
sbit WE = P2^;
unsigned char DuanTable[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,
0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
unsigned char WeTable[] = {0xFE,0xFD,0xFB,0xF7,0xEF,0xDF};
unsigned int t = , num = ;
void delayms(unsigned int n);
int main()
{
unsigned int i = ;
TMOD = 0x01; //TMOD不能位寻址 定时器0工作方式1
TH0 = ( - ) / ;
TL0 = ( - ) % ;
EA = ;//打开总中断
ET0 = ;//打开定时器0中断
TR0 = ;
while()
{
//十位数
DUAN = ;
P0 = DuanTable[num/];
DUAN = ;
P0 = 0xFF;
WE = ;
P0 = WeTable[];
WE = ;
P0 = 0xFF;
delayms(); //个位数
DUAN = ;
P0 = DuanTable[num%];
DUAN = ;
P0 = 0xFF;
WE = ;
P0 = WeTable[];
WE = ;
P0 = 0xFF;
delayms(); }
return ;
} void delayms(unsigned int n) //误差 -0.651041666667us
{
unsigned char a,b;
unsigned int i;
for(i = ; i < n; i++) {
for(b=;b>;b--)
for(a=;a>;a--);
}
} void T0_Time() interrupt //中断函数无需在main前声明 中断全部显示0 P3,2口INT0
{
TH0 = ( - ) / ;
TL0 = ( - ) % ;
t++;
if(t >= ) {
num--;
t = ;
} if(num == )
num = ;
}
十天学会单片机Day1点亮数码管(数码管、外部中断、定时器中断)的更多相关文章
- 十天学会单片机Day0点亮LED (锁存器、三极管、继电器)
C51常用的数据类型 数据类型 关键字 所占位数 表示数范围 无符号字符型 unsigned char 8 0~255 有符号字符型 char 8 -128~127 无符号整型 unsigned in ...
- 《十天学会单片机和C语言编程》
<十天学会单片机和C语言编程> 大家注意了这个文件只有最新版迅雷可以下载,下面的lesson几就是第几课.点击右键使用迅雷下载. ed2k://|file|[十天学会单片机和C语言编程]. ...
- 十天学会单片机Day4串行口通信
并行与串行基本通信方式 1.并行通信方式 通常是将数据字节的各位用多条数据线同时进行传送. 并行通信控制简单.传输速度快:由于传输线较多,长距离传送时成本高且接收方的各位同时接收存在困难. 2.串行通 ...
- 十天学会单片机Day3 D/A与A/D转换器
D/A转换器 1.二进制权电阻网络型D/A转换器 基准电压Vref 数据D(d3d2d1d0) 输出模拟电压V0 i0 = Vref/8R i1 = Vref/4R i2 = Vref/ ...
- 十天学会单片机Day2键盘检测(独立键盘、矩阵键盘)
1.键盘的分类 编码键盘:键盘上闭合键的识别由专用的硬件编码器实现,并产生键编码号或键值的称为编码键盘,如计算机键盘 非编码键盘:靠软件编程来识别的称为非编码键盘.独立键盘.矩阵键盘 2.按键消抖 ...
- 十天学会单片机Day5 IIC总线AT2402芯片(EEPROM)应用
1.采用串行总线技术可以使系统的硬件设计大大简化.系统的体积减小.可靠性提高.同时,系统的更改和扩充极为容易. 常用的串行扩展总线有: IIC (Inter IC BUS)总线.单总线(1-WIRE ...
- 十天学会单片机Day6 学会看数据手册 (IIC总线PCF859芯片( A/D D/A)应用)
1.实际电路 2.引脚图 3.地址 高四位为固定地址1001,A2A1A0可编程地址,通过观察实际电路,可知A2A1A0 为000.最低位为读写为,1为读,0为写. 4.控制字 控制寄存器的高半字节用 ...
- 十年学会编程 著者: Peter Norvig 翻译: Dai Yuwen
为何人人都这么着急? 信步走进任何一家书店,你会看到名为<如何在7天内学会Java>的书,还有各 种各样类似的书: 在几天内或几小时内学会Visual Basic, Windows, In ...
- PHP学习过程_Symfony_(3)_整理_十分钟学会Symfony
这篇文章主要介绍了Symfony学习十分钟入门教程,详细介绍了Symfony的安装配置,项目初始化,建立Bundle,设计实体,添加约束,增删改查等基本操作技巧,需要的朋友可以参考下 (此文章已被多人 ...
随机推荐
- Android-ImageView.ScaleType
ImageView的Scaletype决定了图片在View上显示时的样子,如进行何种比例的缩放,及显示图片的整体还是部分,等等. 设置的方式包括: 1. 在layout xml中定义android:s ...
- HDU2063_过山车_C++
题目:http://acm.hdu.edu.cn/showproblem.php?pid=2063 又是一道二分图匹配的裸题,直接上匈牙利算法 注意一点它末尾的0结束,是标志着有多组数据……坑…… # ...
- 用github pages展示你的静态网页,多项目支持
我看到有分享用github pages来做博客的,不过我并不想挂博客在上面,我只是想将我的一些作品挂上去,然后链接到我的简历里,这样HR可以直接看到. 首先是最基本的操作,在github上创建一个新的 ...
- 国内外CDN服务商CNAME特征串调研
总结 此篇博文给特定需求的人群使用,通过CNAME的某些特征串,确定其使用的是哪家CDN,大多是国外的CDN,国内的CDN厂商只有几个,格式为:[来源地址]+[截图]+[猜测的特征串],整体博文较长, ...
- 利用KeyVault来加强存储Azure Storage访问密钥管理
很多时候管理Azure的存储账号我们都需要通过下面的界面管理访问密钥,大部分情况下通过密钥的轮替使用更新就可以做到安全管理了. 但是很多时候存储账号的Key就会不小心分发到开人员.测试人员.和管理员手 ...
- 慕课网-安卓工程师初养成-2-12 如何在Java中使用注释
来源:http://www.imooc.com/code/1274 在编写程序时,经常需要添加一些注释,用以描述某段代码的作用. 一般来说,对于一份规范的程序源代码而言,注释应该占到源代码的 1/3 ...
- 查询数据库中表或视图或存储过程的数量 sql 语句
如果一个数据库中表的数量较多的话,那么在统计数据库中表的数量或视图或存储过程的数量时,如果还有一个一个去数,那就太麻烦了,其实可以通过 sql 语句来查询的,sql 语句的查询方法如下: sql se ...
- note name
谦谦君子:借用<周易·谦>:“初六,谦谦君子,用涉大川,吉.” 温润如玉:化用<诗经·卫风·淇奥>“有匪君子,如切如磋,如琢如磨”之义.
- Digest [IAB_SRI_Online_Advertising_Effectiveness]
http://www.pwc.com/en_GX/gx/entertainment-media/pdf/IAB_SRI_Online_Advertising_Effectiveness_v3.pdf
- C和C++混合编译
关于extern_C 通常,在C语言的头文件中经常可以看到类似下面这种形式的代码: #ifdef __cplusplus extern "C" { #endif /**** som ...