Thứ Sáu, 24 tháng 2, 2012

Code mẫu cho PIC - Đo nhiệt độ, Hiển thị lên LCD 16x2

Bộ chuyển đổi từ tương tự sang số là một khối mạch điện tử quan trọng, có mặt trong rất nhiều thiết kế điện tử. Các bộ ADC thực tế được đóng gói trong những IC chuyên dụng, do nhiều hãng sản xuất. Điểm quan trong cần lưu ý ở các bộ ADC này là độ phân giải và tốc độ lấy mẫu tìn hiệu. Độ phân giải của bộ ADC có thể là 8‐bít, 10‐bít, 12‐bít, 16‐bít, 24‐bít… Tốc độ lấy mẫu của ADC có thể nhanh hay chậm, tùy từng ứng dụng mà ta chọn tốc độ thích hợp.
Vi điều khiển PIC là một trong những dòng Vi điều khiển có phần giao tiếp ngoại vi mạnh và đa dạng. Bên trong PIC đã được tích hợp sẵn một bộ ADC có độ phân giải tối đa là 10‐bít (tùy chon là 8‐bit hay 10‐bit). Với bộ ADC trong PIC ta có thể làm được khá nhiều công việc, dưới đây tôi trình bày một ứng dụng của bộ ADC trong việc thiết kế mạch đo nhiệt độ sử dụng sensor nhiệt LM335.

Dưới đây là phần code mạch đo nhiệt dộ, hiển thị trên LCD.


//=================================================  =======
// Ten chuong trinh  : Mach do nhiet do
// Mo ta phan cung  : Dung PIC16F877A ‐ thach anh 20MHz
//   : LCD giao tiep voi PORTD
//   : Dau ra LM335 dua vao chan AN0
//‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
// Chu thich : hoac cac chu thich khac
//   : dung che do Power On Reset
//   : chuong trinh viet cho PIC Tutorial
//=================================================  =======
#include "16F877A.h"
#include "def_877a.h"
#device *=16 adc=10
#FUSES NOWDT, HS, NOPUT, NOPROTECT, NODEBUG, NOBROWNOUT,
NOLVP, NOCPD, NOWRT
#use delay(clock=20000000)
#use rs232(baud=115200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=9)
#include <lcd_lib_4bit.c>  // Thu vien ham cho LCD
int8 low,high,key,mode,min,max,mode1,i;
int1 do_F;
void convert_bcd(int8 x);
void bao_dong();
void test();
//‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
void main()
{

 float value;
  on_off =1;
  min    =15;   //nhiet do min default
  max    =35;   //nhiet do max default
  do_F   =0 ;
  i = 50 ;
  mode   =0 ;
  mode1 = 0 ;
   trisa = 0xFF;
   trisb = 0x01;
   trisd = 0x00;
      LCD_init();
      Printf(LCD_putchar,ʺLop DT8 ‐ BKHNʺ);
      LCD_putcmd(0xC0);
      Printf(LCD_putchar,ʺKhoi tao...ʺ);
// Khoi tao cho ngat ngoai
      enable_interrupts (INT_EXT);
      ext_int_edge(H_TO_L);
      enable_interrupts (GLOBAL);
// Khoi tao che do cho bo ADC
      setup_adc_ports(AN0);
      setup_adc(ADC_CLOCK_INTERNAL);
      delay_us(10);
// Lay mau nhiet do lan dau tien
      value=(float)read_adc();
      value = (value ‐ 558.5)/2.048;        // For 5V supply
      //    value = (value ‐ 754.8)/2.048;  // For 3.7V Supply
      //    value = (value ‐ 698.2)/2.048;  // For 4V supply
      convert_bcd((int8)value);  // Tach so tram, chuc, donvi de hien thi len LED 7
      delay_ms(1000);
      LCD_putcmd(0xC0);
      Printf(LCD_putchar,ʺKhoi tao xongʺ);
      while(1)
      {
       if (i==50)
          {
            value = read_adc();

 value=(value‐558.5)/2.048;
            if (do_F==1) value=1.8*value+32;
            convert_bcd((int8)value);
            printf(ʺ\n\rNhiet do phong: %uʺ,value);// Gui gia tri len may tinh
            LCD_putcmd(0xC0);
            printf(LCD_putchar,ʺ  Temp = ʺ);
            LCD_putchar(high); LCD_putchar(low);
            if (do_F==0) printf(LCD_putchar,ʺ Cʺ);
            else printf(LCD_putchar,ʺ Fʺ);
            i=0;
          }
       i++;
       if(((int8)value > 40) || ((int8)value < 15)) on_off=1;
       else
        {
         on_off = 0;
         LCD_Putcmd(0xCF);
         LCD_putchar(ʺ ʺ);
         blink=0;
        }
       if (on_off==1)
       {
       if (blink==0) {
LCD_Putcmd(0xCF);LCD_putchar(ʺ!ʺ);blink=1;delay_ms(250);}
       else          {LCD_Putcmd(0xCF);LCD_putchar(ʺ ʺ);blink=0;delay_ms(250);}
       }
     }
   }//end main‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
#INT_EXT
void test()
{
   if (do_F == 1) do_F=0;
   else          do_F=1;
}
void convert_bcd(int8 x)
  {
   low=x%10;  //chia lay phan du, so hang don vi

 high=x/10;   //tach hang tram va hang chuc
   low = low + 0x30;
   high = high + 0x30;
  }
void bao_dong(){
int8 i;
if (blink == 0) blink = 1;
else            blink=0;
     for(i=0;i<50;i++)
     {
      LCD_Putcmd(0xCF);
      if (blink==0) LCD_putchar(ʺ!ʺ);
      else         LCD_putchar(ʺ ʺ);
     }
}

Dưới đây là một sơ đồ dùng PIC và LM335 để đo nhiệt độ, hiển thị trên LCD. Trong chương trình bạn thấy có hàm chuyển đổi nhiệt độ từ ía trị độ K về độ C. Nguyên nhân có hàm đó là do con LM335 thay đổi 10mV/K, ta cần hiển thị là độ C. Nhận thấy 0oC = 273K, như vậy tại 0oC con LM335 sẽ xuất ra một điện áp là 2.73V và với điện áp này, ADC trong PIC sẽ cho giá trị số là:  (2.73*1023)/5 = 558 . 5585 . Như vậy khi tính toán giá trị nhiệt độ ta cần trừ đi giá trị 558.558 này. Công thức đầy đủ là:

 Do_C= [(adc_value)- 558.558] / 2.048
Giá trị 2.048 có là do ta dùng ADC 10‐bit, điện áp lấy mẫu là 5V, như vậy mỗi mức lượng tử sẽ tương ứng với  5V/1024 = 4.883mV.
LM335 thay dổi 10mV/K do đó ứng với sụ thay đổi 1 độ C sẽ thay đổi 2.048 mức lượng tử (10mV/4.883mV = 2.048). Công thức trên là cho ADC 10‐bit, với các bộ ADC 8‐bit hay 12‐bit việc tính toán chuyển đổi giá trị cũng tương tự.
 Mạch đo nhiệt độ LM335 hiển thị trên LCD 16x2


6 nhận xét:

  1. em dùng toàn bị thiết cái file #include . không biết ép vào như thế nào ạ?
    mình có thể add chương trình con có sẵn như thế nào ạ? ví dụ như #include hoặc #include chẳng hạn
    anh có thể giúp em không ạ?

    Trả lờiXóa
  2. cái include def_877a.h đấy ạ

    Trả lờiXóa
  3. @Cao Song Toàn:
    ok bạn. Bạn sửa lại giùm mình các cặp dấu <> thành "" trong các dòng #include.
    VD: #include"16F877A.h" thay vì #include<16F877A.h>
    p/s: nhớ coppy đầy đủ các thư viện vào cùng thư mục project nhé.

    Trả lờiXóa
  4. cu toàn cóc.t lộc đây.t đang làm cái đồ án vdk về hiển thị lưu lượng khí nạp dùng dây sấy bằng LCD.Không biết làm

    Trả lờiXóa
  5. he he, Lộc 12A1 ah? ông học ngành gì trong đà nẵng thế? có email không?mình liên lạc

    Trả lờiXóa
  6. bạn có thư viện cho def_877a.h với thư viện lcd_lib_4bit.c không cho mình xin với

    Trả lờiXóa