在单片机开发过程中,从硬件设计到软件设计几乎是开发者针对本系统特点亲自完成的。这样虽然可以降低系统成本,提高系统的适应性,但是每个系统的调试占去了总开发时间的2/3,可见调试的工作量比较大。单片机系统的硬件调试和软件调试是不能分开的,许多硬件错误是在软件调试中被发现和纠正的。但通常是先排除明显的硬件故障以后,再和软件结合起来调试以进一步排除故障。可见硬件的调试是基础,如果硬件调试不通过,软件设计则是无从做起。本文结合作者在单片机开发过程中体会,讨论硬件调试的技巧。
当硬件设计从布线到焊接安装完成之后,就开始进入硬件调试阶段,调试大体分为以下几步。
1 硬件静态的调试
1.1排除逻辑故障
这类故障往往由于设计和加工制板过程中工艺性错误所造成的。主要包括错线、开路、短路。排除的方法是首先将加工的印制板认真对照原理图,看两者是否一致。应特别注意电源系统检查,以防止电源短路和极性错误,并重点检查系统总线(地址总线、数据总线和控制总线)是否存在相互之间短路或与其它信号线路短路。必要时利用数字万用表的短路测试功能,可以缩短排错时间。
1.2排除元器件失效
造成这类错误的原因有两个:一个是元器件买来时就已坏了;另一个是由于安装错误,造成器件烧坏。可以采取检查元器件与设计要求的型号、规格和安装是否一致。在保证安装无误后,用替换方法排除错误。
1.3排除电源故障
在通电前,一定要检查电源电压的幅值和极性,否则很容易造成集成块损坏。加电后检查各插件上引脚的电位,一般先检查VCC与GND之间电位,若在5V~4.8V之间属正常。若有高压,联机仿真器调试时,将会损坏仿真器等,有时会使应用系统中的集成块发热损坏。
2 联机仿真调试
联机仿真必须借助仿真开发装置、示波器、万用表等工具。这些工具是单片机开发的最基本工具。
信号线是联络8031和外部器件的纽带,如果信号线连结错误或时序不对,那么都会造成对外围电路读写错误。51系列单片机的信号线大体分为读、写信号线、片选信号线、时钟信号线、外部程序存贮器读选通信号(PSEN)、地址锁存信号(ALE)、复位信号等几大类。这些信号大多属于脉冲信号,对于脉冲信号借助示波器(这里指通用示波器)用常规方法很难观测到,必须采取一定措施才能观测到。应该利用软件编程的方法来实现。例如对片选信号,运行下面的小程序就可以检测出译码片选信号是否正常。
MAIN:MOVDPTR,#DPTR
;将地址送入DPTR
MOVXA,@DPTR
;将译码地址外RAM中的内容送入ACC
NOP;适当延时
SJMPMAIN;循环
执行程序后,就可以利用示波器观察芯片的片选信号引出脚(用示波器扫描时间为1μs/每格档),这时应看到周期为数微秒的负脉冲波形,若看不到则说明译码信号有错误。
对于电平类信号,观测起来就比较容易。例如对复位信号观测就可以直接利用示波器,当按下复位键时,可以看到8031的复位引脚将变为高电平;一旦松开,电平将变低。
总而言之,对于脉冲触发类的信号我们要用软件来配合,并要把程序编为死循环,再利用示波器观察;对于电平类触发信号,可以直接用示波器观察。
下面结合在自动配料控制系统中键盘、显示部分的调试过程来加以说明。本系统中的键盘、显示部分都是由并行口芯片8155扩展而成的。8155属于可编程器件,因而很难划分硬件和软件,往往在调试中即使电路安装正确没有一定的指令去指挥它工作,也是无法发现硬件的故障。因此要使用一些简单的调试程序来确定硬件的组装是否正确、功能是否完整。在本系统中采取了先对显示器调试,再对键盘调试。
② 单片机C程序 LED流水灯的 看不懂 求解释。。
①最外层的 j for循环,用来执行8次流水(第一次、第二次...);
②内层的 i for循环,用来执行每次流水 需要执行多少步(第一次8步,第二次7步...);
③a=_crol_(a,j) 确实如LZ说的,对a 左移 j 位,不过要求带 C 左移,就是循环移位,把a^7移到a^0上,也确实已经对a 进行赋值了;
④a=a<<1,这也是左移一个位,这个移,不带C,就是把a^7踢出去,不要了,a^0补0;这个移的意义在于每次流水都会增加一颗灯,不过它必须是 低电平驱动 的LED 才有效。
执行过程简析如下:当第一次流水完成后(亮完最后一颗灯),第一次 i 循环结束,执行 i 循环内的最后一条语句带C左移,a 又回到第一颗灯状态(0xfe=1111 1110b);执行第③点的左移,此时j=0,相当于不移。再执行第④点的左移,a=0xfc(1111 1100),就变成了2颗灯;
下一个i 循环开始(第二次流水),流水步数为8-j=7(j 已经+1),a现在是2颗灯,7步后亮到最高2颗灯(a=0011 1111),经循环内最后一句带C左移,a=0111 1110,i 循环结束,执行第③点的带C左移,此时 j=1,a=1111 1100,又回到第二次流水时的起始状态。再执行第④点的左移,a=1111 1000,变成了3颗灯,下一个 i 循环开始........一直到8颗灯亮
③ 单片机的点亮一盏灯程序
MAIN: MOV P1,#11111110B;点亮P1.0所接的灯
ACALL YS ;调用延时子程序,让P1.0所接的灯亮一小段时间
MOV P1,#11111101B;点亮P1.1所接的灯
ACALL YS ;调用延时子程序,让P1.1所接的灯亮一小段时间
MOV P1,#11111011B;点亮P1.2所接的灯
ACALL YS ;调用延时子程序,让P1.2所接的灯亮一小段时间
MOV P1,#11110111B;点亮P1.3所接的灯
ACALL YS ;调用延时子程序,让P1.3所接的灯亮一小段时间
MOV P1,#11101111B;点亮P1.4所接的灯
ACALL YS ;调用延时子程序,让P1.4所接的灯亮一小段时间
MOV P1,#11011111B;点亮P1.5所接的灯
ACALL YS ;调用延时子程序,让P1.5所接的灯亮一小段时间
MOV P1,#10111111B;点亮P1.6所接的灯
ACALL YS ;调用延时子程序,让P1.6所接的灯亮一小段时间
MOV P1,#01111111B;点亮P1.7所接的灯 ACALL YS ;调用延时子程序,让P1.7所接的灯亮一小段时间
LJMP MAIN ;循环.这回用长调用指令LJMP,当程序比较长的时候就用
LJMP YS: ;延时子程序YS,功能是能让LED亮起来或者灭掉一小段时间
MOV R1,#200 ;让灯亮灭时间的长短也就是延时的长短跟#号后面的数据有关
D: MOV R2,#200 ;延时长点#号后面的数据就大点,延时短点#号后面的数据
T: MOV R3,#200 ;就小点,但#号后面最大的数据是255
DJNZ R3,$
DJNZ R2,T
DJNZ R1,D
RET ;子程序返回指令,子程序的设计一般都是因为主程序要调用它, ;调用完是要返回到主程序继续运行下一个语句的
END
④ 单片机流水灯程序
程序如下:
#include <reg52.h>
sbit led1 = P2^0;
sbit led2 = P2^1;
sbit led3 = P2^2;
sbit led4 = P2^3。
让电子信息技术与单片机技术相融合,有效提高了单片机应用效果。作为计算机技术中的一个分支,单片机技术在电子产品领域的应用,丰富了电子产品的功能,也为智能化电子设备的开发和应用提供了新的出路,实现了智能化电子设备的创新与发展。
从二十世纪九十年代开始,单片机技术就已经发展起来,随着时代的进步与科技的发展,目前该技术的实践应用日渐成熟,单片机被广泛应用于各个领域。现如今,人们越来越重视单片机在智能电子技术方面的开发和应用,单片机的发展进入到新的时期。
无论是自动测量还是智能仪表的实践,都能看到单片机技术的身影。当前工业发展进程中,电子行业属于新兴产业,工业生产中人们将电子信息技术成功运用。
⑤ 单片机C程序 LED流水灯的 看不懂 求解释。。
内循环你应当能看懂,就是完成灯流水。循环次数取决于外循环,例如第一次外循环(第1个灯)要循环8次、第二次外循环(第1、2个灯)要循环7次。
内循环执行完一遍之后,a回复到了最低位为第一个0的状态,因此要_crol_(a,j)将后续的0也都提上来。最后a
=
a<<1,是为下一次外循环做准备,即下一次将开始多点一个灯。
⑥ 单片机流水灯汇编程序看不懂,求解释...
ORG 000H //定位,使程序放在0000H处
MOV P1,#0FFH //使P1口全为高电平,八个灯全灭
L034: MOV A,#0FEH //11111110B值送入A,只使P1.0为低电平
L033: MOV P1,A //将A值送出P1口,只有D1亮
LCALL SE19 //调用延时子程序(决定每个灯亮的时间长度)
// {可在此再次(或多次)加入“LCALL SE19”使亮的时间增加一倍}
RL A //左循环位移,为了下次只使D2亮(再下次就是D3……)
SJMP L033 //跳转到L033处重新执行,使D1、D2、D3……D1轮流亮
//下面是延时程序,决定每调用一次延时多长时间
ORG 07A0H //定位,将下面的程序(延时程序段)放在07A0H处
SE19: MOV R6,#0A0H //更改#0A0H值
L036: MOV R7,#0FFH //或更改#0FFH值就可以改变其每次调用延时的时间
L035: DJNZ R7,L035
DJNZ R6,L036
RET
END
⑦ 单片机编程 彩灯闪烁
你可以将灯连接到p1口来实现( 假设有八个彩灯,且为共阳的);
1.轮流点亮 逐个点亮
MOV A,#11111110B
;先点亮连p1.0的灯,然后是p1.1的,一直到p1.7的,然后又点亮p1.0的
LOOP:
MOV P1,A
ACALL DELAY;你建一个延时子程序使灯亮一段时间
RL A
SJMP LOOP
2.间隔点亮
MOV A,#10101010B
;先点亮连p1.0,p1.2,p1.4,p1.6的灯,然后是p1.1,p1.3,p1.5,p1.7的
LOOP:
MOV P1,A
ACALL DELAY;你建一个延时子程序使灯亮保持一段时间
RL A
SJMP LOOP
3.全灭全亮
MOV A,#00000000B
;先全部点亮,然后再全灭
LOOP:
MOV P1,A
ACALL DELAY;你建一个延时子程序使灯亮保持一段时间
CPL A
SJMP LOOP
⑧ 求单片机彩灯循环控制程序
ORG0000H
AJMPMAIN
ORG0100H
MAIN:JBP2.0,m1
JBP2.1,m2
JBP2.2,m3
JBP2.3,m4
JBP2.4,m5
JBP2.5,m6
JBP2.6,m7
JBP2.7,m8
SJMPMAIN
m1:MOVR1,#02H;四亮四闪
LOOP:MOVP1,#00H
XRLA,#0AAH
MOVP1,A
CALLDELAY
DJNZR1,LOOP
SJMPMAIN
m2:MOVR1,#08H;向右闪烁
MOVA,#0FEH
LOOP1:MOVP1,A
CALLDELAY
RLA
DJNZR1,LOOP1
SJMPMAIN
m3:MOVR1,#02H;整体闪烁
LOOP2:MOVP1,#00H
CALLDELAY
MOVP1,#0FFH
CALLDELAY
DJNZR1,LOOP2
SJMPMAIN
m4:MOVR1,#08H;奇数向右闪烁
MOVA,#0AAH
LOOP3:MOVP1,A
RRA
CALLDELAY
DJNZR1,LOOP3
SJMPMAIN
m5:MOVR1,#08H;两边中间
LOOP4:MOVP1,#3CH
CALLDELAY
MOVP1,#0C3H
CALLDELAY
;MOVP1,#7EH
;CALLDELAY
;MOVP1,#0BDH
;CALLDELAY
;MOVP1,#0DBH
;CALLDELAY
;MOVP1,#0E7H
;CALLDELAY
DJNZR1,LOOP4
SJMPMAIN
m6:MOVR1,#04H
LOOP5:MOVP1,#0F0H;亮一半灭一半
CALLDELAY
MOVP1,#0FH
CALLDELAY
DJNZR1,LOOP5
JMPMAIN
m7:MOVR1,#02H;中间往两边灭
LOOP6:MOVP1,#00H
CALLDELAY
MOVP1,#18H
CALLDELAY
MOVP1,#3CH
CALLDELAY
MOVP1,#7EH
CALLDELAY
MOVP1,#0FFH
CALLDELAY
DJNZR1,LOOP6
LJMPMAIN
m8:MOVR1,#01H;双灯循环
LOOP7:MOVP1,#3FH
CALLDELAY
MOVP1,#0FCH
CALLDELAY
MOVP1,#0CFH
CALLDELAY
MOVP1,#0F3H
CALLDELAY
DJNZR1,LOOP7
JMPMAIN
DELAY:MOVR5,#10
DEL1:MOVR7,#200
DEL:MOVR6,#123
NOP
NOP
DJNZR6,$
DJNZR7,DEL
DJNZR5,DEL1
RET
就是没有数码管显示!一共八种模式!
⑨ 51单片机流水灯程序
程序如下:
#include <reg52.h>
sbit led1 = P2^0;
sbit led2 = P2^1;
sbit led3 = P2^2;
sbit led4 = P2^3;
sbit led5 = P2^4;
sbit led6 = P2^5;
sbit led7 = P2^6;
sbit led8 = P2^7;
void main()
{
int i,j;
//点亮第一个灯
led1 = 1;
led2 = 0;
led3 = 0;
led4 = 0;
led5 = 0;
led6 = 0;
led7 = 0;
led8 = 0;
//延时1秒
for(i = 0;i < 110; ++i)
{
for(j = 0; j < 1000; ++j)
{
;//什么也不做
}
}
//点亮第二个灯
led1 = 0;
led2 = 1;
led3 = 0;
led4 = 0;
led5 = 0;
led6 = 0;
led7 = 0;
led8 = 0;
//点亮剩余的灯
//省略……
while(1);
}
流水灯几点说明:
void:因为该延时函数不需要返回值,所以写为void
delay1s:该函数的函数名,命名需要符合C语言的标识符命名规则。
(): 不需要传入参数,所以括号中为空
至此我们可以把流水灯程序写为以下形式:
⑩ 80c51单片机 彩灯控制器程序
你的要求也太高了吧,还是请一个软件工程师给你做啦。我们在网上回答也没有报酬,现在设计个软件也是要很多钱的。
我有个万能跑马灯程序,有10种闪灯样式,其实你只用把灯的摆放顺序打乱也可获得想要的发光样式。
#include <REG52.H>
unsigned char RunMode;
void Delay1ms(unsigned int count)
{
unsigned int i,j;
for(i=0;i<count;i++)
for(j=0;j<120;j++);
}
unsigned char code LEDDisplayCode[] = { 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8, //0~7
0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0xFF};
void Display(unsigned char Value)
{
P3 = LEDDisplayCode[Value];
}
void LEDFlash(unsigned char Count)
{
unsigned char i;
bit Flag;
for(i = 0; i<Count;i++)
{
Flag = !Flag;
if(Flag)
Display(RunMode);
else
Display(0x10);
Delay1ms(100);
}
Display(RunMode);
}
unsigned char GetKey(void)
{
unsigned char KeyTemp,CheckValue,Key = 0x00;
CheckValue = P2&0x32;
if(CheckValue==0x32)
return 0x00;
Delay1ms(10);
KeyTemp = P2&0x32;
if(KeyTemp==CheckValue)
return 0x00;
if(!(CheckValue&0x02))
Key|=0x01;
if(!(CheckValue&0x10))
Key|=0x02;
if(!(CheckValue&0x20))
Key|=0x04;
return Key;
}
unsigned int TimerCount,SystemSpeed,SystemSpeedIndex;
void InitialTimer2(void)
{
T2CON = 0x00; //16 Bit Auto-Reload Mode
TH2 = RCAP2H = 0xFC; //重装值,初始值 TL2 = RCAP2L = 0x18;
ET2=1; //定时器 2 中断允许
TR2 = 1; //定时器 2 启动
EA=1;
}
unsigned int code SpeedCode[]={ 1, 2, 3, 5, 8, 10, 14, 17, 20, 30,
40, 50, 60, 70, 80, 90, 100, 120, 140, 160,
180, 200, 300, 400, 500, 600, 700, 800, 900,1000};//30
void SetSpeed(unsigned char Speed)
{
SystemSpeed =SpeedCode[Speed];
}
void LEDShow(unsigned int LEDStatus)
{
P1 = ~(LEDStatus&0x00FF);
P0 = ~((LEDStatus>>8)&0x00FF);
}
void InitialCPU(void)
{
RunMode = 0x00;
TimerCount = 0;
SystemSpeedIndex = 10;
P1 = 0x00;
P0 = 0x00;
P2 = 0xFF;
P3 = 0x00;
Delay1ms(500);
P1 = 0xFF;
P0 = 0xFF;
P2 = 0xFF;
P3 = 0xFF;
SetSpeed(SystemSpeedIndex);
Display(RunMode);
}
//Mode 0
unsigned int LEDIndex = 0;
bit LEDDirection = 1,LEDFlag = 1;
void Mode_0(void)
{
LEDShow(0x0001<<LEDIndex);
LEDIndex = (LEDIndex+1)%16;
}
//Mode 1
void Mode_1(void)
{
LEDShow(0x8000>>LEDIndex);
LEDIndex = (LEDIndex+1)%16;
}
//Mode 2
void Mode_2(void)
{
if(LEDDirection)
LEDShow(0x0001<<LEDIndex);
else
LEDShow(0x8000>>LEDIndex);
if(LEDIndex==15)
LEDDirection = !LEDDirection;
LEDIndex = (LEDIndex+1)%16;
}
//Mode 3
void Mode_3(void)
{
if(LEDDirection)
LEDShow(~(0x0001<<LEDIndex));
else
LEDShow(~(0x8000>>LEDIndex));
if(LEDIndex==15)
LEDDirection = !LEDDirection;
LEDIndex = (LEDIndex+1)%16;
}
//Mode 4
void Mode_4(void)
{
if(LEDDirection)
{
if(LEDFlag)
LEDShow(0xFFFE<<LEDIndex);
else
LEDShow(~(0x7FFF>>LEDIndex));
}
else
{
if(LEDFlag)
LEDShow(0x7FFF>>LEDIndex);
else
LEDShow(~(0xFFFE<<LEDIndex));
}
if(LEDIndex==15)
{
LEDDirection = !LEDDirection;
if(LEDDirection) LEDFlag = !LEDFlag;
}
LEDIndex = (LEDIndex+1)%16;
}
//Mode 5
void Mode_5(void)
{
if(LEDDirection)
LEDShow(0x000F<<LEDIndex);
else
LEDShow(0xF000>>LEDIndex);
if(LEDIndex==15)
LEDDirection = !LEDDirection;
LEDIndex = (LEDIndex+1)%16;
}
//Mode 6
void Mode_6(void)
{
if(LEDDirection)
LEDShow(~(0x000F<<LEDIndex));
else
LEDShow(~(0xF000>>LEDIndex));
if(LEDIndex==15)
LEDDirection = !LEDDirection;
LEDIndex = (LEDIndex+1)%16;
}
//Mode 7
void Mode_7(void)
{
if(LEDDirection)
LEDShow(0x003F<<LEDIndex);
else
LEDShow(0xFC00>>LEDIndex);
if(LEDIndex==9)
LEDDirection = !LEDDirection;
LEDIndex = (LEDIndex+1)%10;
}
//Mode 8
void Mode_8(void)
{
LEDShow(++LEDIndex);
}
void TimerEventRun(void)
{
if(RunMode==0x00)
{
Mode_0();
}
else if(RunMode ==0x01)
{
Mode_1();
}
else if(RunMode ==0x02)
{
Mode_2();
}
else if(RunMode ==0x03)
{
Mode_3();
}
else if(RunMode ==0x04)
{
Mode_4();
}
else if(RunMode ==0x05)
{
Mode_5();
}
else if(RunMode ==0x06)
{
Mode_6();
}
else if(RunMode ==0x07)
{
Mode_7();
}
else if(RunMode ==0x08)
{
Mode_8();
}
}
void Timer2(void) interrupt 5 using 3
{
TF2 = 0; //中断标志清除( Timer2 必须软件清标志!)
if(++TimerCount>=SystemSpeed)
{
TimerCount = 0;
TimerEventRun();
}
}
unsigned char MusicIndex = 0;
void KeyDispose(unsigned char Key)
{
if(Key&0x01)
{
LEDDirection = 1;
LEDIndex = 0;
LEDFlag = 1;
RunMode = (RunMode+1)%9;
Display(RunMode);
}
if(Key&0x02)
{
if(SystemSpeedIndex>0)
{
--SystemSpeedIndex;
SetSpeed(SystemSpeedIndex);
}
else
{
LEDFlash(6);
}
}
if(Key&0x04)
{
if(SystemSpeedIndex<28)
{
++SystemSpeedIndex;
SetSpeed(SystemSpeedIndex);
}
else
{
LEDFlash(6);
}
}
}
main()
{
unsigned char Key;
InitialCPU();
InitialTimer2();
while(1)
{
Key = GetKey();
if(Key!=0x00)
{
KeyDispose(Key);
}
}
}