You are on page 1of 10

HỌC VIỆN CÔNG NGHỆ BƯU CHÍNH VIỄN THÔNG CỘNG HOÀ XÃ HỘI CHỦ NGHĨA VIỆT NAM

KHOA KỸ THUẬT ĐIỆN TỬ 1 Độc lập - Tự do – Hạnh phúc

ĐỒ ÁN THIẾT KẾ HỆ THỐNG NHÚNG

Nhóm: 15
Danh sách thành viên:

Họ và tên Mã SV

Nguyễn Tiến Dũng B20DCDT031

Đinh Đức Duy B20DCDT035

Hoàng Văn Minh B20DCDT135

Trần Đức Nam B20DCDT147

I. Tiến trình

Giai đoạn 1 Lên ý tưởng dự ánvà vẽ sơ đồ khối


Giai đoạn 2 Tìm hiểu hệ điều hành Tìm hiểu giao thức Tìm hiểu giao thức
FreeRTOS SPI I2C
Giai đoạn 3 Xây dựng code Keypad Xây dựng code Thiết kế mạch trên
RFID Proteus
Giai đoạn 4 Tổng hợp code và test mạch
Giai đoạn 5 Hoàn thiện dự án và làm báo cáo

II. Sơ đồ khối
Input Ou output
Keypad LCD
4x4

Vi điều Khiển
STM32
RFID Ổ Khóa
III. Giao thức SPI
SPI – Serial Peripheral Interface – hay còn gọi là giao diện ngoại vi nối tiếp, Là
giao tiếp đồng bộ, bất cứ quá trình nào cũng đều được đồng bộ với xung clock sinh ra
bởi thiết bị Master0

● SCK (Serial Clock): Thiết bị Master tạo xung tín hiệu SCK và cung cấp cho
Slave. Xung này có chức năng giữ nhịp cho giao tiếp SPI. Mỗi nhịp trên chân
SCK báo 1 bit dữ liệu đến hoặc đi → Quá trình ít bị lỗi và tốc độ truyền cao.
● MISO (Master Input Slave Output): Tín hiệu tạo bởi thiết bị Slave và nhận bởi
thiết bị Master. Đường MISO phải được kết nối giữa thiết bị Master và Slave.
● MOSI (Master Output Slave Input): Tín hiệu tạo bởi thiết bị Master và nhận bởi
thiết bị Slave. Đường MOSI phải được kết nối giữa thiết bị Master và Slave.
● SS (Slave Select): Chọn thiết bị Slave cụ thể để giao tiếp. Để chọn Slave giao
tiếp thiết bị Master chủ động kéo đường SS tương ứng xuống mức 0 (Low).
Chân này đôi khi còn được gọi là CS (Chip Select). Chân SS của vi điều khiển
(Master) có thể được người dùng tạo bằng cách cấu hình 1 chân GPIO bất kỳ
chế độ Output.

Khung truyền SPI:


● Mỗi chip Master hay Slave đều có một thanh ghi dữ liệu 8 bits.
● Quá trình truyền nhận giữa Master và Slave xảy ra đồng thời sau 8 chu kỳ đồng
hồ, một byte dữ liệu được truyền theo cả 2 hướng
● Quá trình trao đổi dữ liệu bắt đầu khi Master tạo 1 xung clock từ bộ tạo xung
nhịp (Clock Generator) và kéo đường SS của Slave mà nó truyền dữ liệu xuống
mức Low.
● Cứ 1 xung clock, Master sẽ gửi đi 1 bit từ thanh ghi dịch (Shift Register) của nó
đến thanh ghi dịch của Slave thông qua đường MOSI. Đồng thời Slave cũng gửi
lại 1 bit đến cho Master qua đường MISO.Như vậy sau 8 chu kỳ clock thì hoàn
tất việc truyền và nhận 1 byte dữ liệu.
● Dữ liệu của 2 thanh ghi được trao đổi với nhau nên tốc độ trao đổi diễn ra
nhanh và hiệu quả.

IV. Giao thức I2C


● I2C sử dụng 2 đường truyền tín hiệu:
SCL - Serial Clock Line : Tạo xung nhịp đồng hồ do Master phát đi
SDA - Serial Data Line : Đường truyền nhận dữ liệu.

● Giao tiếp I2C bao gồm quá trình truyền nhận dữ liệu giữa các thiết bị chủ tớ,
hay Master - Slave.
● Thiết bị Master là 1 vi điều khiển, nó có nhiệm vụ điều khiển đường tín hiệu
SCL và gửi nhận dữ liệu hay lệnh thông qua đường SDA đến các thiết bị khác.
● Các thiết bị nhận các dữ liệu lệnh và tín hiệu từ thiết bị Master được gọi là các
thiết bị Slave. Các thiết bị Slave thường là các IC, hoặc thậm chí là vi điều
khiển.
● Master và Slave được kết nối với nhau như hình trên. Hai đường bus SCL và
SDA đều hoạt động ở chế độ Open Drain, nghĩa là bất cứ thiết bị nào kết nối
với mạng I2C này cũng chỉ có thể kéo 2 đường bus này xuống mức thấp
(LOW), nhưng lại không thể kéo được lên mức cao. Vì để tránh trường hợp bus
vừa bị 1 thiết bị kéo lên mức cao vừa bị 1 thiết bị khác kéo xuống mức thấp gây
hiện tượng ngắn mạch. Do đó cần có 1 điện trờ ( từ 1 – 4,7 kΩ) để giữ mặc định
ở mức cao.
Quá trình truyền nhận dữ liệu:
● Bắt đầu: Thiết bị Master sẽ gửi đi 1 xung Start bằng cách kéo lần lượt các
đường SDA, SCL từ mức 1 xuống 0.
V. FreeRTOS
RTOS là viết tắt của cụm từ Real-time operating system hay hệ điều hành thời gian
thực thường được nhúng trong các dòng vi điều khiển dùng để điều khiển thiết bị một
cách nhanh chóng và đa nhiệm. Là một phần mềm dùng để điều hành, quản lý toàn bộ
tất cả thành phần (bao gồm cả phần cứng và phần mềm) của thiết bị điện tử.
Sử dụng cho các tác vụ cần sự phản hồi nhanh của hệ thống, thường được nhúng
trong các loại vi điều khiển và không có giao diện (GUI) tương tác với người dùng.
Chúng cần phản hồi nhanh bởi vì đa số các tác vụ tương tác với thiết bị, máy móc khác
chứ không phải con người. Các tài nguyên bên trong rất hữu hạn nên chỉ một sự chậm
trễ cũng có thể làm hệ thống làm việc hoàn toàn sai lệch.
Tại sao lại phải dùng RTOS ?
● Chia sẻ tài nguyên một cách đơn giản: cung cấp cơ chế để phân chia các yêu cầu
về bộ nhớ và ngoại vi của MCU
● Dễ debug và phát triển: Mọi người trong nhóm có thể làm việc một cách độc
lập, các lập trình viên thì có thể tránh được các tương tác với ngắt, timer, với
phần cứng (cái này mình không khuyến khích lắm vì hiểu được phần cứng vẫn
sẽ tốt hơn nhiều)
Cách hoạt động của RTOS
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.

● Tiếp theo đó, Master gửi đi 7 bit địa chỉ tới Slave muốn giao tiếp cùng với bit
Read/Write.
● Slave sẽ so sánh địa chỉ vật lý với địa chỉ vừa được gửi tới. Nếu trùng khớp,
Slave sẽ xác nhận bằng cách kéo đường SDA xuống 0 và set bit ACK/NACK
bằng ‘0’. Nếu không trùng khớp thì SDA và bit ACK/NACK đều mặc định
bằng ‘1’.
● Thiết bị Master sẽ gửi hoặc nhận khung bit dữ liệu. Nếu Master gửi đến Slave
thì bit Read/Write ở mức 0. Ngược lại nếu nhận thì bit này ở mức 1.
● Nếu như khung dữ liệu đã được truyền đi thành công, bit ACK/NACK được set
thành mức 0 để báo hiệu cho Master tiếp tục.
● Sau khi tất cả dữ liệu đã được gửi đến Slave thành công, Master sẽ phát 1 tín
hiệu Stop để báo cho các Slave biết quá trình truyền đã kết thúc bằng các
chuyển lần lượt SCL, SDA từ mức 0 lên mức 1.

VI. Code KeyPad


Keypad.c
#include "keypad.h"
#include "stm32f10x_gpio.h" // Keil::Device:StdPeriph Drivers:GPIO

ButtonManagement Button[16];

void keypad_config(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef gpio_config;

gpio_config.GPIO_Mode = GPIO_Mode_IPU;
gpio_config.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 |
GPIO_Pin_3;
gpio_config.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &gpio_config);

gpio_config.GPIO_Mode = GPIO_Mode_Out_PP;
gpio_config.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 |
GPIO_Pin_7;
gpio_config.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &gpio_config);

uint8_t Keypad_Read (void)


{
GPIO_WriteBit (R1_, R1_PIN, GPIO_PIN_RESET);
GPIO_WriteBit (R2_, R2_PIN, GPIO_PIN_SET);
GPIO_WriteBit (R3_, R3_PIN, GPIO_PIN_SET);
GPIO_WriteBit (R4_, R4_PIN, GPIO_PIN_SET);

if (Button_OnPress(C1_, C1_PIN, &Button[0]))


{
return 1;
}

if (Button_OnPress(C2_, C2_PIN, &Button[1]))


{
return 2;
}

if (Button_OnPress(C3_, C3_PIN, &Button[2]))


{
return 3;
}

if (Button_OnPress(C4_, C4_PIN, &Button[3]))


{
return 4;
}

GPIO_WriteBit (R1_, R1_PIN, GPIO_PIN_SET);


GPIO_WriteBit (R2_, R2_PIN, GPIO_PIN_RESET);
GPIO_WriteBit (R3_, R3_PIN, GPIO_PIN_SET);
GPIO_WriteBit (R4_, R4_PIN, GPIO_PIN_SET);

if (Button_OnPress(C1_, C1_PIN, &Button[4]))


{
return 5;
}

if (Button_OnPress(C2_, C2_PIN, &Button[5]))


{
return 6;
}

if (Button_OnPress(C3_, C3_PIN, &Button[6]))


{
return 7;
}

if (Button_OnPress(C4_, C4_PIN, &Button[7]))


{
return 8;
}

GPIO_WriteBit (R1_, R1_PIN, GPIO_PIN_SET);


GPIO_WriteBit (R2_, R2_PIN, GPIO_PIN_SET);
GPIO_WriteBit (R3_, R3_PIN, GPIO_PIN_RESET);
GPIO_WriteBit (R4_, R4_PIN, GPIO_PIN_SET);

if (Button_OnPress(C1_, C1_PIN, &Button[8]))


{
return 9;
}

if (Button_OnPress(C2_, C2_PIN, &Button[9]))


{
return 10;
}
if (Button_OnPress(C3_, C3_PIN, &Button[10]))
{
return 11;
}

if (Button_OnPress(C4_, C4_PIN, &Button[11]))


{
return 12;
}

GPIO_WriteBit (R1_, R1_PIN, GPIO_PIN_SET);


GPIO_WriteBit (R2_, R2_PIN, GPIO_PIN_SET);
GPIO_WriteBit (R3_, R3_PIN, GPIO_PIN_SET);
GPIO_WriteBit (R4_, R4_PIN, GPIO_PIN_RESET);

if (Button_OnPress(C1_, C1_PIN, &Button[12]))


{
return 13;
}

if (Button_OnPress(C2_, C2_PIN, &Button[13]))


{
return 14;
}

if (Button_OnPress(C3_, C3_PIN, &Button[14]))


{
return 15;
}

if (Button_OnPress(C4_, C4_PIN, &Button[15]))


{
return 16;
}

return 0;
}

signed char Convert(int t)


{
if(t == 1) return '7';
else if(t == 2) return '8';
else if(t == 3) return '9';
else if(t == 4) return '/';
else if(t == 5) return '4';
else if(t == 6) return '5';
else if(t == 7) return '6';
else if(t == 8) return 'x';
else if(t == 9) return '1';
else if(t == 10) return '2';
else if(t == 11) return '3';
else if(t == 12) return '-';
else if(t == 13) return 'C';
else if(t == 14) return '0';
else if(t == 15) return '=';
else if(t == 16) return '+';
else return -1;
}

Keypad.h
#include "stm32f10x.h"
// Device header
#include "button.h"
#ifndef KETPAD_H
#define KETPAD_H
#define R1_ GPIOA
#define R1_PIN GPIO_Pin_7
#define R2_ GPIOA
#define R2_PIN GPIO_Pin_6
#define R3_ GPIOA
#define R3_PIN GPIO_Pin_5
#define R4_ GPIOA
#define R4_PIN GPIO_Pin_4
#define C1_ GPIOA
#define C1_PIN GPIO_Pin_3
#define C2_ GPIOA
#define C2_PIN GPIO_Pin_2
#define C3_ GPIOA
#define C3_PIN GPIO_Pin_1
#define C4_ GPIOA
#define C4_PIN GPIO_Pin_0
#define GPIO_PIN_RESET (BitAction)0
#define GPIO_PIN_SET (BitAction)1

#define LLMAX 9223372036854775807

void keypad_config(void);
uint8_t Keypad_Read (void);
signed char Convert(int t);
#endif

You might also like