You are on page 1of 45

HỌC VIỆN KỸ 

THUẬT MẬT MÃ
KHOA ĐIỆN TỬ- VIỄN THÔNG

BÁO CÁO MÔN HỌC


HỆ ĐIỀU HÀNH NHÚNG THỜI GIAN THỰC

Đề tài: “Thiết kế đồng hồ thời gian thực có LED nháy theo nhạc sử
dụng hệ điều hành FREERTOS”

Giảng viên hướng dẫn: Lê Thị Hồng Vân

Sinh viên thực hiện: 1. Nguyễn Đình Hiếu DT030216

2. Nguyễn Đăng Toàn DT030244

3. Nguyễn Công Tùng DT030247

Hà Nội 11/ 2022

1
LỜI NÓI ĐẦU

Ngày nay khoa học công nghệ ngày càng phát triển, vi điều khiển AVR và
vi điều khiển PIC ngày càng thông dụng và hoàn thiện hơn, nhưng có thể nói sự
xuất hiện của Arduino vào năm 2005 tại Italia đã mở ra một hướng đi mới cho vi
điều khiển. Sự xuất hiện của Arduino đã hỗ trợ cho con người rất nhiều trong lập
trình và thiết kế, nhất là đối với những người bắt đầu tìm tòi về vi điều khiển mà
không có quá nhiều kiến thức, hiểu biết sâu sắc về vật lý và điện tử . Phần cứng
của thiết bị đã được tích hợp nhiều chức năng cơ bản và là mã nguồn mở. Ngôn
ngữ lập trình trên nền Java lại vô cùng dễ sử dụng tương thích với ngôn ngữ C
và hệ thư viện rất phong phú và được chia sẻ miễn phí. Chính vì những lý do
như vậy nên Arduino hiện đang dần phổ biến và được phát triển ngày càng
mạnh mẽ trên toàn thế giới.

Trên cơ sở kiến thức đã học trong môn học: Tin học đại cương, Điện tử
tương tự và số, Hệ điều hành nhúng thời gian thực… cùng với những hiểu biết
về các thiết bị điện tử, chúng em đã quyết định thực hiện đề tài “Thiết kế đồng
hồ thời gian thực có LED nháy theo nhạc sử dụng hệ điều hành thời gian thực
FreeRTOS”. Do kiến thức còn hạn hẹp nên chắc chắn không tránh khỏi những
thiếu sót, hạn chế vì thế chúng em rất mong có được sự góp ý và nhắc nhờ từ cô
giáo để có thể hoàn thiện đề tài của mình. Chúng em xin chân thành cảm ơn cô
Lê Thị Hồng Vân đã giúp đỡ chúng em rất nhiều trong quá trình tìm hiểu, thiết
kế và hoàn thành đề tài đồ án môn học này.

2
Mục lục
LỜI NÓI ĐẦU...............................................................................................................2
Mục lục...........................................................................................................................3
Danh mục hình ảnh.......................................................................................................4
CHƯƠNG I: TỔNG QUAN VỀ HỆ THỐNG............................................................5
1.1. Đặt vấn đề..........................................................................................................5
1.2. Lý do chọn đề tài...............................................................................................5
1.3. Mục đích nghiên cứu đề tài...............................................................................5
1.4. Giải pháp thiết kế..............................................................................................5
CHƯƠNG II: CƠ SỞ LÝ THUYẾT...........................................................................7
2.1. Tìm hiểu về hệ điều hành nhúng thời gian thực FreeRTOS.................................7
2.1.1 Lịch sử phát triển của hệ điều hành nhúng thời gian thực FreeRTOS...........7
2.1.2. Cách thức hoạt động của FreeRTOS.............................................................8
2.1.3. Các chức năng của FreeRTOS.......................................................................9
2.2. Giới thiệu các thiết bị phần cứng sử dụng..........................................................10
2.2.1. Kit Arduino UNO R3..................................................................................10
2.2.2. Module thời gian thực Module Tiny RTC I2C............................................17
2.2.3. Module LED P10.........................................................................................18
2.2.4. Module cảm biến âm thanh.........................................................................20
CHƯƠNG III: THIẾT KẾ VÀ THI CÔNG SẢN PHẨM......................................22
3.1. Thiết kế và thi công phần cứng..........................................................................22
3.2. Thiết kế và thi công phần mềm..........................................................................24
3.2.1. Chương trình hiển thị lên LED P10.............................................................24
3.2.2. Thiết kế chương trình chính........................................................................25
3.2.3. Chương trình điều khiển sản phẩm..............................................................27
CHƯƠNG IV: TỔNG KẾT.......................................................................................29
4.1. Nhận xét, đánh giá..............................................................................................29
4.2. Hướng phát triển................................................................................................29
4.3. Kết luận..............................................................................................................29
TÀI LIỆU THAM KHẢO..........................................................................................30

3
PHỤ LỤC.....................................................................................................................31

Danh mục hình ảnh


Hình 1: Sơ đồ khối......................................................................................6

Hình 2. 1: Cách hoạt động của RTOS.........................................................9


Hình 2. 2: Board Arduino Uno..................................................................11
Hình 2. 3: Vi điều khiển của Arduino Uno...............................................12
Hình 2. 4: Các chân trên Arduino Uno R3................................................14
Hình 2. 5: Module Tiny RTC I2C (không PIN)........................................17
Hình 2. 6: Màn hình LED P10..................................................................18
Hình 2. 7: Chiều đi của data LED.............................................................19
Hình 2. 8: Module cảm biến âm thanh......................................................20

Hình 3. 1: Mô phỏng mạch trên proteus...................................................22


Hình 3. 2: Thiết kế và thi công vỏ hộp để chứa và bảo vệ các thiết bị.....23
Hình 3. 3: Thuật toán quét LED................................................................24
Hình 3. 4: Phương pháp ngắt timer thực hiện thuật toán quét led............24
Hình 3. 5: Lưu đồ thuật toán của chương trình chính...............................25
Hình 3. 6: Lưu đồ thuật toán tác vụ taskRealTime...................................26
Hình 3. 7: Lưu đồ thuật toán tác vụ “animation”......................................27
Hình 3. 8: Sơ đồ điều khiển sản phẩm......................................................27
Hình 3. 9: Lưu đồ thuật toán chương trình điều khiển..............................28

4
5
CHƯƠNG I: TỔNG QUAN VỀ HỆ THỐNG.
1.1. Đặt vấn đề.
Khoa học kỹ thuật ngày càng phát triển kéo theo việc ra đời các loại đồng
hồ nhằm xác định thời gian rõ ràng và chính xác hơn, tiêu biểu là đồng hồ cơ và
đồng hồ số. Đồng hồ số ra đời mang những tính năng vượt bậc so với đồng hồ
cơ hay những loại đồng hồ xưa về những mặt: kinh phí, độ chính xác và nhiều
tính năng khác.

1.2. Lý do chọn đề tài.


Hiện nay, trên thị trường chỉ có một số loại đồng hồ kim và đồng hồ số
đơn giản thông thường dùng để xem giờ. Thiết kế đồng hồ thời gian thực có
LED nháy theo nhạc ngoài nhằm mục đích hỗ trợ người dùng theo dõi thời gian,
đồng thời đây cũng là một sản phẩm gần gũi, có tính mới lạ đẹp mắt và dễ dàng
sử dụng.
Thiết bị hoạt động dùng vi điều khiển để xử lý nên có độ chính xác cao,
giao tiếp trực tiếp với các module thông dụng thành thể thống nhất. Vì vậy, thiết
bị giúp chúng ta và những người thân trong gia đình có thể sắp xếp và quản lý
thời gian tốt hơn, chính xác hơn với độ tin cậy cao

1.3. Mục đích nghiên cứu đề tài.


Thiết kế và thi công đồng hồ thời gian thực. Đồng hồ có tính năng hiển thị
thời gian đúng giờ, led có thể nháy theo nhạc và có giao diện tiện lợi, đẹp mắt
cho người dùng.

1.4. Giải pháp thiết kế.


Hệ thống được thiết kế gồm 6 khối: Khối nguồn, khối thời gian, khối vi
điều khiển, khối hiển thị, khối điều khiển, khối cảm biến âm thanh.

6
Hình 1: Sơ đồ khối
Chức năng của các khối:
- Khối nguồn: cung cấp nguồn hoạt động cho hệ thống vi điều
khiển.
- Khối xử lý trung tâm: Đóng vai trò đầu não của hệ thống. Xử lý
tín hiệu nhận được từ khối thời gian thực và khối cảm biến âm
thanh từ đó hiển thị thông tin lên khối hiển thị. Nhận tín hiệu điều
khiển để thay đổi trạng thái hoạt động.
- Khối hiển thị: Hiển thị các thông số thời gian như giờ, phút, giây

- Khối RTC: Khối này thực chất là một chíp thời gian thực (Real
Time Clock), được sử dụng với ý nghĩa thời gian tuyệt đối mà
con người đang sử dụng. Trong sơ đồ này nó sẽ đảm nhiệm chức
năng cấp time chính xác cho vi điều khiển xử lý.
- Khối điều khiển: Sử dụng nút bấm. Thực hiện chức năng nhập
các dữ liệu đưa đến vi điều khiển và bao gồm thao tác thay đổi
hiển thị.
- Khối cảm biến âm thanh: Cảm biến âm thanh có chức nặng nhận
biết được âm thanh giúp LED nháy theo điệu nhạc.

7
CHƯƠNG II: CƠ SỞ LÝ THUYẾT.
2.1. Tìm hiểu về hệ điều hành nhúng thời gian thực FreeRTOS.
Hệ điều hành thời gian thực – Real Time Operating Systems (RTOS) là
một hệ điều hành cho các hệ thống nhúng. Loại hệ điều hành này thường được
thiết kế để tiết kiệm tài nguyên và đáng tin cậy. Phần cứng chạy hệ điều hành
nhúng có thể rất hạn chế về tài nguyên như RAM và ROM, do đó thiết kế nhúng
của các hệ điều hành này có thể có phạm vi hẹp phù hợp với ứng dụng cụ thể để
đạt được hoạt động mong muốn theo các ràng buộc này. Để tận dụng tốt hơn sức
mạnh xử lý của CPU, các nhà phát triển phần mềm có thể viết mã quan trọng
trực tiếp bằng ngôn ngữ máy (tốc độ, chi phí, khả năng bảo trì), hoặc ngôn ngữ
khả chuyển (portable language) như C.
Một số hệ điều hành nhúng phổ biến như: QNX, PDOS, pSOS, VxWorks,
Nulceus, ERCOS, EMERALDS, Windows CE….Nhưng trong đồ án môn học
này chúng em sử dụng hệ điều hành nhúng thời gian thực FreeRTOS. Vì
FreeRTOS phù hợp cho nghiên cứu, học tập về các kỹ thuật, công nghệ trong
viết hệ điều hành nói chung và hệ điều hành nhúng thời gian thực nói riêng,
cũng như việc phát triển mở rộng tiếp các thành phần cho hệ điều hành (bổ sung
mô-đun, trình điều khiển, chuyển đổi môi trường thực hiện).

2.1.1 Lịch sử phát triển của hệ điều hành nhúng thời gian thực
FreeRTOS
FreeRTOS là lõi của hệ điều hành thời gian thực miễn phí. Hệ điều hành
này được Richard Barry công bố rộng rãi từ năm 2003, phát triển mạnh đến nay
và được cộng đồng mạng mã nguồn mở ủng hộ. FreeRTOS có tính khả chuyển,
mã nguồn mở, lõi có thể down miễn phí và nó có thể dùng cho các ứng dụng
thương mại. Nó phù hợp với những hệ nhúng thời gian thực nhỏ. Hầu hết các

8
code được viết bằng ngôn ngữ C nên nó có tính phù hợp cao với nhiều nền khác
nhau.
Ưu điểm của nó là dung lượng nhỏ và có thể chạy trên những nền mà
nhiều hệ không chạy được. Có thể port cho nhiều kiến trúc vi điều khiển và
những công cụ phát triển khác nhau. Mỗi port chính thức bao gồm những ứng
dụng ví dụ tiền cấu hình biểu hiện sự riêng biệt của lõi, kiến thức mới và hướng
phát triển. Những hỗ trợ miễn phí được cung cấp bởi cộng đồng mạng. Hỗ trợ
thương mại với những dịch vụ phát triển đầy đủ cũng được cung cấp
FreeRTOS được cấp giấy phép bởi bản đã được chỉnh sửa bởi GPL
(GeneralPublic License và có thể sử dụng trong ứng dụng thương mại với giấy
phép này. Ngoài ra liên quan đến FreeRTOS có OpenRTOS và SafeRTOS.
OpenRTOS là bản thương mại của FreeRTOS.org và không liên quan gì đến
GPL. SafeRTOS là về cơ bản dựa trên FreeRTOS nhưng được phân tích, chứng
minh bằng tài liệu và kiểm tra nghiêm ngặt với chuẩn IEC61508. Và chuẩn
IEC61508 SIL3 đã được tạo ra và phát triển độc lập để hoàn thiện tài liệu cho
SafeRTOS.

2.1.2. Cách thức hoạt động của FreeRTOS.


RTOS là một phân đoạn hoặc một phần của chương trình, trong đó nó giải
quyết việc điều phối các task, lập lịch và phân mức ưu tiên cho task, nắm bắt các
thông điệp gửi đi từ task.
RTOS khá phức tạp, nói một cách dễ hiểu hơn là nó thực hiện việc xử lý
các trạng thái máy (State Machine). Để giải quyết một bài toán nhiều trạng thái
máy, thông thường chúng ta sử dụng code sau:
while(1)
{
switch(state)
{
case 1: //Code for Task 1;

9
state= 2;
case 2: //Code for Task 2;
state= 3;
case 3: //Code for Task 3;
state= 4;
case 4: //Code for Task 4;
state=1;
}
}
Chương trình sẽ thực thi từ states 1 tới states 4 sau đó quay vòng lại. Bất
kì khi nào states thay đổi, chương trình sẽ nhảy qua phục vụ task đó.
Nhược điểm của phương pháp này đó là tài nguyên sử dụng chung, tốc độ
chuyển chậm khi thay đổi states bởi nó phải hoàn thành mỗi Task trước khi
chuyển sang Task khác, khó kiểm soát khi nhiều tác vụ (Task)

Hình 2. 1: Cách hoạt động của RTOS


Nhân Kernel sẽ điều phối sự hoạt động của các tác vụ (Task), mỗi task sẽ
có một mức ưu tiên (prioritize) và thực thi theo chu kì cố định. Nếu có sự tác
động như ngắt, tín hiệu hoặc tin nhắn giữa các Task, Kernel sẽ điều phối chuyển
tới Task tương ứng với Code đó.

10
Sự chuyển dịch giữa các Task rất linh động, độ trễ thấp mang lại độ tin
cậy cao cho chương trình.

2.1.3. Các chức năng của FreeRTOS.


Quản lý công việc: Ứng dụng được chia thành các đơn vị chương trình
nhỏ gọi là các Task (tác vụ), có thể lập lịch và tuần tự được gọi là 'Chủ đề' hoặc
'Nhiệm vụ'. Điều này được thực hiện để đạt được tính đồng thời trong Ứng dụng
thời gian thực. Quản lý tác vụ bằng Kernel bao gồm Tạo tác vụ thời gian thực,
kết thúc, thay đổi mức độ ưu tiên, v.v. Tạo tác vụ liên quan đến việc tạo Khối
điều khiển tác vụ (TCB) có thông tin về id tác vụ, mức độ ưu tiên, trạng thái tác
vụ tức là nếu tác vụ đang ở (nhàn rỗi, đang chạy, sẵn sàng , đã kết thúc) trạng
thái, v.v.
Lập lịch tác vụ: Nó ghi lại trạng thái của từng tác vụ và xác định tác vụ có
mức độ ưu tiên cao nhất sẽ được thực thi. Tác vụ đang chạy bị tạm ngừng và bộ
xử lý thực hiện tác vụ ưu tiên cao.
Đồng bộ hóa tác vụ: Nó là cần thiết để thông tin được truyền một cách an
toàn từ Nhiệm vụ hoặc Chủ đề này sang Nhiệm vụ khác. Đồng bộ hóa tác vụ
cho phép các tác vụ chia sẻ lẫn nhau các tài nguyên như bộ đệm , thiết bị I / O,
v.v.
Quản lý bộ nhớ: Nó phân bổ bộ nhớ cho mỗi chương trình. Có hai loại
Quản lý Bộ nhớ cho RTOS. Họ đang: quản lý ngăn xếp hoặc quản lý đống.
Quản lý thời gian: Để lên lịch cho các tác vụ cần được thực hiện trong
khoảng thời gian xác định, cần có ngắt định kỳ. Do đó phần cứng Timer được
lập trình để ngắt bộ xử lý. Ngắt thời gian được gọi là System Tick .
Xử lý ngắt: CPU được thông báo về bất kỳ sự kiện không đồng bộ nào
thông qua một ngắt . Nó là một cơ chế phần cứng xử lý một sự kiện bằng cách
cung cấp các chức năng như xác định Trình xử lý ngắt, tạo và xóa quy trình dịch
vụ ngắt, v.v.

11
Quản lý I / O thiết bị: Quản lý I / O thiết bị giúp cung cấp khung thống
nhất (API - Giao diện lập trình viên ứng dụng). Nó cũng giúp truy cập trình điều
khiển thiết bị phần cứng cụ thể, tức là nó định vị thiết bị phù hợp cho yêu cầu I /
O.

2.2. Giới thiệu các thiết bị phần cứng sử dụng.


2.2.1. Kit Arduino UNO R3.
Nhắc tới lập trình hay nghiên cứu chế tạo bằng Arduino, dòng đầu tiên mà
mọi người thường tìm hiểu là Arduino Uno và hiện tại đã phát triển đến thế hệ
thứ 3 ( R3 ). Nếu mà người mới tìm hiểu bạn nên nghiên cứu Arduino Uno R3
hơn là tiếp cận những dòng Arduino khác vì dòng Arduino Uno R3 rất dễ sử
dụng đối với những người mới tiếp cận về lập trình .

Hình 2. 2: Board Arduino Uno


Arduino Uno là một bo mạch thiết kế với bộ xử lí trung tâm là vi điều
khiển AVR Atmega 328. Cấu tạo chính bao gồm các thành phần sau:

12
- Cổng USB: đây là loại cổng giao tiếp để ta upload code từ PC lên vi
điều khiển. Đồng thời nó cũng là giao tiếp serial để truyền dữ liệu giữa vi điều
khiển và máy tính.
- Jack nguồn: để chạy Arduino thỉ có thể lấy nguồn từ cổng USB ở trên,
nhưng không phải lúc nào cũng có thể cắm với máy tính được . Lúc đó ta cần
một nguồn từ 9V đến 12V.
- Có 14 chân vào/ra số đánh số thứ tự từ 0 đến 13, ngoài ra có một chân
nối đất (GND) và một chân điện áp tham chiếu (AREF).
- Vi điều khiển AVR: đây là bộ xử lí trung tâm của toàn bo mạch. Với
mỗi mẫu Arduino khác nhau thì con chip là khác nhau. Ở con Arduino Uno này
thì sử dụng ATMega328.
THÔNG SỐ KỸ THUẬT

- Vi xử lý: Atmega328
- Điện áp hoạt động: 5V
- Điện áp đầu vào: 7-12V
- Điện áp đầu vào (Giới hạn): 6-20V
- Chân vào/ra (I/O) số: 14 ( 6 chân có thể cho đầu ra PWM)
- Chân vào tương tự: 6
- Dòng điện trong mỗi chân I/O: 40mA
- Dòng điện chân nguồn 3.3V: 50mA
- Bộ nhớ trong: 32 KB (ATmega328)
- SRAM: 2 KB (ATmega328)
- EEPROM: 1 KB (ATmega328)
- Xung nhịp: 16MHz

 Vi điều khiển của Arduino Uno

13
Hình 2. 3: Vi điều khiển của Arduino Uno
Arduino UNO có thể sử dụng 3 vi điều khiển họ 8bit AVR là ATmega8 ,
ATmega168 , ATmega328 . Bộ não này có thể xử lý những tác vụ đơn giản như
điều khiển đèn LED nhấp nháy , xử lý tín hiệu cho xe điều khiển từ xa , làm một
trạm đo nhiệt độ - độ ẩm và hiển thị lên màn hình LCD , ..
Thiết kế tiêu chuẩn của Arduino UNO sử dụng vi điều khiển ATmega328
với giá khoảng 90.000đ . Tuy nhiên nếu yêu cầu phần cứng của bạn không cao
hoặc túi tiền không cho phép , bạn có thể sử dụng các loại vi điều khiển khác có
chức năng tương đương nhưng rẻ hơn như ATmega8 ( bộ nhớ flash 8KB ) với
giá khoảng 45.000đ hoặc ATmega168 ( bộ nhớ flash 16KB ) với giá khoảng
65.000đ
 Điện áp
Arduino UNO có thể được cấp nguồn 5V thông qua cổng USB hoặc cấp
nguồn ngoài với điện áp khuyên dùng là 7-12V DC và giới hạn là 6-20v,
Thường thi cấp nguồn bằng pin vuông 9V là hợp lí nhất nếu bạn không có sẵn
nguồn từ cổng USB . Nếu cấp nguồn vượt quá ngưỡng giới hạn trên, bạn sẽ làm
hỏng Arduino UNO.
 Các chân năng lượng

14
- GND ( Ground ) : cực âm của nguồn điện cấp cho Arduino UNO Khi bạn
dùng các thiết bị sử dụng những nguồn điện riêng biệt thì những chân này
phải được nối với nhau .
- 5V ; cấp điện áp 5V đầu ra . Dòng tối đa cho phép ở chân này là 500mA .
- 3.3V : cấp điện áp 3.3V đầu ra . Dòng tối đa cho phép ở chân này là
50mA .
- Vin ( Voltage Input ) : để cấp nguồn ngoài cho Arduino UNO , bạn nối
cực dương của nguồn với chân này và cực âm của nguồn với chân GND .
- IOREF : điện áp hoạt động của vi điều khiển trên Arduino UNO có thể
được đo ở chân này . Và dĩ nhiên nó luôn là 5V . Mặc dù vậy bạn không
được lấy nguồn 5V từ chân này để sử dụng bởi chức năng của nó không
phải là cấp nguồn .
- RESET : việc nhấn nút Reset trên board để reset vi điều khiển tương
đương với việc chân RESET được nối với GND qua 1 điện trở 10K .

 Bộ nhớ
Vi điều khiển Atmega328 tiêu chuẩn cung cấp cho người dùng :
32KB bộ nhớ Flash ; những đoạn lệnh bạn lập trình sẽ được lưu trữ trong
bộ Flash của vi điều khiển . Thưởng thì sẽ có khoảng vài KB trong số này sẽ
được dùng cho bootloader nhưng đừng lo , bạn hiếm khi nào cần quả 20KB bộ
nhở này đâu .
2KB cho SRAM ( Stats Random Access Memory ) : giá trị các biến bạn
khai báo khi lập trình sẽ lưu ở đây . Bạn khai bảo càng nhiều biến thì càng cần
nhiều bộ nhớ RAM . Tuy vậy , thực sự thì cũng hiếm khi nào bộ nhớ RAM lại
trở thành thứ mà bạn phải bận tâm . Khi mất điện , dữ liệu trên SRAM sẽ bị
mất .
1KB cho EEPROM ( Electrically Eraseble Programmable Read Only
Memory ) : dây giống như một chiếc ổ cứng mini – nơi bạn có thể đọc và ghi dữ

15
liệu của mình vào đây mà không phải lo bị mất khi cúp điện giống như dữ liệu
trên SRAM .
 Cổng vào ra

Hình 2. 4: Các chân trên Arduino Uno R3


Arduino UNO có 14 chân digital dùng để đọc hoặc xuất tín hiệu . Chúng
chỉ có 2 mức điện áp là 0V và 5V với dòng vào ra tối đa trên mỗi chân là
40mA . Ở mỗi chân đều có các điện trở pull - up từ được cài đặt ngay trong vi
điều khiển ATmega328 ( mặc định thì các điện trở này không được kết nối ) .
Một số chân digital có các chức năng đặc biệt như sau :
- 2 chấn Serial : 0 ( RX ) và 1 ( TX ): dùng để gửi ( transmit - TX )
và nhận ( receive - RX ) dữ liệu TTL Serial. Arduino Uno có thể
giao tiếp với thiết bị khác thông qua 2 chân này. Kết nối
bluetooth thường thấy nói nôm na chính là kết nối Serial không
dây . Nếu không cần giao tiếp Serial , bạn không nên sử dụng 2
chân này nếu không cần thiết.

16
- Chân PWM ( - ) 3 , 5 , 6 , 9 , 10 , và 1l : cho phép bạn xuất ra
xung PWM với độ phân giải 8bit ( giá trị từ 0 – 28-1 tương ứng
với 0V – 5V ) bằng hàm analogWrite ( ) . Nói một cách đơn giản ,
bạn có thể điều chỉnh được điện áp ra ở chân này từ mức 0V đến
5V thay vì chỉ cố định ở mức 0V và 5V như những chân khác .
- Chân giao tiếp SPI : 10 ( SS ) , 11 ( MOSI ) , 12 ( MISO ) 13
( SGK ) . Ngoài các chức năng thông thường , 4 chân này còn
dùng để truyền phát dữ liệu bằng giao thức SPI với các thiết bị
khác ,
- LED 13 trên Arduino UNO có 1 đèn led màu cam ( kí hiệu chữ
L ) . Khi bấm nút Reset , bạn sẽ thấy đèn này nhấp nháy để bảo
hiệu . Nó được nối với chân số 13. Khi chân này được người
dùng sử dụng , LED sẽ sảng .
- Arduino UNO có 6 chân analog ( A0 A5 ) cung cấp độ phân giải
tín hiệu 10bit ( 0 – 210-1 ) để đọc giá trị điện áp trong khoảng 0v
- 5v . Với chân AREF trên board , bạn có thể để đưa vào điện áp
tham chiếu khi sử dụng các chân analog . Tức là nếu bạn cấp điện
áp 2.5V vào chân này thì bạn có thể dùng các chân analog để đo
điện áp trong khoảng từ 0V – 2.5V với độ phân giải vẫn là 10bit .
- Đặc biệt , Arduino UNO có 2 chân A4 ( SDA ) và A5 ( SCL ) hỗ
trợ giao tiếp I2C / TWI với các thiết bị khác.
 Ngắt trong Arduino
Ngắt (interrupt) là quá trình dừng chương trình chính đang chạy để ưu
tiên thực hiện một chương trình khác, chương trình này được gọi là chương trình
phục vụ ngắt (ISR – Interrupt Service Routine). Sau khi thực hiện xong chương
trình phục vụ ngắt thì vi điều khiển quay lại thực hiện tiếp công việc trước đó.
Trong các quá trình ngắt, ta phân biệt thành 2 loại: ngắt cứng và ngắt mềm. Ngắt
mềm là ngắt được gọi bằng một lệnh trong chương trình ngôn ngữ máy. Khác

17
với ngắt mềm, ngắt cứng không được khởi động bên trong máy tính mà do các
linh kiện điện tử tác đông lên hệ thống.
Đối với Arduino, ngắt Timer chủ yếu được dùng để định các khoảng thời
gian nhất định, xuất xung tần số tùy chỉnh ra chân đầu ra số hay định thời gian
kiểm tra dự liệu truyền nối tiếp. Tùy theo Board Arduino mà số lượng Timer
cũng khác nhau
Arduino UNO có 3 Timer, Timer 0, 1 và 2. Các timer này sẽ tăng giá trị
của nó dựa vào xung nhịp của Arduino. Khi bạn đặt giá trị ngắt, Timer sẽ tăng
dần giá trị khi xảy ra xung nhịp và so sánh với giá trị đặt trước, khi bằng nhau
nó sẽ xảy ra một ngắt.
Timer 0, 2 là 2 timer 8 bit, hay nói cách khác nó chỉ có thể đếm từ 0 đến
255 và với Timer1 là timer 16 bit, nó có thể đếm từ 0 đến 65535 mà thôi.
Arduino UNO có xung nhịp là 16MHz, tương đương 1/16000000s, 63ns. Nếu
các Timer đếm các xung nhịp này thì với Timer 0,2 chỉ có thể đếm
256*63ns 16us và với Timer 1 là 4 ms.

18
2.2.2. Module thời gian thực Module Tiny RTC I2C.
Module Thời Gian Thực Tiny RTC I2C là IC thời gian thực giá rẻ, rất
chính xác với thạch anh tích hợp sẵn có khả năng điều chỉnh nhiệt. Sử dụng
chuẩn giao tiếp I2C giúp giao tiếp dễ dang với các dòng vi điều khiển hiện có.
Module có đầu vào cho pin riêng, tách biệt khỏi nguồn chính đảm bảo cho việc
giữ thời gian chính xác. Thạch anh tích hợp sẵn giúp tăng độ chính xác trong
thời gian dài hoạt động và giảm số lượng linh kiện cần thiết khi làm board.
Thời gian trong Module được giữ ở dạng: giờ, phút, giây, ngày, thứ,
tháng, năm. Các tháng có ít hơn 31 ngày sẽ tự động được điều chỉnh, các năm
Nhuận cũng được chỉnh đúng số ngày. Thời gian có thể hoạt động ở chế độ 24h
hoặc 12h AmPM.

Hình 2. 5: Module Tiny RTC I2C (không PIN)


THÔNG SỐ KỸ THUẬT
- Điện áp làm việc: 3.3V đến 5V
- IC RTC:  DS1307
- IC EEPROM:  AT24C32
- Có sẵn chân hàn cảm biến nhiệt độ DS18B20
- Có sẵn điện trở pull-up cho giao tiếp I2C

19
- Pin CMOS 2032/2025
- Kích thước : 27x28x8.4mm

2.2.3. Module LED P10.


Màn hình LED P10 là loại màn hình được cấu tạo từ các module LED có
khoảng cách giữa các điểm ảnh là 10mm, độ phân giải cao, đem lại khả năng
hiển thị thông tin, hình ảnh, video chân thực, rõ nét. Module led ma trận P10
Full color 32×16 gồm 32 led hàng ngang và 16 led hàng dọc, bản thân mỗi led
bên trong có 3 led với 3 màu RGB, mỗi pixel cách nhau 1cm. Tổng số led RGB
là 32×16=512 LED RGB

Hình 2. 6: Màn hình LED P10

20
Chức năng của các chân
R1: Chân data cho màu đỏ của 8 hàng led bên trên
R2: Chân data cho màu đỏ của 8 hàng led phía dưới
G1: Chân data cho màu xanh lá của 8 hàng led bên trên
G2: Chân data cho màu xanh lá của 8 hàng led phía dưới
B1: Chân data cho màu xanh dương của 8 hàng led bên trên
B2: Chân data cho màu xanh dương của 8 hàng led phía dưới
CLK: Chân đẩy data vào ic ghi dịch
LAT: Chân chốt data ( đẩy data lưu trong ic ghi dịch ra ngoài led)
OE: Chân cho phép bảng led sáng ( OE=0 thì bảng led được phép sáng, OE=1
thì bảng led auto tắt)
A,B,C: 3 chân của ic vào 3 ra 8, tức 3 chân dùng để quét led, cho phép hàng nào
sáng. Với 3 chân ABC ta điều khiển đc 8 hàng độc lập, nhưng module P10 có
tới 16 hàng => trong 1 thời điểm có 2 hàng cùng sáng => module này quét kiểu
2/16 = 1/8
=> Trong 1 thời điểm số led RGB ta có thể điều khiển là 512 x 1/8 = 64 LED
RGB
Chiều đi của data

Với P10 1 màu, data đi theo chiều zigzac, thì P10 FULL, data đi theo đường
thẳng

Hình 2. 7: Chiều đi của data LED

Các bạn có thể thấy, module này chia ra làm 2 nửa theo chiều ngang, với dữ liệu
của 8 hàng trên do RGB1 quyết định, còn 8 hàng dưới do RGB2 quyết định.
Chân ABC sẽ quyết định hàng nào trong 8 hàng của cả 2 nửa được sáng.

21
T
rong 1 thời điểm sẽ có 2 hàng được phép sáng ( do ABC quyết định)

2.2.4. Module cảm biến âm thanh


Micro loại điện dung ( condenser ) micro dạng tụ, màng của chúng hoạt
động như một cái mảng tụ điện và khi các âm thanh tác động lên màng thu sẽ
tạo nên các rung động, màng rung sẽ chuyển hóa các rung động âm thanh đấy
thành các tín hiệu âm thanh. Loại micro này có độ nhạy rất cao và bắt âm thanh
chính xác, thích hợp cho thu các dạng tín hiệu mềm như giọng hát, guitar
thùng…

22
Hình 2. 8: Module cảm biến âm thanh
THÔNG SỐ KỸ THUẬT
- Microphone có dải tần từ 50Hz – 13kHz
- Đầu ra là dạng sóng tương tự có thể điều chỉnh được
- Điện áp hoạt động: 5V 1x3
- Header: OUT = đầu ra tương tự, kết nối với đầu vào tương tự trên
MCU VCC = 4~12VDC (5V thông thường) GND = đất
- Kích thước: 36mm x 20mm
ỨNG DỤNG
- Sử dụng chip xử lý âm thanh chất lượng cao
- Có thể điều chỉnh biên độ của tín hiệu âm thanh đầu ra để phát
hiện kích thước của âm thanh
- Hệ thống dây nối đất một điểm được sử dụng để giảm, tăng vòng
lặp và cải thiện chất lượng tín hiệu âm thanh

23
- Giao diện Arduino tiêu chuẩn, có thể kết nối trực tiếp với Arduino
- Độ nhạy tốt, mạch khuếch đại tích hợp, có thể điều chỉnh, tín hiệu
điện áp cường độ âm thanh có thể thu được thông qua chuyển đổi
AD

24
CHƯƠNG III: THIẾT KẾ VÀ THI CÔNG SẢN PHẨM.
3.1. Thiết kế và thi công phần cứng.
Kết nối Arduino và các thiết bị.

Arduino và Module RTC Arduino và cảm biến âm thanh


Arduino UNO Module RTC Arduino UNO Cảm biến âm thanh
GND GND GND GND
5V VCC 5V VCC
A5/SLC SLC A3 A0
A4/SDA SDA
Arduino và LED P10
Arduino LED P10 Arduino LED P10
GND GND 10 CLK
4 R1 11 OE
5 G1 12 STB
6 B1 A A0
7 R2 B A1
8 G2 C A2
9 B2
Arduino và Nút nhấn
Arduino 5V GND OUT
Nút nhấn VCC GND 2
Sơ đồ kết nối các thiết bị mô phỏng trên proteus:

25
Hình 3. 1: Mô phỏng mạch trên proteus
Trong thực tế chúng em sử dụng cáp 7 màu đề kết nối các module vời
nhau. Việc này giúp các module thiết bị kết nối với nhau ổn định, dễ dàng trong
việc nâng cấp và sửa chữa thiết bị.
Sơ đồ kết nối các thiết bị thực tế:

26
Hình 3. 2: Thiết kế và thi công vỏ hộp để chứa và bảo vệ các thiết bị

3.2. Thiết kế và thi công phần mềm.


3.2.1. Chương trình hiển thị lên LED P10.
Hiển thị thông tin lên led ma trận nói chung và led p10 nói riêng thường
sử dụng phương pháp quét led.
Thuật toán quét LED:

Hình 3. 3: Thuật toán quét LED


Với các phương pháp lập trình thông thường khi thực hiện thuật toán quét
LED sẽ xuất hiện hiện tượng LED ma trận bị đứng hình do mất thòi gian xử lý

27
chương trình khác gây khó chịu cho người sử dụng và ảnh hưởng đến chất lượng
hiển thị. Khắc phục tình trạng đó chúng em đã sử dụng phương pháp ngắt timer
đề thực hiện thuật toán quét led. Nó giống như 1 module tự động quét led và làm
công việc hiển thị ra màn hình.
Tuy nhiên giữa chương trình và hàm ngắt phải có 1 mối liên hệ nhất định
để hàm main muốn hiển thị gì thì ngắt phải nghe theo. Do vậy phương pháp này
cần tới 1 Buffer( bộ đệm hiển thị) – nó là 1 mảng dữ liệu chứa dữ liệu cần hiển
thị. Khi hàm main muốn hiển thị gì thì chỉ cần ghi dữ liệu vào bộ đệm. Còn hàm
ngắt sẽ tự động lấy dữ liệu trong bộ đệm ra để hiển thị 1 cách định kì và tự động.

Hình 3. 4: Phương pháp ngắt timer thực hiện thuật toán quét led
Đồi với LED P10 (32X16) tương đương với 512 LED đồng nghĩa với việc
cần 512 bit để quản lý ma trận LED. Mà mỗi LED là sự kết hợp của 3 màu RGB
nên cần thêm một chiều để quản lý màu.
Khai bảo một mảng 3 chiều: char Buffer_display[3][16][4] để quản lý
ma trận LED và làm bộ đệm cho chương trình ngắt Timer.
Xấy dựng chương trình ngắt quét LED dựa trên bộ Timer1 của Arduino.
Để không gây ảnh hưởng đến mắt và não bộ thì tối thiểu là 24-30fps. Ở đây
chúng em sử dụng quét với 33 khung hình trên 1 giây. Đối với Led P10 cứ 8 lần
quét sẽ hoàn thành một khung hình (mối lần ngắt chỉ có thể sáng 1 hàng). Thời
gian cho mỗi lần ngắt là: 1 / (8 x 33) = 0.0037s.
Giá trị nạp vào thanh ghi TCNT1 = 2^16 – 0.0037*(16 *10^6)/256.

28
3.2.2. Thiết kế chương trình chính.
Lưu đồ thuật toán của chương trình chính.

Hình 3. 5: Lưu đồ thuật toán của chương trình chính


Chương trình chính được chia làm hai tác vụ. Tác vụ “taskRealTime” có
chức năng đọc và hiển thị các thông số về thời gian giờ, phút, giây. Tác vụ
“animation” có chức năng hiển thị các hiệu ứng chuyển động và nháy theo điệu
nhạc. Các tác vụ giao tiếp với nhau qua hàng đợi “mode” và được điều khiển
bằng chương trình điều khiển ở mục 3.2.3.
Lưu đồ thuật toán tác vụ taskRealTime:

29
Hình 3. 6: Lưu đồ thuật toán tác vụ taskRealTime
Lưu đồ thuật toán tác vụ “animation”:

30
Hình 3. 7: Lưu đồ thuật toán tác vụ “animation”
3.2.3. Chương trình điều khiển sản phẩm.
Sơ đồ điều khiển sản phẩm

Hình 3. 8: Sơ đồ điều khiển sản phẩm

31
Chương trình điều khiển nhận dữ liệu trực tiếp từ người dùng thông qua nút
nhấn. Để quá trình tương tác này điễn ra và đáp ứng thời gian thực chúng em sử
dụng tính năng ngắt cứng trên arduino uno.
Lưu đồ thuật toán chương trình điều khiển:

Hình 3. 9: Lưu đồ thuật toán chương trình điều khiển

32
CHƯƠNG IV: TỔNG KẾT
4.1. Nhận xét, đánh giá
Sản phẩm hoạt động ổn định, đạt yêu cầu đã đặt ra, tuy nhiên vẫn còn một
số hạn chế như sau:
- Chưa điều chỉnh được ngày, tháng, năm.
- Sản phẩm chưa có tính thẩm mỹ cao.

4.2. Hướng phát triển


- Có thêm hiển thị nhiệt độ và độ ẩm.
- Tích hợp thêm nhiều hiệu ứng có thể chuyển mode qua nút nhấn,
không dây smartphone hoặc PC thông qua các chuẩn không dây
(bluetooth, wifi, NFC,...)
- Đọc tín hiệu âm thanh qua cổng usb của pc.
- Tích hợp phát nhạc trực tiếp từ SD Card hoặc USB có thêm các
chức năng như máy nghe nhạc
- Bổ sung thêm cột led để nháy theo 2 mức âm thanh trái phải riêng
biệt.
- Thiết kế mô hình với kích thước nhỏ gọn, kiểu dáng đẹp hơn.

4.3. Kết luận


Trong suốt quá trình thực hiện đề tài này, với nhiều cố gắng và nỗ lực của
chúng em cùng với sự hướng dẫn, chỉ bảo tận tình của cô Lê Thị Hồng Vân
chúng em đã hoàn thành đề tài này. Tuy nhiên cũng còn một số hạn chế trong
khâu thiết kế. Đây là một hành trang quý báu cho những sinh viên bước vào
cuộc sống nghề nghiệp sau này.
Mặc dù đã có nhiều cố gắng, song do hạn chế về mặt thời gian và khả
năng nên không thể tránh khỏi có những sai sót. Rất mong nhận được sự đóng
góp ý kiến của các thầy và các bạn để chúng em hoàn chỉnh hơn.

33
TÀI LIỆU THAM KHẢO
Trong báo cáo này, chúng em đã sử dụng các tài liệu tham khảo:
[1]. “Giáo Trình Vi Điều Khiển” Của GV Phạm Hùng Kim Khánh
[2]. Từ các trang web: www.dientuvietnam.net, codientu.org
[3]. Vi điều khiển với lập trình C_Ngô Diên Tập
Trang Web tham khảo
http://arduino.vn/bai-viet/369-giao-tiep-i2c-va-su-dung-module-realtime-
clock-ds1307

34
PHỤ LỤC
#include
<avr/inte
rrupt.h>
#include <Arduino_FreeRTOS.h>
#include <queue.h>
#include <Wire.h>
#include <stdlib.h>
#define R1 4
#define G1 5
#define B1 6
#define R2 7
#define G2 8
#define B2 9
#define CLK 10
#define OE 11
#define STB 12
#define A A0
#define B A1
#define C A2
#define M A3
unsigned char Buffer_display[3][16][4];
TaskHandle_t animationHandle = NULL;
TaskHandle_t danceOfMusicHandle = NULL;
TaskHandle_t realTimeHandle = NULL;
char col[32];
int wday, day, month, year;
char color_row[4] = {0x01, 0x03, 0x06, 0x02};
const char font [][7] ={
0x38,0x44,0x4C,0x54,0x64,0x44,0x38, //0 48
0x10,0x30,0x10,0x10,0x10,0x10,0x38, //1 49
0x38,0x44,0x04,0x18,0x20,0x40,0x7C, //2 50
0x38,0x44,0x04,0x38,0x04,0x44,0x38, //3 51
0x08,0x18,0x28,0x48,0x7C,0x08,0x08, //4 52
0x7C,0x40,0x40,0x78,0x04,0x44,0x38, //5 53
0x18,0x20,0x40,0x78,0x44,0x44,0x38, //6 54
0x7C,0x04,0x08,0x10,0x20,0x20,0x20, //7 55
0x38,0x44,0x44,0x38,0x44,0x44,0x38, //8 56
0x38,0x44,0x44,0x3C,0x04,0x08,0x30, //9 57
0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
const char dayOfTheWeek[7][3][7]= {
35
0x38,0x44,0x40,0x38,0x04,0x44,0x38,0x00,0x00,0x48,0x48,0x4
8,0x58,0x28,0x00,0x00,0x68,0x54,0x54,0x44,0x44,// Su
0x44,0x6C,0x54,0x44,0x44,0x44,0x44,0x00,0x00,0x38,0x44,0x4
4,0x44,0x38,0x00,0x00,0x70,0x48,0x48,0x48,0x48,// Mo
0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x48,0x48,0x4
8,0x58,0x28,0x00,0x00,0x38,0x40,0x38,0x04,0x38,// Tu
0x44,0x44,0x54,0x54,0x54,0x54,0x28,0x00,0x00,0x38,0x44,0x7
8,0x40,0x38,0x00,0x00,0x70,0x48,0x48,0x48,0x48,// We
0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x40,0x40,0x70,0x48,0x4
8,0x48,0x48,0x00,0x00,0x48,0x48,0x48,0x58,0x28,// Th
0x7C,0x40,0x40,0x78,0x40,0x40,0x40,0x00,0x00,0x58,0x24,0x2
0,0x20,0x70,0x10,0x00,0x10,0x10,0x10,0x10,0x18,// Fr
0x38,0x44,0x40,0x38,0x04,0x44,0x38,0x00,0x00,0x38,0x04,0x3
C,0x44,0x3C,0x00,0x20,0x78,0x20,0x20,0x28,0x10,// Sa
};
const char miniFont [][3] = {
0xf8, 0x88, 0xf8,// 0
0x40, 0xf8, 0x00,// 1
0xb8, 0xa8, 0xe8,// 2
0xa8, 0xa8, 0xf8,// 3
0xe0, 0x20, 0xf8,// 4
0xe8, 0xa8, 0xb8,// 5
0xf8, 0xa8, 0xb8,// 6
0x80, 0x80, 0xf8,// 7
0xf8, 0xa8, 0xf8,// 8
0xe8, 0xa8, 0xf8 // 9
};
QueueHandle_t mode = NULL;
ISR (TIMER1_OVF_vect) //Chương trình ngắt Timer1
{
static unsigned char z = 0;// biến đếm hàng;
unsigned char i;
digitalWrite (OE, HIGH); // tắt hết LED
for (i = 0; i < 4; i++){
data_transfet (Buffer_display[0][z][i], Buffer_display[1][z][i],
Buffer_display[2][z][i], Buffer_display[0][z+8][i],
Buffer_display[1][z+8][i], Buffer_display[2][z+8]
[i]);
}
rows(z);
digitalWrite (STB, LOW); digitalWrite (STB, HIGH);
digitalWrite (OE, LOW);// bật LED
z++;
36
if (z == 8) z = 0;
delay(1);
TCNT1= 65300;
}
void setup() {
Serial.begin (9600);
Wire.begin();
pinMode (G1, OUTPUT);// cài đặt chế độ hoạt động của các
chân
pinMode (R1, OUTPUT);
pinMode (B1, OUTPUT);
pinMode (R2, OUTPUT);
pinMode (G2, OUTPUT);
pinMode (B2, OUTPUT);
pinMode (A, OUTPUT);
pinMode (B, OUTPUT);
pinMode (C, OUTPUT);
pinMode (CLK, OUTPUT);
pinMode (OE, OUTPUT);
pinMode (STB, OUTPUT);
pinMode (M, INPUT);
pinMode (2, INPUT_PULLUP);
pinMode (3, INPUT_PULLUP);
mode = xQueueCreate (1, sizeof (int));
int status = 0;
xQueueSend(mode, &status, 0);
attachInterrupt(digitalPinToInterrupt(3),changeOnMode ,
RISING);
//attachInterrupt(digitalPinToInterrupt(2),changeMode ,
RISING);
getDate();
cli(); //Tắt ngắt toàn cục
TCCR1A = 0; //Reset Timer1
TCCR1B = 0;
TIMSK1 = 0;
TCCR1B |= (1 << CS11);
TCNT1= 65500;
TIMSK1 |= (1 << TOIE1);
sei();
//xTaskCreate (taskDanceMusic,"1", 128, NULL, 2,
&danceOfMusicHandle);
xTaskCreate (taskRealTime,"2", 128, NULL, 2, &
realTimeHandle);
37
xTaskCreate (animation,"3", 128, NULL, 2, &
animationHandle);
}

void loop(){}

void changeOnMode () {
static int moe = 0 ;
moe = (++ moe)%3;
xQueueOverwriteFromISR (mode, &moe, 0);
vTaskResume(realTimeHandle);
}
void animation (void *pv){
int x, y = 0,b;
while (1){
xQueuePeek(mode, &b,0);
if (b == 1) {
for (x = 0 ; x < 16; x++){
draw_icon(x * 4,0,(y+x) % 3 +1 );
draw_icon1(32 - x * 4,15,(y+x) % 3 +1);
}
y++;
delay(100);
}else if (b == 0 ){
for (y = 0; y <7; y++){
for (x = 0 ; x < 5; x++) {
if ((dayOfTheWeek[wday-1][0][y] & (0x40 >> x) ) !=
0) set_pixel (x + 0, y +9, 0x05);
else set_pixel (x + 0, y +9 ,0x00);
}
}
vTaskDelay(20);
for (y = 0; y <7; y++){
for (x = 0 ; x < 5; x++) {
if ((dayOfTheWeek[wday-1][1][y] & (0x40 >> x) ) !=
0) set_pixel (x + 5, y +9, 0x05);
else set_pixel (x + 5, y +9 ,0x00);
}
}
vTaskDelay(20);
for (y = 0; y <7; y++){
38
for (x = 0 ; x < 5; x++) {
if ((dayOfTheWeek[wday - 1][2][y] & (0x40 >> x) ) !=
0) set_pixel (x + 10, y +9, 0x05);
else set_pixel (x + 10, y +9,0x00);
}
}
vTaskDelay(20);
put_mini_number (16,11,day/10,0x04);
put_mini_number (20,11,day%10,0x04);
vTaskDelay(20);
put_mini_number (25,11,month/10,0x07);
put_mini_number (29,11,month%10,0x07);
delay (5000);
for (x =31; x >=0; x -- ){
for ( y =9; y < 16;y++){
set_pixel(x,y,0x00);
}
vTaskDelay(5);
}
put_char (4,9,2,0x03);
vTaskDelay(20);
put_char (10,9,0,0x03);
vTaskDelay(20);
put_char (16,9,year /10,0x03);
vTaskDelay(20);
put_char (22,9,year %10,0x03);
delay (5000);
for (x =31; x >=0; x -- ){
for ( y =8; y < 16;y++){
set_pixel(x,y,0x00);
}
vTaskDelay(5);
}
}else{
for (x =0; x<31;x++){
y = analogRead(M);
if (y > 507) y = y -508;
else y = 506- y;
drawRow (x,y/3);
}
}
}
}
39
void taskRealTime (void *pv){
int nowStatus, nextStatus;
xQueuePeek(mode,&nowStatus, 0);
while (1){
xQueuePeek(mode,&nextStatus, 0);
if (nowStatus != nextStatus) {
nowStatus = nextStatus;
vTaskDelete(animationHandle);
clear_display();
xTaskCreate (animation,"3", 128, NULL, 2, &
animationHandle);
}
if (nowStatus == 0){
getTime();
}else if (nowStatus == 1) {
getTime1();
}else {
vTaskSuspend(realTimeHandle);
}
}
}
void taskDanceMusic (void *pv){
int i, sensor, sensor2;
while (1){
for (i =1; i<31;i++){
sensor = analogRead(M);
if (sensor > 507) sensor = sensor -508;
else sensor = 506- sensor;
drawRow (i,sensor/3);
}
}
}
void data_transfet (char byte_r1, char byte_g1, char byte_b1, char
byte_r2, char byte_g2, char byte_b2 ){ // chyển dữ liệu vào màn
hình
unsigned char i, mask;
for (i = 0; i < 8; i++){
mask = 0x80 >> i;
digitalWrite (R1, byte_r1 & mask);
digitalWrite (G1, byte_g1 & mask);
digitalWrite (B1, byte_b1 & mask);
digitalWrite (R2, byte_r2 & mask);
digitalWrite (G2, byte_g2 & mask);
40
digitalWrite (B2, byte_b2 & mask);
digitalWrite (CLK, LOW); digitalWrite (CLK, HIGH); // tạo
xung clk cho phép chuyển dữ liệu
}
}
void rows (unsigned char row_number){ // chọn hàng được sáng
switch (row_number){
case 0:{ digitalWrite(A, LOW);digitalWrite (B, LOW);
digitalWrite (C, LOW);break;}
case 1:{ digitalWrite(A, HIGH);digitalWrite (B, LOW);
digitalWrite (C, LOW);break;}
case 2:{ digitalWrite(A, LOW);digitalWrite (B, HIGH);
digitalWrite (C, LOW);break;}
case 3:{ digitalWrite(A, HIGH);digitalWrite (B, HIGH);
digitalWrite (C, LOW);break;}
case 4:{ digitalWrite(A, LOW);digitalWrite (B, LOW);
digitalWrite (C, HIGH);break;}
case 5:{ digitalWrite(A, HIGH);digitalWrite (B, LOW);
digitalWrite (C, HIGH);break;}
case 6:{ digitalWrite(A, LOW);digitalWrite (B, HIGH);
digitalWrite (C, HIGH);break;}
case 7:{ digitalWrite(A, HIGH);digitalWrite (B, HIGH);
digitalWrite (C, HIGH);break;}
}
}
void set_pixel (unsigned char x, unsigned char y, unsigned char
color) {
if (x >31 || x <0 || y >15|| y <0) return;
if ((color & 0x01) != 0) Buffer_display [0][y][x/8] =
Buffer_display[0][y][x/8] | (0x80 >> (x %8));
else Buffer_display[0][y][x/8] = Buffer_display[0][y][x/8] &
(~(0x80 >> (x %8)));

if ((color & 0x02) != 0) Buffer_display [1][y][x/8] =


Buffer_display[1][y][x/8] | (0x80 >> (x %8));
else Buffer_display[1][y][x/8] =Buffer_display[1][y][x/8] &
(~(0x80 >> (x %8)));

if ((color & 0x04) != 0) Buffer_display [2][y][x/8] =


Buffer_display[2][y][x/8] | (0x80 >> (x %8));
else Buffer_display[2][y][x/8] =Buffer_display[2][y][x/8] &
(~(0x80 >> (x %8)));
}
41
void put_char (int i, int j, char txt, char color){
char x =0, y=0, z = txt;
for (y = 0; y <7; y++){
for (x = 0 ; x < 5; x++) {
if ((font[txt][y] & (0x40 >> x) ) != 0) set_pixel (x + i, y +j,
color);
else set_pixel (x + i, y +j ,0x00);
}
}
}
void drawRow(int x,int height){
int i;
if (height > 14) height = 14;
height = 15 - height;
for (i = 14; i > height +1; i--) set_pixel(x,i,0x02);
if (i <= 14){
set_pixel (x,i,0x03);
i--;
}
if (i < 13) {
set_pixel (x,i, 0x01);
i--;
}
for (; i >= 0;i--) set_pixel(x,i,0x00);
col[x] = height;
}
int bcd2dec(byte num){
return ((num/16 * 10) + (num % 16));
}
int dec2bcd(byte num){
return ((num/10 * 16) + (num % 10));
}
void getDate(){
Wire.beginTransmission(0x68);
Wire.write ((byte)0x00);
Wire.endTransmission ();
Wire.requestFrom (0x68, 7);
day = Wire.read();
day = Wire.read();
day = Wire.read();
wday = bcd2dec (Wire.read());
day = bcd2dec (Wire.read());
month = bcd2dec (Wire.read());
42
year = bcd2dec (Wire.read());
}
void getTime(){
Wire.beginTransmission(0x68);
Wire.write ((byte)0x00);
Wire.endTransmission ();
Wire.requestFrom (0x68, 7);
int x;
x = bcd2dec (Wire.read() & 0x7f);
put_mini_number(24,3,x/10,0x03);
put_mini_number(28,3,x%10,0x03);
if (x %2 == 0){
draw_point(11,2,0x01);
draw_point(11,5,0x01);
}else {
draw_point(11,2,0x00);
draw_point(11,5,0x00);
}
x = bcd2dec (Wire.read());
put_char(13,1, x/10,0x02);
put_char(18, 1, x%10, 0x02);
x = bcd2dec (Wire.read());
put_char(1,1, x/10,0x02);
put_char(6, 1, x%10, 0x02);
if (x == 0){
getDate();
}

}
void getTime1(){
Wire.beginTransmission(0x68);
Wire.write ((byte)0x00);
Wire.endTransmission ();
Wire.requestFrom (0x68, 7);
int x;
x = bcd2dec (Wire.read() & 0x7f);
if (x %2 == 0){
draw_point(15,5,0x02);
draw_point(15,9,0x02);
}else {
draw_point(15,5,0x00);
draw_point(15,9,0x00);
43
}
x = bcd2dec (Wire.read());
put_mini_number_2(18,3,x/10,0x01);
put_mini_number_2(25,3,x%10,0x01);
x = bcd2dec (Wire.read());
put_mini_number_2(1,3,x/10,0x01);
put_mini_number_2(8,3,x%10,0x01);
if (x == 0){
getDate();
}
}
void draw_point (int x, int y, char color){
set_pixel (x ,y, color);
set_pixel (x+1,y, color);
set_pixel (x+1,y+1, color);
set_pixel (x,y+1, color);
}
void put_mini_number(int i, int j, char txt, char color){
char x, y;
for (y = 0; y <3; y++){
for (x = 0 ; x < 5; x++) {
if ((miniFont[txt][y] & (0x80 >> x)) != 0) set_pixel(y+i,
x+j, color);
else set_pixel(y+i, x+j, 0x00);
}
}
}
void put_mini_number_2(int i, int j, char txt, char color){
char x, y;
for (y = 0; y <3; y++){
for (x = 0 ; x < 5; x++) {
if ((miniFont[txt][y] & (0x80 >> x)) != 0) draw_point(2*y
+i, x*2 +j, color);
else draw_point(2*y +i, x*2 +j, 0x00);
}
}
}
void draw_icon(int x, int y, char color){
set_pixel (x , y, color);
set_pixel (x+1 , y+1, color);
set_pixel (x+1 , y, color);
set_pixel (x+2 , y, color);
}
44
void draw_icon1(int x, int y, char color){
set_pixel (x , y, color);
set_pixel (x+1 , y-1, color);
set_pixel (x+1 , y, color);
set_pixel (x+2 , y, color);
}
void clear_display (){
unsigned char i, j;
for (i = 0;i < 16; i++)
for (j =0; j < 32; j++){
set_pixel(j,i,0x00);
}
}

45

You might also like