Thông báo

Collapse
No announcement yet.

Đố vui về PIC, các câu đố cực vui và cực hay... hehe..

Collapse
This topic is closed.
X
This is a sticky topic.
X
X
 
  • Lọc
  • Giờ
  • Show
Clear All
new posts

  • Anh qmk đâu rồi?
    Gửi anh F:Nếu em có đáp án 2 và đạt giải có thể đổi PIC lấy con PIC khác ko nhi? ...hi..hi...
    Last edited by thaithutrang; 07-01-2006, 22:11.

    Comment


    • http://www.dantri.com.vn/vieclam/2005/12/96176.vip
      Vẫn biết mỗi lần xa là một lần về lại...

      Comment


      • Nguyên văn bởi thaithutrang
        Không phải là em ko nghĩ ra cách quét = số chân(N) điều khiển.
        Nhưng độ sáng phải đồng đều đó anh. Nên giải pháp xuất nhiều LED 1 lúc sẽ sinh ra hiệu ứng ko hay. Thà sáng mờ như nhau cả còn hơn là cái sáng cái mờ. Do sụt áp qua điện trở ko đều.
        hình như trong hình vẽ không thấy nối điện trở, chắc cái đèn LED đó chạy ở điện áp 5V và dòng tiêu thụ thỉ khoảng 5mA thôi. Vì vậy một chân chịu khoảng 7 cái đèn chắc kô sao nhỉ? Hoặc là hơi tối đi một tẹo thôi.
        Tóm lại là giả sử công suất của I/O khỏe đủ để không bị tối LED. Okie?
        Không biết ý bác Falleaf thế nào, hay bác có giải pháp tốt hơn thì xin cho ý kiến.
        AFH

        Comment


        • Nguyên văn bởi anthrax
          Nghe thằng bạn nói vậy chứ không biết thông tin chi tiết,nó có nói bài toán này.Lại nghe bác qmk đố bài này nên máu hính học nổi lên. Hehe,mới vừa giải xong,bài toán này tương đương bài toán :"Dựng hình tròn tâm D tiếp xúc với 3 đường tròn tiếp xúc từng đôi với tâm tại A,B,C" .Bài toán có 2 nghiệm hình tương ứng với tiếp xúc trong và ngoài

          Bác qmk cho cái trang về cuộc thi trên google đi
          Ok, it's smart.....

          Kiểm tra lại có vẻ chưa đúng bạn nói rõ hơn đi
          Last edited by qmk; 07-01-2006, 23:11.
          Vẫn biết mỗi lần xa là một lần về lại...

          Comment


          • Nguyên văn bởi qmk
            Ví dụ sử dụng vi điều khiển có mã XXX có các thông số sau:
            Portpin hỗ trợ 3 trạng thái.
            Dòng sink tối đa là Ilmax.
            Dòng source tối đa là Ihmax.
            N port pin.

            Cách nối như sau. Một cặp led đấu ngược đầu nối tiếp với 1 điện trở gọi là một Leds Units. Mỗi cặp Pin nối tiếp với một Led Unit này.
            Với cách nối này dễ thấy sẽ có chỉnh hợp chập 2 của N chính là số lượng Led M= N(N-1) (Có N port và mỗi port có N-1 led sink đến)

            Dễ chứng minh là cách nối này khả thi với cách quét sau.
            Đầu tiên Port pin 1 Low (sink) các Led sink vào port muốn sáng thì Port pin source tương ứng lần lượt được quét bằng 1 trong thời gian t. Không muốn sáng thì tris.
            Tiếp đó lần lượt các Port Low và quét các port còn lại.
            Rõ ràng thời gian hết các Led sẽ là T = M.t

            Tần số quét 1/33 (Có thể vẫn hơi rung). Tức là tất cả các Led phải được quét qua trong mỗi T=30ms.
            Với dòng Ilmax và Ihmax thường không quá 20mA. Tôi cho rằng chỉ quét được với N=5. Tức là khoảng 20Led là hết cỡ.

            Tuy nhiên có thể cải tiến bằng cách chấp nhận cho dòng Source lớn hơn mức cho phép vì quét trong thời gian ngắn. Như vậy giả sử mỗi chu kỳ t 2 port có thể mức cao cùng lúc. Như vậy có thể tính một cách gần đúng.
            T=M.t/2. Vậy có thể quét được với N=6 hoặc 7 (chấp nhận hơi mờ). Như vậy có thể dùng phương pháp này để quét từ 35- 42 led với VĐK thông thường.

            Hết.

            Bổ sung số trở bằng: M/2 theo lý thuyết. Lúc đấy giá trị trở sẽ là: R = (Vcc - Vfl(@25mA))/25mA
            Với cách quét từng led một thì có thể cải tiến bằng các nối trở giá trị R/2 vào đầu port như vậy số trở sẽ là N.
            Nguyên tắc kinh điển của lập trình:
            Cấu trúc dữ liệu + giải thuật = chương trình
            Vẫn biết mỗi lần xa là một lần về lại...

            Comment


            • Cái điểm yếu của người lập trình vẫn luôn là muốn biết rõ tất cả mọi trường hợp. Khi dùng timer là một gợi ý của anh để có thể giảm bớt việc viết code, nhưng bản chất bài giải của em vẫn là cố gắng kiểm tra các trường hợp của LED.

              Em thử tưởng tượng xem, nếu trên đời này cái gì mình cũng phải biết hết, thì đến bao giờ mới xong? Có cách nào một lần mình biết một mớ không? Để biết một mớ, thì mình cần phải làm thế nào?

              Chúc vui
              Falleaf
              Công ty TNHH Thương mại và Giao nhận R&P
              58/57 Nguyễn Minh Hoàng - Phường 12 - Quận Tân Bình - TP.HCM
              mail@falleaf.net - VP: (04) 36408561 - (08) 38119870

              Comment


              • //N la so chan dieu khien
                const unsigned int POWER[N-1]={a,b,c....};
                unsigned char PORT_CTR[N];
                unsigned int P[N];
                unsigned char i =0,j;
                bit LED[N][N-1];
                main()
                {
                //Cac khoi tao
                while(1)
                {

                }

                }

                Ham_ngat timer:
                {
                TIMER=P[POWER[i]]; //Thoi gian sang'
                PORTB=0xff; //Tat het LED
                PORTB=PORT_CTR[i];
                if(++i==N) i=0;
                }

                Ham_khoi_tao_buffer(Moi khi thay doi LED thi chay ham nay )
                {
                unsigned char s;
                for (i=0;i<N;i++)
                {
                s=0;
                PORT_CTR[i]=0;
                for (j=0;j<N;j++)
                {
                PORT_CTR[i]*=2;
                if(i==j) PORT_CTR[i]=0;
                else { PORT_CTR[i]=LED[N*i][j]; if(LED[i][j]) s++;}
                }
                P[i]=s;
                }
                }
                Last edited by thaithutrang; 08-01-2006, 00:19.

                Comment


                • Cô bé rất vui tính, nếu em giải được đúng, em muốn bất kỳ con PIC nào anh cũng cho , tất nhiên trong mớ PIC mà anh có. PIC ở HN anh không biết anh BA còn những con nào, nếu em thích một con đặc biệt, riêng đối với em, nếu giải được, anh tặng riêng . Ưu tiên cho em gái cưng của PIC vậy.

                  Định viết cho em khá nhiều, một là để gợi ý, hai là giúp em định hướng tư duy, nhưng anh không thể ưu tiên quá cho em được, vì phần thưởng này cũng dành cho tất cả các bạn học PIC khác.

                  Một cậu bé đã rất ghen tị với em đấy, và cũng nói rất hồn nhiên "em nể cô bé đó thật, nhưng anh yên tâm, về lập trình máy tính bạn đó không thể bằng em được đâu", "tức quá, thấy bạn đó nói nhiều quá trời mà mình không biết gì để nói"... kết quả là có cái tin nhắn cá nhân của anh cho em đó. Đọc tin nhắn đó đi, và có thể em sẽ gặp được cậu bé đó.

                  Anh rất hy vọng ngày mai anh mất một con PIC

                  Bây giờ anh sợ lập trình PIC lắm rồi, nên anh không muốn tự lãnh thưởng một tí nào :-).

                  Đổi bài toán cho nó dễ hơn một chút: Nếu bit nào bằng 0 thì bật đèn, nếu bit nào bằng 1 thì tắt đèn. (một gợi ý vô cùng quan trọng).

                  Chúc vui.
                  Falleaf
                  Công ty TNHH Thương mại và Giao nhận R&P
                  58/57 Nguyễn Minh Hoàng - Phường 12 - Quận Tân Bình - TP.HCM
                  mail@falleaf.net - VP: (04) 36408561 - (08) 38119870

                  Comment


                  • Nguyên văn bởi thaithutrang
                    Không phải là em ko nghĩ ra cách quét = số chân(N) điều khiển.
                    Nhưng độ sáng phải đồng đều đó anh. Nên giải pháp xuất nhiều LED 1 lúc sẽ sinh ra hiệu ứng ko hay. Thà sáng mờ như nhau cả còn hơn là cái sáng cái mờ. Do sụt áp qua điện trở ko đều.
                    Anh đã giả thiết công suất đủ để đảm bảo LED sáng, có thể dùng Trans... khi nó cấp đủ cho số led, chỉ cần em đảm bảo rằng em cho nhấp nháy ở tần số cao, và không quá ít trogn 1 chu kỳ, thì đèn vẫn sáng tốt.

                    Nếu như một xung để sáng led mà em chia làm 8 là tối đa thì còn chấp nhận được vì 20mA / 8 = 2.5mA, chứ em chia xung ra đến 1/56*T thì chắc chắn là đèn sáng yếu rồi. Trường hợp 12 leds, với trở nhỏ, vẫn có thể chạy tốt em à. Nếu em chia 1/56 thì không cách gì sáng nổi đèn. Anh chỉ đố về thuật toán cho vui thôi.

                    Đáp án đầu tiên của em, thì về việc viết chương trình là rất ngắn rồi, nếu miễn cưỡng thì có thể cách này là ngắn nhất, nhưng em thấy rõ ràng nó cũng vô lý phải không? Sau 1/56 mới bật một lần, nếu em chia khoảng 7,8 thì anh chấp nhận nó đúng. Với cách này, em chỉ có thể điều khiển 3 chân thôi. Như vậy nó sẽ là 1/6. Có cách nào giảm từ 1/56 xuống khoảng 1/6 không?

                    Chúc vui
                    Falleaf
                    Công ty TNHH Thương mại và Giao nhận R&P
                    58/57 Nguyễn Minh Hoàng - Phường 12 - Quận Tân Bình - TP.HCM
                    mail@falleaf.net - VP: (04) 36408561 - (08) 38119870

                    Comment


                    • Đây là bài giải của AFH, kô cần dùng tra bảng, xuất giá trị trực tiếp luôn.

                      /* Số chân vào ra được định nghĩa là N
                      Số LED điều khiển là N*(N-1) LED
                      Gọi LED_display là biến biến biểu diễn trạng thái các LED.
                      Vị trí các bit tương ứng các LED sẽ được bố trí như sau:
                      Chia các LED ra thành N nhóm và nhét vào nhóm dó 1 con số 0
                      Số 0 được nhét phía bên phải của nhóm bên phải
                      Ở nhóm tiếp theo thì số 0 dịch từng bit sang bên trái
                      ví dụ với LED=12 ta có LED_display = 0xxx x0xx xx0x xxx0
                      trong dó x=1 nếu LED sáng, x=0 nếu LED tắt.
                      */
                      #define N 4
                      unsigned int LED_display;
                      int main (void)
                      {
                      // thiet lap Timer de 2ms chay ham ngat mot lan
                      // cap nhat gia tri cho LED_display o day
                      return 0;
                      }
                      void Timer_Interrupt(void) // lấy tạm cái tên là Timer_Interrupt cho gọn
                      {
                      static unsigned char i=(N-1); // đặt i=(N-1) để cập nhật temp=LED_display
                      static unsigned char mask;
                      static unsigned int temp;
                      // xóa cờ ngắt tại đây
                      if(++i==N) // nếu đã quét xong một vòng
                      {temp=LED_display; // cập nhật lại giá trị vào biến nháp
                      i=0; // xóa i
                      mask=0x01;} // reset lại biến mask
                      PORTA=temp; // dua gia tri ra LED
                      TRISA=(~temp)^mask; // mo cong tuong ung de den sang
                      temp>>=N; // dich di N bit
                      mask<<=1; // chuyen sang chan I/O ke tiep.
                      } // ket thuc ham ngat

                      Comment


                      • Đôi lời phân tích.

                        Cách của em hơi dài do 2 lý do:
                        -Dài nhưng chạy rất nhanh, hầu hết thời gian chỉ chạy đoạn ngắt:
                        TIMER=P[POWER[i]]; //Thoi gian sang'
                        PORTB=0xff; //Ko cần dòng nay
                        PORTB=PORT_CTR[i];
                        if(++i==N) i=0;

                        -Còn khi muốn thay đổi lại sự sáng tối các LED(trăm thì 10 họa). thì tính toán lại buffer cho mảng:
                        +Mảng PORT_CTR[]//Mảng hiển thị
                        +Mảng POWER[i], mảng thời gian của LED sáng.(Số LED sáng đồng thời càng nhiều thì các led đó càng tối-->giải pháp cần một bảng tra về số led và công suất hay thời gian sáng(thời gian sáng càng dài hơn))
                        -Cách của em quét hết N chứ ko phải N*(N-1).
                        -Cách của Em quét thời gian động nhằm làm các độ sáng = nhau.
                        -Phần thường thi em đùa vậy thôi. Ai nỡ lấy PIC của anh.

                        Comment


                        • Tóm lại:
                          Ngắt timer
                          {
                          TIMER=P[POWER[i]]; //(Giá trị nap timer thay đổi động, ko cố định)
                          PORTB=PORT_CTR[i];
                          if(++i==N) i=0;

                          }

                          Comment


                          • Ví dụ: Nếu cột 1 có 3 led sáng đồng thời, trong khi cột 3 chỉ có 1 led sáng.Vậy cột một sáng yếu hơn(cho dù bỏ quan vấn đề dòng, nhưng do sụt áp qua điện trở chung của cột 1) cột 3.

                            To cậu bé anh F quen,rất vui khi được làm quen với cậu ấy: về lập trình em chỉ Amater nhưng cũng làm được vài thứ: như cơ dữ liệu, mấy cái lập trinh ghép nối đơn giản như RS232,USB HID, VB thì tốt hơn VC một tý. Hi vọng em sẽ học hỏi nhiều thứ từ anh ấy.

                            Comment


                            • Nguyên văn bởi falleaf
                              Anh đã giả thiết công suất đủ để đảm bảo LED sáng, có thể dùng Trans... khi nó cấp đủ cho số led, chỉ cần em đảm bảo rằng em cho nhấp nháy ở tần số cao, và không quá ít trogn 1 chu kỳ, thì đèn vẫn sáng tốt.

                              Nếu như một xung để sáng led mà em chia làm 8 là tối đa thì còn chấp nhận được vì 20mA / 8 = 2.5mA, chứ em chia xung ra đến 1/56*T thì chắc chắn là đèn sáng yếu rồi. Trường hợp 12 leds, với trở nhỏ, vẫn có thể chạy tốt em à. Nếu em chia 1/56 thì không cách gì sáng nổi đèn. Anh chỉ đố về thuật toán cho vui thôi.

                              Đáp án đầu tiên của em, thì về việc viết chương trình là rất ngắn rồi, nếu miễn cưỡng thì có thể cách này là ngắn nhất, nhưng em thấy rõ ràng nó cũng vô lý phải không? Sau 1/56 mới bật một lần, nếu em chia khoảng 7,8 thì anh chấp nhận nó đúng. Với cách này, em chỉ có thể điều khiển 3 chân thôi. Như vậy nó sẽ là 1/6. Có cách nào giảm từ 1/56 xuống khoảng 1/6 không?

                              Chúc vui
                              Chú fall này lắm lý sự quá, ra đề thì để người khác làm chứ. Gợi ý lung tung làm loạn cách suy nghĩ của người ta mất hứng thú nữa. Chắc gì cách của chú đã hay hơn chứ.
                              Vẫn biết mỗi lần xa là một lần về lại...

                              Comment


                              • gửi bạn thaithutrang

                                Nguyên văn bởi thaithutrang
                                //N la so chan dieu khien
                                const unsigned int POWER[N-1]={a,b,c....};
                                unsigned char PORT_CTR[N];
                                unsigned int P[N];
                                unsigned char i =0,j;
                                bit LED[N][N-1];
                                main()
                                {
                                //Cac khoi tao
                                while(1)
                                {
                                }
                                }
                                Ham_ngat timer:
                                {
                                TIMER=P[POWER[i]]; //Thoi gian sang'
                                PORTB=0xff; //Tat het LED
                                PORTB=PORT_CTR[i];
                                if(++i==N) i=0;
                                }

                                Ham_khoi_tao_buffer(Moi khi thay doi LED thi chay ham nay )
                                {
                                unsigned char s;
                                for (i=0;i<N;i++)
                                {
                                s=0;
                                PORT_CTR[i]=0;
                                for (j=0;j<N;j++)
                                {
                                PORT_CTR[i]*=2;
                                if(i==j) PORT_CTR[i]=0;
                                else { PORT_CTR[i]=LED[N*i][j]; if(LED[i][j]) s++;}
                                }
                                P[i]=s;
                                }
                                }
                                1. Bạn khai báo mảng P[N] là thừa một giá trị (vì mảng này chỉ cần N-1 giá trị)
                                2. nếu i>=2 thì làm gì có giá trị LED[N*i][j] ?????
                                3. Bạn xem lại vòng lặp này, giả sử i là bất kỳ, j đạt giá trị cuối là j=N-1
                                for (j=0;j<N;j++)
                                {
                                PORT_CTR[i]*=2; // lệnh này dịch trái 1 bit, kô ảnh hưởng
                                if(i==j) PORT_CTR[i]=0; // nếu i=N-1 thì PORT_CTR[N-1]=0
                                // nếu i != j thì lệnh sau của bạn sẽ gán PORT_CTR[i]=LED[N*i][N-1];
                                // mặc dù ko biết có tồn tại giá trị LED[N*i][j] hay kô nữa nhưng
                                // điều đó có nghĩa là các giá trị bit khi j<N-1 sẽ bị xóa hết. Phải kô?
                                else { PORT_CTR[i]=LED[N*i][j]; if(LED[i][j]) s++;}
                                }
                                4. Hàm ngắt và hàm buffer của bạn đều điều chỉnh giá trị i, do đó, điều gì xảy ra khi đang tăng giá trị i ở hàm ngắt đến i=N (mà chưa kịp so sánh với N) mà hàm buffer cũng tăng giá trị của i ? (hoặc ngược lại) 2 hàm cùng truy xuất một biến chung của chương trình là điều nên tránh, hoặc phải dùng loại trừ (nghĩa là cái này đang chạy thì cái kia phải bị cấm.
                                5. Trong chương trình của bạn kô thấy nhắc đến TRISB ? chả lẽ kô cần đến nó sao?????
                                6. Việc khai báo như bạn sẽ chiếm rất nhiều bộ nhớ RAM, nhất là khi VĐK không hỗ trợ việc xử lý bit, khi đó mảng bit LED[N][N-1] của bạn sẽ chiếm N*(N-1) byte đó.

                                AFH

                                sửa đổi một tý: ở điều (3), nếu lệnh PORT_CTR[i]=LED[N*i][j] chỉ gán bit thấp nhất của PORT_CTR[i] bằng giá trị LED[N*i][j] thì được. Tại tớ chưa lập trình cho PIC kiểu này bao giờ. Với lại tớ mới học lập trình PIC có 1 tuần thôi. Hi hi..... Có gì mong bạn giải thích giùm.
                                Last edited by AFH; 08-01-2006, 11:04.

                                Comment

                                Về tác giả

                                Collapse

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

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

                                Collapse

                                Đang tải...
                                X