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

  • Nguyên văn bởi AFH
    Đâ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
    temp>>=N; Một hàm dịch bit N lần một số 16 bit viết trên VDK là phức tạp. Mỗi lần bạn đều dịch. Xem ra không tối ưu. Cứ nghĩ lệnh này phải đặt trong if {}.
    TRISA=(~temp)^mask; Phép XOR này nữa ????.
    Giả sử trường hợp 1 ứng với
    temp = xxxx.0000b tức là cả 3 led đều sáng
    mask = 0000.0010b
    Sau phep Not
    ~temp = xxxx.1111b
    Sau phép Xor:
    Trisa = xxxx.1101b -> TRISA
    porta = xxxx.0000b -> PORTA hình như không led nào sáng
    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
      temp>>=N; Một hàm dịch bit N lần một số 16 bit viết trên VDK là phức tạp. Mỗi lần bạn đều dịch. Xem ra không tối ưu. Cứ nghĩ lệnh này phải đặt trong if {}.
      TRISA=(~temp)^mask; Phép XOR này nữa ????.
      Giả sử trường hợp 1 ứng với
      temp = xxxx.0000b tức là cả 3 led đều sáng
      mask = 0000.0010b
      Sau phep Not
      ~temp = xxxx.1111b
      Sau phép Xor:
      Trisa = xxxx.1101b -> TRISA
      porta = xxxx.0000b -> PORTA hình như không led nào sáng
      Không hề nhầm, bạn đọc kỹ lại quy ước của tớ, x=1 tương ứng với LED sáng, x=0 ~ LED tắt
      vậy như giả sử của bạn, để 3 LED cuối sáng thì temp=0000 1110 (tạm bỏ byte cao của temp cho dễ hiểu.)
      do vậy, ~temp=1111 0001 phải kô?
      vậy (~temp)^mask = 1111 0001 ^ 0000 0001 = 1111 0000 phải kô
      do vậy TRISA= 1111 0000 phải kô nào?
      còn PORTA=temp=0000 1110;
      thế có phải là cả 4 chân đều là output, chân PORTA.0=0, các chân còn lại =1
      Right????

      Ai bảo lệnh temp>>=N; là lệnh kô tối ưu?
      Nó là lệnh tối ưu để đưa dữ liệu từ bit cao xuống bit thấp đó.
      Chả phải trong chương trình LCD, ngườita vẫn dịch phải 4 bit để đưa Nible cao xuống thành Nibble thấp còn gì?
      Phải kkô nào?
      AFH

      sửa một tý: lúc nãy ghi là "tối ưu nhất", hi hi... nghĩ lại thấy đã tối ưu là nhất rồi, làm gì có tối ưu nhì nữa.

      Còn nữa: mọi người hãy thay đổi lại tiêu chuẩn này đi, dòng cho LED sáng bây giờ đâu có như ngày xưa (thấy sách ghi là 25mA), giờ nó chỉ cỡ 1 hay 2mA thôi, kô tin cứ nối LED mắt cua loại tốt (nếu là loại outdoor thì khỏi bàn cãi) nối với điện trở 560 ohm xem có sáng kô? . Giả sử sụt áp trên đèn bằng 0 thì dòng tối đã cũng chỉ gần 2mA thôi.
      Last edited by AFH; 08-01-2006, 12:13.

      Comment


      • Em biết chắc em được giải nen em ko chuẩn hóa nhiều đến lệnh cụ thể. Vì vấn đề các anh đã bỏ qua đến việc độ sáng các LED và sụt áp qua điện trở. Các anh bị sót mất ý tưởng đó,nên đều bị trừ hết điể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?????
        Ở đây:
        //Cac khoi tao
        Em ko viết cụ thể, vì cụ thể hơn thì phải:khởi tạo ngắt,timer, TRIS, Config(WD,HS...)...hi hi..anh AFH thiếu quá nhiều...đừng bắt bí em nhé, em còn có dòng chú thích(do tính trước).

        Comment


        • do vậy TRISA= 1111 0000 phải kô nào?
          còn PORTA=temp=0000 1110;
          Hihi. có 1 port mức 0 mà tới 3 port cấp dòng.

          Hiểu cách của bạn rồi. Nếu mà sink dòng đủ thì cách của bạn làm được. Nhưng mà làm sao để đệm transistor để cổng vừa source vừa sink lại 3 trạng thái được nhỉ. Đây là một câu đố nữa đây.

          Nhưng nói thật là không có ý nghĩa thực tế mấy. Quét 2ms thì hơi nhanh.

          Lệnh dịch 16 bit khác lệnh dịch 8 bit nhé.
          Last edited by qmk; 08-01-2006, 12:17.
          Vẫn biết mỗi lần xa là một lần về lại...

          Comment


          • Của em,N chân,-->N lần quét tương ứng với mảng N công suất.Nên P[N] là đúng chứ ko phải là P[N-1].
            Còn chuyện i(anh đúng hi hi), phần khởi tạo lại lại có lẽ nên viết một hàm để tránh lãng phí bit, hơn nữa các trình dịch uC thường ko support mảng bit thì phải.
            Vậy viết một hàm khác thay hoàn toàn hàm khợi tao của em sẽ hay hơn.
            Print(unsigned char tt, bit Value);
            Ví dụ:nếu gọi Print(10,1)--->bật sáng led thứ 10 ở mảng bộ đệm hiển thị.
            Ví dụ:nếu gọi Print(11,0)--->tắt led thứ 11 ở mảng bộ đệm hiển thị.
            Last edited by thaithutrang; 08-01-2006, 12:33.

            Comment


            • Lệnh << của C có quay vòng không nhỉ. Nếu không quay một lúc nó sẽ...

              Cái ultra bright đấy giá bằng 5-10 lần led thường nên không thể nói thế được.
              Bạn nên tính lại 5000/560 bằng bao nhiều mA. Có gần 10 không. Tôi hay dùng trở 1K như vậy 3000/1k = 3mA. Thực ra khi quét led 1/16 thì dòng xung sẽ tốt hơn dòng trung bình. Cái này thực tế nhiều có thể sure được.

              Định không tham gia nhưng đoạn ctr này có thể dùng thực tế với 12 led trở xuống được. 20 led thì cũng có thể được. Không ảnh hưởng đến các port bit khác.
              ---------------------------------------------
              Cấu trúc dữ liệu
              Gọi các Led có chân catod nối với Rx và anode nối với
              port y là Lxy
              ...
              Led0 [x] [x] [x] [x] [L03] [L02] [L01] [0]
              Led1 [x] [x] [x] [x] [L13] [L12] [0] [L10]
              Led2 [x] [x] [x] [x] [L23] [0] [L21] [L20]
              Led3 [x] [x] [x] [x] [0] [L32] [L31] [L30]

              Với cấu trúc dữ liệu này muốn bật Led L01 chẳng hạn thì gọi lệnh:
              ClrBit(Led[0],1)

              code const byte mbcMask[4] = {0xFE,0xFD,0xFB,0xF7};
              byte Led[4];

              Hàm quét led gọi 3ms một lần
              void ledscan()
              {
              static byte x = 0
              static byte y = 0
              if (++y==4)
              {
              if (++x==4)
              x=0; // x là Rx port hiện thời
              y = 0;
              }
              if (x==y) return; // Bỏ dòng này đi cũng không sao
              PORTB = (PORTB | 0x0F)& (mbcMask[y] | Led[x]);
              TRISB = (TRISB | 0x0F)& (mbcMask[y] & mbcMask[x]);
              }
              }
              Last edited by qmk; 08-01-2006, 12:42.
              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
                Em biết chắc em được giải nen em ko chuẩn hóa nhiều đến lệnh cụ thể. Vì vấn đề các anh đã bỏ qua đến việc độ sáng các LED và sụt áp qua điện trở. Các anh bị sót mất ý tưởng đó,nên đều bị trừ hết điểm....

                Em ko viết cụ thể, vì cụ thể hơn thì phải:khởi tạo ngắt,timer, TRIS, Config(WD,HS...)...hi hi..anh AFH thiếu quá nhiều...đừng bắt bí em nhé, em còn có dòng chú thích(do tính trước).
                Bạn thật là láu cá.
                TRISB là phần có liên quan đến số lượng LED bạn quét ra. Vậy phải được đưa vào chương trình chứ.???
                Mời em trả lời tiếp thắc mắc (2) và (4) của anh, và giải thích cho anh thắc mắc (3).
                Em xem lại dòng lệnh TIMER=P[POWER[i]]; của em, rõ ràng em khai báo mảng POWER[N-1] do đó nó chỉ có N-1 phần tử, và vì thế giá trị P của em chỉ đến phần tử P[N-2]; là hết rồi, em thừa một giá trị P[N-1];
                Nếu vẫn quả quyết em đúng thì xin giải thích rõ ràng. Đừng có láu cá là " em biết chắc em được giải nên kô chuẩn hóa đến lệnh cụ thể". Sao em kô biết chắc đến mức là đến gặp anh BinhAnh mà nhận chíp luôn đi, khỏi phải đưa chương trình lên làm gì.
                Hê hê... nếu vẫn láu cá nữa thì mời em đến gặp anh BinhAnh nhận giải thưởng.

                AFH

                Comment


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

                  }

                  Ham_ngat timer:
                  {
                  TIMER=POWER[P[i]]; //Thoi gian sang' cột i
                  PORTB=PORT_CTR[i];//Cập nhật led cột i
                  if(++i==N) i=0;
                  }

                  //Ngoài ra làm một hàm khác
                  Print(unsigned char tt,bit value)để mỗi khi thay đổi buffer hiển thị chỉ cần gọi hàm này.

                  Comment


                  • Hi hi..vì TRISB=0 nên ko phải thay đổi liên tục như anh.Cách của e khác cách anh.
                    Anh AFH dỗi rồi.

                    Comment


                    • Nguyên văn bởi qmk
                      Lệnh << của C có quay vòng không nhỉ. Nếu không quay một lúc nó sẽ...

                      Cái ultra bright đấy giá bằng 5-10 lần led thường nên không thể nói thế được.
                      Bạn nên tính lại 5000/560 bằng bao nhiều mA. Có gần 10 không. Tôi hay dùng trở 1K như vậy 3000/1k = 3mA. Thực ra khi quét led 1/16 thì dòng xung sẽ tốt hơn dòng trung bình. Cái này thực tế nhiều có thể sure được.
                      Cái này thì đồng ý với bạn qmk là tớ sai. ... tại tớ hay dùng trở 1k cho con LED mắt cua của Singapore (giá 300d/con mua ở hàng trống) thấy sáng lắm mà. Đã dùng 1 chân của PORT để kích riêng cho một LED-7thanh, vậy tổng cộng là 8 đèn tính cả dấu chấm, thấy nó cũng sáng ngon lành, nhưng tớ mua loại LED-7 thanh tốt, rất sáng, giá của nó hình như là 3,5k hay 4k gì đó.
                      Về cái câu đố dùng transitor tạo đầu ra 3 trạng thái thì lát nữa tớ post sơ đồ lên cho. Okie?

                      AFH

                      Comment


                      • Nguyên nhân sai ở đây:TIMER=P[POWER[i]](sai); --->TIMER=POWER[P[i]](đúng); chứ có lẽ ko phải thừa thiếu giá trị.

                        Comment


                        • Nguyên văn bởi thaithutrang
                          Hi hi..vì TRISB=0 nên ko phải thay đổi liên tục như anh.Cách của e khác cách anh.
                          Anh AFH dỗi rồi.
                          Thế này lại càng vi phạm thuật toán, em thử nghĩ xem, nếu TRISB = 0 liên tục thì làm sao em cho từng LED sáng tắt ngẫu nhiên?????
                          Hê hê... anh còn lâu mới dỗi được.

                          Ha ha... giờ lại đổi lại là TIMER=POWER[P[i]]; hê hê.... thế này lại càng sai hơn
                          Thực ra em sai ở thuật toán dùng mảng truy xuất mảng, em thử tưởng tượng xem, giả sử lấy N=4 thôi, vậy thì giá trị nội dung của P[i] của em có con số nào ngoài 0,1,2,3 kô? (đủ 4 giá trị cho mảng P[N] đó nhé). nếu P[i]=3 thì POWER[P[i]] của em là bất định rồi chứ chưa nói đến giá trị ngoài bộ số đó. hê hê....
                          AFH

                          Comment


                          • Vậy chữa thành:const unsigned int POWER[N]={a,b,c....}; có đúng ko anh ới? rất tiêc là protes của em bị lỗi,nếu ko mô phỏng sẽ biết những kiểu sai+1,-1 thế này.

                            Comment


                            • Nguyên văn bởi qmk
                              Ok, it's smart.....

                              Kiểm tra lại có vẻ chưa đúng bạn nói rõ hơn đi
                              Đã gửi PM cho bác ,hy vọng dễ hiểu

                              Comment


                              • Nguyên văn bởi thaithutrang
                                Vậy chữa thành:const unsigned int POWER[N]={a,b,c....}; có đúng ko anh ới? rất tiêc là protes của em bị lỗi,nếu ko mô phỏng sẽ biết những kiểu sai+1,-1 thế này.
                                thật ra, với cái hàm này, em cần gì phải truy suất mảng lồng mảng.
                                Giả sử N=4, nghĩa là cùng một lúc em chỉ có thể hiển thị tối đa là N-1 LED tương đương 3 LED, do đó, việc em dùng biến s để biểu thị có bao nhiều LED sáng là tốt, và em chỉ việc gán TIMER=POWER[s] là xong rồi. Nhớ rằng hàm buffer của em cùng lắm nó chỉ tăng s = 2 là cùng thôi. Mặc định s=0 là 1 LED sáng, s=1 là 2 LED sáng và s=2 là 3 LED sáng. Nếu kô có LED nào sáng thì các đầu vào TRISB=0xff hết, do đó kô cần quan tâm đến thời gian ở điểm này (coi như vẫn là = Timer cho 1 LED sáng)
                                Vậy là mảng của em sẽ là POWER[N-1]. Đúng chưa cô gái láu cá.
                                p/s: hôm nào em dậy anh cách mô phỏng bằng Protes nhé. Từ xưa đến nay, chưa bao giờ anh biết Debug một chưa trình trên máy tính, từ cái hồi học 89C51 tới nay. Toàn debug trong đầu với những phép toán đơn giản, còn phức tạp thì cứ nạp xuống board xem nó chạy ra làm sao.


                                Bạn qmk ơi, xem hình dưới đây để biết đầu ra TTL dùng transitor nhé.

                                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