PIC Vietnam

PIC Vietnam (http://www.picvietnam.com/forum/index.php)
-   Cơ bản về vi điều khiển và PIC (http://www.picvietnam.com/forum/forumdisplay.php?f=8)
-   -   Học PIC16F877A qua đề tài Lịch Vạn Niên (http://www.picvietnam.com/forum/showthread.php?t=1437)

tinhthanthep 25-08-2007 02:39 PM

Học PIC16F877A qua đề tài Lịch Vạn Niên
 
1 Attachment(s)
Chào các bạn!
Hiện mình đã làm xong mạch Lịch Vạn niên sử dụng PIC16F877A. Mình sẽ lần lượt post các chương trình thử nghiệm trên mạch này. Qua Project này các bạn sẽ làm chủ được con PIC16F877A và trình dịch MikroC, một trình biên dịch rất dễ sử dụng cho người mới bắt đầu học.
Đây là sơ đồ mạch nguyên lý:

tinhthanthep 25-08-2007 02:47 PM

1 Attachment(s)
Dùng PIC16F877A với chuẩn nạp chương trìng bootloader-ICSP của Picvietnam. Thạch anh 20MHz, tụ 1uF lọc nhiễu.

tinhthanthep 25-08-2007 02:52 PM

1 Attachment(s)
Có 4 nút bấm Mode, Set, Up, Down dùng để cài đặt và xem thông tin của lịch vạn niên. Hiển thị bằng màn hình LCD 16x2 cắm qua hàng Jump LCDDISPLAY. Có nút gạt để chọn backlight của LCD. 3 LED đơn mắc ở cổng E dùng để chỉ thị các chế độ.

tinhthanthep 25-08-2007 02:58 PM

1 Attachment(s)
Nhiệt độ môi trường được lấy từ con LM335. Thông qua việc sử dụng LM335 bạn sẽ hiểu được cách sử dụng modul ADC của PIC. Thời gian thực được lấy từ con DS1307, mở rộng thêm bộ nhớ ngoài bằng con 24C04 với 256B, qua cách giao tiếp với 2 con IC này bạn học thêm được cách dùng giao tiếp I2C. Gắn thêm cái loa Speaker vào chân PWM để học cách sử dụng mô đul PWM của PIC.
Như vậy đến đây mạch của ta đã hoàn chỉnh để có thể làm một cái lịch vạn niên hiển thị ngày tháng năm, giờ phút giây, nhiệt độ môi trường, báo giờ chuông. Còn lại là khả năng bay bổng của các bạn bằng phần mềm.

tinhthanthep 25-08-2007 03:01 PM

1 Attachment(s)
Còn nốt cái nguồn cho mạch chạy. Nguồn đầu vào là một cái adapter 9V DC rất phổ biến , cắm vào cái nguồn này đầu ra sẽ là 5VDC cho mạch chạy.

tinhthanthep 25-08-2007 03:11 PM

1 Attachment(s)
Như vậy là mạch nguyên lý đã xong. Mạch in hôm nào chụp ảnh post cho các bạn xem sau. Giờ là bắt tay vào viết chương trình. Đầu tiên bạn lên mạng hỏi thằng google xem hiện giờ MikroC mới nhất là phiên bản nào và tải nó về. Nếu nó hỏi key thì lại nhờ anh google tìm hộ cho cái key. Sau khi cài đặt Trình biên dịch xong thì bạn làm theo các hướng dẫn của file đính kèm theo đây để bắt đầu viết một chương trình cho project.

tinhthanthep 25-08-2007 03:14 PM

Nếu bạn nào hỏi thằng google mãi không được thì mess cho mình mình gửi cả softwave và crack cho nhá.

falleaf 25-08-2007 05:29 PM

Cảm biến nhiệt độ các bạn cố thể dùng các dòng MCP97xx 98xx của Microchip cho thiết kế của mình. Cảm biến nhiệt độ là một phần thiết kế rất quan trọng trong các thiết kế.

Chúc vui.

congduc_1984 26-08-2007 06:59 PM

Hay quá !
 
Chương trình này bạn tự viết phải ko ?Làm sao bạn viết được như vậy?
Tớ tham gia vào Pic là vì muốn học cách lập trình và thiết kế các loại ic này ,nhưng căn bản của mình chỉ hạn chế ở những mạch điện tử thông dụng ko rành về ic nhớ và các loại ic xử lý .
Bây giờ minh muốn học nó thì phải bắt đầu từ đâu vậy .Bạn có thể hướng dẫn cho mình được ko (tất nhiên là có phí học rồi) ,nếu bạn quá bận thì có thể chỉ mình chổ học được ko ?
Mình ở giữa TP.BIÊN HÒA và THỦ ĐỨC
Cảm ơn các bạn nhiều .
Mail "virut_goocky_07@yahoo.com.vn"
Phone :0919310478

tinhthanthep 27-08-2007 04:33 PM

Project1: I/O PORT

Chương trình đầu tiên ta học về cách làm việc với các cổng I/O. Ở đây ta có cổng E mắc với các Led đơn. Ta làm chương trình nháy Led đơn theo thứ tự như sau: 100,010,001,100.... Mỗi lần nháy cách nhau 250ms.

void MAIN() {
PORTE = 0; // Xóa dữ liệu cổng E
TRISE = 0; // ĐỊnh nghĩa cổng E là Output
ADCON1 = 0xE; // Định nghĩa cổng E là I/O Port.

Loop: // Nhãn vòng lặp
PORTE.F0 = 1; // Bật Led 1
PORTE.F1 = 0; // Tắt Led 2
PORTE.F2 = 0; // Tắt Led 3
Delay_ms(250); // Trễ 250ms
PORTE.F0 = 0; // Tắt Led 1
PORTE.F1 = 1; // Bật Led 2
PORTE.F2 = 0; // Tắt Led 3
Delay_ms(250); // Trễ 250ms
PORTE.F0 = 0; // Tắt Led 1
PORTE.F1 = 0; // Tắt Led 2
PORTE.F2 = 1; // Bật Led 3
Delay_ms(250); // Trễ 250ms
goto Loop; // Lặp lại chu trình nháy.
}

Sau khi viết xong các bạn dịch sang file hex bằng cách ấn tổ hợp phím Ctrl + F9. Rồi đem file hex này nạp vào PIC16F877A là mạch chạy ngon lành.

tinhthanthep 27-08-2007 05:13 PM

Bây giờ các bạn lại muốn cả 3 đền nhấp nháy cùng một lúc, khoảng thời gian nhấp nháy là 250ms thì chương trình sẽ như thế này:

void MAIN() {
PORTE = 0; // Xóa dữ liệu cổng E
TRISE = 0; // ĐỊnh nghĩa cổng E là Output
ADCON1 = 0xE; // Định nghĩa cổng E là I/O Port.

Loop: // Nhãn vòng lặp
PORTE = ~PORTE; // Đảo trạng thái cổng E
Delay_ms(250); // Trễ 250ms
goto Loop; // Lặp lại chu trình nháy.
}

linhnc308 27-08-2007 06:04 PM

@ Tinhthanthep: Cậu có file Crack chủa MikroC ver 6 không? Nếu có gửi cho tôi với nhé (cả soft và crack thì càng hay, còn không mình files crack cũng được).
email: linhnc308@gmail.com
YM: linhnc308
Thank.
Topic của bạn rất hữu ích với những người mới học.

tinhthanthep 29-08-2007 03:56 PM

Đã gửi software và crack phiên bản 6.2.1.0 cho linhnc308.
Nếu bạn nào muốn làm cái mạch này để học con PIC16F877A thì liên hệ với mình , mình cho mượn film để đi làm mạch in cho đỡ tốn xèng. Diện tích mạch PCB là 1dm2. Mạch in 2 lớp có phủ flux và mạ bạc ở viện điện tử là 62k/dm2

minhtienbk 30-08-2007 03:12 PM

,anh cho xem cái chương trình ấy , đang làm đồng hồ lại thành chớp LED :)

tinhthanthep 30-08-2007 04:56 PM

Trích:

Nguyên văn bởi minhtienbk (Post 11058)
,anh cho xem cái chương trình ấy , đang làm đồng hồ lại thành chớp LED :)

Mình hướng dẫn các bạn học từ cái cơ bản đầu tiên, đến cuối cùng sẽ là một chương trinh lịch vạn niên hoàn chỉnh. Chứ viết cả chương trình lớn lên đây chắc những người đọc xong cái hiểu ngay thì cũng không cần đến cái project của mình lắm. :D

Tiếp theo chúng ta làm bài toán đọc phím bấm. Ta có tất cả 4 phím bấm là MODE, SET, UP, DOWN tương ứng nằm ở các chân RB1, RB2, RB3 và RB4. Bài toán lần này như sau: Bấm phím RB1 thì LED 1 sáng...Bấm phím RB3 thì LED3 sáng, bấm phím RB4 thì tắt hết các đèn. Chương trình sẽ như sau:

void MAIN() {
PORTB = 0; // Xoá dữ liệu cổng B
TRISB = 0xFF; // Định nghĩa cổng B là input

PORTE = 0;
TRISE = 0;
ADCON1 = 0xE;

Loop:
if (PORTB.F1 == 0) { // Kiểm tra nút ấn RB1 có bấm không? Nếu bấm thì
PORTE = 0x00; // Tắt hết đèn cổng E
PORTE.F0 = 1; // Bật đèn LED1
}
if (PORTB.F2 == 0) { // Kiểm tra nút ấn RB2 có bấm không? Nếu bấm thì
PORTE = 0x00; // Tắt hết đèn cổng E
PORTE.F1 = 1; // Bật đèn LED2
}
if (PORTB.F3 == 0) { // Kiểm tra nút ấn RB3 có bấm không? Nếu bấm thì
PORTE = 0x00; // Tắt hết đèn cổng E
PORTE.F2 = 1; // Bật đèn LED3
}
if (PORTB.F3 == 0) PORTE = 0x00; // Kiểm tra nút ấn RB3 có bấm không? Nếu bấm thì Tắt hết đèn cổng E
goto Loop; // Lặp lại vòng lặp kiểm tra nút bấm

}

chip_nho 01-09-2007 06:10 PM

mình cũng đang làm cái đồng hồ này hiển thị trên LED7seg .nhưng đang gặp vấn đề về cách thiết lạp giờ ,chương trinh thiết lập giờ mình cho vào ngắt ngoài . bạn có thể hướng dẫn cho minh ko. Ah cho minh hỏi thêm là chương trình đọc thời gian thi nên đưa vào ngắt timer hay dung delay.giúp mình nhé. thank

Auto_engine 05-09-2007 11:51 PM

ủa lâu lắm ko thấy bác chủ Topic viết tiếp bài nhỉ, ko bít tình hình có giống mấy topic trc, post 1 thơì gian rùi đem con bỏ chợ ko nữa. Hic...

Tuấn Anh CVN 07-09-2007 06:21 PM

Làm kiểu này thì cũng dài hơi mới tới đích để làm xong đồng hồ lịch vạn niên đấy. Cho mình hỏi con RTC DS1307 có chức năng giống với con RTC S35180A không? Mình đã copy được một đoạn code để dùng con S35180 làm đồng hồ led matrix có chữ chạy vào các thời điểm đặt trước. Nhưng chỉ biết dùng thời gian đọc ra từ con IC này mà chưa hiểu bên trong code như thế nào. Con S35180 cũng có 8 pins dạng SPI như con DS1307.

picpicpic 08-09-2007 11:00 AM

Đề tài bác tinhthanthep khởi xướng hay đây. Em cũng muốn làm 1 phát. Hình như bác tinhthanthep ở mãi ngoài Bắc, em ở trong Nam.

Xin lỗi vì hỏi ở đây. Bác nào rành ở TP.HCM, cho em hỏi chút:

- LCD 16x2 mua ở đâu cho đúng giá.
- LM335 và DS1307 giá cả thế nào, tìm thấy ở cữa hàng nào?

Ths các bác!

linhnc308 08-09-2007 03:46 PM

Trích:

Nguyên văn bởi picpicpic (Post 11223)
Đề tài bác tinhthanthep khởi xướng hay đây. Em cũng muốn làm 1 phát. Hình như bác tinhthanthep ở mãi ngoài Bắc, em ở trong Nam.

Xin lỗi vì hỏi ở đây. Bác nào rành ở TP.HCM, cho em hỏi chút:

- LCD 16x2 mua ở đâu cho đúng giá.
- LM335 và DS1307 giá cả thế nào, tìm thấy ở cữa hàng nào?

Ths các bác!

Cậu ở trong HCM thì tìm mấy thứ đó phải dễ dàng chứ, ra chợ Nhật tảo hay tìm trên diễn đàn có rất nhiều cá nhân cung cấp link kiên mà ở trong HCM. Tôi cũng có đủ những link kiện cậu cần nhưng khuyên câu chân thành là tìm mua trong Nam sẽ rẻ hơn vì không mất phí chuyển phát. tôi ở HN
LCD16x2 có thể mua loại 55k ~ 60K
LM335 ngoài HN bán 12K và DS1307 là 15K

Linh kiện: TI, Maxim, Cypress, MIcrochip

nhh 10-09-2007 10:12 AM

Trích:

Nguyên văn bởi tinhthanthep (Post 10928)
Có 4 nút bấm Mode, Set, Up, Down dùng để cài đặt và xem thông tin của lịch vạn niên. Hiển thị bằng màn hình LCD 16x2 cắm qua hàng Jump LCDDISPLAY. Có nút gạt để chọn backlight của LCD. 3 LED đơn mắc ở cổng E dùng để chỉ thị các chế độ.

Liệu có thể bổ sung thêm Âm lịch, Alarm? Hoàn toàn được = phần mềm. Khổ nỗi cái LCD 16*2 hiển thị ít kí tự quá.

tinhthanthep 11-09-2007 03:36 PM

Trích:

Nguyên văn bởi chip_nho (Post 11107)
mình cũng đang làm cái đồng hồ này hiển thị trên LED7seg .nhưng đang gặp vấn đề về cách thiết lạp giờ ,chương trinh thiết lập giờ mình cho vào ngắt ngoài . bạn có thể hướng dẫn cho minh ko. Ah cho minh hỏi thêm là chương trình đọc thời gian thi nên đưa vào ngắt timer hay dung delay.giúp mình nhé. thank

Trên con IC thời gian thực Ds1307 có chân SQW/INTB phát ra xung có tần số 1Hz (tức là 1s nó on 1 lần) , mắc chân này vào chân ngắt ngoài RB0 của PIC để cứ 1s thì nó kích cho ngắt ngoài hoạt động. Theo suy nghĩ thông thường các bạn hay để chương trình hiển thị trong ngắt nhưng như thế MikroC nó sẽ báo lỗi "ko được dùng chương trình con trong ngắt" nên bạn để chương trình hiển thị ở trong chương trình chính.

tinhthanthep 11-09-2007 03:45 PM

Có một vấn để về cái nút bấm đó là hiện tượng rung phím. Cái này ai hiểu rồi ko nói làm gì , còn bạn nào chưa hiểu thì phải biết. Khi bạn ấn một nút bấm thì các lá đồng tiếp xúc trong phím bấm nó không dính vào nhau ngay lập tức mà nó bật đi bật lại vài lần mới tiếp xúc hẳn (do tính đàn hồi của vật liệu đồng lò xo). Khoảng thời gian lập bập này tuy ngắn nhưng so với tốc độ xử lý của PIC thì còn phải chạy dài. Với chương trình trứoc thì hiện tượng rung phím này không ảnh hưởng gì, nhưng với bài toán như: Bấm phím 1 Led 1 sáng, bấm phát nữa nó tắt thì sẽ có vấn đề. Nhiều khi bạn bấm 1 cái nó vẫn tắt là bởi vì phím bấm nó rung nên thực ra là pic nó tưởng bạn bấm nhiều lần nên lúc sáng lúc tắt kết quả là tắt. Để xử lý vấn đề này thì ta cho chương trình khi phát hiện có bấm nút thì trễ đi một khoảng thoài gian dài hơn hiện tượng rung phím là ok. Khi bấm nút RB1 PIC tạo trễ 1 khoảng thời gian 50ms sau đó kiểm tra xem RB1 còn được bấm không? nếu còn thì cho sáng LED.

tinhthanthep 11-09-2007 03:59 PM

Vậy ta làm nốt bài toán sau là xong hẳn về cái nút bấm: Bài toán là ta bấm phím RB1 thì LEd1 sáng, bấm phát nữa thì nó tắt....Chương trìng như sau:

Code:

void MAIN() {
PORTB = 0; // Xoá dữ liệu cổng B
TRISB = 0xFF; // Định nghĩa cổng B là input

PORTE = 0;
TRISE = 0;
ADCON1 = 0xE;

Loop:
if (PORTB.F1 == 0) {                  // Kiểm tra nút ấn RB1 có bấm không? Nếu bấm thì
if (PORTE.F0 == 0)  PORTE.F0 = 1 // kiểm tra xem đèn đang tắt không? nếu đúng thì bật lên
else PORTE.F0 = 0; // nếu sai thì tắt nó đi
Delay_ms(50);  // Tạo trễ 50ms để khử hết hiện tượng rung phím
Loop1:
if (PORTB.F1 == 0) goto Loop1;  // chạy lòng vòng đợi đến khi tay người nhá hẳn nút bấm ra
}
goto Loop; // Lặp lại vòng lặp kiểm tra nút bấm

}


tinhthanthep 11-09-2007 04:15 PM

Tiếp theo ta làm sang cái LCD nhé. Bạn nào mới làm quen với LCD mà viết bằng assembly thì chắc mất vài ngày quá. Nếu viết bằng MikroC bạn nào kém lắm cũng chỉ 30 phút là xong. Nói thế để các bạn thấy rằng viết ứng dụng mà dùng MikroC thì thôi rồi, viết nhanh và ứng dụng nhanh đi vào cuộc sống, chứ cứ tỉa tót bằng assem thì khi sản phẩm ra thị trường thì đối thủ cạnh tranh đã ra mấy phiên bản khác nhau mất roài.
Giờ ta viết chương trình để hiển thị dòng chữ Hello Picvietnam nhé. Chương trình như sau:

Code:

void INIT_MAIN() {
// Khoi tao cong B
  PORTB  = 0;
  TRISB  = 0xFF;
// Khoi tao cong D
  PORTD  = 0;          // Xóa dữ liệu đang tồn tại sẵn trên cổng D
  TRISD  = 0;            // Định nghĩa cổng D là digital Output
// Khoi tao cong E
  PORTE  = 0;
  TRISE  = 0;
  ADCON1  = 0xE;
// Khoi tao LCD
  Lcd_Config(&PORTD,4,7,6,3,2,1,0);    // các bạn xem sơ đồ mạch để hiểu được cách khai các tham số của hàm này
  Lcd_Cmd(Lcd_CLEAR);                // xóa màn hình
  Lcd_Cmd(Lcd_CURSOR_OFF);        // tắt con trỏ nhấp nháy của LCD

void LCD_DISPLAY() {
  LCD_Out(1,1,"Hello");                // hiện chứ Hello bắt đầu ở dòng 1 cột 1
  LCD_Out(2,1,"Picvietnam");        // hiện chữ Picvietnam bắt đầu ở dòng 2 cột 1
}

void MAIN() {
  INIT_MAIN();
  LCD_DISPLAY();
}

Bạn nên sắp xếp các chương trình con như trên. Trong chương trình chính ta chỉ việc gọi tên các chương trình con thôi.

tinhthanthep 18-09-2007 09:43 AM

Hôm nay ta tiếp tục vào mục chính của bài toán đó là làm việc với con IC thời gian thực ds1307. Trước khi tiếp tục ta phải tìm hiểu qua về con IC này. ds1307 dùng một thạch anh 32.768kHz để tạo dao động tính thời gian, 1 pin V để nuôii khi mất nguồn nuôi ngoài. 1307 có tất cả 64 thanh ghi có địa chỉ từ 00h đến 3FH. 7 thanh ghi đầu tiên chứa dữ liệu về giây, phút, giờ, thứ, ngaỳ, tháng, năm dứoi dạng mã hóa BCD. thanh ghi thứ 8 là thanh ghi điều khiển. 56 thanh ghi còn lại là bộ nhớ RAM. ds1307 giao tiếp với thế giới bên ngoài bằng kiểu giao tiếp nối tiếp I2C. I2C dùng 2 đường truyền SCL và SDA. Ngoài ra ds1307 có chân SQW/OUT phát ra các xung có tần số 1Hz, 4.096kHz, 8.192kHz, 32.768 kHz. Ta sẽ sử dụng tần số 1Hz để cứ sau 1 s thì vi điều khiển phải cập nhật thông tin lại một lần và hiển thị lên màn hình. Vì vậy ta nối chân này của ds1307 vào chân ngắt ngoài INT của PIC16F877A. Việc hiểu thế nào là I2C các bạn sang luồng giao tiếp I2C đọc, nếu không hiểu cũng chẳng sao, với trình dịch MikroC này thì các bạn cứ việc viết theo mẫu sẵn có là ok. Tất nhiên chúng ta thường có tham vọng phải hiểu cái gì nó phải tận gốc rễ, nhưng cũng nên biêt rằng sức người có hạn không thể cho cả thế giới vào cái đầu nhỏ bé của mình được nên những gì mà thằng khác nó đã chuẩn hóa, môddun hóa rồi thì cứ việc dùng đừng lăn tăn xem cơ chế hoạt động của nó thế nào làm gì cho mất công. Cái đó để sau đi, đôi khi bạn làm xong rồi quay lại đọc những cái trước kia chưa hiểu lại thấy hiểu nhanh hơn. Thế nên các bạn cứ theo dõi chương trình nếu có chỗ nào ko hiểu phải phát biểu nhé.

tinhthanthep 18-09-2007 02:21 PM

Ban đầu, ds1307 chưa có giá trị nào cả trong các thanh ghi. Vì vậy, việc đầu tiên là phải nạp một giá trị bất kỳ cho các thanh ghi. Chương trình sau sẽ thực hiện công việc này. Sau này , bạn có thể dùng 4 nút bấm để hiệu chỉnh lại thời gian cho đúng với thực tế.

Code:

void INIT_MAIN() {
// Khoi tao truyen thong I2C
  I2C_Init(100000);      // Kích hoạt môddun truyền thông i2c với tốc độ baud là 100kHz
// Khoi tao DS1307
  I2C_Start();    // điều kiện start
  I2C_Wr(0xD0); // truyền địa chỉ của ds1307 và chọn ghi dữ liệu lên ds1307
  I2C_Wr(0x00); // Truyền địa chỉ ô nhớ đầu tiên của ds1307
  I2C_Wr(0x13); // Khoi tao gia tri ban dau cho  thanh ghi giây
  I2C_Wr(0x03); // Khoi tao gia tri ban dau cho  thanh ghi phút
  I2C_Wr(0x02); // Khoi tao gia tri ban dau cho  thanh ghi giờ
  I2C_Wr(0x03); // Khoi tao gia tri ban dau cho  thanh ghi thứ
  I2C_Wr(0x05); // Khoi tao gia tri ban dau cho  thanh ghi ngày
  I2C_Wr(0x03); // Khoi tao gia tri ban dau cho  thanh ghi tháng
  I2C_Wr(0x03); // Khoi tao gia tri ban dau cho  thanh ghi năm
  I2C_Wr(0x90); // đặt cấu hình cho thanh ghi điều khiển, sử dụng xung 1Hz.
  I2C_Stop();    // Điều kiện stop
}

Chương trình chính
Code:

void MAIN() {
  INIT_MAIN();
}


tinhthanthep 18-09-2007 02:33 PM

Trích:

Nguyên văn bởi nhh (Post 11262)
Liệu có thể bổ sung thêm Âm lịch, Alarm? Hoàn toàn được = phần mềm. Khổ nỗi cái LCD 16*2 hiển thị ít kí tự quá.

Muốn hiển thị âm lịch thì cho sang trang màn hình tiếp theo. Sử dụng nút bấm mode để xem tiếp các thông tin khác của lịch vạn niên.

tinhthanthep 18-09-2007 03:43 PM

vậy là từ bây giờ con ds1307 đã bắt đầu hoạt động và tự cập nhật dữ liệu về thời gian. chỉ khi nào hết pin nó mời ngừng hoạt động. Tiếp theo ta viết một chương trình đọc dữ liệu từ ds1307 rồi xuất ra màn hình LCD. Cứ 1s thì dữ liệu được cập nhật một lần và gửi ra màn hình LCD. Chương trình sẽ như sau:

Code:

/* KHAI BAO BIEN */
unsigned short second, minute, hour, day, date, month, year, flag_time;
char *day_txt;

/* KHOI TAO */
void INIT_MAIN() {
// Khoi tao cong A
  PORTA  = 0;
  TRISA  = 0xFF;
// Khoi tao cong B
  PORTB  = 0;
  TRISB  = 0xFF;
// Khoi tao cong D
  PORTD  = 0;
  TRISD  = 0;
// Khoi tao cong E
  PORTE  = 0;
  TRISE  = 0;
  ADCON1  = 0xE;
// Khoi tao LCD
  Lcd_Config(&PORTD,4,7,6,3,2,1,0);
  Lcd_Cmd(Lcd_CLEAR);
  Lcd_Cmd(Lcd_CURSOR_OFF);
// Khoi tao truyen thong I2C
  I2C_Init(100000);
// Khoi tao ngat ngoai
  INTCON = 0x90; // Mo ngat toan cuc, mo ngat ngoai, xoa co ngat ngoai,  OPTION_REG = 0x87; // Chon suon len cho ngat ngoai
}

/* DOC DU LIEU RTC TU DS1307 */
void READ_RTC() {
  I2C_Start();
  I2C_Wr(0xD0);
  I2C_Wr(0x00);
  I2C_Repeated_Start(); 
  I2C_Wr(0xD1);
  second = I2C_Rd(1u);
  minute = I2C_Rd(1u);
  hour  = I2C_Rd(1u);
  day    = I2C_Rd(1u);
  date  = I2C_Rd(1u);
  month  = I2C_Rd(1u);
  year  = I2C_Rd(1u);
  I2C_Stop();
}

/* XU LY DU LIEU RTC */
void TRANSFORM_RTC() {
  switch (day) {
    case 1: day_txt = "ERO"; break;
    case 2: day_txt = "T.2"; break;
    case 3: day_txt = "T.3"; break;
    case 4: day_txt = "T.4"; break;
    case 5: day_txt = "T.5"; break;
    case 6: day_txt = "T.6"; break;
    case 7: day_txt = "T.7"; break;
    case 8: day_txt = "C.N"; break;
  }
}
/* HIEN THI LCD */
void BCD(unsigned short x, unsigned short y,unsigned short var) {
unsigned short var1, var2;
  var1 = (var >> 4) + 0x30;
  LCD_Chr(x,y,var1);
  var2 = (var & 0x0F) + 0x30;
  LCD_Chr_Cp(var2);
}
void LCD_DISPLAY() {
  LCD_Out(1,1,day_txt);
  BCD(1,5,date);
  LCD_Chr_Cp('/');
  BCD(1,8,month);
  LCD_Out_Cp("/20");
  BCD(1,13,year);
  BCD(2,1,hour);
  LCD_Chr_Cp(':');
  BCD(2,4,minute);
  LCD_Chr_Cp(':');
  BCD(2,7,second);
  LCD_Out(2,10,"T=");
  BCD(2,12,temp);
  LCD_Chr_Cp(223);
  LCD_Chr_Cp('C');
}
void DISPLAY_TIME() {
  READ_RTC();
  TRANSFORM_RTC();
  LCD_DISPLAY();
  PORTE.F0 = ~PORTE.F0;
}

/* XU LY NGAT */
void interrupt() {
    flag_time = 1;
    INTCON.INTF = 0; // Xoa co ngat ngoai
}

/* CHUONG TRINH CHINH */
void MAIN() {
  INIT_MAIN();
  while(1) {
    INTCON.INTE = 1;
    if (flag_time == 1) {
      DISPLAY_TIME();
      flag_time = 0;
    }
  }
}


HL2 19-09-2007 07:27 PM

Tinhthanthep cho mình xin cái software và Crack với nha. Cũng tính mượn bạn film để làm board mạch nhưng chắc là khó rồi, vì mình ở HCM. Nếu cỏ thể cho mình xin file để tập làm.
Địa chỉ mail của mình: hlhluc@yahoo.com
Cám ơn bạn nhiều, những bài viết của các bạn rất hay.

phamngoctan 20-09-2007 12:11 AM

Em đã đọc code của bác.Nói chung là hiểu.Nhưng có 1 vấn đề em k0 hiểu là tại sao để chống rung các bác lai cứ thích dùng delay thế nhỉ, như thế chỉ tổ tốn tài nguyên,em có 1 ý là dùng ngắt timer k0 tốt hơn hay sao ?

tinhthanthep 20-09-2007 02:17 PM

Miễn là khử được rung phím là đạt yêu cầu. Còn dùng cách nào thì tùy thuộc vào thuật toán của mỗi người.

david 25-09-2007 10:54 AM

Trích:

Nguyên văn bởi tinhthanthep (Post 11448)
Muốn hiển thị âm lịch thì cho sang trang màn hình tiếp theo. Sử dụng nút bấm mode để xem tiếp các thông tin khác của lịch vạn niên.

Bác có thể nói rõ hơn được không,theo em hiểu thì mình phải lưu lịch âm vao eeprom đúng không,vì không có công thức toàn học nào có thể chuyển đổi từ ngày dương sang ngày âm được,thể để lưu khoảng 10 năm thì bác làm thế nào? làm sao xác định được ngày âm tương ứng với ngày dương?
Mong hồi âm của bác!

nhh 25-09-2007 01:43 PM

Trích:

Nguyên văn bởi david (Post 11582)
Bác có thể nói rõ hơn được không,theo em hiểu thì mình phải lưu lịch âm vao eeprom đúng không,vì không có công thức toàn học nào có thể chuyển đổi từ ngày dương sang ngày âm được,thể để lưu khoảng 10 năm thì bác làm thế nào? làm sao xác định được ngày âm tương ứng với ngày dương?
Mong hồi âm của bác!

Tất nhiên là phải có công thức chuyển đổi giữa ngày âm lịch Việt Nam và ngày dương lịch chứ. Bác xem ở đây, khổ nỗi code bằng java: http://www.informatik.uni-leipzig.de/~duc/amlich/

Trong khi chưa thể coding mấy cái công thức chuyển đổi loằng ngoằng này, theo cách củ chuối, ta cứ lật tờ lịch ra, đánh dấu các ngày mùng 1 âm lịch hằng tháng xem nó trùng với ngày dương lịch nào, sau đó lưu vào eeprom. 10 năm tầm cỡ 120 giá trị, ko nhiều lắm.

Bác nào hứng thú thì chuyển mã sang C chuyên nghiệp hơn.

david 26-09-2007 12:00 AM

Trích:

Nguyên văn bởi nhh (Post 11588)
Tất nhiên là phải có công thức chuyển đổi giữa ngày âm lịch Việt Nam và ngày dương lịch chứ. Bác xem ở đây, khổ nỗi code bằng java: http://www.informatik.uni-leipzig.de/~duc/amlich/

Trong khi chưa thể coding mấy cái công thức chuyển đổi loằng ngoằng này, theo cách củ chuối, ta cứ lật tờ lịch ra, đánh dấu các ngày mùng 1 âm lịch hằng tháng xem nó trùng với ngày dương lịch nào, sau đó lưu vào eeprom. 10 năm tầm cỡ 120 giá trị, ko nhiều lắm.

Bác nào hứng thú thì chuyển mã sang C chuyên nghiệp hơn.

Cách này nếu làm được thì cũng hay chứ bác. Em có ý này bác xem có được không nhé:
+)Dùng 1 biến đếm tháng dương Count,ta biết cứ qua một tháng dương thì sẽ qua một tháng âm,nên mỗi khi biến đếm tăng lên 1 thì cũng đã sang tháng âm mới, và ngày âm tương ứng với ngày mồng 1 hàng tháng ta sẽ lưu vào eeprpom
+)Khi có một ngày dương lịch ví dụ như 28/12/2007 cần xác định lịch âm ta sẽ dựa vào biết đếm(giả sử biến đếm Count= 3,lấy mốc từ tháng 1/9/2007 ) để gọi ra ngày âm lịch tương ứng với ngày 1/12/2007 là ngày 22/10 ) ta sẽ lấy : (28-1) + 22 -30 = 19 là ngày âm lich tương ứng,ở đây 30 là số ngày của tháng 10 âm lịch,hay là số ngày ứng với biến đếm = 3,điều này có nghĩa là với tập giá trị của Count từ 1 đến 120 (120 tháng ứng với 10 năm) ta cần xác định với giá trị nào Count thì tương ứng với 30,với giá trị nào của Count thì tương ứng với 29 và với giá trị nào của Count thì tương ứng với 28.Ta có thể sử dụng 1 eeprom 256 byte với 120 byte đầu ghi ngày âm,120 byte sau số ngày trong tháng ứng với giá trị biến Count
+)Bổ sung thêm là nếu (ngày dương - 1) +ngày âm (lấy ra từ eeprom) < 28 thì ngày đó là ngày âm cần tìm

Bác hiểu ý em chứ !

david 27-09-2007 10:40 PM

đã bác nào chyển từ dương lịch sang âm lịch chưa,nói cho em cách trên có ổn không với !

tinhthanthep 13-10-2007 10:15 AM

Chương trình đầy đủ đây

Code:

/* KHAI BAO BIEN **************************************************************/
unsigned short second, minute, hour, day, date, month, year;
unsigned short minute_al, hour_al, type_al, count_al;
unsigned short flag_time, delay10s_1 = 0, delay10s_2 = 0;
unsigned short mode;
char *day_txt;
/* KHOI TAO *******************************************************************/
void INIT_MAIN() {
/* Khoi tao cong A -----------------------------------------------------------*/
  TRISA = 0xFF;  // Dinh nghia cong A la Digital Input
  PORTA = 0x00;
/* Khoi tao cong B -----------------------------------------------------------*/
  TRISB = 0xFF;  // Dinh nghia cong B la Digital Input
  PORTB = 0x00;
/* Khoi tao cong C -----------------------------------------------------------*/
  TRISC  = 0x00;
  PORTC  = 0x00;
/* Khoi tao cong D -----------------------------------------------------------*/
  TRISD = 0x00;  // Dinh nghia cong D la Digital Output
  PORTD = 0x00;
/* Khoi tao cong E -----------------------------------------------------------*/
  ADCON1 = 0x0E; // Dinh nghia cong E la Digital + su dung A/D channel AN0
  TRISE  = 0x00; // Dinh nghia cong E la Output
  PORTE  = 0x00; // Xoa du lieu cu tren cong E
/* Khoi tao LCD --------------------------------------------------------------*/
  Lcd_Config(&PORTD,4,7,6,3,2,1,0);
  Lcd_Init(&PORTD);
  Lcd_Cmd(Lcd_CLEAR);
  Lcd_Cmd(Lcd_CURSOR_OFF);
/* Khoi tao truyen thong I2C -------------------------------------------------*/
  I2C_Init(100000);
/* Khoi tao DS1307 -----------------------------------------------------------*/
/* I2C_Start();
  I2C_Wr(0xD0);
  I2C_Wr(0x00); // Khoi tao cac gia tri ban dau cho cac thanh ghi thoi gian
  I2C_Wr(0x13); // chi lam 1 lan.
  I2C_Wr(0x03);
  I2C_Wr(0x02);
  I2C_Wr(0x03);
  I2C_Wr(0x05);
  I2C_Wr(0x03);
  I2C_Wr(0x03);
  I2C_Wr(0x90);
  I2C_Stop();  */
/* Khoi tao ngat ngoai va Timer0 ---------------------------------------------*/
  INTCON = 0x90; // Mo ngat toan cuc, mo ngat ngoai, xoa co ngat ngoai, xoa co ngat Timer0
  OPTION_REG = 0x87; // Chon suon len cho ngat ngoai va Timer0, bo chia ti le 1:256 cho Timer0
  TMR0 = 0x00;
/* Khoi tao cac bien luu trong EEPROM*/
  hour_al = Eeprom_Read(0x00);
  minute_al = Eeprom_Read(0x01);
  type_al = Eeprom_Read(0x02);
}
/* CHUONG TRINH CON ***********************************************************/
/* Doc du lieu RTC tu DS1307 -------------------------------------------------*/
void READ_RTC() {
  I2C_Start();
  I2C_Wr(0xD0);
  I2C_Wr(0x00);
  I2C_Repeated_Start();
  I2C_Wr(0xD1);
  second = I2C_Rd(1u);
  minute = I2C_Rd(1u);
  hour  = I2C_Rd(1u);
  day    = I2C_Rd(1u);
  date  = I2C_Rd(1u);
  month  = I2C_Rd(1u);
  year  = I2C_Rd(1u);
  I2C_Stop();
}
/* Xu ly du lieu Date RTC ----------------------------------------------------*/
void TRANSFORM_RTC() {
  switch (day) {
    case 1: day_txt = "ERO"; break;
    case 2: day_txt = "T.2"; break;
    case 3: day_txt = "T.3"; break;
    case 4: day_txt = "T.4"; break;
    case 5: day_txt = "T.5"; break;
    case 6: day_txt = "T.6"; break;
    case 7: day_txt = "T.7"; break;
    case 8: day_txt = "C.N"; break;
  }
}
/* Xu ly du lieu RTC ---------------------------------------------------------*/
void BCD(unsigned short x, unsigned short y,unsigned short var) {
unsigned short var1, var2;
  var1 = (var >> 4) + 0x30;
  LCD_Chr(x,y,var1);
  var2 = (var & 0x0F) + 0x30;
  LCD_Chr_Cp(var2);
}
/* Hien thi ra LCD -----------------------------------------------------------*/
void LCD_DISPLAY() {
  LCD_Out(1,1,day_txt);
  BCD(1,7,date);
  LCD_Chr_Cp('/');
  BCD(1,10,month);
  LCD_Out_Cp("/20");
  BCD(1,15,year);
  if (type_al == 1) Lcd_Out(2, 1,"Chuong");
  else Lcd_Out(2, 1,"      ");
  BCD(2,9,hour);
  LCD_Chr_Cp(':');
  BCD(2,12,minute);
  LCD_Chr_Cp(':');
  BCD(2,15,second);
}
/* Cap nhat thoi gian --------------------------------------------------------*/
void UPDATE_TIME() {
  READ_RTC();
  TRANSFORM_RTC();
  LCD_DISPLAY();
  PORTE.F0 = ~PORTE.F0;
}
/* Xu ly Du lieu Nhiet do tu LM335 -------------------------------------------*/
void TEMPERATURE() {
  unsigned short temp1, temp2;
  char degree[5];
  temp1 = Adc_Read(0);
  temp2 = (temp1 - 558)/2;
  ByteToStr(temp2, degree);
  LCD_Out_CP(degree);
  LCD_Chr_Cp(223);
  LCD_Chr_Cp('C');
}
/* XOA TIMER0 ----------------------------------------------------------------*/
void CLEAR_TIMER0() {
  delay10s_1 = 0;
  delay10s_2 = 0;
  TMR0 = 0;
}
/* Tinh so ngay Julius -------------------------------------------------------*/
unsigned long jdFromDate(char dd, char mm, char yy) {
  char a, m;
  unsigned y;
  unsigned long jd;
  a = (14 - mm)/12;
  y = (2000 + yy) + 4800 - a;
  m = mm + 12*a - 3;
  jd = dd + (153*m + 2)/5 + 365*y + y/4 - y/100 + y/400 - 32045;
  if (jd < 2299161) jd = dd + (153*m + 2)/5 + 365*y + y/4 - 32083;
  return jd;
}
/* Tinh ngay soc -------------------------------------------------------------*/
char getNewMoonDay(unsigned long k) {
  double T, T2, T3, dr, Jd1, M, Mpr, F, C1, deltat, JdNew;
  T = k/1236.85;
  T2 = T * T;
  T3 = T2 * T;
  dr = 3.1415926/180;
  Jd1 = 2415020.75933 + 29.53058868*k + 0.0001178*T2 - 0.000000155*T3;
  Jd1 = Jd1 + 0.00033*sin((166.56 + 132.87*T - 0.009173*T2)*dr);
  M = 359.2242 + 29.10535608*k - 0.0000333*T2 - 0.00000347*T3;
  Mpr = 306.0253 + 385.81691806*k + 0.0107306*T2 + 0.00001236*T3;
  F = 21.2964 + 390.67050646*k - 0.0016528*T2 - 0.00000239*T3;
  C1=(0.1734 - 0.000393*T)*sin(M*dr) + 0.0021*sin(2*dr*M);
  C1 = C1 - 0.4068*sin(Mpr*dr) + 0.0161*sin(dr*2*Mpr);
  C1 = C1 - 0.0004*sin(dr*3*Mpr);
  C1 = C1 + 0.0104*sin(dr*2*F) - 0.0051*sin(dr*(M+Mpr));
  C1 = C1 - 0.0074*sin(dr*(M-Mpr)) + 0.0004*sin(dr*(2*F+M));
  C1 = C1 - 0.0004*sin(dr*(2*F-M)) - 0.0006*sin(dr*(2*F+Mpr));
  C1 = C1 + 0.0010*sin(dr*(2*F-Mpr)) + 0.0005*sin(dr*(2*Mpr+M));
  if (T < -11) deltat = 0.001 + 0.000839*T + 0.0002261*T2 - 0.00000845*T3 - 0.000000081*T*T3;
  else deltat= -0.000278 + 0.000265*T + 0.000262*T2;
  JdNew = Jd1 + C1 - deltat;
  return (JdNew + 0.5 + 7/24);
}
/* Tinh toa do mat troi ------------------------------------------------------*/
char getSunLongitude(unsigned long jdn) {
  double T, T2, dr, M, L0, DL, L;
  T = (jdn - 2451545.5 - 7/24) / 36525;
  T2 = T*T;
  dr = 3.1415926/180;
  M = 357.52910 + 35999.05030*T - 0.0001559*T2 - 0.00000048*T*T2;
  L0 = 280.46645 + 36000.76983*T + 0.0003032*T2;
  DL = (1.914600 - 0.004817*T - 0.000014*T2)*sin(dr*M);
  DL = DL + (0.019993 - 0.000101*T)*sin(dr*2*M) + 0.000290*sin(dr*3*M);
  L = L0 + DL;
  L = L*dr;
  L = L - 3.1415926*2*(L/(3.1415926*2));
  return (L / 3.1415926 * 6);
}
/* Tim ngay bat dau thang 11 am lich -----------------------------------------*/
char getLunarMonth11(char yy) {
  unsigned long k, off, nm, sunLong;
  off = jdFromDate(31, 12, (2000 + yy)) - 2415021;
  k = (off / 29.530588853);
  nm = getNewMoonDay(k);
  sunLong = getSunLongitude(nm);
  if (sunLong >= 9) nm = getNewMoonDay(k-1);
  return nm;
}
/* Xac dinh thang nhuan ------------------------------------------------------*/
char getLeapMonthOffset(unsigned long a11) {
  unsigned long k, last, arc, i;
  char tmp;
  k = (a11 - 2415021.076998695) / 29.530588853 + 0.5;
  last = 0;
  i = 1;
  tmp = getNewMoonDay(k+i);
  arc = getSunLongitude(tmp);
  do {
          last = arc;
          i++;
          arc = getSunLongitude(tmp);
  }
  while (arc != last && i < 14);
  return i-1;
}
/* Tinh am lich --------------------------------------------------------------*/
void AM_LICH() {
  unsigned long k, dayNumber, monthStart, a11, b11, lunarDay, lunarMonth, lunarYear, lunarLeap, diff, leapMonthDiff;
  char dd, mm, yy;
  unsigned short ld, lm, ly;
  dd = Bcd2Dec(date);
  mm = Bcd2Dec(month);
  yy = Bcd2Dec(year);
  dayNumber = jdFromDate(dd, mm, (2000+yy));
  k = (dayNumber - 2415021.076998695) / 29.530588853;
  monthStart = getNewMoonDay(k+1);
  if (monthStart > dayNumber) monthStart = getNewMoonDay(k);
  a11 = getLunarMonth11(2000+yy);
  b11 = a11;
  if (a11 >= monthStart) {
          lunarYear = 2000+yy;
          a11 = getLunarMonth11(2000+yy-1);
  }
  else {
          lunarYear = 2000+yy+1;
          b11 = getLunarMonth11(2000+yy+1);
  }
  lunarDay = dayNumber-monthStart+1;
  diff = (monthStart - a11)/29;
  lunarLeap = 0;
  lunarMonth = diff+11;
  if (b11 - a11 > 365) {
          leapMonthDiff = getLeapMonthOffset(a11);
          if (diff >= leapMonthDiff) {
                  lunarMonth = diff + 10;
                  if (diff == leapMonthDiff) lunarLeap = 1;
          }
  }
  if (lunarMonth > 12) lunarMonth = lunarMonth - 12;
  if (lunarMonth >= 11 && diff < 4) lunarYear -= 1;
  ld = Dec2Bcd (lunarDay);
  lm = Dec2Bcd (lunarMonth);
  BCD(1,10,ld);
  Lcd_Chr_Cp(':');
  BCD(1,13,lm);
}
/* MODE BUTTON ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/* Hien thi lich am ----------------------------------------------------------*/
void MODE_1() {
  Lcd_Cmd(Lcd_CLEAR);
  Lcd_Out(1, 1, "AM LICH: SORRY");
  Lcd_Out(2, 1, "Next Update");
//  AM_LICH();
  mode = 1;
  Mode_1l:
  if (PORTB.F1 == 0) goto Mode_1l;
}
/* Hien thi nhiet do moi truong ----------------------------------------------*/
void MODE_2() {
  Lcd_Cmd(Lcd_CLEAR);
  Lcd_Out(1, 1, "NHIET DO:");
  TEMPERATURE();
  mode = 2;
  Mode_2l:
  if (PORTB.F1 == 0) goto Mode_2l;
}
/* Hien thi cai dat chuong bao thuc ------------------------------------------*/
void MODE_3() {
  Lcd_Cmd(Lcd_CLEAR);
  Lcd_Out(1, 1, "CHUONG BAO THUC");
  if (type_al == 0) Lcd_Out(2, 1,"Khong su dung");
  else {
    BCD(2,6,hour_al);
    LCD_Chr_Cp(':');
    BCD(2,9,minute_al);
  }
  mode = 3;
  Mode_3l:
  if (PORTB.F1 == 0) goto Mode_3l;
}
/* Hien thi thong tin ve Version thiet ke ------------------------------------*/
void MODE_4() {
  Lcd_Cmd(Lcd_CLEAR);
  Lcd_Out(1, 3, "PIC VIET NAM");
  Lcd_Out(2, 1, "Version 1 - 2007");
  mode = 4;
  Mode_4l:
  if (PORTB.F1 == 0) goto Mode_4l;
}
/* Xu ly phim bam Mode -------------------------------------------------------*/
void MODE_BUTTON() {
  INTCON.INTE = 0;            // OFF ngat ngoai
  PORTE = 0x02;              // Bat LED 2
  MODE_1();                  // Vao man hinh MODE 1
  INTCON.T0IE = 1;            // Kich hoat Timer0 dem thoi gian tre man hinh 10s
  while (delay10s_2 < 5) {    // Quet phim MODE
    Delay_ms(200);            // Khu rung phim
    if (PORTB.F1 == 0) {
      mode++;
      CLEAR_TIMER0();
      switch (mode) {
        case 1 : MODE_1(); break;
        case 2 : MODE_2(); break;
        case 3 : MODE_3(); break;
        case 4 : MODE_4(); break;
        case 5 : goto OUT_MODE;
      }
    }
  }
  OUT_MODE:                      // Ra khoi vong quet
  PORTE = 0x00;                  // OFF LED 2
  Lcd_Cmd(Lcd_CLEAR);            // Xoa man hinh
  CLEAR_TIMER0();                // Xoa bo dem thoi gian tre man hinh
}
/* SET BUTTON ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/* Cap nhat du lieu cai dat --------------------------------------------------*/
void SET_DATA() {
  I2C_Start();
  I2C_Wr(0xD0);
  I2C_Wr(0x00);
  I2C_Wr(second);
  I2C_Wr(minute);
  I2C_Wr(hour);
  I2C_Wr(day);
  I2C_Wr(date);
  I2C_Wr(month);
  I2C_Wr(year);
  I2C_Stop();
  EEprom_Write(0x00, hour_al);
  EEprom_Write(0x01, minute_al);
  EEprom_Write(0x02, type_al);
}
/* Up data -------------------------------------------------------------------*/
unsigned short UP_BUTTON(unsigned short var) {
  Delay_ms(200);
  CLEAR_TIMER0();
  var = Bcd2Dec(var);
  var++;
  var = Dec2Bcd(var);
  return var;
}
/* Down data -----------------------------------------------------------------*/
unsigned short DOWN_BUTTON(unsigned short var) {
  Delay_ms(200);
  CLEAR_TIMER0();
  var = Bcd2Dec(var);
  if (var == 0) var = 101;
  else var--;
  var = Dec2Bcd(var);
  return var;
}
/* Nhap nhay underline cursor ------------------------------------------------*/
void BLINK_CURSOR() {
  Lcd_Cmd(LCD_MOVE_CURSOR_LEFT);
  Lcd_Cmd(LCD_UNDERLINE_ON);
}
/* Hieu chinh gio ------------------------------------------------------------*/
void SET_HOUR() {
  Delay_ms(200);
  hour_lb:
  if (PORTB.F2 == 0) {
    CLEAR_TIMER0();
    goto hour_lb;
  }
  while ((delay10s_2 < 5) && (PORTB.F2)) {
    Delay_ms(100);
    if (PORTB.F3 == 0) hour = UP_BUTTON(hour);
    if (Bcd2Dec(hour) == 24) hour = Dec2Bcd(0);
    if (PORTB.F4 == 0) hour = DOWN_BUTTON(hour);
    if (Bcd2Dec(hour) == 101 ) hour = Dec2Bcd(23);
    Lcd_Cmd(LCD_CURSOR_OFF);
    BCD(2,5,hour);
    BLINK_CURSOR();
  }
}
/* Hieu chinh phut -----------------------------------------------------------*/
void SET_MINUTE() {
  Delay_ms(100);
  minute_lb:
  if (PORTB.F2 == 0) {
    CLEAR_TIMER0();
    goto minute_lb;
  }
  while ((delay10s_2 < 5) && (PORTB.F2)) {
    Delay_ms(200);
    if (PORTB.F3 == 0) minute = UP_BUTTON(minute);
    if (Bcd2Dec(minute) == 60) minute = Dec2Bcd(0);
    if (PORTB.F4 == 0) minute = DOWN_BUTTON(minute);
    if (Bcd2Dec(minute) == 101 ) minute = Dec2Bcd(59);
    Lcd_Cmd(LCD_CURSOR_OFF);
    BCD(2,8,minute);
    BLINK_CURSOR();
  }
}
/* Hieu chinh giay -----------------------------------------------------------*/
void SET_SECOND() {
  Delay_ms(200);
  second_lb:
  if (PORTB.F2 == 0) {
    CLEAR_TIMER0();
    goto second_lb;
  }
  while ((delay10s_2 < 5) && (PORTB.F2)) {
    Delay_ms(100);
    if (PORTB.F3 == 0) second = UP_BUTTON(second);
    if (Bcd2Dec(second) == 60) second = Dec2Bcd(0);
    if (PORTB.F4 == 0) second = DOWN_BUTTON(second);
    if (Bcd2Dec(second) == 101 ) second = Dec2Bcd(59);
    Lcd_Cmd(LCD_CURSOR_OFF);
    BCD(2,11,second);
    BLINK_CURSOR();
  }
}
/* Cai dat thoi gian CLOCK ---------------------------------------------------*/
void SET_1() {
  Lcd_Cmd(Lcd_CLEAR);
  LCD_Out(1,1,"Cai dat dong ho:");
  BCD(2,5,hour);
  LCD_Chr_Cp(':');
  BCD(2,8,minute);
  LCD_Chr_Cp(':');
  BCD(2,11,second);
  Delay_ms(200);
  Set_1l:
  if (PORTB.F2 == 0) goto Set_1l;
  SET_HOUR();
  SET_MINUTE();
  SET_SECOND();
}
/* Cai dat Thu (DAY) ---------------------------------------------------------*/
void SET_DAY() {
  Delay_ms(200);
  day_lb:
  if (PORTB.F2 == 0) {
    CLEAR_TIMER0();
    goto day_lb;
  }
  while ((delay10s_2 < 5) && (PORTB.F2)) {
    Delay_ms(100);
    if (PORTB.F3 == 0) day = UP_BUTTON(day);
    if (Bcd2Dec(day) == 9) day = Dec2Bcd(2);
    if (PORTB.F4 == 0) day = DOWN_BUTTON(day);
    if (Bcd2Dec(day) == 1) day = Dec2Bcd(8);
    TRANSFORM_RTC();
    Lcd_Cmd(LCD_CURSOR_OFF);
    LCD_Out(2,1,day_txt);
    BLINK_CURSOR();
  }
}
/* Cai dat ngay (DATE) -------------------------------------------------------*/
void SET_DATE() {
  Delay_ms(200);
  date_lb:
  if (PORTB.F2 == 0) {
    CLEAR_TIMER0();
    goto date_lb;
  }
  while ((delay10s_2 < 5) && (PORTB.F2)) {
    Delay_ms(100);
    if (PORTB.F3 == 0) date = UP_BUTTON(date);
    if (Bcd2Dec(date) == 32) date = Dec2Bcd(1);
    if (PORTB.F4 == 0) date = DOWN_BUTTON(date);
    if (Bcd2Dec(date) == 0 ) date = Dec2Bcd(31);
    Lcd_Cmd(LCD_CURSOR_OFF);
    BCD(2,7,date);
    BLINK_CURSOR();
  }
}
/* Cai dat thang (MONTH) -----------------------------------------------------*/
void SET_MONTH() {
  Delay_ms(100);
  month_lb:
  if (PORTB.F2 == 0) {
      CLEAR_TIMER0();
    goto month_lb;
  }
  while ((delay10s_2 < 5) && (PORTB.F2)) {
    Delay_ms(200);
    if (PORTB.F3 == 0) month = UP_BUTTON(month);
    if (Bcd2Dec(month) == 13) month = Dec2Bcd(1);
    if (PORTB.F4 == 0) month = DOWN_BUTTON(month);
    if (Bcd2Dec(month) == 0 ) month = Dec2Bcd(12);
    Lcd_Cmd(LCD_CURSOR_OFF);
    BCD(2,10,month);
    BLINK_CURSOR();
  }
}
/* Cai dat nam (YEAR) --------------------------------------------------------*/
void SET_YEAR() {
  Delay_ms(200);
  year_lb:
  if (PORTB.F2 == 0) {
      CLEAR_TIMER0();
    goto year_lb;
  }
  while ((delay10s_2 < 5) && (PORTB.F2)) {
    Delay_ms(100);
    if (PORTB.F3 == 0) year = UP_BUTTON(year);
    if (Bcd2Dec(year) == 100) year = Dec2Bcd(0);
    if (PORTB.F4 == 0) year = DOWN_BUTTON(year);
    if (Bcd2Dec(year) == 101) year = Dec2Bcd(99);
    Lcd_Cmd(LCD_CURSOR_OFF);
    BCD(2,15,year);
    BLINK_CURSOR();
  }
}
/* Cai dat lich duong CALENDAR ---------------------------------------------- */
void SET_2() {
  Lcd_Cmd(Lcd_CLEAR);
  LCD_Out(1,1,"Cai dat Lich:");
  LCD_Out(2,1,day_txt);
  BCD(2,7,date);
  LCD_Chr_Cp('/');
  BCD(2,10,month);
  LCD_Out_Cp("/20");
  BCD(2,15,year);
  Delay_ms(200);
  Set_2l:
  if (PORTB.F2 == 0) goto Set_2l;
  SET_DAY();
  SET_DATE();
  SET_MONTH();
  SET_YEAR();
}
/* Cai dat gio bao thuc ------------------------------------------------------*/
void TIME_ALARM() {
  Lcd_Cmd(Lcd_CLEAR);
  Lcd_Out(1,1,"Gio rung Chuong:");
  BCD(2,6,hour_al);
  Lcd_Out(2,8,":");
  BCD(2,9,minute_al);
  Delay_ms(200);
  Set_4l:
  if (PORTB.F2 == 0) goto Set_4l;
  Delay_ms(200);
  hour_al_lb:
  if (PORTB.F2 == 0) {
    CLEAR_TIMER0();
    goto hour_al_lb;
  }
  Delay_ms(200);
  while ((delay10s_2 < 5) && (PORTB.F2)) {
    Delay_ms(100);
    if (PORTB.F3 == 0) hour_al = UP_BUTTON(hour_al);
    if (Bcd2Dec(hour_al) == 24) hour_al = Dec2Bcd(0);
    if (PORTB.F4 == 0) hour_al = DOWN_BUTTON(hour_al);
    if (Bcd2Dec(hour_al) == 101 ) hour_al = Dec2Bcd(23);
    Lcd_Cmd(LCD_CURSOR_OFF);
    BCD(2,6,hour_al);
    BLINK_CURSOR();
  }
  Delay_ms(200);
  minute_al_lb:
  if (PORTB.F2 == 0) {
    CLEAR_TIMER0();
    goto minute_al_lb;
  }
  while ((delay10s_2 < 5) && (PORTB.F2)) {
    Delay_ms(100);
    if (PORTB.F3 == 0) minute_al = UP_BUTTON(minute_al);
    if (Bcd2Dec(minute_al) == 60) minute_al = Dec2Bcd(0);
    if (PORTB.F4 == 0) minute_al = DOWN_BUTTON(minute_al);
    if (Bcd2Dec(minute_al) == 101 ) minute_al = Dec2Bcd(59);
    Lcd_Cmd(LCD_CURSOR_OFF);
    BCD(2,9,minute_al);
    BLINK_CURSOR();
  }
}
/* Cai dat bao thuc ----------------------------------------------------------*/
void SET_3() {
  Lcd_Cmd(Lcd_CLEAR);
  Lcd_Cmd(LCD_CURSOR_OFF);
  Lcd_Out(1,1,"Cai dat Chuong:");
  Delay_ms(200);
  Set_3l:
  if (PORTB.F2 == 0) goto Set_3l;
  Delay_ms(200);
  while ((delay10s_2 < 5) && (PORTB.F2)) {
    Delay_ms(200);
    if ((PORTB.F3 == 0) || (PORTB.F4 == 0)) {
      if (type_al == 0) type_al = 1;
      else type_al =0;
      CLEAR_TIMER0();
    }
    if (type_al == 0) Lcd_Out(2, 1,"Khong");
    if (type_al == 1) Lcd_Out(2, 1,"Co  ");
  }
  if (type_al == 1) TIME_ALARM();
}
/* Xu ly nut bam Set ---------------------------------------------------------*/
void SET_BUTTON() {
  INTCON.INTE = 0;            // OFF ngat ngoai
  PORTE = 0x04;              // Bat LED 3
  INTCON.T0IE = 1;            // Kich hoat Timer0 dem thoi gian tre man hinh 30s
  SET_1();
  SET_2();
  SET_3();
  PORTE = 0x00;              // OFF LED 3
  Lcd_Cmd(Lcd_CLEAR);        // Xoa man hinh
  Lcd_Cmd(Lcd_CURSOR_OFF);    // OFF con tro man hinh
  CLEAR_TIMER0();            // Xoa bo dem thoi gian tre man hinh
  SET_DATA();                // Cap nhat du lieu
}
/* Nhay bao chuong -----------------------------------------------------------*/
void BLINK_ALARM() {
  INTCON.INTE = 0;            // OFF ngat ngoai
  PORTE = 0x00;
  Lcd_Cmd(Lcd_CLEAR);
  Lcd_Cmd(Lcd_CURSOR_OFF);
  Lcd_Out(1,1,"Bay gio la ");
  BCD(1,12,hour_al);
  Lcd_Out(1,14,":");
  BCD(1,15,minute_al);
  LCD_Out(2,1,day_txt);
  BCD(2,7,date);
  LCD_Chr_Cp('/');
  BCD(2,10,month);
  LCD_Out_Cp("/20");
  BCD(2,15,year);
  while ((count_al < 100) && (PORTB.F1 == 1) && (PORTB.F2 == 1) && (PORTB.F3 == 1) && (PORTB.F4 == 1)) {
    Delay_ms(200);
    PORTE = ~PORTE;
    count_al++;
  }
  Lcd_Cmd(Lcd_CLEAR);
  PORTE = 0x00;
}
/* Quet phim -----------------------------------------------------------------*/
void CYCLE_BUTTON() {
  while(1) {
    INTCON.T0IE = 0;
    INTCON.INTE = 1;
    if (flag_time == 1) {
      UPDATE_TIME();
      flag_time = 0;
    }
    Delay_ms(200);
    if (PORTB.F1 == 0) MODE_BUTTON();
    if (PORTB.F2 == 0) SET_BUTTON();
    if ((hour == hour_al) && (minute == minute_al) && (second == 0x00)) BLINK_ALARM();
    count_al = 0;
  }
}
/* XU LY NGAT *****************************************************************/
void interrupt() {
  if (INTCON.T0IF) {
    delay10s_1++;
    if (delay10s_1 == 200) {
      delay10s_2++;
      delay10s_1 = 0;
    }
  INTCON.T0IF = 0;
  }
  if (INTCON.INTF) {
    flag_time = 1;
    INTCON.INTF = 0; // Xoa co ngat ngoai
  }
}
/* CHUONG TRINH CHINH *********************************************************/
void MAIN() {
  INIT_MAIN();
  CYCLE_BUTTON();
}
/* KET THUC *******************************************************************/


cuongngao 13-10-2007 06:34 PM

ai có thể cho mình biết là những chú PIC nào hỗ trợ module CAN ko?mình đang làm 1 đề tài giao thức CAN mà.mình định sử dụng con 18f458 thì không có trong thư viện Protel99 SE, đang định chuyển xuống 16f877 ko biết có đc ko nữa???

hampic 13-10-2007 09:54 PM

Trích:

Nguyên văn bởi tinhthanthep (Post 11031)
Đã gửi software và crack phiên bản 6.2.1.0 cho linhnc308.
Nếu bạn nào muốn làm cái mạch này để học con PIC16F877A thì liên hệ với mình , mình cho mượn film để đi làm mạch in cho đỡ tốn xèng. Diện tích mạch PCB là 1dm2. Mạch in 2 lớp có phủ flux và mạ bạc ở viện điện tử là 62k/dm2

Cho hỏi viện này nằm ở đâu vậy? Ở đó làm mạch 4 lớp được ko vậy bạn?
Thks!

tinhthanthep 15-10-2007 11:33 AM

Viện điện tử: 156A quán thánh. đt: 04.7163242
Chỉ làm được mạch in đến 2 lớp


Múi giờ GMT. Hiện tại là 10:42 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