PIC Vietnam

PIC Vietnam (http://www.picvietnam.com/forum/index.php)
-   PIC - Thiết kế và Ứng dụng (http://www.picvietnam.com/forum/forumdisplay.php?f=23)
-   -   Nhờ giúp đỡ làm đồng hồ bằng LED (http://www.picvietnam.com/forum/showthread.php?t=2606)

dark_electron 15-07-2008 08:43 AM

Nhờ giúp đỡ làm đồng hồ bằng LED
 
5 Attachment(s)
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:
Code:

        movlw        0x07
        movwf        CMCON

Trích:

Nguyên văn bởi dark_electron (Post 17436)
...
@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

Trích:

Nguyên văn bởi dark_electron (Post 17464)
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:
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);
  }
}

Code:

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

Bộ đếm 4 số (thử trước khi chạy đồng hồ)
 
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

Trích:

Nguyên văn bởi dark_electron (Post 17474)
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à
Code:

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.
Code:

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

Giao tiếp với DS1307
 
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:
Code:

        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:
Code:

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

Trích:

Nguyên văn bởi doremino (Post 17493)
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:
Code:

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

Trích:

Nguyên văn bởi dark_electron (Post 17625)
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


Múi giờ GMT. Hiện tại là 01:33 AM.

Tên diễn đàn: vBulletin Version 3.8.11
Được sáng lập bởi Đoàn Hiệp.
Copyright © PIC Vietnam