51编程
‘壹’ 我想学单片机编程,应该用什么软件啊
1、学习单片机最好从51系列开始
2、过去普遍采用汇编,但建议用目前普遍的c语言
3、开发环境用KEIL C
4、会C不一定会开发单片机,况且单片机C语言与标准的ANSI C尚有一定区别
5、掌握单片机原理是必要的,了解一些模拟元器件和集成电路也是有必要的
你可以参考我空间的一些文章。
‘贰’ 单片机编程
一个明显的区别,中断方式在程序 开头必有一个中断入口 。比如T0中断,必有ORG 000BH
AJMP 中断子程序地址标号
另外,程序里都有一些开中断的指令。如SETB EA ,SETB ET0 ,SETB TR0 等等
而查询就没这些
‘叁’ 51单片机编程
周期2MS的方波,占空比1:2,不就是1MS高电平1MS低电平?
‘肆’ 单片机编程 51单片机
假设在P1口:
loop:
mov a,p1
anl a,#0fh
mov b,a
xrl a,#03h
jz mot1 ;如果cd闭合
mov a,b
xrl a,#0ch ;如果ab闭合
jz mot2
mov a,b
xrl a,#00h ;如果abcd闭合
jz mot3
jnz err ;如果不属于上述情况
mot1:
setb p1.7
clr p1.5
ljmp next
mot2:
clr p1.7
setb p1.5
ljmp next
mot3:
setb p1.7
setb p1.5
ljmp next
err:
clr p1.7
clr p1.5
next:
limp loop
‘伍’ 51单片机用什么软件编程
开源软件mcu8051ide 功能不是一般的强,用c语言编程,界面不输给商业软件,而且提供多种模拟器件如:led 数码管,矩阵数码管(8×8)按键,矩阵按键,甚至温度传感器。开源的没有任何限制,完全免费,自动生成多种烧录文件(我们一般就用.HEX的)感觉keil c弱爆了。
安装方法,下载sdcc(mcu8051ide是基于sdcc的)和mcu 8051 ide都安装好就可以啦,头文件在sdcc的安装文件夹内(include)有些关键字要加两个连在一起的下划线比如 __interrup, __code.
头文件与keil的不通用,比如定义P0口
在keil下是: sfr P0=0x80; 在sdcc下是: __sfr __at P0 0x80; 这个P0^1的不行,但sdcc里面有很多头文件8051.h 80c51.h 80c52.h等等 基本满足要求,给stc单片机编程不用改,加一点特殊的就可以。这样优秀的开源软件不用真的是白不用啊。
‘陆’ 89c51单片机编程
97 是 P1.7的位地址,故弄玄虚。目的就是让其他人为他很牛!
我以前也遇到过一个鸟人,就喜欢这样,一个变量,用指针套了很多环,看着就恼火。
其实他这样写也不对啊!
正确的应该是这样啊:sbit _BUMP_REVERSION = 0x97; //是x而不是*号
标准的写法:sbit _BUMP_REVERSION = P1^7;
‘柒’ 单片机编程51系统的
#include <reg51.h>
#include <intrins.h>
sbit K1 = P1^4; sbit K2 = P1^5;
sbit K3 = P1^6; sbit K4 = P1^7;
void main()
{
while(1)
{
P0 = 0xff;
if(K1==0)
P0 = 0xfe;
if(K2 == 0)
P0 = 0xfd;
if(!K3)
P0 = 0xfb;
if(!K4)
P0 = 0xf7;
}
}
‘捌’ 用51单片机编程
单片机中只有一条语句是对进制调整的
DA A 对累加器A的结果进行十进制调整
如果随意对一个累加器A中的二进制数据进行“二进制转十进制”调整是没有任何实际意义的!
DA调整的对象是ADD或ADDC以后的结果,而且是BCD码相加以后才能够加以调整,否则没有实际意义!
比如,现在我想执行12D+39D也就是两个十进制数相加这样一个加法(有时候程序处理的需要,数据在单片机中是以BCD码的形式存储的,也就是12H和39H(十六进制),但我们可以人为将它们看为12D和39D(十进制),而且还希望相加以后的结果为51H,也就是说符合十进制运算规则12+39=51,而不是4BH的结果),但这样的十进制加法运算在单片机中是不能够直接实现的。因为单片机只能够执行二进制加法指令,也就是所有的运算都按照二进制中的规则进行!
于是就出现了DA调整指令!
现在12H+39H,将12H放于A中,执行 ADD A,#39H指令,则结果为4BH,这不是我们希望的51H的数据形式!!这时执行DA A 指令后,就会将A中的数据调整为51H(具体调整过程和原理你可以详细看书,如果单片机书中讲的不详细,那么微机原理中一定说的非常详细),而我们按照BCD码规则就将其看为51D,符合我们的要求!
也就是说加数和被加数都是BCD码的形式,最大也只可能是99H,也就是我们十进制数中的99,只有这样才会有实际的意义!
所以DA A指令只用于十进制BCD码加法指令以后,否则是没有实际意义的!
在单片机中数据就是以二进制存放的也可以说是以16进制存放(4位二进制就是16进制),所以一般来说在单片机只有二进制转十进制才有意义,通过单片机将十进制转二进制是没意义的。 这个一般都是我们自己把一个十进制数转成二进制再送给单片机处理。
非得编写程序的话 程序如下
----------------------------------------------------------------------
;二进制整数(2位)转换为十进制整数(组合BCD码)
;入口: R3,R4
;出口: R0
IBTD22 : MOV A,R0
PUSH A
MOV R7,#03H
CLR A
IBD221 : MOV @R0,A
INC R0
DJNZ R7,IBD221
POP A
MOV R0,A
MOV R7,#10H
IBD222 : PUSH A
CLR C
MOV A,R4
RLC A
MOV R4,A
MOV A,R3
RLC A
MOV R3,A
MOV B,#03H
IBD223 : MOV A,@R0
ADDC A,@R0
DA A
MOV @R0,A
INC R0
DJNZ B,IBD223
POP A
MOV R0,A
DJNZ
--------------------------------------------------
;二进制整数(M位)转换为十进制整数(组合BCD码)
;入口: R1,M,N
;出口: R0
IBTDMN : MOV A,R0
MOV R2,A
MOV A,R1
MOV R3,A
MOV B,N
CLR A
IBDMN1 : MOV @R0,A
INC R0
DJNZ B,IBDMN1
MOV A,M
SWAP A
RR A
CLR C
MOV R7,A
IBDMN2 : MOV A,R2
MOV R0,A
MOV A,R3
MOV R1,A
MOV B,M
IBDMN3 : MOV A,@R1
RLC A
MOV @R1,A
INC R1
DJNZ B,IBDMN3
MOV B,N
IBDMN4 : MOV A,@R0
ADDC A,@R0
DA A
JNB ACC.4,IBDMN5
SETB C
CLR ACC.4
IBDMN5 : MOV @R0,A
INC R0
DJNZ B,IBDMN4
DJNZ R7,IBDMN2
MOV A,R2
MOV R0,A
RET
----------------------------------------------------------------
BCD整数转换为二进制整数(1位)
;入口: R0(高位地址),R7
;出口: R4
IDTB1: CLR A
MOV R4,A
IDB11: MOV A,R4
MOV B,#0AH
MUL AB
ADD A,@R0
INC R0
MOV R4,A
DJNZ R7,IDB11
RET
------------------------------------------
;BCD整数转换为二进制整数(N位)
;入口: R1(高位地址),M,N
;出口: R0
IDTBMN : MOV A,R0
MOV R2,A
MOV B,N
CLR A
IDBMN1 : MOV @R0,A
INC R0
DJNZ B,IDBMN1
MOV A,R2
MOV R0,A
MOV A,M
MOV NCNT,A
IDBMN2 : MOV R7,N
CLR A
CLR F0
IDBMN3 : XCH A,@R0
MOV B,#0AH
MUL AB
MOV C,F0
ADDC A,@R0
MOV F0,C
MOV @R0,A
INC R0
MOV A,B
DJNZ R7,IDBMN3
MOV A,R2
MOV R0,A
MOV A,@R1
INC R1
ADD A,@R0
MOV @R0,A
DJNZ NCNT,IDBMN2
RET
----------------------------------------------------------
NDIV31 : MOV A,R2
MOV B,R7
DIV AB
PUSH A
MOV R2,B
MOV B,#10H
NDV311 : CLR C
MOV A,R4
RLC A
MOV R4,A
MOV A,R3
RLC A
MOV R3,A
MOV A,R2
RLC A
MOV R2,A
MOV F0,C
CLR C
SUBB A,R7
JB F0,NDV312
JC NDV313
NDV312 : MOV R2,A
INC R4
NDV313 : DJNZ B,NDV311
POP A
CLR OV
JZ NDV314
SETB OV
NDV314 : XCH A,R2
MOV R7,A
RET
‘玖’ 51单片机编程
若要将P1.0口设置为高电平,如何编写程序
前面定义 sbit P10 = P1 ^ 0;
后面 P10 = 1;
若要检测P1口上8个引脚是否全为高电平用什么语句
先配置P1口8个引脚为输入状态: P1 = 0xFF;
然后判定条件示例 if (P1 == 0xFF)
‘拾’ 51单片机的编程问题
1:C51编译器如何区分位地址和字节地址
是靠预定义实现的,比如:sfr P0 = 0x80; sbit P0_0 = 0x80;前者声明了P0端口地址位于0x80,后者说明了P0端口的bit0,即P0.0位于位地址空间0x80处。这2个0x80具有完全不同的含义,靠关键字sfr和sbit来区别。这样当程序被编译时,编译器会依此编译成相应的汇编语言。例如:
C51语句: P0 = 1;
P0声明为sfr,因此编译成:mov 80h,01h,将把0x01数据送入0x80单元,由于0x80单元物理上对应P0端口,因此,P0.0脚将输出高电平(其实是呈现高阻态,P0口独有的),其他.1-.7脚输出低电平。
C51语句: P0_0 = 1;
P0_0声明为sbit,因此编译成:setb 80h,这将把位地址空间的0x80地址的bit的值置1。这个位正是P0口的bit0,执行后,P0.0将输出高阻态。而P0.1-.7不会变化。
2:C51为什么要嵌套汇编
51单片机一个显着优点就是指令执行时间固定,因此可以适应时序要求严格的场合。例如符合ISO7816协议的cpu卡的读写,对时序要求比较严格。其实就是用io脚做出来的同步半双工串口。支持cpu卡的程序一般比较庞大,需要用c51来组织,但是由于c编译的不确定性,必须把底层程序封装成汇编语言模块嵌入到工程中。这就带来几个问题:如何声明函数、参数如何传递等。限于篇幅,不能说得很细。下面举例:
汇编程序单独保存一个文件,加入到工程中,函数如下:
_proc_a:
mov a, r7
inc a
mov r7, a
ret
用c语言在.h文件中声明: extern unsigned char proc_a(unsigned char val);
调用时形如: retvalue = proc_a(0x11);
说明:
a:汇编程序如果带参数,则需要在汇编程序前多加一个下划线。而声明它的地方不用加(伟福编译器这么要求的)。
b:函数的形参中第一参数用R7传递,函数返回值用R7返回,这是C51的通用规范。其他参数都有相应规定。函数可以返回一个位,用psw的c位返回。c:上面的语句,执行顺序是把0x11给R7,然后跳转子程序,子程序将它加1后送回。
d:函数跳转到汇编程序时,本区的R0-R7,A,B,PSW,DPTR等寄存器可以供子程序使用,不必考虑调用后是否要恢复这些常规资源。上例中,A的值被函数使用了,编程者不必恢复调用前的值。