久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 6208|回復: 4
收起左側

51單片機定時中斷與主循環函數執行問題

[復制鏈接]
ID:566127 發表于 2019-6-22 19:29 | 顯示全部樓層 |閱讀模式
顯示函數和按鍵檢測放在主循環里,因為中斷隨時在發生,按鍵檢測和顯示就經常被打斷,按鍵有經常檢測不到,顯示有更新的話,變換很慢。而放在中斷里的話,按鍵檢測倒是沒有問題,顯示更新也快了,但是由于顯示需要計算耗費不少時間,導致中斷不準,輸出波形也就變了。。。

單片機源程序如下:
  1. #include <reg52.h>
  2. #define uchar unsigned char
  3. #define uint unsigned int
  4. uchar code Sin[]={"Sine      "};
  5. uchar code Squ[]={"Square    "} ;
  6. uchar code Tri[]={"Triangle  "};
  7. uchar code No[]={"No Signal out "};
  8. uchar code Wave[]={"Wave: "};
  9. uchar code Fre[]={"f="};
  10. uchar code vpp1[]={"V="};
  11. uint vpp;
  12. uint freq;
  13. uchar i;
  14. sbit RS = P1^0;                                                                                //數據/命令選擇端(H/L)
  15. sbit RW = P1^1;                                                                                //數/寫選擇端(H/L)      
  16. sbit EN = P1^2;                                                                                //使能信號  
  17. float  k=0.4;
  18. uint peri=500;
  19. uchar key_wave=1;//鍵值
  20. unsigned long c;
  21. sbit key1=P2^0;//波形切換按鈕
  22. sbit key2=P2^1;//頻率加
  23. sbit key3=P2^2;//頻率減
  24. sbit key4=P2^3;//幅值加
  25. sbit key5=P2^4;//幅值減

  26. /**************定義數組產生正弦波 64個點******************/
  27. uchar code sine1[]=
  28. {
  29. 0x80,0x8d,0x99,0xa5,0xb1,0xbc,0xc7,0xd1,
  30. 0xda,0xe3,0xea,0xf1,0xf6,0xfa,0xfd,0xff,
  31. 0xff,0xff,0xfd,0xf9,0xf5,0xef,0xe9,0xe1,
  32. 0xd8,0xcf,0xc5,0xba,0xae,0xa2,0x96,0x89,
  33. 0x80,0x72,0x66,0x5a,0x4e,0x43,0x38,0x2e,
  34. 0x25,0x1c,0x15,0x0e,0x09,0x05,0x02,0x00,
  35. 0x00,0x00,0x02,0x06,0x0a,0x10,0x16,0x1e,
  36. 0x27,0x30,0x3a,0x45,0x51,0x5d,0x69,0x76
  37. };
  38. /**************定義數組產生方波 64個點******************/
  39. uchar code Square1[]=
  40. {
  41. 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
  42. 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
  43. 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
  44. 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
  45. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  46. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  47. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  48. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  49. };
  50. /**************定義數組產生三角波 64個點******************/
  51. uchar code Triangle1[]=
  52. {
  53. 0xff,0xf7,0xef,0xeb,0xde,0xd6,0xce,0xc5,
  54. 0xbd,0xb5,0xad,0xa4,0x9c,0x94,0x8c,0x84,
  55. 0x76,0x73,0x6b,0x63,0x5a,0x52,0x4a,0x42,
  56. 0x39,0x31,0x29,0x21,0x19,0x10,0x08,0x00,
  57. 0x00,0x08,0x10,0x19,0x21,0x29,0x31,0x39,
  58. 0x42,0x4a,0x52,0x5a,0x63,0x6b,0x73,0x76,
  59. 0x84,0x8c,0x94,0x9c,0xa4,0xad,0xb5,0xbd,
  60. 0xc5,0xce,0xd6,0xde,0xeb,0xef,0xf7,0xff
  61. };

  62. void Delayms(unsigned int n)

  63. {

  64. unsigned int i,j;

  65. for(j=n;j>0;j--)

  66. for(i=112;i>0;i--);

  67. }

  68. //………………………………定時器初始化…………………………………//
  69. void init_Timer0()
  70. {
  71.    TMOD=0x22;
  72.    TH0 = (unsigned int)(65536-peri)/256;
  73.    TL0 = (unsigned int)(65536-peri)%256;    //確定頻率
  74.   TR0=1;
  75.    ET0=1;
  76.    EA=1;//開中斷
  77. }


  78. /***************************
  79. 測忙函數
  80. *************************/
  81. uchar Busy_Check()
  82. {
  83.         uchar LCD_Status;
  84.         RS=0;  //        寄存器選擇
  85.         RW=1; //讀狀態寄存器
  86.         EN=1;  // 開始讀
  87.         
  88.         Delayms(1);
  89.         LCD_Status=P3;//P3作為輸出口
  90.         EN=0;
  91.         return  LCD_Status;
  92. }
  93. /***************************
  94. 寫入字符
  95. *************************/

  96. void Write_LCD_Command(uchar cmd)
  97. {
  98.            while((Busy_Check()&0x80)==0x80);   //忙等待
  99.            RS=0;  //選擇命令寄存器
  100.            RW=0;  //寫
  101.            EN=0;
  102.            P3=cmd;
  103.            EN=1;
  104.           Delayms(1);
  105.            EN=0;
  106. }
  107. /***************************
  108. 寫入數據
  109. *************************/
  110. void Write_LCD_Data(uchar dat)
  111. {
  112.          while((Busy_Check()&0x80)==0x80);   //忙等待        
  113.           RS=1;
  114.           RW=0;
  115.           EN=0;
  116.           P3=dat;
  117.           EN=1;
  118.           Delayms(1);
  119.           EN=0;        
  120. }
  121. /***************************
  122. 初始化函數
  123. *************************/
  124. void Init_LCD()
  125. {               
  126.         Write_LCD_Command(0x38);
  127.         Delayms(1);
  128.         Write_LCD_Command(0x01); //清屏
  129.         Delayms(1);
  130.         Write_LCD_Command(0x06); //字符進入模式:屏幕不動,字符后移
  131.         Delayms(1);
  132.         Write_LCD_Command(0x0C); //顯示開、關光標
  133.         Delayms(1);
  134.         for (i=0;i<sizeof(Wave);i++)//----顯示WAVE:
  135.                 {
  136.                         Write_LCD_Data(Wave[i]);
  137.                         Delayms(1);
  138.                 }
  139.             Write_LCD_Command(0x80+0x40);//----顯示freq:
  140.      Delayms(1);
  141.     for (i=0;i<sizeof(Fre);i++)
  142.                 {
  143.                         Write_LCD_Data(Fre[i]);
  144.                         Delayms(1);
  145.                 }
  146.                  Write_LCD_Command(0xc0+8);//----顯示vpp:
  147.      Delayms(1);
  148.     for (i=0;i<sizeof(vpp1);i++)
  149.                 Write_LCD_Data(vpp1[i]);
  150.                         Delayms(1);
  151.                
  152.         
  153.         
  154. }

  155. /***************************
  156. 寫入頻率  成功
  157. *************************/
  158. void Write_freq(uint k)
  159. {
  160.         uchar bai,shi,ge;
  161.         bai=k/100%10;
  162.         shi=k/10%10;
  163.         ge=k%10;
  164.   Write_LCD_Command(0xc0+2);
  165.         Write_LCD_Data(0x30+bai);
  166.         Write_LCD_Data(0x30+shi);
  167.         Write_LCD_Data(0x30+ge);
  168.         Write_LCD_Data(0x48);//代表H
  169.         Write_LCD_Data(0x5a);//代表Z
  170. }
  171. /***************************
  172. 寫入幅值       成功
  173. *************************/
  174. void Write_vpp(uint u)
  175. {
  176.   uchar Va,Vb,Vc,Vd;
  177.         Va=1000*u/1000%10;
  178.         Vb=1000*u/100%10;
  179.         Vc=1000*u/10%10;
  180.         Vd=1000*u%10;
  181.   Write_LCD_Command(0xc0+10);//位置
  182.         Write_LCD_Data(0x30+Va);
  183.         Write_LCD_Data(0x30+Vb);
  184.         Write_LCD_Data(0x30+Vc);
  185.         Write_LCD_Data(0x30+Vd);
  186.         Write_LCD_Data(0x6d);///顯示m
  187.         Write_LCD_Data(0x56);///顯示V
  188. }        
  189. /***************************
  190. lcd1602   頻率計算   成功
  191. *************************/
  192. void Xianshi()                  
  193. {

  194.      freq=1/(64*peri*0.000001);
  195.          Write_freq(freq);
  196.           vpp=5*k;
  197.          Write_vpp(vpp);

  198. }
  199. /***************************
  200. lcd1602   幅值計算幅值
  201. amplitude  成功
  202. *************************/

  203. void Write_wave(uchar t )
  204. {
  205.         switch(t)
  206.         {
  207.                 case 0:
  208.                                  Write_LCD_Command(0x86);//定位
  209.                                     for (i=0;i<sizeof(No);i++)
  210.                                         {
  211.                                                 Write_LCD_Data(No[i]);//
  212.                                                 Delayms(1);
  213.                                         }
  214.                                         break;
  215.                 case 1:
  216.                                 Write_LCD_Command(0x86);//定位
  217.                                    Delayms(1);
  218.                                     for (i=0;i<sizeof(Sin)-1;i++)
  219.                                         {
  220.                                                 Write_LCD_Data(Sin[i]);
  221.                                                 Delayms(1);
  222.                                         }
  223.                                 break;
  224.                 case 2:
  225.                                 Write_LCD_Command(0x86);//定位
  226.                                    Delayms(1);
  227.                                     for (i=0;i<sizeof(Squ)-1;i++)
  228.                                         {
  229.                                                 Write_LCD_Data(Squ[i]);
  230.                                                 Delayms(1);
  231.                                          }
  232.                         
  233.                                 break;
  234.                 case 3:

  235.                                 Write_LCD_Command(0x86);//定位
  236.                                    Delayms(1);
  237.                                     for (i=0;i<sizeof(Tri)-1;i++)
  238.                                         {
  239.                                                 Write_LCD_Data(Tri[i]);
  240.                                                 Delayms(1);
  241.                                         }
  242.                                 break;
  243.                                 }
  244. }
  245. void key()
  246. {
  247.         if(key1==0)
  248.         {
  249.                 Delayms(10);//延時消抖
  250.                 if(key1==0)
  251.                 {
  252.                         key_wave+=1;
  253.                         if(key_wave>3)
  254.        {
  255.           key_wave=1;
  256.        }
  257.                 }
  258.                 while(!key1);
  259.         }

  260.         if(key2==0)
  261.         {
  262.                 Delayms(10);//延時消抖
  263.                 if(key2==0)
  264.                 {
  265.                         peri+=50;
  266.                         if(peri>=781)
  267.        {
  268.            peri=781;
  269.        }
  270.                 }
  271.                 while(!key2);
  272.         }
  273.         if(key3==0)
  274.         {
  275.                 Delayms(10);//延時消抖
  276.                 if(key3==0)
  277.                 {
  278.                         peri-=50;
  279.                         if(peri<=31)
  280.        {
  281.            peri=31;
  282.        }
  283.                 }
  284.                 while(!key3);
  285.         }
  286.         if(key4==0)
  287.         {
  288.                 Delayms(10);//延時消抖
  289.                 if(key4==0)
  290.                 {
  291.                         k+=0.1;
  292.                         if(k>=1)
  293.        {
  294.            k=1;
  295.        }
  296.                 }
  297.                 while(!key4);
  298.         }
  299.         if(key5==0)
  300.         {
  301.                 Delayms(10);//延時消抖
  302.                 if(key5==0)
  303.                 {
  304.                         k-=0.1;
  305.                         if(k<=0)
  306.        {
  307.            k=0;
  308.        }
  309.                 }
  310.                 while(!key5);
  311.         }
  312. }        



  313. void main()
  314. {
  315.                 Init_LCD();  //LCD初始化
  316.     init_Timer0();//定時器初始化
  317.         
  318.          while(1)
  319.                 {
  320.           key();
  321.                         
  322.             Write_wave(key_wave);//顯示波形名字
  323.                   Xianshi();//顯示波形大小
  324.                         
  325.           }
  326. }

  327. void Time0_isr(void) interrupt 1  //定時中斷
  328. {
  329.          TH0 = (unsigned int)(65536-peri)/256;
  330.    TL0 = (unsigned int)(65536-peri)%256;    //確定頻率
  331. //        key();
  332.         c++;
  333.   if(c>=64)
  334.    c=0;
  335. switch(key_wave)
  336. //根據輸出哪種波形,從P0口向DAC0832送數字量
  337.         
  338.         {
  339.                
  340.    //無輸出
  341.           case 0:
  342.                 P0=0x00;
  343.           break;
  344.         //正弦波
  345.     case 1:
  346.     P0=k*sine1[c];
  347.     break;
  348.    //方波
  349.     case 2:
  350.     P0=k*Square1[c];
  351.           break;
  352.         //三角波
  353.          case 3:
  354.    P0=k*Triangle1[c];
  355.          break;

  356. }
  357.          
  358. }
復制代碼


回復

使用道具 舉報

ID:332444 發表于 2019-6-22 19:59 | 顯示全部樓層
當按鈕操作時暫停中斷。51單片機資源畢竟有限,對時間的安排是要注意各方面的關系和邏輯,采樣時間也應安排好。
回復

使用道具 舉報

ID:213173 發表于 2019-6-22 23:16 | 顯示全部樓層
由于你的中斷周期太短留給主程序運行的時間非常少,致使按鍵程序和LCD驅動程序響應遲緩。必須做深度優化,盡量使用簡單指令。軟件延時的方法根本就不能用。把按鍵程序和LCD驅動程序打散,放在中斷里。每發生一次中斷只執行一條按鍵或LCD驅動程序。實際就是在一個中斷周期中分時工作。經過多次中斷完成一次按鍵或LCD驅動程序。
回復

使用道具 舉報

ID:401564 發表于 2019-6-24 08:55 | 顯示全部樓層
1,LCD的延時盡量的減少,查詢的延時就不要,直接不斷的去檢測忙碌標志位,只要一空閑就返回,有的時候是不用那么多的時間去等等忙碌位的。
2,LCD顯示是有緩沖的,顯示的頻率是可以比較低,1秒顯示一兩次就可以了,或者是先檢測按鍵,按鍵沒有變化,那么,你的數據也是沒有變化的,顯示也就不用改變了。
比如:你顯示的方波,50HZ,占空比是50%,你是通過按鍵來控制的,顯示一次之后,這個數據是一直保留在LCD上的,按鍵沒有動作的話,LCD就不需要刷新了。

方法是很多的,你可以把LCD的顯示放到按鍵處理函數中,每個按鍵有一次動作就顯示一次,或者是在LCD函數到處加一個按鍵檢測,這樣就不會錯過按鍵動作了
回復

使用道具 舉報

ID:123289 發表于 2019-6-24 08:57 | 顯示全部樓層
經驗不足,思路窄,規劃得不好。
1、決不用硬延時,延時一定用中斷做。
2、事件的處理,盡可能在主程序中做,不要在中斷中做。
3、中斷服務程序盡可能短,對于要處理的事件,盡可能只做標記,讓事件在主程序中依據標記決定是否有事件要處理?并做處理。
4、中斷盡可能少發生,例如:中斷的時間間隔放長一點。
能做到以上四點,你的問題就解決了。
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 亚洲国产精品久久 | 欧美在线观看免费观看视频 | 亚洲精品亚洲人成人网 | 91麻豆精品国产91久久久久久久久 | 一级片在线免费播放 | 毛片网站在线观看 | 99热播放| 国产视频精品免费 | 日韩在线视频一区 | 免费观看av | 欧美精品在线一区 | 一级毛片在线看 | 粉嫩粉嫩芽的虎白女18在线视频 | 国产精品精品久久久 | 91精品国产乱码久久久久久久久 | 国产成人jvid在线播放 | 午夜影视| 久草.com| 成人区一区二区三区 | 国产精品欧美日韩 | 99视频久| 亚洲精品国产电影 | 欧美一区二区免费 | 久久99深爱久久99精品 | 欧美日韩高清一区二区三区 | 免费久久99精品国产婷婷六月 | 日本在线视 | 中文字幕亚洲区一区二 | 久久久久网站 | 国产二区三区 | 91精品国产乱码久久久 | 91精品国产综合久久福利软件 | 欧区一欧区二欧区三免费 | 91精品久久久久久久久 | 亚洲精品电影网在线观看 | 羞羞的视频在线观看 | 欧美日韩亚洲一区 | 蜜桃av一区二区三区 | 久久爆操| 女人夜夜春 | 亚洲一二视频 |