找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4339|回复: 4
打印 上一主题 下一主题
收起左侧

单片机程序keil DEBUG运行到初始化定时器后一直循环中断?

[复制链接]
跳转到指定楼层
楼主
ID:490607 发表于 2019-4-15 13:26 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 gq2352100 于 2019-4-15 19:08 编辑

写了一个温度控制程序,DS18B20采集,LCD1602显示,根据当前温度和设定温度的误差输出5档PWM,但是不知道为什么,用 keil DEBUG的时候,一旦运行到初始化定时器后,就不会再继续运行下面的代码,而是一直循环STARTUP.A51里面的两行,一直到左上R0寄存器减1到0就会复位,从头执行程序。如图:
找了半天不知道问题所在,请各位大佬帮帮忙,感激万分。

单片机代码贴上:

  1. //这是主程序
  2. #include < reg52.h >
  3. #include < intrins.h >
  4. #include < ds18b20.h >
  5. #include < lcd1602.h >
  6. #include < fuzzy.h >
  7. #include < pwm.h >


  8. #define uchar unsigned char
  9. #define uint   unsigned int



  10. void init_time()
  11. {
  12.         TMOD=0x01;   //T0都是定时方式1
  13.         TH0=0xFC;   //T1  10us初值
  14.         TL0=0x18;
  15.         TR0=1;
  16.         ET0=1;
  17.         EA=1;
  18.         time=0;
  19.         zkb=50;
  20. }

  21. void main()
  22. {
  23.         lcd_display();
  24.   delayms(500);
  25.   ow_reset();
  26.         if(presence==0)
  27.         {
  28.                 Ok_Menu ();
  29.                 delayms(500);        
  30.                 init_time();
  31.           while(1)
  32.           {
  33.                   temperature_trans();
  34.                         fuzzy();
  35.                         pwmchange();
  36.       c_display();
  37.                         temperature_display();
  38.     }

  39. //下面是DS18B20程序
  40.                
  41. #include < reg52.h >
  42. #include < intrins.h >

  43. #define uchar unsigned char
  44. #define uint   unsigned int

  45. sbit DQ = P0^0;   //定义DS18B20端口DQ
  46. bit presence=1;           //ds18b20应答信号 0允许,1禁止
  47. unsigned char data   temp_data[2] = {0x00,0x00} ;  //用于存储16位温度

  48. /*us级延时,延时时间约4+2*i*/
  49. void delayus(uchar us)
  50. {
  51.   while(--us);
  52. }

  53. /*ms级别      */
  54. void delayms(uint ms)
  55. {
  56. uint i;
  57. uchar j;
  58. for(i=0;i<ms;i++)
  59.    for(j=0;j<250;j++)
  60.    {
  61.     _nop_();          //一个机器周期,1us
  62.     _nop_();          //适用于精度高的
  63.     _nop_();
  64.     _nop_();
  65.    }
  66. }
  67. /*复位,每次读写之前都要进行复位*/
  68. /**********************************/
  69. bit ow_reset(void)
  70. {

  71. DQ = 1 ;       //DQ复位
  72. delayus(8) ;     //稍做延时

  73. DQ = 0; //拉低约600us
  74. delayus(250);


  75. DQ = 1;//产生上升沿,延时约15~60us
  76. delayus(20);

  77. presence=DQ;      


  78. delayus(250);
  79.         

  80. return(presence); //等待应答信号 0允许,1禁止

  81. }

  82. /*读取数据一位            */
  83. //---------------------------------
  84. bit Read_bit()
  85. {
  86. uint i = 0;
  87. bit b = 0;

  88. DQ = 0; //产生读时隙  
  89. i++;         //维持低电平至少1us

  90. DQ = 1; //1us以上后拉高
  91. delayus(2); //延时8us,DO下降沿15内ds18b20输出的数据才有效


  92. b = DQ; //读取数据
  93. delayus(40);         //每个读时隙至少持续60us

  94. return(b);
  95. }

  96. /*读取一个字节             */
  97. //------------------------------------
  98. uchar Read_byte()
  99. {
  100. uchar byte_read = 0;
  101. uchar i, j;

  102. for(i=0; i<8; i++)
  103.   {
  104.    j = Read_bit();
  105.    byte_read = (j<<i) | byte_read; //低位读起
  106.   }

  107. return(byte_read);
  108. }

  109. //-----------------------------------------
  110. /*写一个字节         */
  111. void Write_byte(uchar byte_to_write)
  112. {
  113. uchar i = 0;
  114. uchar j = 0;
  115. bit write_bit = 0;

  116. for(j=0; j<8; j++)
  117.   {
  118.    write_bit =         (byte_to_write & 0x01);
  119.     if(write_bit == 1) //写1
  120.          {
  121.           DQ = 0;  //产生写时隙
  122.          delayus(3);           //延时15us
  123.          
  124.           DQ = 1;  //写1
  125.           delayus(40);   //延时,写时隙不得低于60us
  126.          }
  127.         else
  128.          {
  129.           DQ = 0;  //产生写时隙
  130.           delayus(50);   //延时,保持低约60us~120us
  131.           DQ = 1;  
  132.           i++;
  133.          }
  134.    byte_to_write = byte_to_write >> 1;
  135.   }
  136. }
  137. //-----------------------------------
  138. /*读取温度,启动温度转换*/
  139. /*启动温度转换*/
  140. void start_convert()
  141. {
  142.   ow_reset();          // 发出复位脉冲,每次操作都从复位开始
  143.   delayms(1);
  144.   Write_byte(0xcc); //skip room命令,跳过序列号命令字
  145.   Write_byte(0x44); //启动温度转换命令
  146. }

  147. /*读取温度值*/
  148. void read_tempreture()
  149. {
  150.   ow_reset();          // 发出复位脉冲,每次操作都从复位开始
  151.   delayms(1);
  152.   Write_byte(0xcc); //跳过rom命令
  153.   Write_byte(0xbe); //读取暂存器命令
  154.   temp_data[0] = Read_byte(); //存储温度低字节值 (整数部分低四位和小数部分) 先从低字节读取
  155.   temp_data[1] = Read_byte(); //存储温度高字节值 (其中高五位为符号位)
  156. }


  157. //下面是LCD1602程序

  158. #include < reg52.h >
  159. #include < ds18b20.h >

  160. #define uchar unsigned char
  161. #define uint   unsigned int

  162. #define lcddata P2

  163. sbit LCDRS=P1^7;              //液晶数据选择命令端
  164. sbit LCDRW=P1^6;             //液晶读写命令端
  165. sbit LCDEN=P1^5;            //液晶使能端

  166. uint cc,cc2;       //变量cc中保存读出的温度值
  167. float cc1;
  168. uchar flag;    //正负标志
  169. uchar  cdis2[ ] = "+00.00";     //将来测得的温度修改各位即可
  170. uchar code cdis5[ ] = "Temp: ";
  171. uchar code cdis0[ ] = "CHECKING...";
  172. uchar code cdis1[ ] = "   DS18B20 OK   " ;
  173. uchar code cdis3[ ] = " DS18B20   ERR0R " ;
  174. uchar code cdis4[ ] = "   PLEASE CHECK  " ;

  175. void delaylcd(uint z)
  176. {uchar x,y;
  177. for(x=z;x>0;x--)
  178.   {for(y=110;y>0;y--);
  179.   }
  180. }



  181. /*写命令to lcd        */
  182. /**********************************/
  183. void write_com(uchar com)//写命令
  184. {
  185.   LCDRW=0;         //低电平为写
  186.   LCDRS=0;         //低电平为命令选择
  187.   lcddata=com;
  188.   delaylcd(5);
  189.   LCDEN=1;
  190.   delaylcd(5);
  191.   LCDEN=0;
  192. }


  193. /*lcd1602初始化        */
  194. /**********************************/
  195. void lcd_init(void)
  196. {
  197. LCDRW=0;                 //低电平为写
  198. LCDEN=0;
  199. write_com(0x38);                 //使用8位数据开关,显示两行,使用5*7字形

  200. write_com(0x0c);                //显示器开,光标关,字符不闪烁         0x0e 光标开

  201. write_com(0x06);           //字符不动,光标自动右移动一位

  202. write_com(0x01);          //清屏
  203. }



  204. /*写数据to lcd             */
  205. /**********************************/
  206. void write_data(uchar  date)
  207. {
  208. LCDRW=0;  //低电平为写
  209. LCDRS=1;  //高电平为数据选择
  210. lcddata=date;
  211. delaylcd(5);
  212. LCDEN=1;
  213. delaylcd(5);
  214. LCDEN=0;
  215. }

  216. /*设定显示位置             */
  217. /********************************/
  218. void lcd_pos(uchar pos)
  219. {                                 //第一行第几列直接写pos为几,第二行pos从0x40开始
  220.     write_com(pos|0x80);   //数据指针=80+地址变量

  221. }


  222. //--------------------------------------
  223. /* CHECKING...显示              */
  224. void lcd_display()
  225. {
  226. uchar   m ;
  227. lcd_init() ;                 //初始化LCD
  228. lcd_pos(0) ;                 //设置显示位置为第一行的第1个字符
  229.       m = 0 ;
  230.      while(cdis0[m] != '\0')
  231.       {                          //显示字符
  232.         write_data(cdis0[m]) ;
  233.         m++ ;
  234.       }
  235. }

  236. //--------------------------------------
  237. /* DS18B20 OK 显示菜单                 */
  238. void Ok_Menu ()
  239. {
  240.      uchar   m ;
  241.      lcd_init() ;                 //初始化LCD
  242.             
  243.      lcd_pos(0) ;                 //设置显示位置为第一行的第1个字符
  244.       m = 0 ;
  245.      while(cdis1[m] != '\0')
  246.       {                          //显示字符
  247.         write_data(cdis1[m]) ;
  248.         m++ ;
  249.       }         
  250. }




  251. //------------------------------------
  252. /*Temp:      ℃显示        */
  253. void c_display()
  254. {
  255.   uchar m;
  256.   lcd_init() ;
  257.   lcd_pos(0);
  258.   m=0;
  259.   while(cdis5[m]!='\0')
  260.   {
  261.    write_data(cdis5[m]);
  262.    m++;
  263.   }
  264.   lcd_pos(12);
  265.   write_data(0xDF);                //°
  266.         lcd_pos(13);                  
  267.   write_data('C');
  268. }


  269. //------------------------------------
  270. /*采集温度转换成LCD显示的格式                       */

  271. void temperature_trans()
  272. {
  273.      EA=0;                           //DS18B20读写数据按照严格的时序,最好不要被打断,故把所有中断关闭
  274.     start_convert();                          //启动温度转换
  275.     delayms(100);
  276.     read_tempreture();
  277.                                    //读取温度
  278.                          cc=temp_data[1]*256+temp_data[0];   
  279.     if(temp_data[1]>0xF8)
  280.        {flag=1;cc=~cc+1;}
  281.                 else
  282.                           flag=0;   //高5位全1负,全0正
  283.     cc1=cc*0.0625;    //浮点数温度
  284.     cc2=cc1*100;
  285.     cdis2[1]=cc2/1000+0x30;
  286.     if(cdis2[1]==0x30)
  287.        cdis2[1]=0x20;
  288.         cdis2[2]=cc2/100%10+0x30;
  289.         cdis2[4]=cc2%100/10+0x30;
  290.         cdis2[5]=cc2%10+0x30;
  291.         if(flag==1)
  292.            cdis2[0]='-';
  293.         else
  294.            cdis2[0]='+';
  295.     EA=1;
  296.    
  297.                                 
  298. }


  299. //------------------------------------
  300. /*温度显示                       */
  301. void temperature_display()
  302. {

  303.      uchar m;   
  304.      lcd_pos(6);                 //设置显示位置为第一行的第6个字符
  305.      m=0;
  306.      while(cdis2[m]!='\0')
  307.        {                          //显示字符
  308.         write_data(cdis2[m]) ;
  309.                 m++;
  310.        }                                                                  
  311. }

  312. //下面是根据采集温度和设定温度差值查表得输出的程序

  313. #include <reg52.h>
  314. #include <lcd1602.h>

  315. #define uint unsigned int

  316. float set_temp=20.0000;     //设置温度


  317. uchar u;
  318. uchar e_f;  
  319.         
  320. void fuzzy()
  321. {
  322.         
  323.         float e=cc1-set_temp;  //算出误差
  324.   unsigned int code ely[ ]={0,1,2,3,4};
  325.   unsigned int code uly[ ]={0,1,2,3,4};


  326.   e_f=(e/5*10+5)/10;   //误差转换成0-4整数

  327.   if(e_f<0)
  328.   {e_f=0;}
  329.   if(e_f>4)
  330.   e_f=4;

  331.   u=uly[e_f];          //差表得到控制输出,改变PWM占空比
  332. }


  333. //下面是PWM的程序

  334. #include<reg52.h>
  335. #include<fuzzy.h>
  336. #include<lcd1602.h>

  337. #define uint unsigned int
  338. #define uchar unsigned char

  339. uchar time;  //计数
  340. uchar zkb;  //占空比

  341. sbit pwm=P1^0;                //P1^0口输出方波



  342. void pwmchange()                  //根据算法输出调节占空比,5个档位
  343. {
  344.         EA=0;
  345.         if(u==0)
  346.           {zkb=0;}
  347.         else if(u==1)
  348.                 {zkb=25;}
  349.         else if(u==2)        
  350.                 {zkb=50;}
  351.         else if(u==3)
  352.                 {zkb=75;}
  353.         else if(u==4)
  354.           {zkb=100;}
  355.   EA=1;
  356. }

  357. //----------------------------------------------

  358. //------------------------------------------
  359. void time_1() interrupt 1
  360. {
  361.         TH0=0xFC;   //T1  10us初值
  362.         TL0=0x18;
  363.         if(time<zkb)
  364.                 pwm=1;      //方波翻转  
  365.         else
  366.                 if(time>=zkb)  
  367.                 pwm=0;
  368.         time++;
  369.          if(time==100)       //100份 最大100%
  370.                 time=0;

  371. }
复制代码




分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:213173 发表于 2019-4-15 15:18 | 只看该作者
程序不全,猜不出来。
回复

使用道具 举报

板凳
ID:490607 发表于 2019-4-15 18:31 | 只看该作者
wulin 发表于 2019-4-15 15:18
程序不全,猜不出来。

谢谢你得提醒。我马上上传完整程序
回复

使用道具 举报

地板
ID:490607 发表于 2019-4-15 19:03 | 只看该作者
wulin 发表于 2019-4-15 15:18
程序不全,猜不出来。

已经上传完整程序,请大家帮帮忙,谢谢!
回复

使用道具 举报

5#
ID:213173 发表于 2019-4-16 06:24 | 只看该作者
gq2352100 发表于 2019-4-15 18:31
谢谢你得提醒。我马上上传完整程序

你的主程序本身就是不完整的,补全后出现更多的错误和警告。给你一个比较成熟程序参考。
1602+ds1302+18B20万年历+仿真.zip (146.93 KB, 下载次数: 9)

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表