欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 6812|回復: 0
打印 上一主題 下一主題
收起左側

利用AVR單片機設計的DS18B20測溫程序

[復制鏈接]
跳轉到指定樓層
樓主
ID:75926 發表于 2015-4-3 00:57 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
  1. /********************************
  2.   DS18B20測溫程序
  3.   文件名:main.c
  4.   編譯:WinAVR-20070122

  5.   硬件環境:CA-M8X   打開的開關如下
  6.             S6(1,2,5,6,7)   - 外部4MHz晶振和595接口
  7.             J8(EN-SEG)      - 數碼管顯示允許
  8.             S7(4)          - 連接PC1 與DS18B20數據口
  9.             (在CA-M8X 上DS18B20為非總線供電)
  10.   
  11.   芯藝設計室 2004-2007  版權所有
  12.   轉載請保留本注釋在內的全部內容
  13.   Email: changfutong@sina.com
  14. *******************************/
  15. #include <avr/io.h>
  16. #include <util/delay.h>
  17. #include <stdint.h>

  18. #include "seg.h"  //聲明數碼管顯示接口函數

  19. #define CLR_1WIRE_BUS DDRC|=_BV(PC1) //設置為輸出,此時由于PORTC1是低所以輸出低
  20. #define SET_1WIRE_BUS DDRC&=~_BV(PC1)//設置為輸入,此時由于PORTC1是低所以程高阻,又因為外部有上拉電阻所以相當于設置總線為高
  21. #define GET_1WIRE_BUS PINC&_BV(PC1)

  22. #define DS18B20_READ_ROM 0x33
  23. #define DS18B20_MATCH_ROM 0X55
  24. #define DS18B20_SKIP_ROM 0XCC
  25. #define DS18B20_SEARCH_ROM 0XF0
  26. #define DS18B20_ALARM_SEARCH_ROM 0XEC
  27. #define DS18B20_WRITE_RAM 0X40
  28. #define DS18B20_READ_RAM 0XBE
  29. #define DS18B20_COPY_RAM 0X48
  30. #define DS18B20_CONVERT_TEM 0X44
  31. #define DS18B20_EECALL_EEPROM 0XB8
  32. #define DS18B20_READ_POWER_SUPPLY 0XB4

  33. //總線端口初始化
  34. void BusInit(void)
  35. {
  36.   PORTC&=~_BV(PC1);//此口總保持低
  37.   DDRC&=~_BV(PC1); //初始化為輸入,用外部上拉電阻保持總線的高電平
  38. }

  39. //由于系統時鐘為4MHz,一個_delay_loop_2正好延時一us
  40. #define DelayUs(x) _delay_loop_2(x)

  41. void DelayMs(uint16_t t)
  42. {
  43.   uint16_t i;
  44.   for(i=0;i<t;i++)
  45.     _delay_loop_2(250 * 4);
  46. }

  47. //單總線復位
  48. uint8_t ds18b20_reset(void)
  49. {
  50.   uint8_t ret=0;
  51.   CLR_1WIRE_BUS;
  52.   DelayUs(500);  //拉低總線至少480us
  53.   SET_1WIRE_BUS;
  54.   DelayUs(100);//釋放總線后等待15-60us
  55.   if((GET_1WIRE_BUS)==0)//檢測到DS18B20把總線拉低
  56.     ret=1;        //復位成功
  57.   DelayUs(1000);//等待器件釋放總線
  58.   return ret;
  59. }

  60. //單總線讀一字節
  61. uint8_t ds18b20_read(void)
  62. {
  63.   uint8_t data=0;
  64.   uint8_t i=0;
  65.   for(i=0;i<8;i++)
  66.   {
  67.     data>>=1;
  68.     CLR_1WIRE_BUS;
  69.     DelayUs(2);//此時>1us
  70.     SET_1WIRE_BUS;
  71.     DelayUs(4);//此時<15us
  72.     if(GET_1WIRE_BUS)
  73.       data|=0x80;
  74.     DelayUs(60);//此時>60us
  75.   }
  76.   return(data);
  77. }
  78. //單總線寫一字節
  79. void ds18b20_write(uint8_t data)
  80. {
  81.   uint8_t i=0;
  82.   for(i=0;i<8;i++)
  83.   {
  84.     if(data&0x01)
  85.     {
  86.       CLR_1WIRE_BUS;
  87.       DelayUs(8);//8us
  88.       SET_1WIRE_BUS;
  89.       DelayUs(55);//55us
  90.     }
  91.     else
  92.     {
  93.       CLR_1WIRE_BUS;
  94.       DelayUs(55);//55us
  95.       SET_1WIRE_BUS;
  96.       DelayUs(20);//8us
  97.     }
  98.     data>>=1;
  99.   }
  100. }

  101. //執行轉換
  102. uint8_t Ds18b20Convert(uint8_t *t)
  103. {
  104.   //發送轉換命令
  105.   if(ds18b20_reset()==0)
  106.     return 0;
  107.   ds18b20_write(DS18B20_SKIP_ROM); //忽略地址匹配,總線上只有一個器件時,或對總線所有器件操作
  108.   ds18b20_write(DS18B20_CONVERT_TEM);//開始轉換命令
  109.   
  110.   //等待轉換完成,ds18b20默認轉換精度為12位,此時最大轉換時間為750ms
  111.   DelayMs(1000);
  112.   
  113.   //讀溫度字節
  114.   if(ds18b20_reset()==0)
  115.     return 0;
  116.   ds18b20_write(DS18B20_SKIP_ROM); //忽略地址匹配
  117.   ds18b20_write(DS18B20_READ_RAM); //讀RAM命令
  118.   t[0]=ds18b20_read();
  119.   t[1]=ds18b20_read();
  120.   
  121.   return 1;
  122. }

  123. //根據DS18B20中讀的溫度字節,計算實際溫度值
  124. int8_t GetTemperature(uint8_t *t)
  125. {
  126.   int8_t ret;
  127.   uint32_t  val;
  128.   uint16_t tmp=(t[1]*256)+t[0];
  129.   uint8_t sflag=0;

  130.   if((t[1]&0xf8)==0xf8) //若負溫度,從補碼轉換(取反加一)
  131.   {
  132.     sflag=1;
  133.     tmp=~tmp;
  134.     tmp++;
  135.   }
  136.   tmp&=0x07ff;    //確保前5位為0
  137.   
  138.   //乘0.0625操作,為此本函數只適用于DS18B20 12位轉換(默認)時
  139.   val=((uint32_t)tmp)*625;
  140.   val/=10000;
  141.   
  142.   ret=(int8_t)val;
  143.   
  144.   if(sflag)
  145.     ret|=0x80;//變負數
  146.    
  147.   return ret;
  148. }

  149. //測試主函數
  150. int main(void)
  151. {
  152.   uint8_t tmp[2];//保存溫度字節
  153.   int8_t tval;    //保存溫度值
  154.   
  155.   SegInit();//數碼管初始化
  156.   SegNumberOut(0,0);//顯示 0
  157.   BusInit();  //單總線I/O口初始化

  158.   while(1)
  159.   {
  160.     if(Ds18b20Convert(tmp))//如果轉換成功
  161.     {
  162.       tval=GetTemperature(tmp);//計算實際溫度值
  163.       if(tval>=0)
  164.         SegNumberOut(tval,0);//十進制顯示溫度值
  165.       else
  166.         SegNumberOut(0,0);//數碼管無法顯示負數,只能顯示0
  167.     }
  168.   }
  169.   return 0;
  170. }


  171. seg.c文件:


  172. /********************************
  173.   74HC95驅動的數碼管顯示模塊
  174.   文件名:seg.c
  175.   編譯:WinAVR-20070122

  176.   硬件環境:CA-M8X   打開的開關如下
  177.             S6(1,2,5,6,7)   - 外部4MHz晶振和595接口
  178.             J8(EN-SEG)      - 數碼管顯示允許
  179.   
  180.   芯藝設計室 2004-2007  版權所有
  181.   轉載請保留本注釋在內的全部內容
  182.   WEB: http://www.chipart.cn
  183.   Email: changfutong@sina.com
  184. *******************************/

  185. #include <avr/io.h>
  186. #include <util/delay.h>
  187. #include <stdint.h>

  188. #include "seg.h"

  189. #define SER_PORT  PORTD
  190. #define SER_DAT  PD4
  191. #define SER_RCK  PD5
  192. #define SER_SCK  PD6

  193. //顯示碼(可從chipart.cn下載生成工具)
  194. static uint8_t g_aDisplayBuf[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

  195. //向595 寫一字節
  196. static void ser_out(uint8_t dat)
  197. {
  198.   uint8_t i;

  199.   for(i=0;i<8;i++)
  200.   {
  201.     if(dat&0x80)
  202.       SER_PORT|=_BV(SER_DAT);
  203.     else
  204.       SER_PORT&=~_BV(SER_DAT);
  205.       
  206.     //產生移位脈沖   
  207.     SER_PORT|=_BV(SER_SCK);
  208.     SER_PORT&=~_BV(SER_SCK);
  209.     dat<<=1;
  210.   }
  211. }
  212. //數碼管顯示數(0~255)
  213. //num :顯示的數   hex:是否用十六進制顯示
  214. void SegNumberOut(uint8_t num,uint8_t hex)
  215. {
  216.   uint8_t buf[2];//發送顯示碼緩沖區
  217.   uint8_t temp;
  218.   
  219.   if(hex) //十六進制
  220.   {
  221.     buf[0]=g_aDisplayBuf[num>>4];//高位
  222.     buf[1]=g_aDisplayBuf[num&0x0f];//低位
  223.   }
  224.   else//十進制
  225.   {
  226.     buf[1]=g_aDisplayBuf[num%10];
  227.     temp=num%100;
  228.     buf[0]=g_aDisplayBuf[temp/10];
  229.     temp=num/100;
  230.    
  231.     if(temp>0)
  232.       buf[1]|=0x80; //第一個數碼管小數點表示百位1
  233.     if(temp>1)
  234.       buf[0]|=0x80;//兩個數碼管小數點表示百位2
  235.   }
  236.   
  237.   //串行發送數據
  238.   ser_out(buf[0]);
  239.   ser_out(buf[1]);

  240.   //產生鎖存脈沖
  241.   SER_PORT|=_BV(SER_RCK);
  242.   SER_PORT&=~_BV(SER_RCK);
  243. }

  244. void SegInit(void)
  245. {
  246.   //595控制I/O初始化
  247.   DDRD=_BV(SER_DAT)|_BV(SER_SCK)|_BV(SER_RCK);  
  248.   SER_PORT&=~_BV(SER_SCK);
  249.   SER_PORT&=~_BV(SER_RCK);
  250. }
復制代碼


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表