Thông báo

Collapse
No announcement yet.

Pic16f877a tách chuỗi dữ liệu nhận được từ rs232

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

  • Pic16f877a tách chuỗi dữ liệu nhận được từ rs232

    Tôi muốn dùng VĐK PIC16f877a nhận chuỗi dữ liệu từ một thiết bị khác thông qua cổng com(RS232) và tách dữ liệu này theo mong muốn
    VD chuổi nhận được từ cổng RS232 là "+QNH 1010 QFE 1009 TEMP 25.5 OK"
    Giá trị tách ra theo mong muốn là:
    QNH=1010
    QFE=1009
    TEMP=25.5
    Xin các cao thủ giúp mình cho một ví dụ về ngôn ngữ c thể hiện yêu cầu trên.
    Thanks
    Cả thế giới đều nằm trong cuốn "Tự điển" do đó tôi rất thích điện tử

  • #2
    Nguyên văn bởi dtbinhtomay2 Xem bài viết
    Tôi muốn dùng VĐK PIC16f877a nhận chuỗi dữ liệu từ một thiết bị khác thông qua cổng com(RS232) và tách dữ liệu này theo mong muốn
    VD chuổi nhận được từ cổng RS232 là "+QNH 1010 QFE 1009 TEMP 25.5 OK"
    Giá trị tách ra theo mong muốn là:
    QNH=1010
    QFE=1009
    TEMP=25.5
    Xin các cao thủ giúp mình cho một ví dụ về ngôn ngữ c thể hiện yêu cầu trên.
    Thanks
    Không ai có thể giúp mình ah?
    Cả thế giới đều nằm trong cuốn "Tự điển" do đó tôi rất thích điện tử

    Comment


    • #3
      Nguyên văn bởi dtbinhtomay2 Xem bài viết
      VD chuổi nhận được từ cổng RS232 là "+QNH 1010 QFE 1009 TEMP 25.5 OK"
      sao ko ví dụ vậy cho dễ :
      AxxBxxCxxD
      trong đó xx là các số hex 00-> FF = 00 -> 65535
      A,B,C,D LÀ KÝ TỰ

      tại ngắt rda bạn kiểm tra xem byte đầu tiên nhận đc có phải là "A" hay ko?
      NẾU ĐÚNG LÀ "A" THÌ BÁO HIỆU BIẾT CÓ MỘT LUỒNG DỮ LIỆU ĐC GỮI
      sau đó khởi động một vòng lập 1 -> 9

      KHI NHẬN ĐỦ MÔT BYTE THÌ LƯU LẠI THEO THỨ TỰ

      byte thứ 2 lưu vào biến tạm thứ 1
      byte thứ 3 lưu vào biến tạm thứ 2
      ...
      ...
      byte thứ 10 lưu vào biến tạm thứ 9

      kiểm tra BIẾN TẠM thứ 3 có phải là "B" hay ko?
      kiểm tra BIẾN TẠM thứ 6 có phải là "C" hay ko?
      kiểm tra BIẾN TẠM thứ 9 có phải là "D" hay ko?

      NẾU ĐÚNG HẾT THÌ BIẾT CÓ LUỒNG DỮ LIỆU ĐÃ NHẬN ĐỦ VÀ ĐÚNG
      NẾU KO -> NHẬN SAI -> LÀM GÌ ĐÓ...(SỬA SAI, BÁO GỮI LẠI...)

      A= LẤY BIẾN TẠM THỨ 1 VÀ 2 KẾT HỢP LẠI THÀNH BIẾN 16BIT
      B= LẤY BIẾN TẠM THỨ 4 VÀ 5 KẾT HỢP LẠI THÀNH BIẾN 16BIT
      C= LẤY BIẾN TẠM THỨ 7 VÀ 8 KẾT HỢP LẠI THÀNH BIẾN 16BIT
      Đang thất nghiệp 0988-010-486

      Comment


      • #4
        Nguyên văn bởi tay mơ Xem bài viết
        sao ko ví dụ vậy cho dễ :
        AxxBxxCxxD
        trong đó xx là các số hex 00-> FF = 00 -> 65535
        A,B,C,D LÀ KÝ TỰ

        tại ngắt rda bạn kiểm tra xem byte đầu tiên nhận đc có phải là "A" hay ko?
        NẾU ĐÚNG LÀ "A" THÌ BÁO HIỆU BIẾT CÓ MỘT LUỒNG DỮ LIỆU ĐC GỮI
        sau đó khởi động một vòng lập 1 -> 9

        KHI NHẬN ĐỦ MÔT BYTE THÌ LƯU LẠI THEO THỨ TỰ

        byte thứ 2 lưu vào biến tạm thứ 1
        byte thứ 3 lưu vào biến tạm thứ 2
        ...
        ...
        byte thứ 10 lưu vào biến tạm thứ 9

        kiểm tra BIẾN TẠM thứ 3 có phải là "B" hay ko?
        kiểm tra BIẾN TẠM thứ 6 có phải là "C" hay ko?
        kiểm tra BIẾN TẠM thứ 9 có phải là "D" hay ko?

        NẾU ĐÚNG HẾT THÌ BIẾT CÓ LUỒNG DỮ LIỆU ĐÃ NHẬN ĐỦ VÀ ĐÚNG
        NẾU KO -> NHẬN SAI -> LÀM GÌ ĐÓ...(SỬA SAI, BÁO GỮI LẠI...)

        A= LẤY BIẾN TẠM THỨ 1 VÀ 2 KẾT HỢP LẠI THÀNH BIẾN 16BIT
        B= LẤY BIẾN TẠM THỨ 4 VÀ 5 KẾT HỢP LẠI THÀNH BIẾN 16BIT
        C= LẤY BIẾN TẠM THỨ 7 VÀ 8 KẾT HỢP LẠI THÀNH BIẾN 16BIT
        Cám ơn bạn đã trả lời.
        Bạn có thể minh hoạ cụ thể bằng ngôn ngữ C được không? Mình cũng đã làm thử bằng CCS nhưng không chạy

        #include <16F877A.h> // PIC16F877 header file
        #use delay(clock=8000000) // for 8Mhz crystal
        #fuses HS, NOWDT, NOPROTECT, NOLVP // for debug mode
        #include "LCD.c"
        #use rs232(baud=2400, xmit=PIN_C6, rcv=PIN_C7, stream=PC)


        int8 temp;
        char buffRev[32];
        int8 idx = 0, i = 0;
        void displayOnLCD(void);

        void main(void)
        {
        lcd_init(); // Init LCD.
        lcd_gotoxy(1,1);
        printf(lcd_putc, "%s", "Please wait..");
        delay_ms(5000);
        lcd_init();
        lcd_gotoxy(1,1);
        printf(lcd_putc, "%s", "Boot done!");
        delay_ms(2000);
        lcd_init();
        putc('P');//gui lenh den thiet bi de gui du lieu
        //delay_ms(1000);
        while(1)
        {
        if(0 != kbhit())//kbhit=1 dang thu
        {
        temp = fgetc(PC);
        if(temp=='+'){ // Neu ky tu nhan dc bang ky tu + thi khoi tao lai gia tri.
        for(i=0; i<sizeof(buffRev); i++) buffRev[i]= ' ';
        idx = 0;
        continue;
        }else if(temp=='O'){ // neu bang ky tu ket thuc thi truyen lai cho PC(OK: layky tu ket thuc la chu O).
        for(i=0; i<idx; i++)
        {
        //giai thuat tach du lieu o day.
        }
        displayOnLCD(); // Hien thi ket qua thu duoc len LCD.
        continue;
        }
        buffRev[idx++] = temp;
        }
        }
        }
        //hien thi chuoi du lieu nhan duoc
        void displayOnLCD()
        {
        lcd_init(); // Init LCD.
        lcd_gotoxy(1,1);
        printf(lcd_putc, "%s", buffRev);
        delay_ms(2000);//sau moi 2s gui tiep lenh den thiet bi
        putc('P');
        }
        Cả thế giới đều nằm trong cuốn "Tự điển" do đó tôi rất thích điện tử

        Comment


        • #5
          giả sử bên máy phát - phát ra 6 byte như sau
          Code:
          while (true){
          putc('A');
          putc('1');
          putc('2');
          putc('B');
          putc('3');
          putc('4');
          delay_ms(700);
          putc('A');
          putc('9');
          putc('8');
          putc('B');
          putc('7');
          putc('6');
          delay_ms(700);}
          Bên máy thu nhận và phân tách byte

          Code:
          void main() {
          int bytenhanduoc[6];
          int i;
          loop:
          if(kbhit()){
          bytenhanduoc[i]=getch();
          ++i;
          if (i==6)
          {
          i=0;
          goto hienthi;
          }
          
          }
          goto loop;
          
          hienthi:
          LCD_PutCmd ( 0x80);
          Printf(LCD_putchar,"%c" bytenhanduoc[0]);
          Printf(LCD_putchar,"%c" bytenhanduoc[1]);
          Printf(LCD_putchar,"%c" bytenhanduoc[2]);
          Printf(LCD_putchar,"%c" bytenhanduoc[3]);
          Printf(LCD_putchar,"%c" bytenhanduoc[4]);
          Printf(LCD_putchar,"%c" bytenhanduoc[5]);
          goto loop;
          }
          mô phỏng
          Click image for larger version

Name:	mophong-rs232.JPG
Views:	1
Size:	104.9 KB
ID:	1367936
          Đang thất nghiệp 0988-010-486

          Comment


          • #6
            Cám ơn bạn đã trả lời.
            Như ví dụ trên ta chỉ mới hiển thị chuổi số liệu từ máy phát trên LCD, chưa có tách chuỗi như mong muốn
            Ý của mính là: ví dụ như máy phát phát ra chuỗi số liệu:"A12.3B25.6" có nghĩa là A=12.3 ; B=25.6
            mình muốn lấy giá trị A=12.3 và giá trị B=25.6 là tính toán sau đó mói hiển thị giá trị tính toán được lên LCD.
            Cụ thể là A=12.3 * 0.2= 2.46, mình muốn hiển thị 2.46 lên LCD
            Mình nghĩ là trước hết tách chuỗi 12.3 gán vào biến A sau đó đổi kiểu dữ liệu từ str sang float và làm tính toán và hiển thị kết quả.
            mình không rành về c lắm nên không biết có các hàm nào hổ trợ các vấn đề trên k?(vd đổi chuổi sang số hay tách chuổi như hàm mid trong vb)
            Last edited by dtbinhtomay2; 10-10-2012, 08:23.
            Cả thế giới đều nằm trong cuốn "Tự điển" do đó tôi rất thích điện tử

            Comment


            • #7
              các cao thủ đi đâu hết ùi
              Cả thế giới đều nằm trong cuốn "Tự điển" do đó tôi rất thích điện tử

              Comment


              • #8
                mình đã nói ở trên mà :
                FF = 65535
                thì thay vì bạn lưu a = 12.3 bạn sẽ lưu là a= 1230
                1230*2 = 2460
                khi hiển thị chỉ hiển thị 2 kí tự thôi rồi hiển thị dấu chấm "." và 2 kí tự cuối %2.2w

                Code:
                void main() {
                LCD_init();
                int16 m;
                m = 2460;
                LCD_PutCmd ( 0x80);
                Printf(LCD_putchar,"%2.2w"m);
                => 24.60
                Đang thất nghiệp 0988-010-486

                Comment


                • #9
                  Nguyên văn bởi tay mơ Xem bài viết
                  mình đã nói ở trên mà :
                  FF = 65535
                  thì thay vì bạn lưu a = 12.3 bạn sẽ lưu là a= 1230
                  1230*2 = 2460
                  khi hiển thị chỉ hiển thị 2 kí tự thôi rồi hiển thị dấu chấm "." và 2 kí tự cuối %2.2w

                  Code:
                  void main() {
                  LCD_init();
                  int16 m;
                  m = 2460;
                  LCD_PutCmd ( 0x80);
                  Printf(LCD_putchar,"%2.2w"m);
                  => 24.60
                  ý của tui là :
                  Giá trị chuổi nhận được kg phải là int mà là số thực:
                  Lấy VD chuỗi trên "A12.3B25.6". Như vậy có nghĩa là
                  Chr data[4];
                  data[0]='A'
                  data[1]='1'
                  data[2]='2'
                  data[3]='.'
                  data[4]='3'
                  .
                  .
                  .
                  data[9]='6'
                  - cho vòng lặp i=1 đến 4 tui sẽ tách ra được chuỗi "12.3" và tui gán vào biến A kiễu mang 4 phần tử tui có được A="12.3"
                  - dùng hàm strcpy vd: strcpy(bientinh,A)
                  - dùng hàm atol() chuyển kiễu string sang number vd:ketqua=atol(bientinh) . biến ketqua bây giờ là số dùng để tính toán theo muc đích yêu cầu
                  vd: giatri_in=ketqua * 0.2 (0.2 là ví dụ)
                  - hiển thị ra LCD: printf(lcd_putc, "%2.2f", y);//in ra kiểu số thực 02 số trước dấu "." và 02 số sau dấu "."
                  Tui đã nạp code vào chip và chạy thành công. Cám ơn bạn tay mơ đã giúp đỡ
                  Cả thế giới đều nằm trong cuốn "Tự điển" do đó tôi rất thích điện tử

                  Comment


                  • #10
                    luồng này ko biết còn hoạt động không T T.
                    Mình cũng đang lập trình rs232 PIC16<->máy tính mình ko lập trình bằng CCS mà lập trình bằng Hi-tech không biết có khác gì ko.
                    Theo mình nhớ thì truyền UART thường để dạng char (để có thể truyền được cả ký tự thường sẽ là kiểu char) mình chuyền đi 12.3 thì sẽ là 4 char '1','2','.','3' lúc này bạn phải viết chuơng trình đọc cái chuỗi string này ra kiểu int. không xử lý trực tiếp được.
                    Code:
                    int chuyendoi(char data[],int s,int t)//data[] mang kieu char, s chi so bat dau chuoi, t chi so ket thuc chuoi
                    {
                    int kq=data[t];
                    int j,i=10;
                    for(j=t-1;j>=s;j--)
                    {
                    	switch(data[j])
                    	{
                    	case '1':kq+=1*i;
                    			break;
                    	case '2':kq+=2*i;
                    			break;
                    	case '3':kq+=3*i;
                    			break;
                    	case '4':kq+=4*i;
                    			break;
                    	case '5':kq+=5*i;
                    			break;
                    	case '6':kq+=6*i;
                    			break;
                    	case '7':kq+=7*i;
                    			break;
                    	case '8':kq+=8*i;
                    			break;
                    	case '9':kq+=9*i;
                    			break;
                    	i=i*10;
                    	}
                    }
                    break kq;
                    )
                    cách trên ưu điểm có thể truyền các số bự ( uart bình thường truyền 8 bit đọc kiểu int chỉ đến 256) nhược điểm loằng ngoằng
                    cách khác là ký hiệu một ký tự đặc biệt, dùng lệnh for, if phát hiện ký tự đặc biệt rồi đọc ký tự tiếp ngay sau nó ở dạng int .

                    Tiện đây mọi người cho mình hỏi. mình lập trình truyền uart từ máy tính xuống Pic6f877a thì truyền được(vxl nhận lệnh thực hiện lệnh) , vxl của mình cứ 1s lại gửi dữ liệu lên 1 lần nhưng máy tính không nhận được. mình sử có sử dụng usb converter 232 để nối Pic & máy tính. dùng terminal gửi-nhận dữ liệu T T. giả lập chạy rất tốt ra mạch thật thì máy tính chỉ gửi được mà ko nhận được >"< mình đã test cái usb converter 232 ko bị lỗi. ai biết tại sao ko?

                    Comment


                    • #11
                      chủ topic đã giải quyết rồi
                      - quay lại với điều bạn nói :mình đang nói về ccs , nói chung ngôn ngữ c giống nhau thôi
                      nhưng cách bạn nói gữi số 12.3 mà phải tốn đến 4 byte :'1','2','.','3' trong khi tôi chỉ dùng 2 byte "1230xdec"

                      trong những trường hợp cụ thể ta dùng khác đi như đo nhiệt độ thì không phải gữi character làm gì

                      vd:thực tế vài mạch đo gữi giá trị nhiệt độ từ 0 độ đến 200 độ với 1 số thập phân
                      tức là 0.0 tới 199.9 thì ta dùng 2 byte : 0000 tới 1999
                      nếu với 2 chữ số thập phân ta vẫn dùng 2 byte (0.00 -> 199.99) 00000 tới 19999 ( vì nó < 65535)
                      trong khi cách bạn phải tốn 6 byte

                      CCS có sẳn hàm xử lý luôn nhưng nếu xài ta sẽ tốn nhiều chu kì lệnh (pic16 chậm mà- trường hợp vđk phải dành thời gian làm việc khác)

                      Lỗi bạn nói ở trên có khi do phần cứng hay code trên vb - nói chung chung vậy ko giải thích được
                      mà mô phỏng với làm mạch thiệt khác nhau nhiều lắm - đừng quá tự tin vào mô phỏng
                      (vd mô phỏng có cần cấp nguồn đâu mà nó chạy vèo vèo - đến lúc làm mạch thật thì mối hàn hở - ko chạy cứ tưởng code lỗi)

                      àh PIC là Vi điều khiển chứ không phải là vi xử lý đâu
                      Đang thất nghiệp 0988-010-486

                      Comment


                      • #12
                        sử dung hàm strtok() của thư viện string để xử lý vụ này là tối ưu nhất.


                        http://www.dientuvietnam.net/forums/...76/#post631773
                        Last edited by chumanh; 18-11-2012, 11:37.

                        Comment


                        • #13
                          Cảm ơn! tôi làm được rồi!

                          Comment


                          • #14
                            0x0D 0x02 0x31 0x30 0x20 0x30 0x35 0x30 0x36 0x38 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x0D 0x02 0x31 0x30 0x20 0x30 0x35 0x30 0x36 0x38 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x0D
                            Cao thu cho hoi...! toi co 1 chuoi so hex nhu tren. toi dung pic 16f887 doc len tu 1 thiet bi khac. chuoi nay dc truyen len lien tuc byte bat dau la 0X0D va khi thay 0x0D tiep theo dc lap lai thi co nghia la het 1 chuoi. bjo lam sao de tach lay tung byte so hex va luu vao mang tam dc. toi dung ngat.
                            Moi khi so tren thiet bi thay doi thi phai nhay vao ngat de nhan lai chuoi so moi.....
                            Moi nguoi giup toi voi....! Cam on nhieu...!

                            Comment

                            Về tác giả

                            Collapse

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

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

                            Collapse

                            Đang tải...
                            X