Nguyên văn bởi diamond
Xem bài viết
Thông báo
Collapse
No announcement yet.
Cần giúp về Led sáng dồn bằng C
Collapse
X
-
cơ bản về thuật toán mình đẳ hiểu, nếu nói như bạn thì mình củng đẳ nghỉ đến và củng đẳ thử nhưng code dài và rắc rối. chủ yếu là dải thuật ngắn gọn, dể hiểu và để đở tốn bộ nhớ cho vdk. bên asm mình đẳ làm được truyền 4 port dùng lệnh RRC hoặc RLC rồi truyền từ từ nhưng chuyển qua c chỉ có lệnh <<= hoặc =>> nên mình chưa nghỉ ra thuật toán cụ thể để thay thể cho lệnh RRC như bên ASM đượcNguyên văn bởi ccccccNếu bạn điều khiển mỗi led bằng 1 chân vđk thì cứ dồn 1 port rồi giữ nguyên trạng thái của port đó rồi dồn tiếp port còn lại thì khi chạy sẽ tạo hiệu ứng như đồn 2 port thôi mà. Quan trọng là viết cho đúng chiều ko lại cái dồn ngược cái dồn xuôi
Comment
-
Hi em.tham khảo code sau rồi tìm thuật toán cho riêng mình.Nguyên văn bởi kervin Xem bài viếtcơ bản về thuật toán mình đẳ hiểu, nếu nói như bạn thì mình củng đẳ nghỉ đến và củng đẳ thử nhưng code dài và rắc rối. chủ yếu là dải thuật ngắn gọn, dể hiểu và để đở tốn bộ nhớ cho vdk. bên asm mình đẳ làm được truyền 4 port dùng lệnh RRC hoặc RLC rồi truyền từ từ nhưng chuyển qua c chỉ có lệnh <<= hoặc =>> nên mình chưa nghỉ ra thuật toán cụ thể để thay thể cho lệnh RRC như bên ASM được
Code://code sang don 32 led (Ktot chung)da test bang proteus chay ok. #include <at89X52.h> unsigned long chay,don_led,luu_hieu_ung; void de_lay(unsigned int dem){ unsigned int lap; for( lap=0;lap<dem;lap++){ TR0 = 1; while(TF0==0){}; TH0 = 0x00; // TL0 = 0x00; TF0=0; TR0 = 0;} } main(){ TMOD = 0x01; TH0 = 0x00; TL0 = 0x00; while(1){ char vong,don,lap_don; don_led=0xffffffff; lap_don =32; for(don=0;don<32;don++){ chay=1; for(vong=0;vong<lap_don;vong++){ luu_hieu_ung=chay|~don_led; P1= luu_hieu_ung;//xuat port P0=luu_hieu_ung>>=8;//xuat port P2=luu_hieu_ung>>=8;//xuat port P3=luu_hieu_ung>>=8;//xuat port de_lay(1); chay<<=1; }don_led=(don_led/2);lap_don--;}} }|
Comment
-
thank bác nhiều. thuật toán của bác rẩt dể hiểu, xem xong mình mới biết kiểu khai báo unsigned long có thể chạy 0 đến 0xffffffff nhưng có một điều mình không hiểu là đoạn P1=luu_hieu_ung, lúc này hiệu ứng là 0x00000001; vậy P1 nhận giá trị 8 bit cuối (2 byte 01) của luu_hieu_ung phải không ạ. Nếu đúng như vậy thì mình có một thắc mắc nhỏ là khi vòng lặp for(vong=0;vong<lap_don;vong++) khi vong=3 thì luu_hieu_ung=0x02040809 thì P1=0x09 chứ đâu vẩn là P1=0x80 ạ mong bác giả thích giùm mình vớiNguyên văn bởi tdm Xem bài viếtHi em.tham khảo code sau rồi tìm thuật toán cho riêng mình.
Code://code sang don 32 led (Ktot chung)da test bang proteus chay ok. #include <at89X52.h> unsigned long chay,don_led,luu_hieu_ung; void de_lay(unsigned int dem){ unsigned int lap; for( lap=0;lap<dem;lap++){ TR0 = 1; while(TF0==0){}; TH0 = 0x00; // TL0 = 0x00; TF0=0; TR0 = 0;} } main(){ TMOD = 0x01; TH0 = 0x00; TL0 = 0x00; while(1){ char vong,don,lap_don; don_led=0xffffffff; lap_don =32; for(don=0;don<32;don++){ chay=1; for(vong=0;vong<lap_don;vong++){ luu_hieu_ung=chay|~don_led; P1= luu_hieu_ung;//xuat port P0=luu_hieu_ung>>=8;//xuat port P2=luu_hieu_ung>>=8;//xuat port P3=luu_hieu_ung>>=8;//xuat port de_lay(1); chay<<=1; }don_led=(don_led/2);lap_don--;}} }
Comment
-
lấy đâu ra luu_hieu_ung=0x02040809Nguyên văn bởi kervin Xem bài viếtthank bác nhiều. thuật toán của bác rẩt dể hiểu, xem xong mình mới biết kiểu khai báo unsigned long có thể chạy 0 đến 0xffffffff nhưng có một điều mình không hiểu là đoạn P1=luu_hieu_ung, lúc này hiệu ứng là 0x00000001; vậy P1 nhận giá trị 8 bit cuối (2 byte 01) của luu_hieu_ung phải không ạ. Nếu đúng như vậy thì mình có một thắc mắc nhỏ là khi vòng lặp for(vong=0;vong<lap_don;vong++) khi vong=3 thì luu_hieu_ung=0x02040809 thì P1=0x09 chứ đâu vẩn là P1=0x80 ạ mong bác giả thích giùm mình với
bạn chuyển sang dạng mã bin cho dể hiểu:
lúc đầu :bien chay=00000000 00000000 00000000 00000001 và don_led=0xffffffff;
luu_hieu_ung=chay|~don_led;
vong=0 :luu_hieu_ung =00000000 00000000 00000000 00000001
vong=1 :luu_hieu_ung =00000000 00000000 00000000 00000010
vong=2 :luu_hieu_ung =00000000 00000000 00000000 00000100
vong=3: luu_hieu_ung =00000000 00000000 00000000 00001000
.......
bạn nên phân tích thêm code đề hiểu rõ hơn.|
Comment
-
mình không hiểu ở chổ code màu đỏ đấy. nếu như vong=0 và ct chạy đến đến P3=luu_hieu_ung>>=8 thì lúc này luu_hieu_ung phải được dich 24 bit rồi chứ và nó sẻ bằng P3=luu_hieu_ung=00000000 00000000 00000001 00000000 và lưu kết quả luu_hieu_ung để bắt đầu đến vòng=1. theo mình hiẻu thì luu_hieu_ung<<=8 thương đương với luu_hieu_ung=luu_hieu_ung>>8 (8 này là 8 lần dịch bit có phải không ạ)Nguyên văn bởi tdm Xem bài viếtlấy đâu ra luu_hieu_ung=0x02040809Code:while(1){ char vong,don,lap_don; don_led=0xffffffff; lap_don =32; for(don=0;don<32;don++){ chay=1; for(vong=0;vong<lap_don;vong++){ luu_hieu_ung=chay|~don_led; P1= luu_hieu_ung;//xuat port P0=luu_hieu_ung>>=8;//xuat port <=> tương đương lệnh luu_hieu_ung>>=8; P0=luu_hieu_ung; P2=luu_hieu_ung>>=8;//xuat port <=> tương đương lệnh luu_hieu_ung>>=8; P2=luu_hieu_ung; P3=luu_hieu_ung>>=8;//xuat port <=> tương đương lệnh luu_hieu_ung>>=8; P3=luu_hieu_ung; de_lay(1); chay<<=1; }don_led=(don_led/2);lap_don--;}} }
bạn chuyển sang dạng mã bin cho dể hiểu:
lúc đầu :bien chay=00000000 00000000 00000000 00000001 và don_led=0xffffffff;
luu_hieu_ung=chay|~don_led;
vong=0 :luu_hieu_ung =00000000 00000000 00000000 00000001
vong=1 :luu_hieu_ung =00000000 00000000 00000000 00000010
vong=2 :luu_hieu_ung =00000000 00000000 00000000 00000100
vong=3: luu_hieu_ung =00000000 00000000 00000000 00001000
.......
bạn nên phân tích thêm code đề hiểu rõ hơn.
Comment
-
biến luu_hieu_ung chỉ có nhiệm vụ lưu kết quả tính toán rồi đem ra hiển thị.Nguyên văn bởi kervin Xem bài viếtmình không hiểu ở chổ code màu đỏ đấy. nếu như vong=0 và ct chạy đến đến P3=luu_hieu_ung>>=8 thì lúc này luu_hieu_ung phải được dich 24 bit rồi chứ và nó sẻ bằng P3=luu_hieu_ung=00000000 00000000 00000001 00000000 và lưu kết quả luu_hieu_ung để bắt đầu đến vòng=1. theo mình hiẻu thì luu_hieu_ung<<=8 thương đương với luu_hieu_ung=luu_hieu_ung>>8 (8 này là 8 lần dịch bit có phải không ạ)
vd:luu_hieu_ung =0xaabbccdd
P1= luu_hieu_ung;//P1 có giá trị dd
P0=luu_hieu_ung>>=8;//P0 có giá trị cc
P2=luu_hieu_ung>>=8;//P2 có giá trị bb
P3=luu_hieu_ung>>=8;//P3 có giá trị aa|
Comment
-
thank bác nhiều. nhờ có bác mà mình hiểu ra rất nhiều điều và có thể rút ngắn code của mình.Nguyên văn bởi tdm Xem bài viếtbiến luu_hieu_ung chỉ có nhiệm vụ lưu kết quả tính toán rồi đem ra hiển thị.
vd:luu_hieu_ung =0xaabbccdd
P1= luu_hieu_ung;//P1 có giá trị dd
P0=luu_hieu_ung>>=8;//P0 có giá trị cc
P2=luu_hieu_ung>>=8;//P2 có giá trị bb
P3=luu_hieu_ung>>=8;//P3 có giá trị aa
Comment
-
có ai cho mình hỏi. muốn điều khiển nửa port thì làm như thế nào. VD mình muốn điều led sáng từ giữa ra trong 1 port. hoặc 4 chân của 1 port có 1 led chạy với tốc độ khác 4 chân còn lại thì làm như thế nào vậy. mình mới tìm hiểu lên gà lắm.
Comment
-
mình củng mới tìm hiểu con này thôi. tùy theo bạn muốn điều khiển ntn. nếu điều khiển led sáng 1 port mà sáng giửa ra thì củng dể, nếu chưa hiểu thuật toán thì có thể dùng mảng rồi rút gọn code. nếu 1 port mà sáng với 2 trạng thái tốc dộ khác nhau thì dùng ngắt timer hoặc dùng vòng lặp ( cái này giống kiểu 2 chương trình độc lập không liên quan gì đến nhau )Nguyên văn bởi buitoan09 Xem bài viếtcó ai cho mình hỏi. muốn điều khiển nửa port thì làm như thế nào. VD mình muốn điều led sáng từ giữa ra trong 1 port. hoặc 4 chân của 1 port có 1 led chạy với tốc độ khác 4 chân còn lại thì làm như thế nào vậy. mình mới tìm hiểu lên gà lắm.
Comment
-
Trên là 1 số hàm thư viện cần có để thực hiện theo cách của mình, nếu bạn thực sự muốn lập trình tốt mình nghĩ nên đi theo hướng này vì nó sẽ mang tính "reuse(tái sử dụng)" và mạch lạc hơn code ở trên rất nhiều. Sau đây mình sẽ hướng dẫn cách dùng các hàm ở trên làm led dồn nhanh và đơn giản nhất.Code:typedef{ char b[4]; }xData; xData trangThai={0}; unsigned char bitIt[8]={1, 1<<1, 1<<2, 1<<3, 1<<4, 1<<5, 1<<6, 1<<7}; void setBitAt(char b0)// đặt trạng thái bit là 1 tại vị trí b0 { if(b0<0) return; b0%=32; trangThai.b[b0/8]|=bitIt[b0%8]; } // Nếu bạn code LED sáng dồn cho trái tim thì hãy tưởng tượng đó là 1 hình tròn // nên đường nối giữa 2 điểm có thể là nửa trái hoặc nửa phải của 1 hình tròn // Khi vị trí(vt) bắt đầu nhỏ hơn vt kết thúc thì đó là nửa phải // Và ngược lại // Còn nếu bạn code cho 1 đoạn led như là 1 dòng của ma trận thì bạn có thể sắp xếp lại // saao cho vt bắt đầu nhỏ hơn vị trí kết thúc rồi set bit tại các vị trí từ bắt đầu đến kết thúc void vectorSetBit(char from, char to) { if(from<0||to<0) return; from%=32; to%=32; if(from==to) // Nếu vị trí bắt đầu = vị trí kết thúc thì set trạng thái tại điểm đó = 1 setBitAt(from); else if(from<to)// Nếu điểm bắt đầu nhỏ hơn điểm kết thúc thì set 1 tại vị trí từ bắt đầu tới kết thúc for(i=from;i<=to;i++) setBitAt(i); else if(from>to) { for(i=from; i<24; i++)// Nếu bắt đầu lớn hơn kết thúc thì ...... setBitAt(i); for(i=0; i<=to; i++) setBitAt(i); } } void zeroTrangThai() { trangThai.b[0]=0; trangThai.b[1]=0; trangThai.b[2]=0; trangThai.b[3]=0; }
Comment
-
và đây là hàm LED sáng dồn mà bạn cần
Code:void ledSangDon(void) { char i, k=31; ; while(k>=0) { for(i=0;i<k;i++)// 1 điểm chạy từ đầu đến vị trí mà khối LED đang được thắp sáng { zeroTrangThai(); setBitAt(i); vectorSetBit(k, 31); delay();// Dừng lại bao nhiêu tùy ý bạn để xem cách led chạy // Tất nhiên ở đây chưa đưa trạng thái từ trangThai ra LED, bạn có thể đưa ra ở ngay sau hàm vectorSetBit // Hoặc bạn có thể dùng timer để đưa trạng thái từ trangThai ra LED } k--; } }
Comment
-
Khi bạn muốn bật 1 khối đèn LED từ đèn số 3 đến đèn số 31 thì bạn chỉ cần gọi hàm vectorSetBit(3, 31)
còn nếu chỉ muốn bật sáng 1 led đơn nào đó nằm trong khoảng từ 0 đến 31 thì gọi setBitAt(vị trí cần bật)
vậy là nhiệm vụ của bạn chỉ là bật đèn nào, hay bật khối đèn nào, khi khi hiển thị xong thì lại dùng hàm zeroTrangThai để xóa đi sau đó vẽ lại
Cách này sẽ tiêu tốn xử lý của CPU hơn cách phía trên TDM đưa ra, nhưng chắc chắn dễ hiểu, dễ dùng hơn và có thể tái sử dụng cho các mục đích khác nhau.
Comment
-
thấy có bạn hỏi LED sáng từ giữa ra của 1 port nhưng vì nó nhỏ quá nên mình mở rộng thành sáng từ giữa ra 2 bên của 32 LED nhé
Code:void giuaRaHaiBen32LED() { char i, j, k=31; ; while(k>=0) { for(i=16;i<k;i++) { zeroTrangThai(); // Doan nay cho doan tu 16-31 setBitAt(i); vectorSetBit(k, 31); // Doan nay cho doan tu 0-15 setBitAt(31-i); vectorSetBit(0, 31-k); delay(); } k--; } }
Comment
-
Những hàm vẽ ở trên mình chỉ vẽ nó ra biến trangThai, vì nó là biến toàn cục nên bạn có thể dùng timer để đưa trạng thái từ đó ra các port hoặc đưa trực tiếp như mình hướng dẫn ở trên. Còn dưới đây là cách đưa từ trangThai ra port.
Code:void show() { P0=trangThai.b[0]; P1=trangThai.b[1]; P2=trangThai.b[2]; P3=trangThai.b[3]; }
Comment
Bài viết mới nhất
Collapse
-
Trả lời cho Đấu tắt điện cho máy tính bảngbởi bqvietBqv cáo lỗi vì chưa đủ khả năng diễn giải để người đọc hiểu. Người làm kỹ thuật sâu đôi khi như thế đó. Về việc nạp pin không vào dù cell mới, khả năng cái mạch quản lý đó đã hỏng - cũng chính là nguyên nhân đám cell cũ hỏng từ đầu.
-
Channel: Thiết bị điện tử cá nhân
Hôm qua, 17:17 -
-
Trả lời cho Xin hỏi về mạch thu FM/AM trong catsettebởi nguyendinhvanTheo tôi, nó chỉ là cái Tuy- ê - nơ, hoặc là khối Trung Văn Tần, nó một phần trong cái Da đì ô thôi. Vì có thấy một chỗ có ba chân hàn, giiống như chân Cờ rít sờ tăng 455 ki nô hẹc. Còn khối Tuy ê nơ thì không nhìn thây cái Di ốt Va di cáp...
-
Channel: Điện thanh
05-12-2025, 19:59 -
-
Trả lời cho Đấu tắt điện cho máy tính bảngbởi afrendlyCó vẻ ngoài hiểu biết của mình rồi. Cuối cùng mình quyết định tìm mua 2 pin trên Shopee, giá 200K thay vào. Tuy nhận pin được 1%, sạc mãi không vào nhưng cũng mở được máy lên. Vậy cũng tạm. Cảm ơn bạn đã hỗ trợ nhé....
-
Channel: Thiết bị điện tử cá nhân
04-12-2025, 01:27 -
-
Trả lời cho Máy điện châm ?bởi nick22Đúng như bạn nói, máy điện châm hiện nay trên thị trường đã khá đa dạng về mẫu mã, chức năng và giá thành.
-
Channel: Điện tử y sinh
01-12-2025, 13:23 -
-
Trả lời cho Làm thế nào để check IC LM358bởi thetungĐể check IC sống hay chết thì đơn giản : bạn lắp cái mạch ( khuếch đại hoặc dao động ) chạy bằng con IC đó ,nhưng vị trí IC thì lắp cái đế .... thế là cứ cắm rút thì biết . Còn không thì kiếm cái này : https://shopee.vn/Xu-M%C3%A1y-ki%E1%...di-%C4%91%E1%B...
-
Channel: Hướng dẫn tìm thông tin linh kiện
28-11-2025, 14:34 -
-
bởi ngochung90Tình hình là em có mua mạch 3s về để hàn vào khối pin 12v, hàn xong em đo tại các chân từ B-, B1, B2, B+ thì điện áp pin vẫn đủ 12,6v, nhưng tại 2 chân ra P- P+ thì đo chỉ được 6,3v là bị sao các bác, và chân P- P + này đồng thời là chân sạc xả thì mình cắm sạc xả cùng lúc được ko ạ
...-
Channel: Điện tử dành cho người mới bắt đầu
28-11-2025, 10:32 -
-
Trả lời cho Làm thế nào để check IC LM358bởi nguyendinhvanViệc đó tùy thuộc trình độ khoa học kỹ thuật công nghệ ứng dụng hiện tại thôi.
Trong datasheet,họ đưa ra nhiều thông số. Tùy theo khả năng , và những thông số họ cần, họ sẽ kiểm tra casc số đo có khớp với số liệu trong datasheet...-
Channel: Hướng dẫn tìm thông tin linh kiện
27-11-2025, 18:00 -
-
bởi kqbn9091Em có mạch AT89s8253 đang cần sửa số serial no của CHIP mà giờ lâu quá rồi không dùng keil nên không biết phải làm sao, trong khi chỉ còn file hex. Mạch nạp thì progris khi viết không sửa được số serial của IC. Rất cần bác nào còn làm về 89...
-
Channel: Vi điều khiển họ 8051
27-11-2025, 11:13 -

Comment