suncat0504 发表于 2019-6-18 21:52 我在外部中断INT0那里将 ET0 ET1 EX1都取反来实现中断的禁止和开启(我之前说我仿真可以实现暂停和开始,但实物不行,后来我发现是我焊接的问题,事实上仿真和实物都可以实现),但是都只能在按下暂停键后让正在实施的中断的代码全部运行完了之后才暂停,想问下怎么实现按下暂停键就将正在运行中断的实物停在那里,就是说按下暂停键后就停止在那个灯的位置(前段时间在期末考试没有时间上论坛) |
czd175711 发表于 2019-6-17 21:37 在你的代码中,我没有看到中断处理中,对其他中断做禁止和许可的操作啊 |
czd175711 发表于 2019-6-17 21:42 在我印象中,汇编语言的左移有两种,一种是含进位的,RLC A;一种是不含进位C的左移 RL A,都是循环模式。对于循环左移一次,Bit7变成Bit0;其他的,顺序左移。 但是在C语言中,只有<<左移,>>右移,是不具有循环方式的(抱歉没有说清楚),也就是说,在C语言中,使用<<一次后,最右侧Bit0补零;使用>>移位一次后,最左侧Bit7补零。 |
你暂停了之后没有保存当前的值,当开启之后丢失了当前值,还有一个就是你暂定后,只是中断停止了,但是外面的while循环还在执行LED |
1441 发表于 2019-6-17 17:28 汇编,,,我不怎么会汇编,,,而且汇编的可看性不好,,我一个小白还是先用C语言来学比较好 |
suncat0504 发表于 2019-6-17 16:36 但是loopled=0xfe 循环左移 不应该是 0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f 这样吗? |
suncat0504 发表于 2019-6-17 16:41 我现在附上完整代码了 可以帮我看看,,谢谢 |
用汇编比较简单 左移右移 |
czd175711 发表于 2019-6-17 14:19 我是给你举个在中断中禁止其他中断的例子。你的程序仿真没有问题,写入芯片后不执行,需要调试。通过管脚输出数据或者通过串口向PC发数据,来观察中间的处理过程。没有你的程序,我也只能告诉你这么做。 |
czd175711 发表于 2019-6-17 14:00 循环左移场合,字节的Bit0会自动补入0,不或上‘1’的话,会导致bit0对应的LED也被点亮。 对于数据FF,不断左移后的变化是:FE,FC, F8, F0, E0,C0,80, 00 |
suncat0504 发表于 2019-6-10 00:18 哦,,,我好像理解了,|表示的应该是或的意思吧, |
suncat0504 发表于 2019-6-13 12:50 有个问题想问,,,,为什么要用串口来实现中断?INT0的优先级是最高的,,那用INT0会不会更好,而且我小白,,,这个代码有点看不懂。 我用INT0中断去将EX1 ET0 ET1 取反 在仿真上可以实现暂停,但我将代码烧录进实物 却实现不了,想问下为什么 |
suncat0504 发表于 2019-6-10 00:18 有段代码不怎么理解 ,想问一下什么意思 // 循环左移 loopled=loopled<<1; // 最右补1,防止点亮最后一个LED loopled=loopled|1; loopled<<1// 循环左移 到最后loopled应该等于0X7F 那么最右补1 怎么能做到防止点亮最后一个LED [// 最右补1,防止点亮最后一个LED loopled=loopled|1;】这个代码是怎么理解的 |
可以先一个一个点亮试试,再整合代码逐个点亮,加油! |
我也在做这个 |
czd175711 发表于 2019-6-13 11:01 尽量不要用取反,使用明确的赋值。比如在串口中断中,禁止使用计时器0 的中断时, /*------------------------------------------------ 串口中断程序 ------------------------------------------------*/ void com_intr (void) interrupt 4 //串行中断服务程序 { unsigned char Temp; //定义临时变量 uchar i=0; ET=0; // 临时禁止Timer0的中断 if(RI) { //判断是接收中断产生 RI=0; //标志位清零 Temp=SBUF; //读入缓冲区的值 SBUF=Temp; //把接收到的值再发回电脑端 } if(TI) { //如果是发送标志位,清零 comio=~comio; TI=0; } ET0=1; // 允许Timer0的中断 } |
suncat0504 发表于 2019-6-11 22:09 应该会出错吧 |
suncat0504 发表于 2019-6-12 20:46 这个我知道,我试过用中断,但是中断里面的代码应该是什么?把总中断EA取反吗? |
初学编程的人,给你们提一个建议:一点更要养成良好的编程习惯。比如加注释,变量、函数命名方式,对其缩进等等,开始可能觉得很烦,习惯了就好了。这样自己做的东西,别人也容易理解。自己以后修改或者代码重用,也不会出现摸不到头脑的情况。 |
czd175711 发表于 2019-6-12 19:15 中断处理中控制其它中断,还需要考虑优先级的问题。比如在低级中断中控制高级中断,会出现这样的情况:低级的在执行高级中断禁止的时候,还没来得及执行禁止语句的时候,高级中断发生了。也就是说,有时候,你觉得你已经禁止某个中断了,结果实际运行中,还是出现了那个被禁止的中断被执行过。这就是优先级有高低而产生的问题,在实际应用中要加以注意。 不忙的时候,多看看原理方面的书,对工作会有很大帮助的。 |
czd175711 发表于 2019-6-12 19:15 利用中断控制位啊。建议你看看单片机原理。每个中断都有自己的控制位,比如51单片机中的ET0,ET1,ES等。通常控制位=0,就表示禁止那个中断的响应处理。控制位=1,表示允许那个中断来的时候,调用对应的中断处理。 |
数据集 发表于 2019-6-12 09:14 谢谢了,楼上的大佬已经帮我搞定了,,,谢谢 |
suncat0504 发表于 2019-6-11 22:09 那我想问大佬个问题,我想要实现用中断去控制其他中断的暂停和开始该怎么做? |
suncat0504 发表于 2019-6-10 00:18 我印象中我有做过流水灯 |
如果不能的话,我建议你改一下图 |
#include<reg52.h> #include<intrins.h> #define uint unsigned int #define uchar unsigned char #define led_8 P1 uchar m; void ys (uint x) { uchar i; while(x--) for(i=0;i<120;i++); } void main() { uchar j,k; while(1) { for(j=0;j<3;j++) { m=0x7f; k=0; while(k!=8) { m=_crol_(m,1); led_8=m; ys(500); k++; } led_8=0xff; ys(500); for(j=0;j<3;j++) { led_8=0x55; ys(500); led_8=0xaa; ys(500); } led_8=0xff; ys(500); k=0; while(k!=8) { led_8<<=1; ys(500); k++; } } } } |
4楼的写的还可以了 |
比我写的好多了,我还是个初学者 |
while语句有没有{}无所谓的。有,表示条件为真时执行一段代码块,因为执行语句多,所以用{}包起来。没有{}的话,条件为真时,执行紧邻其后的一个有效语句,哪怕是一个“;”,表示空语句,什么也不做。楼主的代码中,所有处理都放在中断处理中执行,所以主处理中什么都不做,仅仅是一个死循环罢了。 |
冰麒麟 发表于 2019-6-11 08:26 呃,,,这个我解释不了,这个代码是我老师说的 我并不理解,但他说没错的 |
感觉你的代码也有一定的问题,while(1)中无论有没有语句好像都需要{}这个吧,即使是空循坏也是需要这个的 |
文二 发表于 2019-6-10 01:38 我需要逐个点亮16个LED灯 所以要2个端口 ,直接用循环左移只能点亮一半或者2个端口一起逐个点亮 |
suncat0504 发表于 2019-6-10 00:18 很强,,,我代码写得有点差 ,,大佬你的代码很强,谢谢 |
逐个点亮不是可以用,循环左移_crol(0,1),我感觉可以用 |
我的程序中没有使用中断。改成中断的话,需要调整按钮连接的口线,连接到P3口的外部中断管脚上(INT0或者INT1),同时把程序中P3组的循环改成P1。51的外部中断的设置,参照的例子很多,也很简单。 设置中断处理后,当按钮按下时,会自动产生中断。在中断处理中执行led()函数就可以的。 |
我发给你的,没有接入LED。你只需要仿真,看到P0,P2,P3口随着按钮每按一次,只有一个口线输出0(视为点亮LED),并一直保持循环即可。 |
/** 流水灯*/ #include<reg52.h> #define uchar unsigned char #define uint unsigned int sbit button=P1^0; /* 函数申明 -----------------------------------------------*/ void delay(uint z); void led(void); /* ******************************************************************************** ** 函数名称 : main(void) ** 函数功能 : 主函数 ******************************************************************************** */ uchar loopled=0xfe; uchar flag=0; void main() { P0=loopled; P2=0xFF; P3=0xFF; while(1) { // 按钮按下了? if (button==0) { delay(200); // 等待按钮松开 while(button==0); if (button==1) { // 按钮按下又抬起 led(); } } } } // 流水灯 void led(void) { // 循环左移 loopled=loopled<<1; // 最右补1,防止点亮最后一个LED loopled=loopled|1; if (loopled==0xff) { // 一路循环完成场合,指向下一组 flag++; // 下一组最后一个LED点亮 loopled=0xFE; // 三组循环完成了,重新指向第一组 if (flag==3) { flag=0; } } // 将循环数据送给当前组 switch(flag) { case 0:// P0组 P2=0xFF; // 关闭P2组 P3=0xFF; // 关闭P3组 P0=loopled; break; case 1:// P2组 P0=0xFF; // 关闭P0组 P3=0xFF; // 关闭P3组 P2=loopled; break; case 2:// P3组 P0=0xFF; // 关闭P0组 P2=0xFF; // 关闭P2组 P3=loopled; break; } } /* ******************************************************************************** ** 函数名称 : delay(uint z) ** 函数功能 : 延时函数 ******************************************************************************** */ void delay(uint z) { uchar j; for(z;z>0;z--) for(j=100;j>0;j--); } |
tt123 发表于 2019-6-8 19:58 呃,, 左移的代码是跟老师学的,,,我要做的效果是 按一下按钮就中断去点亮下一个灯, 你能帮我改一下吗 |
逐个点亮的部份,其实不用写得那麽难看懂,你写得简单一点,方便自己,也方便他人。 建议先检查,测试一下硬件连接有没问题,然後拆分逐个点亮的代码部份,逐一调试。 |