找回密码
 立即注册

QQ登录

只需一步,快速开始

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

简单的单片机ds18b20,但实在调不通程序

[复制链接]
跳转到指定楼层
楼主
各位大佬和努力中朋友,本人制作个数码管时钟,mcu是stc15w408as,之前用的是12T,单独测试时钟,温度都能显示,本来改1T也是轻轻松松的事,但结果耗费我多少个晚上和周末,现在时钟没问题,自动调光也没问题,但温度显示始终是有问题的,现在一直显示-06℃。我也大概知道可能时序问题,但参照很多例程,就是调不好,真是绝望的很。只能求助了。

单片机源程序如下:
ds18b20.c
  1. //===========================================================================
  2. //                包含头文件
  3. //===========================================================================
  4. #include "DS18B20.h"
  5. #include "Delay.h"

  6. //===========================================================================
  7. //                宏定义
  8. //===========================================================================



  9. //===========================================================================
  10. //                函数原型声明
  11. //===========================================================================


  12. //===========================================================================
  13. //                全局变量声明
  14. //===========================================================================
  15. u8 DisplayData[4];
  16. u8 const code smgduan[] = {0x3c};                       // 'c'符号,1100 0110数码管0是亮
  17. u8 const code dis_code_z[] = {                              // 正装共阳数码管
  18.                                                 0xC0,                  // '0'
  19.                                                 0xF9,                  // '1'
  20.                                                 0xA4,                  // '2'
  21.                                                 0xB0,                  // '3'
  22.                                                 0x99,                  // '4'
  23.                                                 0x92,                  // '5'
  24.                                                 0x82,                  // '6'
  25.                                                 0xF8,                  // '7'
  26.                                                 0x80,                  // '8'
  27.                                                 0x90,                  // '9'
  28.                                                 0xFF                   // off
  29.                                                 };                                                      

  30. u8 const code dis_code_d[] = {                            // 倒装共阳数码管
  31.                                                 0xC0,                 // '0'
  32.                                                 0xCF,                 // '1'
  33.                                                 0xA4,                 // '2'
  34.                                                 0x86,                 // '3'
  35.                                                 0x8B,                 // '4'
  36.                                                 0x92,                 // '5'
  37.                                                 0x90,                 // '6'
  38.                                                 0xC7,                 // '7'
  39.                                                 0x80,                 // '8'
  40.                                                 0x82,                 // '9'
  41.                                                 0xFF                  // 'off'
  42.                                                 };                                                               



  43. //===========================================================================
  44. //                外部变量声明
  45. //===========================================================================




  46. /*""FUNC COMMENT""***********************************************************
  47. *----------------------------------------------------------------------------
  48. * 功    能        : 初始化
  49. *----------------------------------------------------------------------------
  50. * 引    数        : 无
  51. *----------------------------------------------------------------------------
  52. * 返 回 值        : 初始化成功返回1,失败返回0
  53. *----------------------------------------------------------------------------
  54. * 注意事项        : 无
  55. *----------------------------------------------------------------------------
  56. *""FUNC COMMENT END""*******************************************************/
  57. bit ds18b20_reset(void)
  58. {
  59.         u8 F_init = 0;        
  60.         
  61.          DQ = 1;                                // 首先将数据线置高
  62.         delay_us(1);                          // 短暂延时 (大约2us)
  63.         DQ = 0;                                // 送出低电平复位信号
  64.         delay_250us();                     // 延时在480~960US之间
  65.         delay_250us();
  66.     delay_250us();
  67.     DQ = 1;                                // 拉高 释放数据线
  68.         delay_70us();                  // 延时等待要求大于60us
  69.         F_init = DQ;                   // DS18B20产生“存在脉冲”                                                                                                                                          
  70.                                         // 检测DQ若低,则复位成功,DS18B20存在
  71.                                       // 若高,则复位失败,DS18B20损坏或不存在
  72.     delay_250us();             // 等待释放数据线,避免影响下一步操作
  73.         delay_250us();
  74.    
  75.         return (F_init);           // 返回复位结果
  76. }

  77. /*""FUNC COMMENT""***********************************************************
  78. *----------------------------------------------------------------------------
  79. * 功    能        : 向18B20写入一个字节
  80. *----------------------------------------------------------------------------
  81. * 引    数        : dat
  82. *----------------------------------------------------------------------------
  83. * 返 回 值        : 无
  84. *----------------------------------------------------------------------------
  85. * 注意事项        : 无
  86. *----------------------------------------------------------------------------
  87. *""FUNC COMMENT END""*******************************************************/
  88. void ds18b20_writeData(u8 byte)
  89. {
  90.         u8 i;
  91.    
  92.         for (i = 0; i < 8; i++)     // 重复直到发送完整个字节
  93.         {
  94.         DQ = 1;
  95.                 delay_us(1);
  96.                 DQ = 0;                      // 数据线首先拉低,开始写
  97.                 delay_us(1);               // 低电平保持1us以上
  98.         DQ = byte & 0x01;             // 送出数据                                 
  99.                 delay_70us();           // 写周期在60us-120us间,等待时间片结束
  100.                 DQ = 1;                  // 释放数据线
  101.                 byte >>= 1;
  102.                 delay_us(1);          // 恢复延时      
  103.         }
  104. }

  105. /*""FUNC COMMENT""***********************************************************
  106. *----------------------------------------------------------------------------
  107. * 功    能        : 读取一个字节
  108. *----------------------------------------------------------------------------
  109. * 引    数        : 无
  110. *----------------------------------------------------------------------------
  111. * 返 回 值        : 读取的数据
  112. *----------------------------------------------------------------------------
  113. * 注意事项        : 无
  114. *----------------------------------------------------------------------------
  115. *""FUNC COMMENT END""*******************************************************/
  116. u8 ds18b20_readData(void)
  117. {
  118.         u8 i;
  119.     u8 byte = 0;
  120.         
  121.         for (i = 0; i < 8; i++)           // 重复接收直到读完整个字节
  122.         {
  123.         
  124.         DQ = 0;                         // 开始时间片,开始一个读过程
  125.                 delay_us(1);         // 保持1us以上
  126.         DQ = 1;                     // 准备接收,开始读取数据线状态        
  127.                 delay_us(1);      // 读时间片开始后15us内主机对数据线进行采集
  128.                 byte >>= 1;
  129.                 if(DQ)
  130.                 {
  131.                         byte |= 0x80;  // 读取数据        
  132.                 }
  133.                 delay_70us();            // 等待时间片结束,读周期60us-120us间
  134.         }
  135.         return (byte);
  136. }

  137. /* void ds1820_setResolution(u8 res)//设置分辨率 默认12wei
  138. {
  139.     while (ds18b20_reset());
  140.     ds18b20_writeByte(0x4E);
  141.     ds18b20_writeByte(0xFF);
  142.     ds18b20_writeByte(0xFF);
  143.     ds18b20_writeByte(0x1F | (res << 5));   //设置分辨率(0 R1 R0 1  1111)   
  144. } */

  145. /*""FUNC COMMENT""***********************************************************
  146. *----------------------------------------------------------------------------
  147. * 功    能        : 读温度
  148. *----------------------------------------------------------------------------
  149. * 引    数        : 无
  150. *----------------------------------------------------------------------------
  151. * 返 回 值        : 读取的温度数据
  152. *----------------------------------------------------------------------------
  153. * 注意事项        : 无
  154. *----------------------------------------------------------------------------
  155. *""FUNC COMMENT END""*******************************************************/
  156. u16 ds18b20_readTemperature(void)
  157. {
  158.         u8 TPL, TPH;

  159.        u16 temp;//@001
  160.         ds18b20_reset();
  161.         ds18b20_writeData(0xCC);                                
  162.         ds18b20_writeData(0x44);                                                     
  163.                                                               
  164.         while(!DQ);                                    
  165.                                                                                                                
  166.         ds18b20_reset();                                 
  167.         ds18b20_writeData(0xCC);  
  168.         ds18b20_writeData(0xBE);  
  169.                
  170.         TPL = ds18b20_readData();   
  171.         TPH = ds18b20_readData();  
  172.         
  173.          temp = TPH;
  174.        temp <<= 8;                                                                                    
  175.         temp |= TPL;                              
  176.    
  177.         return (temp);  
  178. }

  179. /*""FUNC COMMENT""***********************************************************
  180. *----------------------------------------------------------------------------
  181. * 功    能        : 获取温度数据并处理
  182. *----------------------------------------------------------------------------
  183. * 引    数        : temp
  184. *----------------------------------------------------------------------------
  185. * 返 回 值        : 无
  186. *----------------------------------------------------------------------------
  187. * 注意事项        : 无
  188. *----------------------------------------------------------------------------
  189. *""FUNC COMMENT END""*******************************************************/
  190. void ds18b20_dataProcess(u16 temp) //@@1
  191. {
  192.         float tp;
  193. //        if (temp < 0)                                                                              
  194.         if ((temp & 0xF800) != 0)
  195.         {
  196.                 DisplayData[3] = 0xBF; // '-'

  197.                 //因为读取的温度是实际温度的补码,所以减1,再取反求出原码
  198.                 temp = temp - 1;
  199.                 temp = ~temp;
  200.                 tp = temp;
  201.                 temp = tp*0.0625*100 + 0.5;
  202.                 //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
  203.                 //后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
  204.                 //算加上0.5,还是在小数点后面。
  205.                 DisplayData[2] = dis_code_z[temp / 10];        // 十位
  206.                 DisplayData[1] = dis_code_d[temp % 10];      // 个位
  207.                 DisplayData[0] = smgduan[0];                       // 显示C符号
  208.         }
  209.         else
  210.         {
  211.                 //DisplayData[0] = 0x00;
  212.                 tp = temp;//因为数据处理有小数点所以将温度赋给一个浮点型变量
  213.                 //如果温度是正的那么,那么正数的原码就是补码它本身
  214.                 temp = tp*0.0625*100 + 0.5;
  215.                 //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
  216.                 //后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
  217.                 //算加上0.5,还是在小数点后面。
  218.                 if (( temp / 100 ) == 0)
  219.                 {
  220.                         DisplayData[3] = 0xFF;
  221.                 }
  222.                 else
  223.                 {
  224.                         DisplayData[3] = dis_code_z[temp / 100];        // 千位
  225.                         DisplayData[2] = dis_code_z[temp % 100 / 10] & 0x7F;// 十位
  226.                         DisplayData[1] = dis_code_d[temp % 10];      // 个位
  227.                         DisplayData[0] = smgduan[0];                       // 显示C符号        
  228.                 }
  229.         }        
  230. }

复制代码
还有个很莫名的问题也废了很多时间就是定时中断,参照着datasheet改1T,但若不加/12就不是1ms中断。。后来发现后加上能输出1ms。
        #define T1MS    (65536 - FOSC/1000/12)  

Snipaste_2019-09-03_21-00-53.png (66.1 KB, 下载次数: 110)

Snipaste_2019-09-03_21-00-53.png
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:84492 发表于 2019-9-3 21:09 | 显示全部楼层
期间用到的1us,实测在4us;70us,250us大概差不多

Snipaste_2019-09-03_21-09-25.png (2.66 KB, 下载次数: 94)

Snipaste_2019-09-03_21-09-25.png
回复

使用道具 举报

板凳
ID:84492 发表于 2019-9-4 09:36 | 显示全部楼层
这是上面说的1ms定时,中断配置

Snipaste_2019-09-04_09-32-01.png (34.3 KB, 下载次数: 90)

Snipaste_2019-09-04_09-32-01.png
回复

使用道具 举报

地板
ID:84492 发表于 2019-9-4 20:56 | 显示全部楼层
温度一直一个数值,难道是转换部分有问题?
回复

使用道具 举报

5#
ID:84492 发表于 2019-9-4 22:03 | 显示全部楼层
防尘            
回复

使用道具 举报

6#
ID:84492 发表于 2019-9-5 20:07 | 显示全部楼层
l6931639 发表于 2019-9-5 17:17
你先把单片机其他功能都去掉单独调好1820再放到一起

我之前用12T时也只调试温度,可以显示但温度比实际低个10度左右,现在正和时钟就改1T,但真是崩溃
回复

使用道具 举报

7#
ID:84492 发表于 2019-9-5 20:10 | 显示全部楼层
没有你 发表于 2019-9-5 09:28
用逻辑分析仪器看一下单片机和DS18B20的通信过程,看看DS18B20能否正常回应数据。DS18B20对时序要求很严格 ...

水平也不行,所以调试这个真是太费时间了,你的建议我会试试但估计看不懂
回复

使用道具 举报

8#
ID:84492 发表于 2019-9-9 17:06 | 显示全部楼层
fox_hk 发表于 2019-9-5 20:37
这东西 很扣时序。在读这个时 中断都最好关掉

你是正确的,后来我在电源网上看到说中断会影响,关闭之后就可以正常显示温度了。这个问题真是耗费了我很多精力和时间,要是能早点看到你的回复就好了,也多谢回复!
回复

使用道具 举报

9#
ID:84492 发表于 2019-9-9 17:07 | 显示全部楼层
wulin 发表于 2019-9-6 09:02
楼主调不成功主要还是时序问题,给你一个1T单片机的示例程序,是在郭天祥的12T程序基础上改的,经过实物验 ...

确实是时序问题,是中断引起的。多谢!
回复

使用道具 举报

10#
ID:84492 发表于 2019-9-9 17:10 | 显示全部楼层
谢谢各位的帮助,已经实现了。也谢谢51hei这个平台一直能有网友帮助和学习机会。
回复

使用道具 举报

11#
ID:84492 发表于 2019-9-27 16:49 | 显示全部楼层
l6931639 发表于 2019-9-9 18:25
使用定时器中断非阻塞程序设计就可以随便移植,基本不用每次重新调试。

你好,你的意思是把计时相关的放中断去处理吗?之前我也是想过,但实际操作发现程序写起来不顺手。。。比如:1820需要延迟120us,中断10us一次,那么在中断中只做减减,当12次中断后时间为零,这时在其他函数做判断处理,当时间为0则进行之后程序并重新时间赋值,这样延迟做到了,也没有傻傻的delay。对吗?
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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