找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

PIC16f877a單片機DS18b20源程序

[復制鏈接]
ID:615929 發(fā)表于 2019-9-24 22:16 | 顯示全部樓層 |閱讀模式
//調試總結:
//顯著的問題是,寫時序、讀時序中,PIC MCU向總線寫1是通過改方向為輸入方向由上拉電阻拉高數(shù)據(jù)線實現(xiàn)的,而非在輸出方向下輸出1,與AVR不同
//某IO口8位未全使用時,對整個IO口讀取進行位運算無效
//使用if(dat2&0xf8==0xf8)時,進錯分支導致顯示亂碼仍未找到原因,用if(dat2>=240)代替正常
  1. #include<pic.h>
  2. #define uchar unsigned char
  3. #define uint unsigned int
  4. #define rs_h (PORTC|=0x01)
  5. #define rs_l (PORTC&=0xfe)
  6. #define rs_o (TRISC&=0xfe)
  7. #define rw_h (PORTC|=0x02)
  8. #define rw_l (PORTC&=0xfd)
  9. #define rw_o (TRISC&=0xfd)
  10. #define en_h (PORTC|=0x04)
  11. #define en_l (PORTC&=0xfb)
  12. #define en_o (TRISC&=0xfb)
  13. #define temp_h (PORTC|=0x08)
  14. #define temp_l (PORTC&=0xf7)
  15. #define temp_o (TRISC&=0xf7)
  16. #define temp_i (TRISC|=0x08)
  17. #define led_o (TRISC&=0xef)
  18. #define led_l (PORTC&=0xef)
  19. #define led_h (PORTC|=0x10)
  20. #define LCD PORTB
  21. uchar dat1,dat2;//保存讀出的溫度z
  22. unsigned long int dat;
  23. void delayms(uint x) //4M晶振下,延時1ms
  24. {
  25.         uint y,z;
  26.         for(y=x;y>0;y--)
  27.                 for(z=110;z>0;z--);
  28. }
  29. void Ds18b20_reset(void)//DS18B20初始化
  30. {
  31.         uint count;
  32.         uchar i,flag=1;
  33.         temp_o;
  34.         temp_l;
  35.         for(count=60;count>0;count--);//延時480us
  36.         temp_i;
  37.         while(flag)
  38.         {
  39.                 //temp=PORTC;//此例中,C口部分引腳未使用處于高阻態(tài),對整個C口的讀取無效,所以if(RC3)不能換成if(temp&0x08==0x08)
  40.                 if(RC3)//temp&0x08==0x08)
  41.                         flag=1;
  42.                 else
  43.                         flag=0;        
  44.         }
  45.         led_o;
  46.         led_l;//開指示燈
  47.         for(count=60;count>0;count--);//延時480us
  48. }
  49. void Ds18b20_write(uchar datt)//向DS18B20寫一個字節(jié)
  50. {
  51.         uchar count;
  52.         uchar i;
  53.         temp_o;
  54.         for(i=8;i>0;i--)
  55.         {
  56.                 temp_o;
  57.                 temp_l;
  58.                 for(count=1;count>0;count--);
  59.                 //temp_h;//不能有此語句
  60.                 if(datt&0x01==0x01)
  61.                         temp_i;
  62.                 else
  63.                 {        
  64.                         temp_o;
  65.                         temp_l;
  66.                 }
  67.                 for(count=23;count>0;count--);//延時60us
  68.                 temp_i;
  69.                 for(count=1;count>0;count--);
  70.                 datt>>=1;        
  71.         }        
  72. }
  73. uchar Ds18b20_read(void) //從DS18B20讀一個字節(jié)
  74. {
  75.         uchar i,datt;
  76.         uchar count;
  77.         for(i=8;i>0;i--)
  78.         {
  79.                 datt>>=1;
  80.                 temp_o;
  81.                 temp_l;
  82.                 for(count=1;count>0;count--);
  83.                 temp_i;//改為輸入方向時,上拉電阻把數(shù)據(jù)線拉高,釋放總線,此語句必須有,參考datasheet的P15
  84.                 for(count=1;count>0;count--);
  85.                 if(RC3)//(PORTC&0x08==0x08)//換成(PORTC&0x08==0x08)后程序不正確
  86.                         datt|=0x80;
  87.                 for(count=23;count>0;count--);//延時60us        
  88.         }
  89.         return datt;
  90. }
  91. void lcd_com(uchar com)//向LCD1602寫命令
  92. {
  93.          rs_o;
  94.         rw_o;
  95.         en_o;
  96.         TRISB=0x00;//配置RB為輸出方向
  97.         rs_l;        
  98.         rw_l;
  99.         LCD=com;
  100.         delayms(1);
  101.         en_h;
  102.         delayms(1);        
  103.         en_l;
  104.         delayms(1);               
  105. }
  106. void lcd_dat(uchar dat)//向LCD1602寫數(shù)據(jù)
  107. {
  108.          rs_o;
  109.         rw_o;
  110.         TRISB=0x00;//配置RB為輸出方向
  111.         en_o;
  112.         rs_h;        
  113.         rw_l;
  114.         LCD=dat;
  115.         delayms(1);
  116.         en_h;
  117.         delayms(1);
  118.         en_l;
  119.         delayms(1);        
  120. }
  121. void lcd_write(uchar c,uchar r,uchar dat)//向LCD1602指定行、指定列、寫數(shù)據(jù)
  122. {
  123.         lcd_com(0x80+0x40*c+r);
  124.         lcd_dat(dat);
  125.         delayms(1);
  126. }
  127. void lcd_init(void)//LCD1602初始化,初始化后第一行顯示temperature:,第二行顯示.C
  128. {
  129.         lcd_com(0x38);
  130.         lcd_com(0x0c);
  131.         lcd_com(0x06);
  132.         lcd_write(0,2,0x54);
  133.         lcd_write(0,3,0x65);
  134.         lcd_write(0,4,0x6d);
  135.         lcd_write(0,5,0x70);
  136.         lcd_write(0,6,0x65);
  137.         lcd_write(0,7,0x72);
  138.         lcd_write(0,8,0x61);
  139.         lcd_write(0,9,0x74);
  140.         lcd_write(0,10,0x75);
  141.         lcd_write(0,11,0x72);
  142.         lcd_write(0,12,0x65);
  143.         lcd_write(0,13,0x3a);
  144.         lcd_write(1,11,0xdf);
  145.         lcd_write(1,12,0x43);
  146. }
  147. void show(void)//把溫度值送LCD1602顯示
  148. {
  149.         uchar flag;
  150.         uchar t[4];
  151.         uint temp;
  152.         if(dat2>=240)//遺留問題,溫度為25時讀出dat1=144,dat2=1正確,但卻進入if(dat2&0xf8==0xf8)分支導致顯示亂碼;
  153.         {
  154.                 dat= (~(dat2*256+dat1)+1)*(0.0625*10);//取反加一,保留一位小數(shù)
  155.                 flag=1;
  156.         }
  157.         else
  158.         {
  159.                 dat=(dat2*256+dat1)*(0.0625*10);
  160.                 flag=0;
  161.         };
  162.         temp=dat%10;
  163.         t[0]=(0x30+temp);
  164.         temp=dat%100;
  165.         temp=temp/10;
  166.         t[1]=(0x30+temp);
  167.         temp=dat%1000;
  168.         temp=temp/100;
  169.         t[2]=(0x30+temp);
  170.         temp=dat/1000;
  171.         t[3]=(0x30+temp);
  172.         if(flag==1)//負溫度顯示
  173.         {
  174.                 lcd_write(1,10,t[0]);
  175.                 lcd_write(1,9,0xa5);
  176.                 lcd_write(1,8,t[1]);
  177.                 lcd_write(1,7,t[2]);
  178.                 lcd_write(1,6,t[3]);
  179.                 lcd_write(1,5,0x2d);
  180.         }
  181.         if(flag==0)//正溫度顯示
  182.         {
  183.                 lcd_write(1,10,t[0]);
  184.                 lcd_write(1,9,0xa5);
  185.                 lcd_write(1,8,t[1]);
  186.                 lcd_write(1,7,t[2]);
  187.                 lcd_write(1,6,t[3]);
  188.                 lcd_write(1,5,0x20);//顯示空格,刷掉負號
  189.         }
  190. }
  191. void main(void)
  192. {
  193.         lcd_init();
  194.         while(1)
  195.         {
  196.                 Ds18b20_reset();
  197.                 Ds18b20_write(0xcc);
  198.                 Ds18b20_write(0x44);//發(fā)送溫度轉換命令
  199.                 delayms(1000);//延時1s,等待溫度轉換完成
  200.                 Ds18b20_reset();
  201.                 Ds18b20_write(0xcc);
  202.                 Ds18b20_write(0xbe);//發(fā)送讀溫度寄存器命令
  203.                 dat1=Ds18b20_read();
  204.                 dat2=Ds18b20_read();
  205.                 show();
  206.                 led_h;//關指示燈
  207.                 delayms(2000);
  208.         }
  209. }
復制代碼



PICds18b20(4M).zip

87.02 KB, 下載次數(shù): 36, 下載積分: 黑幣 -5

回復

使用道具 舉報

ID:592524 發(fā)表于 2019-9-26 21:21 | 顯示全部樓層
用什么編譯器?
回復

使用道具 舉報

ID:23844 發(fā)表于 2021-7-18 21:37 | 顯示全部樓層
bbb168 發(fā)表于 2019-9-26 21:21
用什么編譯器?

我估計是MPLAB,看那個#include<pic.h>猜的
回復

使用道具 舉報

ID:955831 發(fā)表于 2021-7-28 15:37 | 顯示全部樓層
bbb168 發(fā)表于 2019-9-26 21:21
用什么編譯器?

應該是PICC編譯器
回復

使用道具 舉報

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

本版積分規(guī)則

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

Powered by 單片機教程網(wǎng)

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