Thông báo

Collapse
No announcement yet.

Cấp phát dữ liệu động, xử lý bit khó quá !!!

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

  • Cấp phát dữ liệu động, xử lý bit khó quá !!!

    Trong khi cả thế giới điện tử đang lao vào và các ứng dụng đều mang tính động , dữ liệu động ( dynamic data ) bây giờ ứng dụng quá nhiều trong khi các anh em vẫn chưa được tiếp xúc và phổ cập ( trong đó có cả QD nữa ), rất mong các bác " nói nhiều trên diễn đàn " , những người có kinh nghiệm góp chút sức lực cho chủ đề.
    Dữ liệu động có thể làm gì ???
    Đó là cách xử lý thông minh và hiện đại : với dữ liệu động bạn có thể thay đổi liên tục dữ liệu ( nó ứng dụng trong truyền thông ) , trong bảo mật nó được ứng dụng cảnh báo , mã khóa .
    trong điều khiển nó được coi là mấu chốt " bộ não " giao tiếp với con người
    nó còn được xử lý cấp phát phân luồng trong các bộ nhớ.
    và tất nhiên còn rất nhiều ứng dụng ( mà tôi mới tìm hiểu nên không biết ... hic hic ).

    Dưới đây là một bài toán :

    Đề bài : phát một chuỗi bit cố định 12 bit ra chân RB1
    các bit này được nhập từ bàn phím ( số nhập từ bàn phím là thập phân )
    thứ tự các bit phát ra như sau : bit 11 , bit 11, bit 10 ... bit 0

    ( theo hàm thời gian bit 0 được truyền ra chân RB1 trước , bit 11 sau cùng )

    lấy ví dụ : nhập từ bàn phím số 9 ( đổi ra nhị phân được 1001 ) vậy ta sẽ phải phát một chuỗi như sau : 000000001001

    giới hạn của đề bài : không được dùng mảng để lưu trữ và xử lý dữ liệu , chỉ được thao tác trên phạm vi byte , bit

    Không biết các cao thủ " vi điều khiển " có ý kiến gì hay cho tại hạ xem.
    ( tại hạ chỉ sử lý được bài trên với mảng dữ liệu động , còn thao tác xử lý trên bit , byte ( không dùng mảng ) thì chịu ).

    ( có tham khảo ý kiến của bác Binh ANH tuy nhiên ý của các không khả thi - vì nếu dùng mảng hoặc khai báo bank khác vẫn tốn tài nguyên và khi sử dụng bank thì không đặt dữ liệu tĩnh khi cần thiết được ).
    Last edited by queduong; 15-04-2006, 23:19.
    Module RF chuyên dụng điều khiển, truyền dữ liệu, thiết kế đề tài, dự án điện tử - chuyển giao công nghệ... ĐT: 0904964977 - email: dientuqueduong@yahoo.com

  • #2
    liệu có thể chỉ dùng dịch bit trong trường hợp này ??? chưa chắc đã ăn thua.
    Bác Falleaf bảo học DSP trong một ngày hay hai ngày gì đó thử giúp tôi với.
    Module RF chuyên dụng điều khiển, truyền dữ liệu, thiết kế đề tài, dự án điện tử - chuyển giao công nghệ... ĐT: 0904964977 - email: dientuqueduong@yahoo.com

    Comment


    • #3
      Nguyên văn bởi queduong
      Đề bài : phát một chuỗi bit cố định 12 bit ra chân RB1
      các bit này được nhập từ bàn phím ( số nhập từ bàn phím là thập phân )
      thứ tự các bit phát ra như sau : bit 11 , bit 11, bit 10 ... bit 0

      ( theo hàm thời gian bit 0 được truyền ra chân RB1 trước , bit 11 sau cùng )

      lấy ví dụ : nhập từ bàn phím số 9 ( đổi ra nhị phân được 1001 ) vậy ta sẽ phải phát một chuỗi như sau : 000000001001

      giới hạn của đề bài : không được dùng mảng để lưu trữ và xử lý dữ liệu , chỉ được thao tác trên phạm vi byte , bit
      Cái này của bác QD có liên quan gì đến cấp phát dữ liệu động đâu nhỉ ?
      Liệu làm như này có đc ko :

      void OutBit(unsigned int xData)
      {
      unsigned char i;
      for(i=0;i<12;i++)
      {
      DataOut = ((xData & 0x01)==1?1:0);//DataOut là chân ra của VDK
      xData>>=1; // dịch phải 1 bit
      }

      }

      hoặc : có thể dùng con thanh ghi dịch vào song ra nối tiếp , vd 74HC597 .
      Last edited by trungkt; 12-04-2006, 09:58.

      Comment


      • #4
        Nguyên văn bởi queduong
        ( có tham khảo ý kiến của bác Binh ANH tuy nhiên ý của các không khả thi - vì nếu dùng mảng hoặc khai báo bank khác vẫn tốn tài nguyên và khi sử dụng bank thì không đặt dữ liệu tĩnh khi cần thiết được ).
        Bác cần thêm vài dòng NOP ở những chỗ cần thiết, chứ truyền 12 bit xong lại truyền thêm các bit cố định khác nữa mà ko chèn NOP thì dữ liệu tất nhiên không đều. Tui đã làm mấy cái này cho module rfPIC cũng như cho IR mấy năm nay vẫn chạy tốt, thậm chí dùng dao động nội của PIC12F683(8mhz) chứ chưa nói tới thạch anh đâu.
        Sửa một tý của bác trungkt thì chạy nhanh hơn tẹo.
        void OutBit(unsigned int xData)
        {
        unsigned char i=12;
        while(i--){
        DataOut = ((xData & 0x01)==1?1:0);//DataOut là chân ra của VDK
        xData>>=1; // dịch phải 1 bit
        DELAY();
        }
        }

        Cách khác:
        const unsigned int mask_bit()={0b100000000000,0b010000000000,0b0010.. .}

        void OutBit(unsigned int xData)
        {
        unsigned char i=12;
        while(i--){
        DataOut = ((XData & mask_bit(i)) ==1?1:0));//DataOut là chân ra của VDK
        DELAY();
        }
        }

        Hoặc bác khai báo biến thành 2 byte và làm tương tự trên cũng đc.

        Nếu bác truyền dài hơn nữa thì thỉnh thoảng bên thu phải đồng bộ lại, nếu dùng mã Maschester thì khó hơn, nhưng nếu dùng mã kiểu PWM(giống như mã của tivi SONY) thì càng dễ

        Comment


        • #5
          Cảm ơn hai bác đã tận tình chỉ dạy có một điều là khi dùng với truyền thông có dây ... ta có thể thay đổi liên tục giá trị nạp vào và phần phát vẫn đồng bộ với phần thu .
          Ở đây nếu dùng cách này để phát " mã hóa dữ liệu " trong truyền không dây ( wireless ) thì ... chỉ được đúng một chuỗi đầu tiên .
          Các chuỗi sau không tài nào đồng bộ được khi đang truyền mà thay đổi dữ liệu , nếu thêm các bit cố định ( ví dụ các phần khởi tạo ) thì khả năng mất đồng bộ giữa thu và phát do sai lệch về thời gian.

          Tôi đã thử làm với mảng và nó chính xác hơn , nhưng tốn rất nhiều tài nguyên . Đây là một đoạn mã :
          int N ; // N là số được nhập vào từ bàn phím
          unsigned char dulieu[12], i ;
          ...........................
          for (i=11 ; i>0 ; i--)
          { if ((N&1) ==1) {dulieu[i] =1;} else {dulieu[i] =0;}
          if(i>1) { N >> =1;}
          }

          sau đó truyền theo thời gian , truyền bit o trước ( thực chất là dulieu[0] )

          for (i =0 ; i<11 ; i++)
          { if ((dulieu[i]&1) ==1) { RB1 =1;} else {RB1 =0; }
          Delay();

          //////////////////
          Áp dụng cách này tốn kém tới 12 byte bộ nhớ nhưng truyền rất chính xác theo thời gian và rất dễ đồng bộ .
          Tuy nhiên với những bài cần truyền 64 bit hoặc nhiều hơn thì hết chỗ của bộ nhớ. ==> Bó tay

          Không biết hai bác có nhã ý giải thích hộ tôi xem nếu truyền 3 lần vòng for như của bác BA và trungkt thì cái thời gian chiếm mỗi vòng ( for ) là bao nhiêu vậy , tôi không biết nên chưa biết cách bù trừ thế nào cả .
          Cứ ngồi gõ bù thêm từng lệnh NOP(); cả chiều nay mà vẫn không đồng bộ được
          ( có cách nào như kiểu ta lắp hoàn toàn dữ liệu vào mảng " kiểu lắp đạn vào băng đây " sau đó cứ thế là bắn không ).

          Có cách dùng mảng mà tối giản được không ?

          -------------
          Bác BA có bảo khai báo mảng trên một bank khác tôi cũng đã thử
          unsigned char bank1 dulieu[12]; ( sử dụng PIC16F84A )

          tuy nhiên khi dịch bị hiện lên cảnh báo :
          Warning[000] not special -p option (C:\HTPIC \ LIB \a40.obj )
          không hiểu có gì sai ở đây .
          Mong lời giải đáp
          Module RF chuyên dụng điều khiển, truyền dữ liệu, thiết kế đề tài, dự án điện tử - chuyển giao công nghệ... ĐT: 0904964977 - email: dientuqueduong@yahoo.com

          Comment


          • #6
            Hiz, từ đề bài phát 12 bít bạn bay qua luôn 64 bít.
            "không được dùng mảng để lưu trữ và xử lý dữ liệu , chỉ được thao tác trên phạm vi byte , bit" : mà dùng byte thì phải dùng nhiều byte, thế thì lại thành mảng . 64 bít thì 8 byte, thì như là mảng 8 phần tử unsigned char vậy.
            Mà hình như bạn lại không thích dùng thêm phần cứng phụ trợ đồng bộ ngoài !

            Dùng Comparator được không bác, hoặc PWM, timer gì đó cũng được ? cái này là để chính xác thời gian đồng bộ, có sẵn trong PIC mà.
            Cứ cho là 64 bít, mất 8 byte, vậy thêm 8x4 = 32 byte cho 4 lần nhập dữ liệu.
            Rồi.

            Comment


            • #7
              Tôi thấy bài toán này nếu sử dụng assemler thì tốn rất cực kỳ ít tài nguyên và chạy nhanh. Cụ thể, đoạn chương trình dưới đây là mở rộng cho 12 bít của 1 đoạn sử dụng để truyền 8 bit dữ liệu tôi đã làm từ cách đây 6-7 năm, chạy liên tục đến nay vẫn tốt.
              ; Chuong trinh con truyen so 12 bit qua port RB1
              ; 8 bit thap dat trong N1, 4 bit cao dat trong N2

              Transmit ;
              movlw 0x08
              movwf counter
              bcf PORTB,RB1 ; Truyen bit start
              call Delay_one_bit
              Transmit_loop1 ; Truyen 8 bit thap cua N
              rrf N1
              btfsc STATUS,C
              bsf PORTB,RB1
              btfss STATUS,C
              bcf PORTB,RB1
              call Delay_one_bit
              decfsz counter,f
              goto Transmit_loop1

              movlw 0x04 ; Truyen 4 bit cao cua N
              movwf counter
              Transmit_loop2
              rrf N2
              btfsc STATUS,C
              bsf PORTB,RB1
              btfss STATUS,C
              bcf PORTB,RB1
              call Delay_one_bit
              decfsz counter,f
              goto Transmit_loop2

              bsf PORTB,RB1 ; Truyen bit stop
              call Delay_one_bit

              return

              Đoạn chương trình này chỉ sử dụng 1 biến nháp counter (1 byte). Để truyền 64 bit, thêm 1 vòng lặp và 1 biến counter2 nữa thôi.

              Comment


              • #8
                Nguyên văn bởi saosau89
                Hiz, từ đề bài phát 12 bít bạn bay qua luôn 64 bít.
                "không được dùng mảng để lưu trữ và xử lý dữ liệu , chỉ được thao tác trên phạm vi byte , bit" : mà dùng byte thì phải dùng nhiều byte, thế thì lại thành mảng . 64 bít thì 8 byte, thì như là mảng 8 phần tử unsigned char vậy.
                Mà hình như bạn lại không thích dùng thêm phần cứng phụ trợ đồng bộ ngoài !

                Dùng Comparator được không bác, hoặc PWM, timer gì đó cũng được ? cái này là để chính xác thời gian đồng bộ, có sẵn trong PIC mà.
                Cứ cho là 64 bít, mất 8 byte, vậy thêm 8x4 = 32 byte cho 4 lần nhập dữ liệu.
                Rồi.

                Các bạn chưa hiểu ý đồ của bài toán , để lấy bất kì bit ở vị trí nào trong chuỗi phát đi ( nếu đơn giản ta dùng mảng )
                ta có thể phát đi tín hiệu 1 hoặc 0 ra 1 chân nếu sử dụng mảng [i]

                nhưng ở đây : với bài toán 12 bit ta có thể khai báo mảng thành
                unsigned char dulieu[12];
                như vậy tốn mất 12 byte
                Đáng lẽ ra nếu ta chỉ sử lý bằng byte và bit ( không khai báo mảng ) ta chỉ dùng hết 2 byte thay vì 12 byte nếu dùng mảng.
                ( 2 byte = 16 bit )
                --- Đặt trường hợp tiếp theo : nếu bài toán yêu cầu truyền 64 bit ( các bit này có thể thay đổi dữ liệu liên tục )

                Nếu dùng byte bit để xử lý , ta chỉ mất có 8 byte bộ nhớ.
                Nếu dùng mảng mà chỉ sử lí 2 trạng thái 0 và 1 phát ra thì ta mất tới 64 byte bộ nhớ và như vậy không còn bộ nhớ để viết nữa ( vì bộ nhớ Ram của vi điều khiển có hạn : ví dụ PIC16F84A chẳng hạn )

                /////////////////////////////

                Trở lại vấn đề về 2 cách của bác Trungkt và BinhAnh , thực ra hai cách của các bác không khác gì cách của tôi như sau :

                for ( i =0; i<12 ; i++)
                { if((xData&1) ==1) { RB1 =1;} else { RB1 =0;}
                if (i<11) {xData >>=1; }
                Delay();
                }

                Vấn đề này tôi đã đề cập.
                /////////////////////////////////////////////
                Với bài của 2 bác BA và Trungkt dữ liệu đầu ra bị ngược
                Ví dụ : xData = 280 ;
                thì tại chân RB1 ( với bài giải của bác BA và Trungkt ) sẽ thu được :
                000110001000 bit 14 --- bit 0 ( bit 0 thu được trước )

                Đáng lẽ ra phải thu được : 000100011000 mới là đúng đề bài .
                Dữ liệu của các bác phát ra bị ngược so với đề bài . Cách này thì em cũng làm được

                Không biết các bác có cao kiến gì để đảo ngược dữ liệu vậy ???

                ( theo bác BA là đảo ngược trước khi phát : tôi chưa hình dung ra là làm thế nào ).
                Module RF chuyên dụng điều khiển, truyền dữ liệu, thiết kế đề tài, dự án điện tử - chuyển giao công nghệ... ĐT: 0904964977 - email: dientuqueduong@yahoo.com

                Comment


                • #9
                  Cách ghi vào biến nháp ( không dùng mảng ) của bạn supernova dùng trong C có giải thuật thế nào , mong các bác hướng dẫn.
                  Module RF chuyên dụng điều khiển, truyền dữ liệu, thiết kế đề tài, dự án điện tử - chuyển giao công nghệ... ĐT: 0904964977 - email: dientuqueduong@yahoo.com

                  Comment


                  • #10
                    Nếu dùng byte bit để xử lý , ta chỉ mất có 8 byte bộ nhớ.
                    Nếu dùng mảng mà chỉ sử lí 2 trạng thái 0 và 1 phát ra thì ta mất tới 64 byte bộ nhớ và như vậy không còn bộ nhớ để viết nữa ( vì bộ nhớ Ram của vi điều khiển có hạn : ví dụ PIC16F84A chẳng hạn )
                    Thì tui nói rồi, cứ cho là tín hiệu của bạn là 64 bít thì cũng chỉ mất 8x4=32 static byte cho 4 lần nhập dữ liệu khác nhau thôi, cái phần xử lý thì cứ dùng cơ chế truy cập bít, muốn chính xác thời gian phát ra cho mỗi bít thì dùng ngắt đồng bộ, cứ xem như là usart vậy.

                    Còn muốn gửi MSB trước thì chữa lại thế này:

                    #include <REGX51.H>

                    void main (void)
                    {
                    unsigned int send12bit = 152; //000010011000
                    unsigned char i;

                    for(i=12; i>0; i--)
                    {
                    if(send12bit & (1 << (i-1)))
                    P1_0 = 1;
                    else
                    P1_0 = 0;
                    }

                    while(1);
                    }

                    Bạn test bằng Keil 8051 cho nhanh. dùng PIC thì chuyển sang tí tẹo.

                    Comment


                    • #11
                      Nói thêm chỗ này: Keil nó tự động ép số 1 trong dòng if(...) là 0x0001, đừng lo thiếu. Còn muốn chắc ăn thì ép kiểu luôn (unsigned int)1

                      Comment


                      • #12
                        Hihi... đơn giản như vậy thôi anh. Đây có gì gọi là cao kiến đâu?
                        Cách 1:
                        Nếu dịch phải trái thì trong vòng for:
                        if(data & 0b100000000000) data[i]=1;else data[i]=0;
                        data=(data<<1);
                        Cách 2:
                        Hoặc là dùng vòng lặp tiến(i++) bị ngược thì dùng vòng lặp lùi(i--) và ngược lại.
                        Xoay quanh chỉ có việc sử dụng dịch trái hay phải, lặp tiến hay lùi thôi

                        Comment


                        • #13
                          Những thủ tục liên quan đến xử lý bit trong C tốt nhất là sử dụng inline asm.
                          Vẫn biết mỗi lần xa là một lần về lại...

                          Comment


                          • #14
                            Vấn đề là phần thu của bác QD xử lý bit thấp (LSB) hay bit cao (MSB) trước . Nếu dữ liệu phải truyền bit cao trước thì ta có thể dịch trái dữ liệu giống như cách của Trang :

                            void OutBit(unsigned int xData)
                            {
                            unsigned char i;
                            xData<<=4; //Dịch trái 4 bit để chuẩn bị truyền 12 bit tiếp theo
                            for(i=0;i<12;i++)
                            {
                            DataOut = ((xData & 0x8000)==0x8000?1:0);//DataOut là chân ra của VDK
                            xData<<=1; // dịch trái 1 bit
                            }
                            }

                            Bác QD xem làm như vậy có được ko ?

                            Comment


                            • #15
                              Nguyên văn bởi thaithutrang
                              Hihi... đơn giản như vậy thôi anh. Đây có gì gọi là cao kiến đâu?
                              Cách 1:
                              Nếu dịch phải trái thì trong vòng for:
                              if(data & 0b100000000000) data[i]=1;else data[i]=0;
                              data=(data<<1);
                              Cách 2:
                              Hoặc là dùng vòng lặp tiến(i++) bị ngược thì dùng vòng lặp lùi(i--) và ngược lại.
                              Xoay quanh chỉ có việc sử dụng dịch trái hay phải, lặp tiến hay lùi thôi

                              Cách của em Trang không sai ( cách này thì anh đã làm được từ năm ngoái rồi ).
                              Cách của em 3T có dùng mảng data[i] làm trung gian sau đó dùng vòng for để đảo dữ liệu . Tốn kém quá .
                              Tôi chưa thử cách của bạn saosau89 ( tôi sẽ test thử và sẽ đưa kết quả lên sau ).
                              Cách của bạn trungkt ( không phát ra được dữ liệu gì ,) tất cả dữ liệu phát ra = 0 ( vì bạn đã dịch trái hết mất rồi ).

                              Tôi đang chờ câu trả lời của bác Binh Anh , quả thực sử lí bit trong ngôn ngữ C không đơn giản một chút nào , Dùng ASM chắc chắn là được bởi vì ASM có hỗ trợ đến bit , mỗi lần truy suất dữ liệu nó đều lấy dữ liệu tại bộ đệm ra và ta dễ dàng đảo chiều dữ liệu phát đi.
                              Tuy nhiên trong lập trình C , muốn đảo chiều nó ta cần dùng 1 mảng hay một bộ đệm nào đó để lưu trữ các bit dữ liệu của ta , sau đó dùng vòng for để đảo chiều .
                              Với cách dùng mảng ta có thể đảo chiều dễ dàng bằng cách gọi các chỉ số ( index) của mảng .
                              Tôi lấy ví dụ : unsigned char mang1[12];
                              Thuận chiều : for (i=0; i<12; i++) {;....... }
                              Đảo chiều : for (i =12; i>0 ; i--) { ;......}

                              ---- Với sử lí bit hoặc byte ( ta không có các chỉ số index) như của mảng nên việc truy cập từng bit hoặc đảo chiều là khó khăn .
                              Ta có thể dùng cách dịch trái , dịch phải tuy nhiên chỉ dịch phải thì dữ liệu còn phát ra , còn dịch trái thì mất hết dữ liệu ( nó chỉ có dữ liệu trừ khi ta định nghĩa được bit 0 ( là điểm nào ) sau đó mới dịch trái từ bit 0 đến bit 11 như vậy là ta đã giải quyết được bài toán.
                              Tuy vậy tôi chưa thấy định nghĩa hay chỉ dẫn của các bạn bit 0 bắt đầu từ đâu ,
                              Khi chạy mô phỏng trên Proteus không thấy một bit cao nào phát ra ( tức là đã bị mất hết dữ liệu ).
                              Không tin tưởng Proteus lắm , nạp thử chương trình , soi trên oxi lô thật thì cũng chẳng khác gì khi mô phỏng ảo cả.

                              -------------------------------------------------------------------
                              Dưới đây tôi đưa lại bài toán một cách chính xác để các bạn quan tâm và cố vấn hộ xem như thế nào :

                              Bài toán : Nhập một số nguyên N vào từ bàn phím (0<N< 4095 : tức là nhỏ hơn 12 bit đó )
                              Phát chuỗi xung theo giá trị N 12 bit ra chân RB1 của PIC16 F84A
                              theo thời gian Delay();
                              nếu nhìn trên OSC thì vị trí các bit như sau : bit11 , bit 10 , bit9....đến bit 0)
                              tính theo thứ tự vào ra thì " vào trước ra trước " như vậy để được như giản đồ trên thì bit 11 sẽ được phát trước , bit 0 sau cùng.
                              ---- Giới hạn bài toán : không được dùng khai báo mảng , tối ưu tiết kiệm bộ nhớ ) ( tôi đã làm với cách dùng Mảng và tốn mất 12 byte bộ nhớ-- xài sang quá, chưa tìm ra cách sử lí để cho nó ít hơn )

                              --->// Một ví dụ mẫu : Từ bàn phím ta nhập vào số 290 ( như vậy N = 290 )
                              phát N ra chân RB1 ( đủ khung 12 bit --- bit nào thiếu thì tự chèn =0 ).
                              - Đổi N ra nhị phân ta được : 100100010 ( 9 bit -- thiếu 3 bit )
                              ta phải phát ra chân RB1 là : 000 100100010 ( tự điền : bit 11 =0 ; bit 10 =0; bit 9 =0 )

                              --- Theo các bài viết trên tôi thấy các bác toàn bị ngược hoặc không ra dữ liệu
                              Đây là dữ liệu của các bác phát ra : ( 2 bài đầu của trung kt và Binh Anh : 010001001 000

                              và các 1 bài sau : 000000000000 ( đủ 12 bit )

                              --- Ví dụ thứ 2 : nhập vào số 315 ( đổi ra nhị phân :100111011 - cái này thì tự phần mềm nó đổi rồi ) : phải phát ra là : 000 100111011

                              ---- Đây chỉ đơn giản là chèn thêm và đảo chiều phát ra của 1 khung truyền cố định thôi . Tuy nhiên tôi chưa tìm được lời giải đáp.

                              ( mới chỉ truyền cố định mà chưa được --- một số cái ứng dụng : khóa két bây giờ họ truyền dữ liệu thay đổi liên tục : ranrom code ) thì làm sao mà chơi nổi .
                              Xin các bạn cho lời khuyên

                              // Lưu ý : tất cả thuật toán chỉ được làm trên C " không chèn ASM " nếu chèn ASM thì có một bài của bạn nova đã giải quyết được rồi .
                              Module RF chuyên dụng điều khiển, truyền dữ liệu, thiết kế đề tài, dự án điện tử - chuyển giao công nghệ... ĐT: 0904964977 - email: dientuqueduong@yahoo.com

                              Comment

                              Về tác giả

                              Collapse

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

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

                              Collapse

                              Đang tải...
                              X