Nếu đây là lần đầu tiên đến với Điện Tử Việt Nam, bạn có thể đọc phần Hỏi đáp bằng cách nhấn vào liên kết. Có thể bạn cần đăng kí trước khi có thể gửi bài . Để bắt đầu xem bài viết, chọn diễn đàn bạn muốn thăm dưới đây.
Thông báo
Collapse
No announcement yet.
Đố vui về PIC, các câu đố cực vui và cực hay... hehe..
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
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
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
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?
//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;
}
}
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).
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?
Đâ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
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.
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.
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ứ.
//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.
Dạ thời thế giờ thay đổi theo hướng tích cực hơn rồi chú trung sĩ ạ. Kiến thức được chia sẻ ngày càng nhìu nên làm ăn gian dối ko còn dễ dàng như trước đâu ạ. Những thợ nhỏ rồi sẽ thành công nhân sản xuất đồ mới hết thay vì sửa chữa lặt vặt...
Dạ cùng chuẩn tín hiệu thì chắc chắn là nhận ạ. Vì bản chất oled hay lcd thì đều phải có mạch chuyển đổi trên thanh gỗ rồi chuyển sang những chip xử lý hàng nghìn chân gắn trên những tab mỏng dính rồi mới ra các điểm ảnh theo hàng...
Dạ ý chú là màn oled ấy ạ. Cùng chuẩn lvds cùng độ phân giải thì cắm được ạ. Còn nó mà khác thì hơi khó vì oled các điểm ảnh nó tự phát sáng chứ ko dùng đèn nền như lcd. Cháu chỉ biết đến vậy thôi ạ. Chú muốn nghịch phải tự tìm hiểu kỹ trước khi mua thôi, khó mà ông thợ nào tư vấn vụ này...
Hay đấy bạn ạ. Đây có thể hiểu là máy đo cuộn dây. Tiện đây xin cho hỏi bạn có hiểu rõ về máy nạp rôm pcb 45 của hãng thiên minh không giúp mình cách cài fw của nó với vì mình vừa được anh bạn cho nhưng lại không biết cài fw nên chưa dùng được. Nếu có thể thì bạn giúp mình với...
Comment