Thông báo

Collapse
No announcement yet.

Đọc ADC với pic 16f887

Collapse
X
 
  • Lọc
  • Giờ
  • Show
Clear All
new posts

  • Đọc ADC với pic 16f887

    Em đang gặp phải 1 vấn đề là nếu mạch bình thường cắm lm35 vô thì nhiệt độ ít thay đổi. Nhưng không hiểu tại sao khi cắm thêm RS232 vô mạch để hiển thị nhiệt độ lên máy tính thì nhiệt độ chạy liên tục, em nghĩ chắc là do cắm nguồn chung với mạch pic nên bị như thế. Mấy bạn cho mình hỏi cách khắc phục và khai báo lại với. Xin cảm ơn.
    setup_adc_ports(sAN0|VSS_VDD);
    setup_adc(ADC_CLOCK_DIV_2);
    em khai như thế này ko biết có đúng ko, em dùng ADC 10bit

  • #2
    thứ 1: lm35 của bạn có qua opamp khuếch đại ko hay cắm trực tiếp ? Bạn có chắc là từ đầu đã tính toán đúng nhiệt độ chưa ?
    thứ 2: cắm thêm rs232 là cắm như thế nào ? hiển thị qua lcd hay led ...
    thứ 3: ghi code cụ thể ra mới biết đường nói chứ ai biết port nào chân nào, setup, delay ...

    "bạn" của "em" đọc xong chẳng ai muốn trả lời
    Đang thất nghiệp 0988-010-486

    Comment


    • #3
      Mình dùng LM35 cắm qua opam khuếch đại.
      Mình cắm cổng RS232 vô luôn trên mạch, nguồn dùng nguồn chung với VDK.
      Hiển thị qua LCD
      #include "D:\Chuong trinh\Do nhiet do\new\main.h"
      #include <def_877a.h>
      #include <lcd_lib_4bit.c>
      int16 giatri,caidat,giatri1;
      int8 mode=0,n=0,i=0,rda=0;
      int8 string[16];
      void hienthi(int8 t);
      void quetphim();
      void gui_rs232(int8 a);
      void gui_cd(int8 a);
      #INT_RDA
      void RDA_interrupt(){
      rda=getc();delay_ms(10);
      n=getc();
      delay_ms(10);

      }
      void main()
      {
      set_tris_A(0xff);
      set_tris_D(0x00);
      lcd_init();
      lcd_putcmd(0x01);
      lcd_putcmd(0x80);
      ENABLE_INTERRUPTS(INT_RDA);
      enable_interrupts(GLOBAL);
      setup_adc_ports(sAN0);
      setup_adc(ADC_CLOCK_DIV_2);
      set_adc_channel(0);



      while (mode==0) {
      giatri=read_ADC();
      giatri=giatri/2.048/4;
      if (giatri!=giatri1) {
      gui_rs232(giatri);
      gui_cd(n);
      }
      giatri1=giatri;
      LCD_putcmd(0x80);
      LCD_putchar("Nhiet do: ");
      LCD_putcmd(0x89);
      HIENTHI(giatri);
      LCD_putchar("oC ");
      LCD_PutCmd(0xC0);
      LCD_putchar("Cai dat : ");
      LCD_putcmd(0xC9);
      HIENTHI(n);
      LCD_putcmd(0xCD);
      LCD_putchar("oC ");
      delay_ms(0.1);
      quetphim();

      }


      }



      void hienthi(int8 t)
      {
      unsigned char v;
      if(t<10)

      LCD_putchar(t+48);
      else
      if(t<100)
      {
      LCD_putchar(t/10+48);
      LCD_putchar(t%10+48);
      }
      else
      {
      v=t/10;
      LCD_putchar(v/10+48);
      LCD_putchar(v%10+48);
      LCD_putchar(t%10+48);
      }
      }
      void quetphim() {
      if (RB0==0) {while (RB0==0) {;} {mode=1;}
      while (mode==1) {
      LCD_putcmd(0x80);
      LCD_putchar("CAI DAT NHIET DO");
      LCD_putcmd(0x89);
      LCD_PutCmd(0xC0);
      LCD_putchar("Cai dat : ");
      LCD_putcmd(0xC9);
      HIENTHI(n);
      LCD_putcmd(0xCD);
      LCD_putchar("oC ");
      delay_ms(0.1);
      if (RB1==0) {while (RB1==0) {;} {n=n+1;}}
      if (RB2==0) {while (RB2==0) {;} {if (n>0) {n=n-1;}}}
      if (RB0==0) {while (RB0==0) {;} gui_cd(n);mode =0;}
      }

      }
      }

      void gui_rs232(int8 a) {

      if(a<10)
      {

      string[1]=a+48;

      puts("A");
      putc(string[0]);
      putc(string[1]);

      }
      if(a>9&&a<100)
      {
      unsigned char c=a/10;
      unsigned char d=a%10;
      string[2]=(c+48);
      string[3]=(d+48);

      puts("A");
      putc(string[2]);
      putc(string[3]);
      }
      if(a>99)
      {
      unsigned char t=a/100;
      unsigned char c=a/10-10*t;
      unsigned char d=a%10;

      string[4]=(t+48);
      string[5]=(c+48);
      string[6]=(d+48);
      puts("B");
      putc(string[4]);
      putc(string[5]);
      putc(string[6]);
      }

      }


      void gui_cd(int8 a) {

      if(a<10)
      {

      string[1]=a+48;

      puts("B");

      putc(string[1]);

      }
      if(a>9&&a<100)
      {
      unsigned char c=a/10;
      unsigned char d=a%10;
      string[2]=(c+48);
      string[3]=(d+48);

      puts("B");
      putc(string[2]);
      putc(string[3]);
      }
      if(a>99)
      {
      unsigned char t=a/100;
      unsigned char c=a/10-10*t;
      unsigned char d=a%10;

      string[4]=(t+48);
      string[5]=(c+48);
      string[6]=(d+48);
      puts("A");
      putc(string[4]);
      putc(string[5]);
      putc(string[6]);
      }

      }

      Comment


      • #4
        Khi rút RS232 ra thì mạch chạy ổn định lắm, nhiệt độ ít thay đổi. Khi cắm vô thì nó nhảy lung tung nhưng vẫn nằm trong khoảng nhiệt độ bình thường,
        nghĩa là +-2 độ. Nhưng nó nhảy kinh quá

        Comment


        • #5
          các khai báo này có ở main.h àh ?

          #device *=16
          #FUSES NOWDT, HS, NOPUT, NOPROTECT, NOBROWNOUT
          #use delay(clock= )
          #use rs232(baud= , xmit=PIN_ ,rcv=PIN_ )
          Đang thất nghiệp 0988-010-486

          Comment


          • #6
            Nguyên văn bởi tay mơ Xem bài viết
            các khai báo này có ở main.h àh ?

            #device *=16
            #FUSES NOWDT, HS, NOPUT, NOPROTECT, NOBROWNOUT
            #use delay(clock= )
            #use rs232(baud= , xmit=PIN_ ,rcv=PIN_ )
            khai báo này ở main.h bạn. Đâu cũng được mà

            Comment


            • #7
              Tui compile lại thấy nhiều warning báo thiếu delay prevent - nhưng vì không biết file main.h nên thôi ko nói về code nữa - cứ coi như code đúng thì phần cứng lỗi,ic max232 bị die, ngắt RDA lấy lệnh (n) từ máy tính - mà máy tính có ON - hoặc gữi sai byte khi sai baud, khi nó bị gọi ngắt liên tục hoặc chạm đè phím quét
              Đang thất nghiệp 0988-010-486

              Comment


              • #8
                không cần cắm vô máy tính thì nó cũng nhảy, đã thử disable ngắt RDA. chỉ cần cắm nguồn của max232 vô là nhảy mặc dù dữ liệu truyền lên và xuống đều đúng

                Comment


                • #9
                  Nguyên văn bởi emperordx Xem bài viết
                  không cần cắm vô máy tính thì nó cũng nhảy, đã thử disable ngắt RDA. chỉ cần cắm nguồn của max232 vô là nhảy mặc dù dữ liệu truyền lên và xuống đều đúng
                  Gửi hình nguyên lý lên đi bạn. Cả hình đi dây mạch in nếu có thể.

                  Việc đọc ADC bạn đã lấy trung bình chưa? Lấy trung bình là một cách đơn giản để ổn định hơn kết quả.

                  p/s: cách viết lệnh của bạn khó nhìn quá. Bạn nên chia thành từng block để phân biệt khối lệnh chức năng, nên cách lề đều cho khối rẽ nhánh hay lặp...
                  Bạn có thấy viết lệnh như phía dưới dễ đọc hơn không?

                  Code:
                  void main()
                  {
                     set_tris_A(0xff);
                     set_tris_D(0x00);
                     lcd_init();
                     lcd_putcmd(0x01);
                     lcd_putcmd(0x80);
                     ENABLE_INTERRUPTS(INT_RDA);
                     enable_interrupts(GLOBAL);
                     setup_adc_ports(sAN0);
                     setup_adc(ADC_CLOCK_DIV_2);
                     set_adc_channel(0);
                     //
                     while (mode==0)
                       {
                        giatri=read_ADC();
                        giatri=giatri/2.048/4;
                        if (giatri!=giatri1)
                          {
                           gui_rs232(giatri);
                           gui_cd(n);
                          }
                        giatri1=giatri;
                        LCD_putcmd(0x80);
                        LCD_putchar("Nhiet do: ");
                        LCD_putcmd(0x89);
                        HIENTHI(giatri);
                        LCD_putchar("oC ");
                        LCD_PutCmd(0xC0);
                        LCD_putchar("Cai dat : ");
                        LCD_putcmd(0xC9);
                        HIENTHI(n);
                        LCD_putcmd(0xCD);
                        LCD_putchar("oC ");
                        delay_ms(0.1);
                        quetphim();
                       }
                  }
                  Tôi không chắc CCSC sẽ xử lý đúng ý đồ của bạn với lệnh giatri=giatri/2.048/4delay_ms(0.1).

                  Comment


                  • #10
                    cảm ơn anh em đã đóng góp ý kiến, mình đã giải quyết được vấn đề này rồi.

                    Comment


                    • #11
                      cho e hỏi cái các bác, e viét chương trình đo adc hiện lcd, chương trình đã chạy nhưng có cái thắc mắc là sao e khai báo #device adc=8 thì ccs dịch bị lỗi, bỏ dòng đó đi thì dịch được, ở đầu chương trình e khai báo #include <16f887.h> rùi. Cho e hỏi luôn trong ccs muốn láy được giá trị adc 10 bít thì lấy như thế nào vậy ạh , sao e thấy lệnh nó ngắn gọn quá, chỉ có readadc thôi àh, thì nó chỉ ra toàn 8 bit thôi hix
                      CK6C -HUI

                      Comment


                      • #12
                        Nguyên văn bởi minhtri0405 Xem bài viết
                        cho e hỏi cái các bác, e viét chương trình đo adc hiện lcd, chương trình đã chạy nhưng có cái thắc mắc là sao e khai báo #device adc=8 thì ccs dịch bị lỗi, bỏ dòng đó đi thì dịch được, ở đầu chương trình e khai báo #include <16f887.h> rùi. Cho e hỏi luôn trong ccs muốn láy được giá trị adc 10 bít thì lấy như thế nào vậy ạh , sao e thấy lệnh nó ngắn gọn quá, chỉ có readadc thôi àh, thì nó chỉ ra toàn 8 bit thôi hix
                        Hàm read_adc() sẽ trả về giá trị ADC có số bit bằng với số bit đã khai báo trong câu lệnh
                        #device *=16 adc=x.
                        Đương nhiên là để lấy được đúng 10 bit phải dùng biến 16 bit.

                        Comment


                        • #13
                          bởi vì pic16f887 có bộ adc 10 bit nên phải khai báo là adc=10 (xem datasheet)
                          muốn thu adc 10 bit thì ta phải có một biến 16 bit (WORD) - tức là dùng 2 biến 8 bit (BYTE), một cái làm byte low, một cái làm byte high ( trong đó byte low dùng đủ 8 bit - byte high chỉ dùng có 2 bit ), nhưng CCS làm ngầm hết mọi chuyện này rồi

                          Code:
                          #include <16F877A.h>
                          #device *=16 ADC=10
                          #fuses HS,NOWDT,NOLVP
                          #use delay(clock=20000000)
                          ...
                          INT16 ADC16
                          ...
                          void main() {
                          ...
                          SET_ADC_CHANNEL (0);
                          ADC16 = READ_ADC ();
                          PRINTF(LCD_PUTCHAR, "%04lu" ADC16 );
                          số đọc đc sẽ hiển thì là từ "0000" tới "1023"
                          zậy thôi
                          Đang thất nghiệp 0988-010-486

                          Comment


                          • #14
                            Nguyên văn bởi tay mơ Xem bài viết
                            bởi vì pic16f887 có bộ adc 10 bit nên phải khai báo là adc=10 (xem datasheet)
                            muốn thu adc 10 bit thì ta phải có một biến 16 bit (WORD) - tức là dùng 2 biến 8 bit (BYTE), một cái làm byte low, một cái làm byte high ( trong đó byte low dùng đủ 8 bit - byte high chỉ dùng có 2 bit ), nhưng CCS làm ngầm hết mọi chuyện này rồi

                            Code:
                            #include <16F877A.h>
                            #device *=16 ADC=10
                            #fuses HS,NOWDT,NOLVP
                            #use delay(clock=20000000)
                            ...
                            INT16 ADC16
                            ...
                            void main() {
                            ...
                            SET_ADC_CHANNEL (0);
                            ADC16 = READ_ADC ();
                            PRINTF(LCD_PUTCHAR, "%04lu" ADC16 );
                            số đọc đc sẽ hiển thì là từ "0000" tới "1023"
                            zậy thôi
                            Không nhất thiết khai báo ADC = 10 tuy ADC là 10 bit.
                            Khai báo ADC = x ( 8 hoặc 10 ) để hỗ trợ trong hàm Read_ADC(). Nếu khai báo ADC=10 thì hàm Read_ADC sẽ trả về giá trị 10 bit tức là giá trị đúng của bộ ADC. Nếu khai báo ADC = 8 thì trong hàm Read_ADC nó sẽ đọc 10 bit của bộ ADC, sau đó chia giá trị 10 bit này cho 4 để được 1 giá trị 8 bit và trả về giá trị 8 bit này và do đó chỉ cần 1 biến 8 bit để lưu giá trị ADC.

                            Comment


                            • #15
                              Nguyên văn bởi duong_act Xem bài viết
                              ...
                              Khai báo ADC = x ( 8 hoặc 10 )
                              ...
                              Với PIC16877 thì x có thể là 8 hoặc 10 hoặc 16.


                              Nguyên văn bởi duong_act Xem bài viết
                              ...
                              Nếu khai báo ADC = 8 thì trong hàm Read_ADC nó sẽ đọc 10 bit của bộ ADC, sau đó chia giá trị 10 bit này cho 4 để được 1 giá trị 8 bit và trả về giá trị 8 bit này và do đó chỉ cần 1 biến 8 bit để lưu giá trị ADC.
                              Làm gì có vụ chia cho 4 ở đây nhỉ. Nếu chọn ADC=8 thì A/D RESULT REGISTERS sẽ được định dạng Left Justified và kết quả trả về của hàm read_adc() là Byte ADRESH.
                              Last edited by Acxen_lupine; 28-03-2013, 00:46.
                              Hôm nay trời nắng chang chang.
                              Mèo con đi học chẳng mang thứ gì.
                              Chỉ mang một cái bút chì.
                              Và mang một mẩu bánh mì con con.

                              Comment

                              Về tác giả

                              Collapse

                              emperordx Tìm hiểu thêm về emperordx

                              Bài viết mới nhất

                              Collapse

                              Đang tải...
                              X