PDA

View Full Version : Nhờ giúp đỡ làm đồng hồ bằng LED


dark_electron
15-07-2008, 08:43 AM
Hi các bác,
Em mới học PIC tính làm cái đồng hồ to to báo giờ để phòng khách cho vui. Do nguồn cung cấp không đủ nên em làm theo phương pháp quét LED, nhưng lạ một điều là khi em mới quét thử 4 LED cho các LED sáng từ 0 - 3 thì hai LED cuối (số 2, 3) sáng bình thường, còn hai LED đầu (số 0 và 1) thì lại bị hiện tượng bóng ma mới đau đầu chớ.
Em attached cái sơ đồ mạch, chương trình em viết thử để scan LED và hình chụp các LED lên đây, nhờ các cao thủ chỉ giáo em với.
Thanks in advance.
@admins: các bác cho em hỏi với là cú pháp chèn đoạn text để trong thẻ code lên diễn đàn là như thế nào? Em muốn add đoạn chương trình của em lên bằng thẻ code mà làm mãi ko được.

namqn
15-07-2008, 09:09 PM
Sau khi reset, các chân RA0-RA3 của PIC16F628A ở trạng thái ngõ vào analog, do tác dụng của thanh ghi CMCON. Để port A của PIC16F628A làm việc như I/O số, bạn cần đặt lại trạng thái cho thanh ghi CMCON. Giá trị có thể dùng là 0x07. Bạn thêm các lệnh sau vào trước nhãn REPEAT, ngay sau lệnh xóa thanh ghi PORTB của bạn:
movlw 0x07
movwf CMCON

...
@admins: các bác cho em hỏi với là cú pháp chèn đoạn text để trong thẻ code lên diễn đàn là như thế nào? Em muốn add đoạn chương trình của em lên bằng thẻ code mà làm mãi ko được.
Bạn đọc luồng sau nhé:
http://www.picvietnam.com/forum/showthread.php?t=2610

Thân,

linhnc308
16-07-2008, 09:53 AM
ASM cho PIC tôi không dùng, nhưng đọc code của bạn, tôi thấy có vẻ không ổn trong thuật giải quét Led. Bạn dùng PORTB là Data và PORTA để chốt các Trans cấp dòng cho Led. KHi quét Led tôi hay làm theo các bước như sau: Gửi data > bật Led > tạo trễ > tắt Led > xóa Data. Chu trình cứ lặp đi lặp lại như vậy cho các Led. Khi quét bạn có thể dùng vòng lặp hoặc ngắt Timer để quét led. Tôi thường hay dùng ngắt Timer, như vậy hệ thống sẽ có thể làm việc khác mà không ảnh hưởng tới quét led và độ sáng led.
Trong code, ngay sau khi tắt led (clear PORTA) bạn không cần gọi Delay, như vậy sẽ là giảm độ sáng của Led. Bạn thay dòng Delay bằng việc xóa data portB, hiện tượng bóng mờ sẽ hết. Nếu vẫn còn bạn kiểm tra xem còn nguyên nhân nào khác (trans bị rò, chân điều khiển trans có vẫn đề, thử thêm trở kéo GND cho các chân khiển trans...) Tôi thường làm nhiều cách, nhưng đầu tiên vẫn là xem lại Code, rồi phần cứng, mọi nguyên nhân gây ra lỗi có thể có. Bạn nên chú ý cả vấn đề anh Nam đề cập.
Chúc thành công.

dark_electron
16-07-2008, 05:29 PM
Hi bác,
Bác có thể cho em một cái ví dụ về quét LED bằng ngắt timer ko? Bác nói sơ sơ về giải thuật cũng được ko cần phải post nguyên chương trình đâu. Em mới tập tễnh vào nghề lập trình PIC nên cũng noob. Cám ơn bác trước.

linhnc308
16-07-2008, 06:44 PM
Hi bác,
Bác có thể cho em một cái ví dụ về quét LED bằng ngắt timer ko? Bác nói sơ sơ về giải thuật cũng được ko cần phải post nguyên chương trình đâu. Em mới tập tễnh vào nghề lập trình PIC nên cũng noob. Cám ơn bác trước.

Code cho PIC tôi hay dùng C (CCS Compiler). Quét kiểu timer nó như sau:

main:
- KHởi tạo cho các Port IN/OUT tương ứng
- Khởi tạo Timer(chọn chế độ chạy clock) + ngắt Timer, thời gian timer chạy đến lúc ngắt chính là thời gian Led sáng. ví dụ 2ms
- Khởi tạo các biến
- Cho phép ngắt timer chạy
- main loop: thực hiện các công việc khác theo yêu cầu lập trình

Ngắt timer:
- tắt Led
- Gửi Data của Led kế tiếp
- Cho Led sáng
- Reset timer
- Thoát

Về cơ bản như vậy, còn đây là sample code:
#int_RTCC
void RTCC_isr()
{
Num_Timer0_INT++;
// Printf("\nINT %d",Num_Timer0_INT);
if (Num_Timer0_INT == 13) // 10*13.1ms ~ 500ms. Update Led
{
disable_interrupts(INT_RTCC);
ClearLed(); // Tat Led
Send_595(led7[DispBuffer[NextLed]]); // Gui data
SelectLed(NextLed);// Cho Led sang
Num_Timer0_INT = 0;
set_timer0(0); // Reset timer
enable_interrupts(INT_RTCC);
}
}



void main()
{
// Khoi tao In/Out
delay_ms(100);
output_a(0xff);
set_tris_a(0b011110001);
set_tris_b(0x03);
output_low(PIN_B7);
// Setup Analog
setup_adc_ports(sAN0);
setup_adc(ADC_CLOCK_INTERNAL); // ADC_CLOCK_INTERNAL
// Setup Timer
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4); // Timer 0, overflow 204uS @ 20MHz
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
// Cho phép ngắt
enable_interrupts(INT_RTCC);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
while (TRUE)
{
// Chương trình xử lý chính
} // End of While
}// En dof Main

dark_electron
17-07-2008, 09:00 AM
Hi,
Các bác cho em hỏi là trong chương trình của em thời gian đếm một số bằng thời gian quét 4 LED (5x4=20ms) hơi nhanh, có cách nào cho delay đếm khác với delay quét mà vẫn đảm bảo các LED sáng đều ko các bác?
Hix, chắc phải chuyển qua quét theo kiểu timer như bác Linh bày quá, quét kiểu lặp khó phối hợp cho chương trình làm việc khác quá đi.

doremino
17-07-2008, 07:40 PM
bạn ơi! cho mình hỏi tí nhé!!bạn hàn những con led đơn lên tấm gì vậy??mua nó ở đâu chỉ mình với??mình cũng muốn làm một cái như bạn??để hàn được những con led ngay hàng đẹp như vậy thì bạn có phải làm mạch in ko vậy???...mình hỏi nhiều quá bạn thông cảm nha??!!!

linhnc308
18-07-2008, 09:55 AM
Hi,
Các bác cho em hỏi là trong chương trình của em thời gian đếm một số bằng thời gian quét 4 LED (5x4=20ms) hơi nhanh, có cách nào cho delay đếm khác với delay quét mà vẫn đảm bảo các LED sáng đều ko các bác?
Hix, chắc phải chuyển qua quét theo kiểu timer như bác Linh bày quá, quét kiểu lặp khó phối hợp cho chương trình làm việc khác quá đi.

Yêu cầu của bạn hoàn toàn thực hiện được.
Gọi Display() là hàm quét Led, thời gian là 20ms. Về cơ bản hàm main của bạn sẽ là
void main(){
// Khoi tao
//vong lap chinh
while(1){
updateCounter(); // Ham nay chuyen gia tri Counter thanh dang du lieu cho Led
display();
Counter++;
}
}Nếu bạn muốn thời gian đếm lâu hơn, bạn thêm một biến khác đếm số lần gọi hàm Display, khi đủ thì tăng biến đếm. Lấy ví dụ bạn muốn biến đếm 1s tăng 1 lần, thực hiện như sau.
void main(){
// Khoi tao
unsigned int NumCallDisplay = 0;
//vong lap chinh
Counter = 0;
updateCounter(); // Ham nay chuyen gia tri Counter thanh dang du lieu cho Led
while(1){
Display();
if (++NumCallDisplay == 50) // So lan goi Display là 50 tương ứng 50x20ms = 1000ms = 1s
{ Counter++;
updateCounter(); // Ham nay chuyen gia tri Counter thanh dang du lieu cho Led
}
}
}Chúc thành công.

dark_electron
21-07-2008, 05:18 PM
Hix, xong phần ngắt quét LED rồi giờ chuyển qua viết giao tiếp với DS1307 bằng ASM cực quá là cực. PIC16F628A ko hỗ trợ I2C hardware mà phải code bằng phần mềm. Em copy luôn cái phần I2C protocol của Nigel, sửa lại vài chỗ mà nó ko chịu chạy. Lạ một điều là em chỉ mới có khởi tạo cho con DS1307 mà chip nó không thèm chạy luôn:

movlw 0x00
movwf Adr_Lo
movlw 0x00 ;set CH bit to Zero
call Write_RTC ;reset SECOND register to zero

phần subroutine Write_RTC em code như sau:

Write_RTC ; write W register to address Adr_Lo
movwf DAT_VAL ; save W
call I2C_Start
call I2C_Set_Write

call I2C_Lo_Adr
movf DAT_VAL, W ; send the actual data
movwf OutputByte

call I2C_Out
call I2C_NAK
call I2C_Stop
call WaitForWrite
return

các subroutine còn lại em copy y nguyên như tut6.5 của Nigel, chỉ bỏ phần báo lỗi lên LCD mà thôi. Về lý thuyết, nếu giao tiếp với RTC không được thì Interrupt của chip vẫn phải chạy và vẫn phải quét LED cho em. Nhưng đây khi em viết đoạn mã ở trên vào thì nó im như cái nhíp luôn, còn bỏ đoạn mã giao tiếp I2C đó ra khỏi chương trình thì timer0 interrupt chạy mượt, quét LED ngon lành. Thế là thế nào nhỉ???
Em thiết kế phần cứng như sau: portB gửi data ra LED, portA chân RA0 đến RA3 quét 4 LED, chân RA6 làm SDA và chân RA7 làm SCL, kéo lên bằng điện trở 10k. Sử dụng dao động nội 4MHz.
Các bác cho em hỏi nguyên nhân làm chip bị đơ khi giao tiếp với DS1307? Có phải do giá trị điện trở kéo lên quá lớn so với giá trị recommended? Cái thứ 2 nữa là em có thể sử dụng chân RA5 (MCLR) như là một chân I/O bình thường được ko, vì chân này bị nối với con trở 10k làm mạch reset rồi? Thanks.

dark_electron
21-07-2008, 09:38 PM
bạn ơi! cho mình hỏi tí nhé!!bạn hàn những con led đơn lên tấm gì vậy??mua nó ở đâu chỉ mình với??mình cũng muốn làm một cái như bạn??để hàn được những con led ngay hàng đẹp như vậy thì bạn có phải làm mạch in ko vậy???...mình hỏi nhiều quá bạn thông cảm nha??!!!
Cái này vẽ bằng Eagle và đem làm mạch in thôi bạn ơi, bạn ra nhìn cái đèn giao thông nào thấy nó đẹp đẹp thì về bắt chước mà làm :D

dark_electron
22-07-2008, 08:50 AM
Hix, tự trả lời được 1 câu, RA5 của PIC6F628A luôn luôn có chức năng Input nên không thể dùng lái out được. Còn chỗ điện trở kéo lên em hạ xuống 4k7 rồi 2k2 rồi 1k nó vẫn không chịu chạy. Thứ nữa là khi em gỡ chân 2 con điện trở này ra khỏi mạch thì chip lại quét bình thường. Thật không thể hiểu nổi???

dark_electron
22-07-2008, 09:52 PM
Hix, ko ai giúp em hết sao? Em thực sự rối rồi. Đọc phân tích code của Nigel và hướng dẫn lập trình I2C thấy matched hết mà, đâu có lỗi gì? I'm confused, somebody help me plz.

namqn
22-07-2008, 10:42 PM
WaitForWrite của Nigel trong tutorial 6.5 như sau:
WaitForWrite ; poll ACK for write timing
call I2C_Start
call I2C_Set_Write
btfsc I2Cflags, 0
goto WaitForWrite
return
Về lý thuyết, nếu bạn gọi Write_RTC mà không giao tiếp được thì có khả năng chương trình kẹt ở đó luôn. Vì WaitForWrite của Nigel là một vòng lặp chỉ có một cách thoát là bit 0 của I2Cflags phải bị xóa về 0 (tín hiệu ACK), mà đã không giao tiếp được thì có bao giờ nhận được ACK đâu.

Vì chân SDA thuộc loại cực thu/máng hở, nên bạn gỡ điện trở kéo lên đồng nghĩa với tự động ACK. Do đó, chip sẽ chạy như đã nhận được ACK. Bây giờ bạn còn phát biểu "Thật không thể hiểu nổi" không?

Thân,

lion
22-07-2008, 11:19 PM
Hix, ko ai giúp em hết sao? Em thực sự rối rồi. Đọc phân tích code của Nigel và hướng dẫn lập trình I2C thấy matched hết mà, đâu có lỗi gì? I'm confused, somebody help me plz.
mà sao bác dark_electron ko dung CCS viết chương trình cho dễ nhỉ .
bác viết = assemble làm mọi người khó giúp bác quá.
thực ra thì ý tưởng của bác đâu có khó thực hiện quá đâu

dark_electron
23-07-2008, 08:36 AM
Hi các bác,
Thanks đã trả lời em, ý kiến của bác namqn em cũng thử sau khi post bài #9 rồi nhưng nó vẫn không chịu chạy. Ở đây chip không chạy đồng nghĩa với không thực hiện bất kỳ thao tác gì, vì ở trong chương trình chính em có cho timer0 chạy ngắt trước khi gọi RTC. Về lý thuyết nếu đúng như bác namqn nói, nếu bị lặp vô tận ở chỗ WaitForWrite thì vẫn còn ngắt timer0 chạy và vẫn quét được LED, và LED phải sáng để báo cho mình thấy là nó hoạt động được.
Thứ 2 là em tháo điện trở kéo lên 2 chân SDA và SCL ra khi đã tắt nguồn chip và bật lên lại thì nó mới chạy, chớ lúc nó đang im lìm mà tháo ra thì cũng vậy à.
Tổng hợp 2 ý trên em mới phán câu "Thật ko thể hiểu nổi" đó các bác.
@lion: em mới học PIC, muốn nắm càng kỹ càng tốt sau này có ai đó hỏi mình biết đường trả lời nên em chọn viết bằng asm trước, với lại cũng đang theo mấy cái tut của Nigel :D Ý tưởng của em gì đâu, toàn bắt chước làm lại mà làm còn chưa được nữa kìa, khối người làm ngon lành ngoài kia, em noob mà bác :D:D:D

dark_electron
24-07-2008, 09:05 AM
Hix, sau nhiều ngày đêm nếm mật nằm gai, bày mưu tính kế, suy đi nghĩ lại, đọc hết sách thánh hiền, điện thoại hỏi búa xua (hix, hơi quá :D) em cũng khiến được con nhóc DS1307 chịu mở cái mồm nó ra bằng asm rồi :D Đúng là gái 18 hơi khó dzụ dzỗ :D:D:D

trunghaudt2_
24-07-2008, 10:16 AM
Hi các bác,
Em mới học PIC tính làm cái đồng hồ to to báo giờ để phòng khách cho vui. Do nguồn cung cấp không đủ nên em làm theo phương pháp quét LED, nhưng lạ một điều là khi em mới quét thử 4 LED cho các LED sáng từ 0 - 3 thì hai LED cuối (số 2, 3) sáng bình thường, còn hai LED đầu (số 0 và 1) thì lại bị hiện tượng bóng ma mới đau đầu chớ.
Em attached cái sơ đồ mạch, chương trình em viết thử để scan LED và hình chụp các LED lên đây, nhờ các cao thủ chỉ giáo em với.
Thanks in advance.
@admins: các bác cho em hỏi với là cú pháp chèn đoạn text để trong thẻ code lên diễn đàn là như thế nào? Em muốn add đoạn chương trình của em lên bằng thẻ code mà làm mãi ko được.
vấn đề led bị lem đó là do dùng bjt
dùng có 1 Led thôi mà làm j mà dùng 2 bjt dữ vậy. dùng 1 con thôi,mà nên dùng a1015 để khi mức 0 sẽ dẫn, nếu dùng con ngược lại thì mức 1 yếu thì led sẽ sáng yếu.

dark_electron
25-07-2008, 10:22 AM
Bác xem hình thấy con led của em nó to thế mà bảo em dùng 1 con BJT thôi à? A1015 dòng Ice có 150mA thôi bác, trong khi đó con led của em tới 3.5A (nếu cho sáng toàn bộ, không quét) mà bác bảo em dùng A1015 thì có mà die sớm :D:D:D Với lại vấn đề ở đây đâu phải là sáng yếu hay ko yếu mà nó bị bóng mờ, cái này có hai lí do một là do BJT lái bị rò, hai là do giải thuật phần mềm bị sai. Em xử lý được rồi.