PDA

View Full Version : Mach den trang tri


tmtm
10-01-2007, 08:48 PM
Em moi hoc Pic, kien thuc con non lam. Em dang duoc giao thiet ke mot he thong den trang tri (mot dong chu) dung LeD, voi nhiem vu la: Cho 26 LEd lan luot sang (Tu 1 den 26), tat tat ca, roi cho tung nhom LeD sang tu trai qua phai, cuoi cung la tat tat ca roi lap lai tu dau. Mong cac anh chi va cac ban di truoc giup em mot tay (tu A toi Z, neu moi nguoi khong phien)! Em xin cam on!

namqn
10-01-2007, 11:12 PM
Em moi hoc Pic, kien thuc con non lam. Em dang duoc giao thiet ke mot he thong den trang tri (mot dong chu) dung LeD, voi nhiem vu la: Cho 26 LEd lan luot sang (Tu 1 den 26), tat tat ca, roi cho tung nhom LeD sang tu trai qua phai, cuoi cung la tat tat ca roi lap lai tu dau. Mong cac anh chi va cac ban di truoc giup em mot tay (tu A toi Z, neu moi nguoi khong phien)! Em xin cam on!
Nếu bạn phải thiết kế cả phần cứng (mạch điện) và phần mềm (chương trình trong PIC) thì bạn tham khảo bên dientuvietnam (http://www.dientuvietnam.net/forums/index.php) về thiết kế phần cứng, sau đó trở lại vấn đề viết chương trình cho PIC tại picvietnam.

Thân,

thaithienanh
11-01-2007, 10:57 PM
Bạn cố gắng tự mình viết code nhé tới chừng thành công được chương trình đầu tay của mình bạn sẽ cảm thấy rất là vui không thể tả được (niềm vui này chỉ có khi mới bắt đầu với pic bạn đừng nên bỏ lỡ)

PIC-NGHEO
12-01-2007, 07:09 AM
Tại diển đàn này, và tại room Thiết kế và ứng dụng này cũng có bài viết tương tự thiết kế Bạn muốn (tìm thử coi!). Nhưng giúp cho tiến bộ khác với " dọn mâm sẵn" từ A tới Z.
Ít nhất là có được một phần thiết kế của Bạn (phần cứng hoặc code). Khi Bạn gởi bài lên diễn đàn này, dựa trên thiết kế của Bạn, chỗ nào "Bí" thì sẽ có các Bạn khác giúp đỡ, như thế mới thực sự đúng tinh thần học hỏi tiến bộ.
Cố gắng nhé !

tmtm
13-01-2007, 09:05 PM
Em cam on moi nguoi, em se o gang. Khi thuc hien co gi bi thi cac anh cac chi giup em nhe!

tmtm
31-08-2008, 07:12 PM
Sau một thời gian học PIC, việc quét led đã ko còn là vấn đề khó nhưng quay lại bài toán của em: ví dụ em muốn quét led đơn (dùng PIC16F877A) với số lượng lớn, ví dụ là 33 led (bằng với số chân I/O của PIC), với yêu cầu led 1 sáng -> led 2 sáng (lúc này led 1 vẫn sáng)... cứ như vậy đến led 33. Tất nhiên, nếu set tất cả các chân I/O của PIC làm đầu ra rồi thực hiện quét led cũng được nhưng làm như thế chắc các anh trên diễn đàn chị cười em chết. Vậy ko biết có cách nào sử dụng ít chân của PIC hơn mà vẫn đạt được mục đích ko? Mong các anh chị giúp đỡ!

lion
31-08-2008, 11:45 PM
bạn dùng thanh ghi dịch ma` làm , dùng hàng trăm con led mà chỉ mất 3 chân của PIC thôi

picpen
31-08-2008, 11:51 PM
Để giải quyết bài toán của bạn ( sử dụng ít chân của pic ),thì cần phải kết nối phần cứng với các thiết bị ngoại vi khác để mở rộng cổng như IC 8255 ,hoặc sử dụng IC số cũng là 1 cách hay . bạn có thể sử dụng IC 74hc164 là IC nghi dịch ,mỗi IC này có 8 chân ra vậy là cần 4 con ( 8*4=32 ) sẽ được 32 đèn. bạn dùng pic để tạo xung clock cho 4 IC này ( tốn 1 chân của pic ), thêm một số chân để điều khiển chức năng CHO PHEP và RESET ic 74hc164 . vị chi bạn tốn khoảng 10 chân của pic

********* Chúc bạn làm tốt ********

thaithienanh
02-09-2008, 08:17 AM
Bạn nên kết hợp cả IC ghi dịch và ma trận, để rõ hơn bạn nên tìm hiểu về led matrix và cách quét led matrix (gợi ý : xem trong luồng làm quang báo á, dù bạn không làm cái này nhưng cũng xem qua cho những ứng dụng nhỏ của mình, rất hay), như vậy bài toán tiết kiệm chân vi điều khiển và IC sẽ đuợc giải quyết tối ưu :)

Thân.

tmtm
02-09-2008, 11:15 AM
Dùng 74HC164 thì sẽ có một hiệu ứng là sáng dồn, nghĩa là ví dụ có 8 led nối tới các đầu ra của 74HC164 chẳng hạn thì các led nối tới q0...q7 sáng lần lượt rồi giữ ở led q7, sau đó tiếp tục quá trình lặp lại và giữ ở led q6... cho tới khi q0 sáng. Có phải ko ah? (xem datashhet của nó em suy luận thế ko biết có đúng ko nữa?). Mà em muốn các chữ do các led tạo thành sáng theo nhiều hiệu ứng khác nhau, do đó em cảm thấy dùng 74HC164 có gì đó chưa ổn với ý đồ của mình lắm. Bài toán của em là cho nháy sáng 25 led (của một dòng chữ) theo các hiệu ứng khác nhau, trong đó có cả việc cho dòng chữ này sáng dần, tắt dần dùng PWM (cái này em giải quyết được). Nhưng số chân VDK phải dùng quá lớn, em vẫn đang tiếp tục theo hướng dùng các chân I/O của PIC (portB + portD + portE +portA = 25 chân, vừa đủ), C1 cho PWM. Khở tạo PortA là các chân I/O thì anh Nam đã hướng dẫn, còn PortE thì có phải khởi tạo ko ah? Em xem datasheet PIC16F877A ko thấy nói tới. Các anh chị cho em xin ý kiến về cách làm của em và vấn đề PortE với, em cảm ơn nhiều!

0509592
02-09-2008, 09:25 PM
uh! ban hiểu sai về IC ghi dịch rồi????
bạn có thể dùng IC ghi dịch để lập trình chúng giống như các port của VDK.
nghĩa là có thể điều khiển tùy ý mình!
với bài toán quét led như vậy thì bạn không cần phải dùng đến PWM.
còn về PORTE thì bạn vẫn phải khởi tạo cho nó là các chân I/O.
PORTE ở địa chỉ tiếp theo của các PORT bắt đầu từ PORTA là 0x05 cứ lần lượt đến PORTE.
chúc vui!

tmtm
02-09-2008, 09:57 PM
uh! ban hiểu sai về IC ghi dịch rồi????
bạn có thể dùng IC ghi dịch để lập trình chúng giống như các port của VDK.
nghĩa là có thể điều khiển tùy ý mình!

Việc dịch dữ liệu vào IC dựa vào xung clock, mỗi 1 xung vào thì dữ hiệu lại được dịch dần vào. (qo ... q7) chứ ko giống như 74HC138, 74HC154... có các đầu vào chọn A0, A1, A2. Mình hiểu như vậy, bạn có thể cho mình một ví dụ cụ thể được ko?

còn về PORTE thì bạn vẫn phải khởi tạo cho nó là các chân I/O.
PORTE ở địa chỉ tiếp theo của các PORT bắt đầu từ PORTA là 0x05 cứ lần lượt đến PORTE.
chúc vui!
Tất nhiên, cần phải khai báo địa chỉ của portE trước khi điều khiển các chân vào ra của nó.
#byte porte = 0x09
Ý của mình là giống như portA, các chân của nó có nhiều chức năng, khi sử dụng nó làm I/O thì phải được thiết lập phù hợp cho nó. Với portE có phải làm như vậy ko?
Mong bạn và các anh chị giúp đỡ!

namqn
02-09-2008, 10:41 PM
Việc dịch dữ liệu vào IC dựa vào xung clock, mỗi 1 xung vào thì dữ hiệu lại được dịch dần vào. (qo ... q7) chứ ko giống như 74HC138, 74HC154... có các đầu vào chọn A0, A1, A2. Mình hiểu như vậy, bạn có thể cho mình một ví dụ cụ thể được ko?

Tất nhiên, cần phải khai báo địa chỉ của portE trước khi điều khiển các chân vào ra của nó.
#byte porte = 0x09
Ý của mình là giống như portA, các chân của nó có nhiều chức năng, khi sử dụng nó làm I/O thì phải được thiết lập phù hợp cho nó. Với portE có phải làm như vậy ko?
Mong bạn và các anh chị giúp đỡ!
Datasheet của PIC16F877A có đề cập đến port E và những vấn đề liên quan. Các chân RE0 .. RE2 được dồn kênh với các chân AN5 .. AN7 của module ADC. Do đó bạn cũng phải thiết lập một cách thích hợp các bit PCFG3:PCFG0 của thanh ghi ADCON1, các bit tương ứng của TRISE.

Nếu bạn muốn dùng tất cả các chân được dồn kênh với các ngõ vào analog của module ADC như các chân digital, bạn có thể đặt giá trị "0110" hay "0111" cho các bit PCFG3:PCFG0 của thanh ghi ADCON1.

Thân,

0509592
02-09-2008, 10:58 PM
nguyên văn bởi tmtm
Việc dịch dữ liệu vào IC dựa vào xung clock, mỗi 1 xung vào thì dữ hiệu lại được dịch dần vào. (qo ... q7) chứ ko giống như 74HC138, 74HC154... có các đầu vào chọn A0, A1, A2. Mình hiểu như vậy, bạn có thể cho mình một ví dụ cụ thể được ko?

bạn hiểu sai rồi! bạn đưa vào nó dữ liệu 8 bit nối tiếp vào một chân data thì đầu ra là 8 bit tương ứng.
giả sử mình dùng IC ghi dịch 74HC164 nhé!
bạn vào google dwon về!
nó có hai chân data A1, A2. nếu đồng thời cả hai chân đều sử dụng là data thì đầu ra sẽ là phép and của hai đầu vào!
còn nếu dùng một chân!
giả sử chân A1 không dung làm data và được treo lên mức high, và chân A2 làm chân data thì khi mình gửi vào dữ liệu là 0x01 thì chỉ có một đầu ra(QA) là mức cao còn lại là thấp. tương tự với 2 đầu ra(QA, QB) mức cao thì đưa dữ liệu vào là 0x03. còn các đầu ra khác là mức thấp!
tương tự cho các đầu ra khác!
và tương tự như vậy nếu bạn chon đầu vào data là chân A2,
nó giông như lập trình cho các post của VDK mà.

nguyên văn bởi tmtm
Tất nhiên, cần phải khai báo địa chỉ của portE trước khi điều khiển các chân vào ra của nó.
#byte porte = 0x09
Ý của mình là giống như portA, các chân của nó có nhiều chức năng, khi sử dụng nó làm I/O thì phải được thiết lập phù hợp cho nó. Với portE có phải làm như vậy ko?
Mong bạn và các anh chị giúp đỡ!

còn về porte thì bạn cũng phải khai báo là công I/O giống như porta . bởi porte còn có chức năng analog nữa mà....
chuc vui!
----------------**^^o0o^^**--------------
"tháng ngày dong duổi cuộc đời
nhớ người cố hữu hẹn ngày tái ngộ"

tmtm
02-09-2008, 11:51 PM
chân A2 làm chân data thì khi mình gửi vào dữ liệu là 0x01 thì chỉ có một đầu ra(QA) là mức cao còn lại là thấp. tương tự với 2 đầu ra(QA, QB) mức cao thì đưa dữ liệu vào là 0x03. còn các đầu ra khác là mức thấp!
tương tự cho các đầu ra khác!
và tương tự như vậy nếu bạn chon đầu vào data là chân A2,
nó giông như lập trình cho các post của VDK mà.
ví dụ, ta muốn tất cả các đầu ra ở mức cao thì ta phải gửi tới A2 dữ liệu là 0x07 phải ko ah? Vấn đề là chỉ nối 1 chân vi điều khiển tới A2 thì bạn sẽ làm thế nào để gửi 0x07 tới được? Bạn có thể giúp mình chỗ này được chứ?

còn về porte thì bạn cũng phải khai báo là công I/O giống như porta . bởi porte còn có chức năng analog nữa mà...

Vấn đề là khai báo như thế nào? Ở trên thì bác Nam đã chỉ ra cách làm, mình hay dùng CCSC, mình cũng chưa kịp thử. Bạn làm như thế nào với vấn đề này bằng CCSC?

tmtm
03-09-2008, 10:44 PM
Em đang thử với portA, em dùng 1 đoạn code sau để kiểu tra xem chân RA0 đã thành 1 chân I/O chưa.
#include <16F877a.h>
#include <def_877a.h>
#fuses NOWDT,PUT,XT,NOPROTECT, NOLVP
#use delay(clock=4000000)
#use fast_io(a)
main()
{
ADCON1 = 0x06;
TRISA = 0x00;
While(1);
{
output_a(1);
delay_ms(1000);
output_a(0);
}
}

Chân RA0 được nối tới Anot của một led, Katot của led nối mass. Vậy mà led cứ sáng suốt. Ko hiểu sai chỗ nào. Việc thiết lập portA dựa vào hướng dẫn của anh Nam tại đây http://www.picvietnam.com/forum//showthread.php?t=901
Các bác xem giúp em với!

namqn
03-09-2008, 11:06 PM
Sau output_a(0) bạn cần delay một khoảng thời gian thì mới thấy nó bị tắt (thêm vào delay_ms(1000) chẳng hạn).

Thân,

0509592
04-09-2008, 01:56 AM
uh! thì tôi cũng dùng CCS C mà!

nguyên văn bởi: tmtm
ví dụ, ta muốn tất cả các đầu ra ở mức cao thì ta phải gửi tới A2 dữ liệu là 0x07 phải ko ah? Vấn đề là chỉ nối 1 chân vi điều khiển tới A2 thì bạn sẽ làm thế nào để gửi 0x07 tới được? Bạn có thể giúp mình chỗ này được chứ?

bạn muốn làm được điều này thì bạn phải viết một thủ tục gửi từng bit dữ liệu cho ic ghi dịch!
đơn giản thế này nhe!

void send(unsigned char data)
{
portb0=0;//nối portb0 với chân clock và cho reset về mức 0
portb1=0x01&data;//chân portb1 nối vào một chân data. vậy giá trị đầu ra là một bit
//đầu tiên ở mức cao hay thấp tùy vào biến data
portb0=1;//kích chân clock lên mức cao
delay_us(10);
portb0=0;//nối portb0 với chân clock và cho reset về mức 0
portb1=0x02&data;//chân portb1 nối vào một chân data. vậy giá trị đầu ra là một bit
//thứ hai ở mức cao hay thấp tùy vào biến data
portb0=1;//kích chân clock lên mức cao
//.......... cứ tiếp tục cho đến đầu ra số 7 (QH)

}
void main()
{

//rồi vào chương trình chính thì bạn chỉ viêc gọi thủ tục ra với mong muốn đầu ra
//nào được set lên cao đầu ra nào ở mức thấp.
//giả sử mình muốn đầu ra QA và QB là cao còn lại là thấp thì gọi ra
send(0x03);
//như vậy là QA và QB mức cao.
//tương tụ với các đầu ra khác.
}

như vậy bạn có thể điều khiển đầu ra của thanh ghi dịch theo ý muốn.


nguyên văn bởi: tmtm
Vấn đề là khai báo như thế nào? Ở trên thì bác Nam đã chỉ ra cách làm, mình hay dùng CCSC, mình cũng chưa kịp thử. Bạn làm như thế nào với vấn đề này bằng CCSC?

thì bạn định nghĩa porte như sau:
#byte porte =0x09
#byte trise=0x89;
khi vào chương trình chính thì bạn chỉ cần khai báo
porte là cổng I/O
trise=0x00;//cổng ra
chúc bạn thành công.
code của bạn được sửa và tôi thêm doạn porte vào cho bạn như sau:

#include <16F877a.h>
#include <def_877a.h>
#fuses NOWDT,PUT,XT,NOPROTECT, NOLVP
#use delay(clock=4000000)
#use fast_io(a)
main()
{
ADCON1 = 0x06;
TRISA = 0x00;
trise=0x00;
While(1);
{
output_a(1);
delay_ms(1000);
output_a(0);
delay_ms(1000);
output_port_e(0x07);//cả porte cùng sáng
delay_ms(1000);
output_port_e(0x00);//cả porte cùng tắt
delay_ms(1000);//nếu bạn muốn dùng từng bit một thì định nghĩa như bạn đã làm
//cho porta.

}
}

-------------**^^o0o^^**-------------
"tháng ngày dong duổi cuộc đời
nhớ người cố hữu hẹn ngày tái ngộ"

tmtm
04-09-2008, 08:17 AM
//giả sử mình muốn đầu ra QA và QB là cao còn lại là thấp thì gọi ra
send(0x03);

Bạn có thể giải thích rõ hơn về dòng lệnh này dược ko? Nếu ta sử dụng 2 chân RB2 & RB3 để điều khiển 1 IC74HC164 thứ 2 ... RB4 & RB5 điều khiển IC74HC164 thứ 3... thì ta phải xử lý như thế nào?

cskiller
04-09-2008, 10:24 AM
Bạn có thể giải thích rõ hơn về dòng lệnh này dược ko? Nếu ta sử dụng 2 chân RB2 & RB3 để điều khiển 1 IC74HC164 thứ 2 ... RB4 & RB5 điều khiển IC74HC164 thứ 3... thì ta phải xử lý như thế nào?

Khi bạn thiết kế với nhiều Port bạn có thể gom chúng lại để việc điều khiển và quản lý code dễ dàng hơn.
Nếu ngoài output bạn muốn sử dụng nhiều nhiều hiệu ứng hơn thì đồng thời với xuất ra led bạn nên dùng 1 buffer đi kèm theo để lưu lại.

//////////////////////////////////Data - CLK, Data - CLK, ...
#define PORT_NUMBER 4
const unsigned long PORT_TABLE[PORT_NUMBER*2]={PIN_B0,PIN_B1,PIN_B2,PIN_B3,PIN_B4,PIN_B5,PIN_B6 ,PIN_B7};
unsigned char PortData[PORT_NUMBER];

//prototype
void Write2Led();
void WritePort2Led(int port_num,unsigned char data);
void WriteByte(int port_num,unsigned char data);
void WriteBit(int bit_num,unsigned short data);
void WriteInt32(int32 data);
void WriteArray(unsigned char data[PORT_NUMBER]);

//Update all data to leds
void Write2Led()
{
int i,j;
for(i=0;i<PORT_NUMBER;i++){
WritePort2Led(i,PortData[i]);
}
}

//Update data port to leds
void WritePort2Led(int port_num,unsigned char data)
{
int i;
for(i=0;i<8;i++){
output_bit(PORT_TABLE[port_num],data&0x01);
output_high(PORT_TABLE[port_num+1]);
delay_us(1);
data>>=1;
output_low(PORT_TABLE[port_num+1]);
}
}

//Write 1 byte data to buffer and update to leds
void WriteByte(int byte_num,unsigned char data)
{
PortData[byte_num]=data;
WritePort2Led(byte_num,data);
}

//Write 1 bit data to buffer and update to leds
void WriteBit(int bit_num,unsigned short data)
{
PortData[bit_num/8]=(data == 0x01)?(PortData[bit_num/8]|(data&0x01)<<(bit_num%8)):(PortData[bit_num/8]&(~(data&0x01)<<(bit_num%8)));
WritePort2Led(bit_num/8,PortData[bit_num/8]);
}

//Write 1 integer 32 bits data to buffer and update to leds
void WriteInt32(int32 data)
{
int i;
for(i=0;i<PORT_NUMBER;i++){
PortData[i]=data&0xFF;
data>>=8;
}
Write2Led();
}

//Write 1 array data to buffer and update to leds
void WriteArray(unsigned char data[PORT_NUMBER])
{
int i;
for(i=0;i<PORT_NUMBER;i++){
PortData[i]=data[PortData];
}
Write2Led();
}


Good luck!

0509592
04-09-2008, 01:50 PM
nguyên văn bởi: tmtm
Trích:
Nguyên văn bởi 0509592
//giả sử mình muốn đầu ra QA và QB là cao còn lại là thấp thì gọi ra
send(0x03);

Bạn có thể giải thích rõ hơn về dòng lệnh này dược ko? Nếu ta sử dụng 2 chân RB2 & RB3 để điều khiển 1 IC74HC164 thứ 2 ... RB4 & RB5 điều khiển IC74HC164 thứ 3... thì ta phải xử lý như thế nào?

thứ nhất dòng lệnh send(0x03);
đây là lệnh gọi chương trình con void send(unsigned char data)
đã viết ở trên
bạn nhìn vào hàm send ở trên thì thấy nếu gọi send(0x03); thì data =0x03
//
portb0=0;//nối portb0 với chân clock và cho reset về mức 0
portb1=0x01&data;//chân portb1 nối vào một chân data. vậy giá trị đầu ra là một bit
//đầu tiên ở mức cao hay thấp tùy vào biến data
portb0=1;//kích chân clock lên mức cao

portb0=0;//nối portb0 với chân clock và cho reset về mức 0
portb1=0x02&data;//chân portb1 nối vào một chân data. vậy giá trị đầu ra là một bit
//đầu tiên ở mức cao hay thấp tùy vào biến data
portb0=1;//kích chân clock lên mức cao
//
thì ở đây sẽ có hai giá trị được tính đó là portb1=0x01&0x03; ta được 0x01; QA mức cao.
và portb1=0x02&0x03; ta được 0x02//QB=1; mức cao.
tương tự nếu bạn làm cho các đầu ra QAN ; QGN khác!
còn khi bạn sử dụng 2 chân data của một IC và dùng hai IC thì cũng làm tương tự.
nếu bạn nối vào 2 chân RB2 & RB3 thì đầu ra là kết quả của phép and giữa RB2 và RB3, bạn cũng làm tương tự như trên .
chúc bạn thàng công.
------------**^^o0o^^**-------------
"tháng ngày dong duổi cuộc đời
nhớ người cố hữu hẹn ngày tái ngộ"

thaobeo
27-09-2008, 11:09 AM
em cũng muốn tìm hiểu thêm xem thế nào các anh cứ chỉ giáo đi rồi em học hỏi

thaobeo
27-09-2008, 11:15 AM
thử xem nào