|
發布時間: 2019-6-7 13:21
正文摘要:可以實現閃爍、輪流點亮和逐個點亮,但暫停不行(實物不能暫停,仿真可以),求大佬改一下。 #include<reg52.h> #define uchar unsigned char #define unit unsigned int void delay_ms(unsigned int); sbit ... |
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 呃,, 左移的代碼是跟老師學的,,,我要做的效果是 按一下按鈕就中斷去點亮下一個燈, 你能幫我改一下嗎 |
|
逐個點亮的部份,其實不用寫得那麼難看懂,你寫得簡單一點,方便自己,也方便他人。 建議先檢查,測試一下硬件連接有沒問題,然後拆分逐個點亮的代碼部份,逐一調試。 |