- Vật liệu thiết yếu:
- Điều kiện tiên quyết:
- Sơ đồ mạch:
- Lập trình cho Đồng hồ báo thức:
- Mô phỏng:
- Hoạt động của Đồng hồ báo thức kỹ thuật số sử dụng PIC16F877A:
Cuộc cách mạng kỹ thuật số bắt đầu vào năm 1950 thay đổi tất cả các cấu trúc cơ khí và điện tử tương tự hiện có thành máy tính kỹ thuật số. Kể từ khi sự phát triển của điện tử kỹ thuật số theo cấp số nhân, ngày nay hầu như không thể nào một người cưỡng lại việc sử dụng bất kỳ thiết bị điện tử nào. Bắt đầu từ chiếc đồng hồ báo thức đánh thức bạn và chiếc máy nướng bánh mì phục vụ bữa sáng cho bạn, mọi thứ đều là sự đóng góp của các thiết bị điện tử kỹ thuật số. Nghĩ về tất cả những điều này, thật sự thú vị khi lập trình những thứ của riêng chúng ta có thể thực hiện các nhiệm vụ đơn giản nhưng hữu ích, như Đồng hồ báo thức mà chúng ta sẽ chế tạo trong dự án này với Bộ vi điều khiển PIC. Trước đây chúng tôi đã xây dựng đồng hồ báo thức với các Bộ vi điều khiển khác:
- Đồng hồ báo thức Raspberry Pi sử dụng Mô-đun RTC DS1307
- Đồng hồ kỹ thuật số dựa trên Arduino có báo thức
- Đồng hồ báo thức sử dụng Vi điều khiển ATmega32
Đồng hồ báo thức này sẽ có màn hình LCD 16x2 sẽ hiển thị thời gian hiện tại và thời gian cài đặt. Chúng tôi sẽ sử dụng một vài nút nhấn để đặt thời gian báo thức bất cứ khi nào được yêu cầu. Thời gian hiện tại sẽ được theo dõi bằng cách sử dụng mô-đun DS3231 RTC và chúng tôi sẽ sử dụng giao tiếp IIC để nhận các giá trị này từ mô-đun RTC. Chúng ta đã tìm hiểu về mô-đun RTC và cách giao diện nó với PIC. Vì vậy, chúng tôi khuyên bạn nên đọc qua hướng dẫn đó, chúng tôi sẽ bỏ qua hầu hết các thông tin được đề cập trong hướng dẫn đó.
Vật liệu thiết yếu:
- Bread Board - 2Nos
- PIC16F877A
- Nguồn điện 5V - Mô-đun cung cấp
- Tinh thể 20 MHz
- Tụ 33pf - 2Nos
- Mô-đun RTC DS3231
- Mô-đun màn hình LCD 16 * 2
- LẨU 10K
- 10k và điện trở 1K
- Các nút nhấn - 5Nos
- Buzzer
- Kết nối dây
Điều kiện tiên quyết:
Dự án này yêu cầu bạn biết một số kiến thức cơ bản về vi điều khiển PIC và cách lập trình nó. Chúng tôi sẽ sử dụng GPIO, màn hình LCD và mô-đun RTC cho dự án này. Vì vậy, tốt hơn là bạn nên học cách sử dụng các mô-đun này trước. Các liên kết sau đây sẽ giúp bạn tìm hiểu tương tự
- Viết chương trình đầu tiên của bạn với Vi điều khiển PIC
- Giao diện LCD với PIC
- Giao tiếp I2C bằng PIC
- DS3231 RTC giao tiếp với PIC
Sơ đồ mạch:
Sơ đồ mạch cho Dự án Đồng hồ Báo thức dựa trên PIC này được hiển thị bên dưới, được tạo bằng phần mềm proteus. Nó cũng sẽ được sử dụng để mô phỏng thêm trong dự án này.
Năm nút nhấn sẽ hoạt động như một đầu vào để cài đặt báo thức trong thời gian cần thiết. Vì vậy, một đầu của tất cả các nút nhấn được kết nối với đất và các đầu còn lại được kết nối với chân PORTB, điện trở kéo bên trong sẽ được sử dụng trên các chân này để tránh các chân bị nổi. Buzzer sẽ hoạt động như một đầu ra và sẽ phát cho chúng ta một tiếng bíp khi cảnh báo được kích hoạt và được kết nối với chân PORT S. Thời gian hiện tại luôn được theo dõi bởi mô-đun DS3231 RTC mà từ đó PIC nhận dữ liệu thông qua bus I2C, do đó các chân SCL và SDA của mô-đun RTC được kết nối với chân SCL và SDA của bộ điều khiển PIC. Màn hình LCD được gắn vào PORTD của PIC được sử dụng để hiển thị thời gian hiện tại và thời gian cài đặt. Tìm hiểu thêm về cách sử dụng mô-đun DS3231 RTC với PIC tại đây.
Mạch hoàn chỉnh có thể được xây dựng trên một breadboard. Vì có vài chục dây để kết nối nên chỉ cần kiên nhẫn và đảm bảo các kết nối là chính xác. Thiết lập phần cứng của tôi trông giống như thế này bên dưới khi tôi đã hoàn tất các kết nối
Tôi đã sử dụng mô-đun breadboard và bộ chuyển đổi 12V để cấp nguồn cho mô-đun. Đây là nguồn điện áp cung cấp + 5V của tôi. Ngoài ra, tôi phải sử dụng hai bảng mạch để giữ cho mạch sạch. Bạn cũng có thể hàn toàn bộ mạch vào bảng mạch hoàn thiện nếu bạn đang muốn tạo ra một dự án mạnh mẽ hơn.
Lập trình cho Đồng hồ báo thức:
Các chương trình PIC hoàn chỉnh cho dự án Alarm Clock này có thể được tìm thấy ở dưới cùng của trang này. Dự án này cũng yêu cầu ba thư viện để sử dụng LCD, I2C và RTC với PIC. Mã hoàn chỉnh với các tệp tiêu đề có thể được tải xuống từ tệp ZIP tại đây và có thể được mở bằng MPLABX sau khi giải nén. Bên dưới, tôi chỉ giải thích tệp c chính dưới dạng các đoạn mã nhỏ. Bạn có thể quay lại các hướng dẫn đã đề cập ở trên nếu bạn muốn biết cách các tệp tiêu đề hoạt động.
Trước khi vào chương trình chính, chúng ta phải xác định các chân mà chúng ta đã sử dụng với tên có ý nghĩa hơn. Bằng cách này, bạn sẽ dễ dàng sử dụng chúng trong quá trình lập trình. Các chân được xác định trong chương trình của chúng tôi được hiển thị bên dưới
// Xác định chân LCD #define RS RD2 // Đặt lại chân của LCD #define EN RD3 // Kích hoạt chân của LCD #define D4 RD4 // Bit dữ liệu 0 của LCD #define D5 RD5 // Bit dữ liệu 1 của LCD #define D6 RD6 // Bit dữ liệu 2 của LCD #define D7 RD7 // Bit dữ liệu 3 của LCD // Định nghĩa các nút #define MB RB1 // Nút ở giữa #define LB RB0 // Nút trái #define RB RB2 // Nút phải # xác định UB RB3 // Nút trên #define BB RB4 // Nút dưới cùng // Xác định Buzz #define BUZZ RD1 // Buzzer được kết nối với RD1
Bên trong chức năng chính, chúng ta bắt đầu bằng cách khai báo các chân Input và output. Trong dự án của chúng tôi, PORTB được sử dụng cho các nút nhấn là thiết bị đầu vào, vì vậy chúng tôi đặt các chân của chúng làm đầu vào và PORTD được sử dụng cho LCD và buzzer vì vậy chúng tôi đặt các chân của chúng làm Đầu ra. Ngoài ra, một chân không bao giờ được để nổi, các chân I / O phải luôn được kết nối với đất hoặc với điện áp + 5V. Trong trường hợp của chúng tôi đối với các nút nhấn, các chân sẽ không được kết nối với bất kỳ thứ gì khi nút không được nhấn, vì vậy chúng tôi sử dụng một điện trở kéo lên bên trong đặt chân thành Cao khi không sử dụng. Điều này được thực hiện bằng cách sử dụng các thanh ghi điều khiển như hình dưới đây
TRISD = 0x00; // Tạo các chân Cổng D làm outptu cho giao diện LCD TRISB = 0xFF; // switchs được khai báo là chân đầu vào OPTION_REG = 0b00000000; // Kích hoạt tính năng kéo lên điện trở trên cổng B cho switchs BUZZ = 0; // Lượt của buzzer
Vì chúng ta có tệp tiêu đề LCD và I2C được liên kết với chương trình chính, chúng ta có thể bắt đầu khởi tạo LCD bằng cách gọi một hàm đơn giản. Điều tương tự cũng có thể được thực hiện cho quá trình khởi tạo I2C. Ở đây chúng tôi đang bắt đầu giao tiếp I2C ở 100kHz vì mô-đun RTC hoạt động với 100kHz.
Lcd_Start (); // Khởi tạo mô-đun LCD I2C_Initialize (100); // Khởi tạo I2C Master với xung nhịp 100KHz
Chức năng dưới đây được sử dụng để đặt thời gian và ngày trên mô-đun RTC, sau khi ngày và giờ được thiết lập, hãy xóa dòng này. Khác với mỗi lần bạn bắt đầu chương trình, thời gian và ngày tháng sẽ được thiết lập lại nhiều lần
// Xóa dòng dưới đây khi ngày và giờ được đặt lần đầu tiên. Set_Time_Date (); // đặt ngày và giờ trên mô-đun RTC
Để cho biết chương trình đang khởi động, chúng tôi hiển thị một màn hình giới thiệu nhỏ hiển thị tên dự án và tên trang web như hình dưới đây
// Đưa ra thông báo giới thiệu trên LCD Lcd_Clear (); Lcd_Set_Cursor (1,1); Lcd_Print_String ("Đồng hồ báo thức"); Lcd_Set_Cursor (2,1); Lcd_Print_String ("Thông báo mạch điện"); __delay_ms (1500);
Tiếp theo bên trong vòng lặp while, chúng ta cần đọc ngày và giờ hiện tại từ mô-đun RTC, điều này có thể được thực hiện bằng cách gọi hàm dưới đây.
Update_Current_Date_Time (); // Đọc ngày và giờ hiện tại từ mô-đun RTC
Gọi hàm trên sẽ cập nhật các biến sec, min và giờ với giá trị hiện tại. Để hiển thị chúng trên màn hình LCD, chúng ta phải chia chúng thành từng ký tự bằng cách sử dụng mã bên dưới.
// Tách thành các char để hiển thị trên lcd char sec_0 = sec% 10; char sec_1 = (giây / 10); char min_0 = min% 10; char min_1 = min / 10; char giờ_0 = giờ% 10; char giờ_1 = giờ / 10;
Tiếp theo, chúng tôi cập nhật các giá trị trên màn hình LCD. Thời gian hiện tại sẽ được hiển thị ở dòng đầu tiên và thời gian đã đặt mà báo thức phải được kích hoạt được hiển thị trên dòng thứ hai. Mã thực hiện tương tự được hiển thị bên dưới.
// Hiển thị Giờ hiện tại trên màn hình LCD Lcd_Clear (); Lcd_Set_Cursor (1, 1); Lcd_Print_String ("TIME:"); Lcd_Print_Char (giờ_1 + '0'); Lcd_Print_Char (giờ_0 + '0'); Lcd_Print_Char (':'); Lcd_Print_Char (min_1 + '0'); Lcd_Print_Char (min_0 + '0'); Lcd_Print_Char (':'); Lcd_Print_Char (giây_1 + '0'); Lcd_Print_Char (sec_0 + '0'); // Hiển thị Ngày trên màn hình LCD Lcd_Set_Cursor (2, 1); Lcd_Print_String ("Báo thức:"); Lcd_Print_Char (alert_val + '0'); Lcd_Print_Char (alert_val + '0'); Lcd_Print_Char (':'); Lcd_Print_Char (alert_val + '0 '); Lcd_Print_Char (alert_val + '0');
Bây giờ, chúng tôi đã hiển thị thời gian và cài đặt thời gian trên màn hình LCD, chúng tôi phải kiểm tra xem người dùng có đang cố gắng cài đặt thời gian báo thức hay không. Để thực hiện điều này, người dùng phải nhấn nút giữa, vì vậy chúng tôi sẽ kiểm tra xem nút giữa có được nhấn hay không và chuyển đổi một biến để vào chế độ đặt báo thức. Nút tương tự sẽ được nhấn một lần nữa để xác nhận rằng các giá trị đã được đặt và trong trường hợp đó, chúng tôi phải thoát ra khỏi chế độ đặt cảnh báo. Vì vậy, chúng tôi sử dụng dòng mã dưới đây để thay đổi trạng thái của biến set_alarm .
// Sử dụng nút giữa để kiểm tra xem có phải đặt báo thức không if (MB == 0 && set_alarm == 0) {// Nếu nhấn nút giữa và báo thức không được bật trong khi (! MB); // Chờ cho đến khi nút được giải phóng set_alarm = 1; // bắt đầu cài đặt giá trị cảnh báo } if (MB == 0 && set_alarm == 1) {// Nếu nhấn nút giữa và báo thức không tắt trong khi (! MB); // Chờ cho đến khi nút được giải phóng set_alarm = 0; // dừng cài đặt giá trị cảnh báo }
Nếu người dùng đã nhấn nút giữa, nghĩa là họ đang cố gắng cài đặt thời gian báo thức. Trong trường hợp này, chương trình sẽ chuyển sang chế độ cài đặt cảnh báo bằng cách sử dụng mã trên. Bên trong chế độ đặt báo thức nếu người dùng nhấn nút trái hoặc phải nghĩa là chúng ta phải di chuyển con trỏ sang trái hoặc phải. Để làm điều này, chúng tôi chỉ cần tăng giảm giá trị của vị trí mà tại đó con trỏ phải được đặt
if (LB == 0) {// Nếu nhấn nút bên trái while (! LB); // Chờ cho đến khi nút được phát hành pos--; // Sau đó di chuyển con trỏ sang trái } if (RB == 0) {// Nếu nút bên phải được nhấn while (! RB); // Chờ cho đến khi nút được phát hành pos ++; // Di chuyển con trỏ sang phải }
Trong khi sử dụng nút nhấn với bộ vi điều khiển hoặc bộ vi xử lý, có một vấn đề phổ biến cần giải quyết. Sự cố này được gọi là chuyển đổi nảy. Đó là khi nút được nhấn, nó có thể tạo ra các xung nhiễu cho MCU / MPU, điều này có thể giả mạo MCU cho nhiều mục nhập. Vấn đề này có thể được giải quyết bằng cách thêm một tụ điện trên công tắc hoặc bằng cách sử dụng chức năng trì hoãn ngay khi phát hiện thấy nút bấm. Loại dung dịch này được gọi là khử dội. Ở đây chúng ta đã sử dụng một trong khi vòng lặp để tổ chức chương trình tại chỗ cho đến khi nút được phát hành. Đây không phải là giải pháp khử nảy tốt nhất nhưng đối với chúng tôi, nó sẽ hoạt động tốt.
trong khi (! RB);
Tương tự như nút trái và phải, chúng ta cũng có nút trên và nút dưới dùng để tăng hoặc giảm giá trị của thời gian báo thức. Mã để làm điều tương tự được hiển thị bên dưới. Lưu ý rằng mỗi ký tự của thời gian cảnh báo đã đặt được giải quyết bằng giá trị chỉ số của mảng. Điều này là chúng ta có thể dễ dàng truy cập vào ký tự được yêu cầu có giá trị được thay đổi.
if (UB == 0) {// Nếu nút trên được nhấn while (! UB); // Chờ cho đến khi nút được phát hành alert_val ++; // Tăng giá trị char cụ thể đó } if (BB == 0) {// Nếu nhấn nút thấp hơn while (! UB); // Chờ cho đến khi nút được phát hành alert_val--; // Giảm giá trị char cụ thể đó }
Sau khi đặt thời gian báo thức, người dùng sẽ nhấn lại nút giữa. Sau đó, chúng ta có thể bắt đầu so sánh thời gian hiện tại với thời gian đã đặt. So sánh bằng cách kiểm tra xem mọi ký tự của thời gian hiện tại có bằng với ký tự của thời gian đã đặt hay không. Nếu các giá trị bằng nhau thì chúng tôi kích hoạt cảnh báo bằng cách đặt biến trigger_alarm khác, chúng tôi chỉ so sánh cho đến khi nó bằng nhau.
// Báo thức NẾU được đặt Kiểm tra xem giá trị đặt có bằng với giá trị hiện tại không nếu (set_alarm == 0 && alert_val == giờ_1 && alert_val == giờ_0 && alert_val == min_1 && alert_val == min_0) trigger_alarm = 1; // Bật trình kích hoạt nếu giá trị khớp
Nếu báo thức được đặt, chúng tôi phải phát ra tiếng bíp còi để báo động cho người dùng. Điều này có thể được thực hiện bằng cách bật Buzzer một cách đều đặn như hình dưới đây.
if (trigger_alarm) {// Nếu cảnh báo được kích hoạt // Beep the buzzer BUZZ = 1; __delay_ms (500); BUZZ = 0; __delay_ms (500); }
Mô phỏng:
Chương trình này cũng có thể được mô phỏng bằng phần mềm proteus. Chỉ cần tạo lại mạch được hiển thị ở trên và tải tệp hex vào PIC. Mã hex cho dự án này có thể được tìm thấy tại tệp ZIP được liên kết ở đây. Ảnh chụp màn hình được chụp trong quá trình mô phỏng được hiển thị bên dưới
Mô phỏng trở nên rất hữu ích khi bạn đang cố gắng thêm các tính năng mới vào dự án. Bạn cũng có thể sử dụng mô-đun trình gỡ lỗi I2C để kiểm tra dữ liệu nào đang vào và ra thông qua bus I2C. Bạn có thể thử nhấn các nút và cũng có thể đặt thời gian báo thức. Khi thời gian đặt bằng với thời gian hiện tại thì bộ rung sẽ tăng cao.
Hoạt động của Đồng hồ báo thức kỹ thuật số sử dụng PIC16F877A:
Xây dựng mạch trên breadboard, lấy mã từ liên kết tải xuống và biên dịch nó bằng trình biên dịch MplabX và XC8. Nếu bạn đã tải xuống mã từ tệp ZIP được cung cấp tại đây, thì bạn sẽ không gặp vấn đề gì khi biên dịch mã vì các tệp tiêu đề đã được đính kèm.
Sau khi biên dịch, hãy tải chương trình lên phần cứng của bạn bằng trình lập trình PicKit3. Kết nối để kết nối bộ lập trình pickit với IC PIC cũng được thể hiện trong sơ đồ mạch. Sau khi chương trình được tải lên, bạn sẽ thấy màn hình giới thiệu và sau đó thời gian được hiển thị, sau đó bạn có thể sử dụng các nút nhấn để đặt thời gian báo thức. Thiết lập phần cứng của tôi khi được cấp nguồn trông như sau.
Khi thời gian báo thức khớp với thời gian hiện tại, còi sẽ bắt đầu phát ra tiếng bíp để báo động cho người dùng. Toàn bộ hoạt động có thể được tìm thấy tại video dưới đây. Dự án có rất nhiều lựa chọn để xây dựng. Mô-đun RTC có thể theo dõi bất kỳ ngày giờ nào, vì vậy bạn có thể thực hiện một công việc đã lên lịch vào bất kỳ thời điểm / ngày nào được yêu cầu. Bạn cũng có thể kết nối thiết bị AC như quạt hoặc đèn và lên lịch để BẬT hoặc TẮT khi cần thiết. Vẫn còn nhiều điều bạn có thể xây dựng dựa trên dự án này, hãy cho tôi biết ý tưởng nào xuất hiện trong đầu bạn khi bạn nâng cấp dự án này và tôi sẽ rất vui khi được nghe ý kiến của bạn.
Hy vọng bạn đã hiểu dự án và học được điều gì đó hữu ích từ quá trình này. Nếu bạn có bất kỳ nghi ngờ nào trong dự án này, hãy sử dụng phần bình luận để đăng chúng hoặc sử dụng diễn đàn để được trợ giúp kỹ thuật.
Mã PIC hoàn chỉnh với các tệp tiêu đề có thể được tìm thấy tại đây