各个端口可以用P0,P1,P2,P3表示,同时也可以用P1.1来控制详细的位,很棒了。我喜欢汇编。
$NOMOD51 ;Ax51宏汇编器控制命令,禁止预定义的8051。使编译器不使能预定义的;8051符号,避免产生重复定义的错误。
反正就是这么个意思,实际意思还是不怎么懂。
$INCLUDE (8051.MCU) ;就是字面上意思了,没什么不好懂的。
8051.mcu出奇的少呢,全是定义:
; 8051 processor definition file
; ==============================
P0 DATA 080H
SP DATA 081H
DPL DATA 082H
DPH DATA 083H
PCON DATA 087H
TCON DATA 088H
TMOD DATA 089H
TL0 DATA 08AH
TL1 DATA 08BH
TH0 DATA 08CH
TH1 DATA 08DH
P1 DATA 090H
SCON DATA 098H
SBUF DATA 099H
P2 DATA 0A0H
IE DATA 0A8H
P3 DATA 0B0H
IP DATA 0B8H
PSW DATA 0D0H
ACC DATA 0E0H
B DATA 0F0H
IT0 BIT 088H
IE0 BIT 089H
IT1 BIT 08AH
IE1 BIT 08BH
TR0 BIT 08CH
TF0 BIT 08DH
TR1 BIT 08EH
TF1 BIT 08FH
RI BIT 098H
TI BIT 099H
RB8 BIT 09AH
TB8 BIT 09BH
REN BIT 09CH
SM2 BIT 09DH
SM1 BIT 09EH
SM0 BIT 09FH
EX0 BIT 0A8H
ET0 BIT 0A9H
EX1 BIT 0AAH
ET1 BIT 0ABH
ES BIT 0ACH
EA BIT 0AFH
RXD BIT 0B0H
TXD BIT 0B1H
INT0 BIT 0B2H
INT1 BIT 0B3H
T0 BIT 0B4H
T1 BIT 0B5H
WR BIT 0B6H
RD BIT 0B7H
PX0 BIT 0B8H
PT0 BIT 0B9H
PX1 BIT 0BAH
PT1 BIT 0BBH
PS BIT 0BCH
P BIT 0D0H
OV BIT 0D2H
RS0 BIT 0D3H
RS1 BIT 0D4H
F0 BIT 0D5H
AC BIT 0D6H
CY BIT 0D7H
RESET CODE 000H
EXTI0 CODE 003H
TIMER0 CODE 00BH
EXTI1 CODE 013H
TIMER1 CODE 01BH
SINT CODE 023H
单片机中寄存器A和B区别为:使用不同、存放不同、他用不同。
一、使用不同
1、寄存器A:输入/输出指令必须通过寄存器A使用。
2、寄存器B:输入/输出指令不通过寄存器B,在乘法和除法运算中配合寄存器A使用。
二、存放不同
1、寄存器A:寄存器A用于存放参与算术或逻辑运算的低字节执作数及运算结果。
2、寄存器B:寄存器B用于存放参与算术或逻辑运算的高字节执作数及运算结果。
三、他用不同
1、寄存器A:寄存器A也可在循环和串操作中充当累计器。
2、寄存器B:寄存器B也可用作间接寻址的地址寄存器和基地址寄存器。
寄存器A应该是指 累加器A,寄存器B应该是通用寄存器B。寄存器A是专门用来放操作数和运算结果的,51单片机的所有运算几乎都要通过累加器A来实现,不通过累加器A实现不了。而寄存器B是专门为乘法和处罚设计的寄存器,用来放运算前的乘数、除数,运算后的积的低8位、余数,除此之外基本没有其他功能。
C是进位位,属于位存储器,也是布尔处理机进行位运算最常用的位寄存器,同时受某些算术、逻辑运算指令影响,表征结果的状态。
ACC就是A,是8位累加器,要具体对A上的每一位操作的时候,就要用ACC.*。
ACC.7就是ACC的第七位,比如说A的值是11011010,那么ACC.7就等于1(第七位就是左数第二位)。
OV是psw上的溢出标志位,开始为0,如果之前的运算结果溢出,OV就会变成1
SJMP 如果跳转到的标号地址距bai离当前PC所指的du地址小于256字节,zhi用SJMP。
AJMP 如果跳转到的标号地址距离当前PC所指的地址小于2K字节,用AJMP。
LJMP 如果跳转到的标号地址距离当前PC所指的地址小于64K字节,用LJMP。
ACALL是调用的子程序入口地址距离当前PC所指地址需介于0~2K,LCALL是0~64K。
AJMP 的范围是11位地址,也就是2K的空间内,占用存储空间2个字节,执行周期24个时钟周。
LJMP 的范围是16位地址,也就是64K的空间内,占用存储空间3个字节,执行周期24个时钟周期。
SJMP 的范围是8位地址,也就是256BIT的空间内,占用存储空间2个字节,执行周期24个时钟周期。
JMP一般配合DPTR使用,存储空间1个字节,执行周期24个时钟周期。一般用于多分枝选择的时候使用,比如按键处理。
ACALL,LCALL和以上说明类似,是调用指令,ACALL占用存储空间2个字节,执行周期24个时钟周期。LCALL占用存储空间3个字节,执行周期24个时钟周期。
个人觉得bai最好用的是LJMP,因为它是长转移,所以无du论程序在何处,都zhi可以跳到你要dao的地方,同样LCALL也是非常好用,它是长调用子程序,也是无论程序执行到何处,遇到它都可以调内存里任何一个位置子程序
所以我用最简单的一句话告诉你,在你需要跳转的时候就用LJMP,在你需要调程序的时候就用LCALL,用其他的仅仅是语义的问题。
1、一个8位 的微处理器CPU。
2、片内数据存储器(RAM128B/256B):用以存放可以读/写的数据,如运算的中间结果、最终结果以及欲显示的数据等。
3、片内4kB程序存储器Flash ROM(4KB):用以存放程序、一些原始数据和表格。
4、四个8位并行I/O(输入/输出)接口 P0~P3:每个口可以用作输入,也可以用作输出。
5、两个或三个定时/计数器: 每个定时/计数器都可以设置成计数方式,用以 对 外部事件进行计数,也可以设置成定时方式,并可以根据计数或定时的结果 实现计算机控制
6、一个全双工UART的串行I/O口:可实现单片机与单片机或其它微机之间串行通信。
8、五个中断源的中断控制系统。
9、具有节电工作方式:休闲方式及掉电方式。
在ROM中有六个单元具有特定功能。
0000H单元:复位时程序计数器PC所指向的单元,因此用来 存放程序中的第一条指令;
0003H单元:外部中断/INT0的矢量入口地址;
000BH单元:定时器T0溢出中断的矢量入口地址;
0013H单元:外部中断/INT1的矢量入口地址;
001BH单元:定时器T1的溢出中断矢量入口地址;
0023H单元:串行口接收、传送的中断矢量入口地址。
单片机第一条指令的两个特征:
①存放在ROM的0000H单元;
②必须是“跳转指令”以跳过下面的5个中断矢量,转到后面的真正的主程序入口0100H单元。
; Reset Vector
org 0000h
jmp Start
;====================================================================
; CODE SEGMENT
;====================================================================
org 0100h
这个就很明显是什么意思了。
每日小常识:
1、STC89C51在AT89C51的基础上加入了AD数模转换,集成程度更高;AT89C51是老式的255位单片机
2、STC89C51是宏晶公司生产;AT89C51是Atmel公司生产。
3、STC89C51可以在线编程,即有ISP功能;而AT89C51必须通过编程器编程。
4、STC89C51具有6T模式,速度更快;AT89C51是12T模式,速度较慢。
5、STC89C51集成了512或1280字节的RAM ,而AT89C51没有。
6、STC89C51有三个16位定时器;AT89C51只有两个(AT89C52是三个)。
7、STC89C51的工作电压是5.5V~3.3V;AT89C51的工作电压是5.25V~4.75V。
8、STC89C51用户的程序空间从4K到64K不等,可以选择;而AT89C51用户的程序空间是4K。
keil uvision4 只是keil公司的一个集成开发环境。目前使用Keil uVision4的产品有Keil MDK-ARM,Keil C51,Keil C166和Keil C251。而你只装了MDK_ARM,因此找不到C51的芯片
通常,我们使用keil5开发32,keil4开发51。因此用5兼容4版本最好了。
实际上keil用来编译c语言文件,Proteus来执行和调试C语言文件。
keil安装上c51包后,随便选一个51芯片,然后做就可以了。
编译是一个文件一个文件编译的。让Proteus编译C语言文件是很困难的,因此还是用keil就好了,keil仅仅用来编译hex文件而已。
led以及源码见这里:
https://www.cnblogs.com/varlxj/archive/2010/05/14/1735047.html
keil设置中文:
https://blog.csdn.net/weixin_42839965/article/details/88532269
接下来说说C语言
sbit 用于特殊功能寄存器中可位寻址的位地址。类似于C语言中的宏定义,对选定位地址进行某特殊功能的命名。
格式为:sbit 命名功能 = 位地址
然后就是类似引用的那种感觉,例如
sbit DSPORT=P1^0;
然后DSPORT直接引用P1^0的地址,然后给DSPORT赋值实际上是给P1^0赋值了,这个sbit好像一个bit的指针。
还不允许创建bit的指针。。。
直接设一个整的,然后位操作就好了。
“^”是取位符号,sbit con=P0^0,取P0口的第0位
主程序中不能再改变端口的定义了,就算是sbit也是不行的。
遍历获取值
xxxx xxxx这是1个字节。
用 char c = P1;
c再分割就好了。
遍历赋予值
char = xxxx xxxx
P1 = c 就可以了。
unsigned int index=0;
unsigned char DS_Bit_Read()
{
unsigned char c = P1;
switch (index)
{
case 0:
return ((c & 1)>0?1:0);
case 1:
return ((c & 2)>0?1:0);
case 2:
return ((c & 4)>0?1:0);
case 3:
return ((c & 8)>0?1:0);
case 4:
return ((c & 16)>0?1:0);
case 5:
return ((c & 32)>0?1:0);
case 6:
return ((c & 64)>0?1:0);
case 7:
return ((c & 128)>0?1:0);
default:
return 0; // 如果没有识别到任何命令,输出一个警告信息
}
}
void DS_Bit_Write(unsigned char c)
{
if (c > 0)
P1 = 255;
else
P1 = 0;
}