Arduino cho người mới bắt đầu (Phần 2)

Chuẩn giao tiếp truyền

nhận dữ liệu SPI

Chương này chúng ta sẽ tìm hiểu về một chuẩn giao tiếp khá thông dụng trong truyền nhận dữ liệu,

đó là chuẩn giao tiếp truyền nhận SPI. Điểm qua 1 số nội dung sẽ tìm hiểu ở chương này:

• Giới thiệu về chuẩn SPI, lịch sử hình thành và nguyên lí hoạt động.

• Một số ví dụ sử dụng SPI trong truyền, nhận dữ liệu như điều khiển LED matrix và đọc giá trị

nhiệt độ, áp suất, độ cao bằng cảm biến BMP280 hiển thị giá trị lên màn hình OLED.

Arduino cho người mới bắt đầu 105/188Giao thức SPI

Giới thiệu

Với tốc độ phát triển của công nghệ ngày nay thì việc truyền dữ liệu qua các chuẩn truyền I2C, UART

chưa đáp ứng được đối với các dự án cần truyền dữ liệu với tốc độ cao, để đáp ứng điều đó hãng

Motorola đã đề xuất ra chuẩn truyền SPI.

SPI là chữ viết tắt của Serial Peripheral Interface, chuẩn giao tiếp nối tiếp đồng bộ tốc độ cao do

hãng Motorola đề xuất được sử dụng cho truyền thông khoảng cách ngắn, chủ yếu là trong các hệ

thống nhúng. Giao diện được Motorola phát triển vào giữa những năm 1980 và đã trở thành tiêu

chuẩn trong thực tế. Các ứng dụng điển hình như Secure Digital cards (các loại thẻ nhớ SD ví dụ:

miniSD, microSD cards) và liquid crystal displays (màn hình tinh thể lỏng).

Đôi khi SPI còn được gọi là chuẩn truyền thông "4 dây" vì nó có 4 đường giao tiếp là SCK (Serial

Clock), MISO (Master Input/Slave Output), MOSI (Master Output/Slave Input) và SS(Slave Select).

• SCK (Serial Clock): Là đường xung giữ nhịp cho chuẩn SPI, là chân output từ master, do chuẩn

SPI là giao tiếp đồng bộ nên phải cần dùng một đường giữ nhịp. Đây là sự khác biệt giữa truyền

thông đồng bộ và truyền thông không đồng bộ như chuẩn giao tiếp UART. SCK giúp chuẩn SPI

có tốc độ truyền/nhận dữ liệu cao và ít xảy ra lỗi trong quá trình truyền/nhận dữ liệu.

• MISO (Master Input/Slave Output): Với master thì MISO là chân input và với slave là chân output,

2 chân MISO của master và slave nối trực tiếp với nhau.

• MOSI (Master Output/Slave Input): Với chip master thì MOSI là chân output và với chip slave là

chân input, 2 đường MOSI của master và slave nối trực tiếp với nhau.

• SS (Slave Select): Là chân chọn thiết bị slave cần giao tiếp, trên thiết bị slave sẽ có một chân

slave kết nối với chân SS của master và trên thiết bị master sẽ có nhiều chân SS điều khiển

thiết bị slave. Chân SS trên các chip slave sẽ ở mức cao khi không giao tiếp, nếu chip master

kéo đường SS của một slave nào đó xuống mức thấp thì master sẽ giao tiếp với slave đó.

Chuẩn truyền SPI sử dụng kiểu truyền thông master-slave, với một master có thể điều khiển nhiều

slave thông qua việc lựa chọn các đường SS (Slave Select), muốn điều khiển slave nào thì chỉ cần

chọn SS của slave đó. Các thiết bị sử dụng chuẩn truyền SPI sẽ truyền dữ liệu song công (duplex

communication) là truyền và nhận dữ liệu cùng lúc, master có thể gửi dữ liệu đến slave và nhận dữ

liệu từ slave cùng một thời điểm.

pdf 84 trang yennguyen 5320
Bạn đang xem 20 trang mẫu của tài liệu "Arduino cho người mới bắt đầu (Phần 2)", để tải tài liệu gốc về máy hãy click vào nút Download ở trên

Tóm tắt nội dung tài liệu: Arduino cho người mới bắt đầu (Phần 2)

Arduino cho người mới bắt đầu (Phần 2)
Chuẩn giao tiếp truyền
nhận dữ liệu SPI
Chương này chúng ta sẽ tìm hiểu về một chuẩn giao tiếp khá thông dụng trong truyền nhận dữ liệu,
đó là chuẩn giao tiếp truyền nhận SPI. Điểm qua 1 số nội dung sẽ tìm hiểu ở chương này:
• Giới thiệu về chuẩn SPI, lịch sử hình thành và nguyên lí hoạt động.
• Một số ví dụ sử dụng SPI trong truyền, nhận dữ liệu như điều khiển LED matrix và đọc giá trị
nhiệt độ, áp suất, độ cao bằng cảm biến BMP280 hiển thị giá trị lên màn hình OLED.
Arduino cho người mới bắt đầu 105/188
Giao thức SPI
Giới thiệu
Với tốc độ phát triển của công nghệ ngày nay thì việc truyền dữ liệu qua các chuẩn truyền I2C, UART
chưa đáp ứng được đối với các dự án cần truyền dữ liệu với tốc độ cao, để đáp ứng điều đó hãng
Motorola đã đề xuất ra chuẩn truyền SPI.
SPI là chữ viết tắt của Serial Peripheral Interface, chuẩn giao tiếp nối tiếp đồng bộ tốc độ cao do
hãng Motorola đề xuất được sử dụng cho truyền thông khoảng cách ngắn, chủ yếu là trong các hệ
thống nhúng. Giao diện được Motorola phát triển vào giữa những năm 1980 và đã trở thành tiêu
chuẩn trong thực tế. Các ứng dụng điển hình như Secure Digital cards (các loại thẻ nhớ SD ví dụ:
miniSD, microSD cards) và liquid crystal displays (màn hình tinh thể lỏng).
Đôi khi SPI còn được gọi là chuẩn truyền thông "4 dây" vì nó có 4 đường giao tiếp là SCK (Serial
Clock), MISO (Master Input/Slave Output), MOSI (Master Output/Slave Input) và SS(Slave Select).
• SCK (Serial Clock): Là đường xung giữ nhịp cho chuẩn SPI, là chân output từ master, do chuẩn
SPI là giao tiếp đồng bộ nên phải cần dùng một đường giữ nhịp. Đây là sự khác biệt giữa truyền
thông đồng bộ và truyền thông không đồng bộ như chuẩn giao tiếp UART. SCK giúp chuẩn SPI
có tốc độ truyền/nhận dữ liệu cao và ít xảy ra lỗi trong quá trình truyền/nhận dữ liệu.
• MISO (Master Input/Slave Output): Với master thì MISO là chân input và với slave là chân output,
2 chân MISO của master và slave nối trực tiếp với nhau.
• MOSI (Master Output/Slave Input): Với chip master thì MOSI là chân output và với chip slave là
chân input, 2 đường MOSI của master và slave nối trực tiếp với nhau.
• SS (Slave Select): Là chân chọn thiết bị slave cần giao tiếp, trên thiết bị slave sẽ có một chân
slave kết nối với chân SS của master và trên thiết bị master sẽ có nhiều chân SS điều khiển
thiết bị slave. Chân SS trên các chip slave sẽ ở mức cao khi không giao tiếp, nếu chip master
kéo đường SS của một slave nào đó xuống mức thấp thì master sẽ giao tiếp với slave đó.
Chuẩn truyền SPI sử dụng kiểu truyền thông master-slave, với một master có thể điều khiển nhiều
slave thông qua việc lựa chọn các đường SS (Slave Select), muốn điều khiển slave nào thì chỉ cần
chọn SS của slave đó. Các thiết bị sử dụng chuẩn truyền SPI sẽ truyền dữ liệu song công (duplex
communication) là truyền và nhận dữ liệu cùng lúc, master có thể gửi dữ liệu đến slave và nhận dữ
liệu từ slave cùng một thời điểm.
106/188
IoT Maker Viet Nam
Hình 88. Hình ảnh cách kết nối các thiết bị trong giao thức SPI (Nguồn en.wikipedia.org)
SPI, ưu và nhược điểm
Ưu điểm
• Chuẩn truyền thông nối tiếp SPI có tốc độ truyền dữ liệu và ít lỗi phát sinh trong quá trình
truyền/nhận dữ liệu hơn các chuẩn truyền nối tiếp khác.
• Hỗ trợ truyền thông song công (duplex communication) là dữ liệu có thể truyền và nhận cùng
một thời điểm.
• Có giao diện phần cứng khá đơn giản.
• Không giới hạn tốc độ xung clock, cho phép truyền dữ liệu với tốc độ cao.
• Hỗ trợ điều khiển nhiều slave.
Nhược điểm:
• Tốn năng lượng.
• Chỉ hỗ trợ một master.
• Không có giao thức kiểm tra lỗi.
• SPI đòi hỏi các slave có một đường SS (slave Select) riêng biệt, vì thế nếu cần nhiều slave thì sẽ
cần nhiều đường SS sẽ làm tốn chân của chip master và nhiều dây sẽ gây rối.
Arduino cho người mới bắt đầu 107/188
Nguyên lý hoạt động
Thiết bị master và slave mỗi thiết bị có thanh ghi dữ liệu 8 bit. Khi đường SCK của master tạo ra một
xung nhịp thì một bit trong thanh ghi dữ liệu của master truyền qua slave trên đường MOSI, và ngược
lại một bit dữ liệu từ slave sẽ truyền qua master trên đường MISO, do 2 dữ liệu được truyền cùng một
lúc trên một nhịp xung nên quá trình truyền dữ liệu này gọi là truyền dữ liệu "song công".
Hình 89. Quá trình truyền nhận dữ liệu trong giao thức SPI (Nguồn learn.sparkfun.com)
108/188
IoT Maker Viet Nam
SPI, các ví dụ mẫu
Hiển thị chữ trên LED matrix
Yêu cầu
Đây là một ví dụ cơ bản của chuẩn giao tiếp nối tiếp SPI. Vi điều khiển giao tiếp với module LED matrix
để hiển thị chữ.
Hình 90. Hình ảnh module LED ledmatrix
LED matrix 8x8 MAX7219 dùng IC 7219 để điều LED matrix 1 cách dễ dàng và đơn giản hơn, dùng 3 dây
dữ liệu để truyền dữ liệu và 2 dây nguồn. Module 8x8 LED matrix sử dụng khá đơn giản, có thể điều
chỉnh độ sáng của LED ngay trên phần mềm.
Linh kiện cần dùng
• Board IoT Maker UnoX
• Module LED matrix MAX7219
• Dây cắm breadboard male-female
Kết nối IoT Maker UnoX với LED matrix
Board IoT Maker UnoX sẽ là master và LED matrix sẽ là slave.
• Master sẽ gửi dữ liệu ra từ chân D11 (MOSI) và slave sẽ nhận dữ liệu bằng chân DIN.
• Chân D13 (SCK) của master sẽ tạo xung clock qua chân CLK của slave mỗi nhịp sẽ gửi 1bit dữ
liệu qua slave.
• Chân D10 (SS) của master nối với chân CS của slave khi muốn giao tiếp với slave thì chân D10
(SS) của master sẽ kéo chân CS của slave xuống mức thấp.
Arduino cho người mới bắt đầu 109/188
Bảng 13. Bảng kết nối LED matrix và board IoT Maker UnoX
LED matrix Board IoT Maker UnoX
VCC 5V
GND GND
DIN D11 (MOSI )
CLK D13 (SCK)
CS D10 (SS)
Hình 91. Hình ảnh kết nối module LED matrix với board IoT Maker UnoX
Thư viện cần dùng:
Với những thư viện không có sẵn trong trình biên dịch Arduino IDE thì cần phải clone (dùng với git)
hoặc Download về máy và add vào chương trình. Các thư viện cần dùng cho ứng dụng được kiệt kê
bên dưới:
• Thư viện "SPI.h" là thư viện đã có sẵn trong trình biên dịch Arduino IDE.
• Thư viện bitBangedSPI.
• Thư viện MAX7219_Dot_Matrix.
Source code
110/188
IoT Maker Viet Nam
#include 
#include 
#include 
MAX7219_Dot_Matrix display (chips, 10); // Chân D10 là chân SS của board Iotmaker Uno X
const byte chips = 1; // Số chip MAX7219 được sử dụng
const char message [] = "IOT MAKER VN"; // Nội dung được hiển thị
unsigned long lastMoved = 0;
unsigned long MOVE_INTERVAL = 40; // Thời gian chạy chữ đơn vị (ms)
int messageOffset;
void updateDisplay ()
{
  // Hiển thị chữ của mảng message, bắt đầu từ pixel mesageOffset
  display.sendSmooth (message, messageOffset);
  // Mỗi thời gian hiển thị một pixel từ phải qua trái
  if (messageOffset++ >= (int) (strlen (message) * 8))
  messageOffset = -chips * 8;
}
void setup ()
{
  display.begin (); // Khởi tạo hiển thị
}
void loop ()
{
  // Nội dung được hiển thị lại sau khi chạy
  if (millis() - lastMoved >= MOVE_INTERVAL) {
  updateDisplay ();
  lastMoved = millis();
  }
}
Kết quả
Arduino cho người mới bắt đầu 111/188
Đọc dữ liệu từ cảm biến BMP280, hiển thị trên OLED
Yêu cầu
Ứng dụng này giúp chúng ta đọc dữ liệu từ cảm biến áp suất và hiển thị giá trị lên màn hình OLED.
Module cảm biến áp suất BMP280
Hình 92. Hình ảnh module cảm biến áp suất BMP280
BPM280 là cảm biến nâng cấp thế hệ tiếp theo cho BMP085/BMP180/BMP183. Với chi phí thấp, độ
chính xác cao. Module có chức năng đo áp suất khí quyển và nhiệt độ. Chúng ta cũng có thể sử dụng
nó như một module đo độ cao (sai số ± 1m) bởi mối liên hệ giữa áp suất và độ cao.
Linh kiện cần dùng
• Board IoT Maker UnoX
• Module cảm biến áp suất BPM280
• Màn hình OLED
• Dây cắm breadboard male-female
Kết nối :
• Arduino sẽ là master và cảm biến BMP280 sẽ là slave, slave sẽ gửi dữ liệu qua đường SDI.
• Mỗi nhịp xung clock từ chân SCK (D13) của master tạo ra sẽ ứng với 1bit dữ liệu được truyền.
• Chân D10 (SS) của master nối với chân CS của slave khi muốn giao tiếp với slave thì chân D10
(SS) của master sẽ kéo chân CS của slave xuống mức thấp.
112/188
IoT Maker Viet Nam
Bảng 14. Bảng đấu nối cảm biến BMP280 và board IoT Maker UnoX
BMP280 IoT Maker UnoX
VCC 3.3V
GND GND
SDI D11 (MOSI )
SCK D13 (SCK)
CSE D10 (SS)
SDO D12(MISO)
Hình 93. Hình ảnh kết nối module cảm biến áp suất BMP280 với board IoT Maker UnoX
Kết nối board IoT Maker UnoX với OLED
Xem chương I2C để hiểu hơn về giao tiếp Arduino giao tiếp với OLED, chúng ta có thể cắm trực tiếp
OLED vào header đã được thiết kế sẵn trên board IoT Maker UnoX hoặc kết nối theo hướng dẫn bên
dưới.
Bảng 15. Bảng đấu nối OLED với board IoT Maker UnoX
OLED IoT Maker UnoX
VCC 3.3V
GND GND
SDA SDA(hoặc A4)
SCL SCL(hoặc A5)
Arduino cho người mới bắt đầu 113/188
Hình 94. Hình ảnh kết nối OLED SSD1306 với board IoT Maker UnoX
Thư viện cần dùng:
• Thư viện "SPI.h" và "Wire.h" là hai thư viện có sẵn trong Arduino IDE.
• Thư viện Adafruit_SSD1306.h.
• Thư viện Adafruit_GFX.h.
• Thư viện Adafruit_Sensor.h.
• Thư viện Adafruit_BMP280.h.
Source code
#include 
#include 
#include 
#include 
#include 
#include 
#define BMP_SCK 13
#define BMP_MISO 12
#define BMP_MOSI 11
#define BMP_CS 10
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
// Chọn giao tiếp SPI (BMP280 có 2 chuẩn giao tiếp SPI và I2C)
Adafruit_BMP280 bmp(BMP_CS, BMP_MOSI, BMP_MISO, BMP_SCK);
void setup()
{
  Serial.begin(9600);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // Lấy địa chỉ I2C của oled
  display.clearDisplay(); // Lệnh xóa màn hình hiển thị
  display.setTextColor(WHITE); // Chọn màu chữ
  display.setTextSize(1); // Chọn kích thước chữ
  display.setCursor(15, 15); // Chọn vị trí của chữ
114/188
IoT Maker Viet Nam
  display.print(" IOT MAKER VN ");
  display.display();
  delay(2000);
  Serial.println(F("BMP280 test"));
  if (!bmp.begin()) { // In ra thông báo nếu kết nối thất bại
  Serial.println(F("Could not find a valid BMP280 sensor, check wiring!"));
  while (1);
  } else
  Serial.println("BMP280 OK"); // Hiển thị "BMP280 OK" khi kết nối thành công
}
void loop()
{
  display.clearDisplay();
  display.setTextSize(1);
  display.setCursor(0, 0);
  display.print("Temperature:");
  display.print(bmp.readTemperature()); // Lấy giá trị nhiệt độ
  display.print("*C");
  // Hiển thị giá trị nhiệt độ trên serial monitor
  Serial.print("Temperature:");
  Serial.print(bmp.readTemperature()); // Lấy giá trị nhiệt độ
  Serial.println("*C");
  display.setCursor(0, 10);
  display.print("Pressure:");
  display.print(bmp.readPressure()); // Lấy giá trị áp suất
  display.print("Pa");
  // Hiển thị giá trị áp suất trên serial monitor
  Serial.print("Pressure:");
  Serial.print(bmp.readPressure()); // Lấy giá trị áp suất
  Serial.println("Pa");
  display.setCursor(0, 20);
  display.print("h:");
  display.print(bmp.readAltitude()); // Lấy giá trị độ cao
  display.print("m");
  // Hiển thị giá trị độ cao trên serial monitor
  Serial.print("h:");
  Serial.print(bmp.readAltitude()); // Lấy giá trị độ cao
  Serial.println("m");
  display.display();
  delay(2000);
}
Kết quả
Arduino cho người mới bắt đầu 115/188
Hình 95. Hình ảnh kết quả hiển thị trên OLED
116/188
IoT Maker Viet Nam
Tổng kết
Qua phần này, bạn đã tìm hiểu được những khái niệm quan trọng trong giao tiếp SPI, các chân giao
tiếp theo chuẩn SPI là SCK, MISO, MOSI, SS. Cách chọn slave để giao tiếp của master và SPI hoạt
động theo kiểu truyền song công là như thế nào. Từ đó, chúng ta có thể dễ dàng xây dựng các ứng
dụng có hỗ trợ giao tiếp SPI.
Arduino cho người mới bắt đầu 117/188
Chuẩn giao tiếp 1-Wire
Trong chương này chúng ta sẽ cùng tìm hiểu thêm về 1 chuẩn giao tiếp truyền nhận dữ liệu nữa đó
là chuẩn giao tiếp 1-Wire, các ví dụ thực hành đọc cảm biến bằng chuẩn giao tiếp 1-Wire, kết hợp
chuẩn giao tiếp 1-Wire với các chuẩn giao tiếp khác như I2C hay SPI.
118/188
IoT Maker Viet Nam
1-Wire
1-Wire là gì?
Chuẩn giao tiếp 1-Wire được nghiên cứu và phát triển bởi Dallas Semiconductor (Maxim). Không như
các chuẩn giao tiếp đã được đề cập trước đó như I2C cần 2 dây hoặc SPI cần 4 dây để truyền nhận
dữ liệu. 1-Wire chỉ cần một dây để có thể truyền và nhận dữ liệu.
Chuẩn giao tiếp 1-Wire là chuẩn giao tiếp không đồng bộ và bán song công (half-duplex: tại một thời
điểm, tín hiệu chỉ có thể chạy theo một hướng). Vì 1-Wire chỉ sử dụng một dây để nối nguồn và truyền
dữ liệu, nên khi ở trạng thái rãnh (không có dữ liệu trên đường truyền) thì nó cần phải ở mức cao, do
đó cần kết nối dây này với nguồn thông qua một điện trở. Điện trở này thường được gọi là điện trở
kéo lên (pull-up resistor). Tùy theo các thiết bị mà giá trị điện trở này có thể thay đổi, cần tham khảo
datasheet của thiết bị để biết rõ.
1-Wire thường sử dụng các cổng logic CMOS/TTL tương ứng với mức logic 0 thì điện áp đỉnh ở mức
0.8V và điện áp tối thiểu cho mức logic 1 là 2.2V. Các thiết bị 1-Wire có nguồn cấp trong khoảng 2.8V
đến 6V.
1-Wire có hai chế độ làm việc là standard và overdrive. Khi làm việc ở chế độ standard thì tốc độ
truyền dữ liệu là 15.4kbps, với chế độ overdrive là 125kbps.
Chuẩn giao tiếp 1-Wire tuân theo mô hình master-slave. Trên một đường truyền dữ liệu có thể gắn
nhiều thiết bị slave, nhưng chỉ có duy nhất một thiết bị là master. Mỗi một thiết bị slave sẽ có duy
nhất 64-bit địa chỉ lưu trữ trong bộ nhớ ROM của mình. Nhờ thế, khi kết nối vào chung một bus dữ liệu
thì thiết bị master sẽ có thể nhận biết được giữa các slave. Trong 8 byte (64 bit) này sẽ được chia ra
làm 3 phần chính:
• Bắt đầu là LSB (least significant bit), byte đầu tiên bao gồm 8 bit được gửi đi là mã họ thiết bị
(family codes) giúp xác định đó là loại thiết bị nào. 6 byte tiếp theo lưu trữ một địa chỉ riêng của
từng thiết bị với 48 bit tùy biến. Byte cuối cùng MSB (most significant bit) là byte kiểm tra tính
toàn vẹn của dữ liệu - cyclic redundancy check (CRC), đây là byte giúp kiểm tra xem tín hiệu gửi
đi có bị lỗi hay không.

Với số lượng 2^48 bit địa chỉ được tạo ra thì vấn đề về địa chỉ không phải là vấn
đề chính trong chuẩn giao tiếp này.
Khi có nhiều thiết bị 1-Wire trên một mạch thì nó thường được gọi là mạng 1-Wire hoặc MicroLAN.
Trong mạng này, yêu cầu chỉ có duy nhất một master và phải có ít nhất là một slave. Có thế kết
nối bao nhiêu slave tùy thích, nhưng khi vượt quá con số 20 thì việc truyền nhận dữ liệu có thể sẽ
xảy ra lỗi.
Đường truyền giữa master và slave có thể lên tới 200 mét. Khi sử dụng dây ở khoảng cách lớn thì cần
Arduino cho người mới bắt đầu 119/188
được bảo quản tốt hơn, như tránh băng qua các đường dây điện để tránh tín hiệu sẽ bị nhiễu. Khi sử
dụng ở khoảng cách xa, loại dây rẻ nhất và dễ sử dụng nhất là dây CAP5 được sử dụng trong mạng
LAN (dây cable internet).
1-Wire hoạt động như thế nào?
Chuẩn giao tiếp 1-Wire sử dụng khái niệm time slot (khe thời gian). Một time slot là một khoảng thời
gian trong đó mức logic 1 hoặc 0 sẽ được ghi hoặc đọc. Time slot có khoảng thời gian là 60µs khi
hoạt động ở chế độ standard, và 8µs với chế độ overdrive.
Có 3 thao tác hoạt động cơ bản của 1 Wire là Reset/Present, Read, Write.
1. Reset/Present.
Master sẽ kéo tín hiệu truyền xuống mức thấp trong khoảng 480µs đến 640µs. Khoảng thời gian
này được hiểu là khoảng thời gian ... g pulseIn(pin,[HIGH, LOW])
/* Trả về (ms) của xung HIGH/LOW trên chân pin */
/* CHỨC NĂNG NGẮT */
attachInterrupt(interrupt, func, mode)
/* Thiết lập chức năng ngắt ở các chân digital */
/*
interrupt: số ngắt (thường là chân sử dụng chức năng
ngắt)
func : hàm sẽ được gọi khi ngắt xảy ra (lưu ý : hàm
không có tham số đầu vào cũng như kiểu trả về)
mode : gồm các chế độ LOW,CHANGE, RISING, FALLING. Ngắt
180/188
IoT Maker Viet Nam
sẽ được kích hoạt khi chân ngắt ở mode tương ứng
*/
detachInterrupt(interrupt)
/* Vô hiệu hóa ngắt interrupt */
noInterrupts()
/* Vô hiệu hóa tấ cả các ngắt */
interrupts()
/* Cho phép tái ngắt sau khi dùng noInterrupts() */
/*************************************************
 * THƯ VIỆN PHỔ BIẾN *
 *************************************************/
/*************************************************
 * Serial *
 *Thư viện giao tiếp với PC hoặc thông qua RX/TX*
 *************************************************/
begin(long speed)
/* Thiết lập giao tiếp serial-UART với tốc độ speed */
end()
/* Vô hiệu hóa giao tiếp serial */
int available()
/* Trả về số bytes có sẵn để đọc */
int read()
/* đọc dữ liệu đến từ serial (trả về byte đầu tiên của
dữ liệu từ serial hoặc -1 nếu dữ liệu không có */
flush()
/* Chờ quá trình truyền dữ liệu serial hoàn tất */
print(data)
/* In ra serial port dữ liệu data (với bất kì kiểu dữ
liệu nào được thiết lập */
println(data)
/* Tương tự như print(data) nhưng sau khi in ra serial
-port, con trỏ sẽ xuống dòng tiếp theo */
write(byte)
/* Gửi dữ liệu value/string/array đến serial port */
SerialEvent()
/* Hàm được gọi khi có dữ liệu đến từ chân RX */
/*************************************************
 * Servo.h *
 * Thư viện hỗ trợ điều khiển động cơ servo *
 *************************************************/
attach(pin, [min_uS, max_uS])
/*
Thiết lập chân kết nối với servo và độ rộng xung
pin : Chân kết nối với servo
[min_uS, max_uS] : Độ rộng xung tính theo us tương ứng
với góc xoay từ 0 đến 180
*/
write(angle)
/* Ghi dữ liệu góc xoay cho động cơ angle từ 0~180 */
writeMicroseconds(uS)
/* Viết giá trị để điều khiển góc quay cho servo, giá
trị từ 700 ~ 2300 */
int read()
/* Đọc giá trị góc xoay (0 đến 180 độ) */
bool attached()
/* Trả về true nếu biến servo đã kết nối đến pin */
detach()
/* Gỡ bỏ biến servo ra khỏi chân đã kết nối */
/*************************************************
 * Wire.h *
 * Dùng trong giao tiếp I2C *
 *************************************************/
begin()
 /* Master khởi tạo thư viện Wire với giao tiếp I2C */
 begin(addr)
/* Slave tham gia vào kết nối i2C, addr là 7 bits địa
chỉ của slave */
requestFrom(address, count, stop)
/*
Master yêu cầu 1 số byte từ slave:
address: 7bits địa chỉ của slave.
count: Số lượng byte master yêu cầu
stop: Kiểu boolean, nếu true, master tín hiệu stop sau
khi yêu cầu và giải phóng bus I2C, nếu false, master
gửi yêu cầu restart để giữ kết nối
*/
beginTransmission(addr)
/* Gửi tín hiệu bắt đầu, truyền dữ liệu đến slave có
địa chỉ addr */
send(byte)
/* Gửi dữ liệu (1 byte)đến slave */
send(char * string)
/* Gửi dữ liệu (string) đến slave */
send(byte * data, size)
/* Gửi dữ liệu (1 mảng ) với số byte là size */
endTransmission()
/* Gửi tín hiệu kết thúc truyền dữ liệu tới slave */
int available()
/* Trả về số byte availabe sau khi đọc bởi read() */
byte receive()
/* truy xuất đến 1 byte đã truyền từ slave đến master
hoặc truyền ở chiều ngược lại khi nhận được
requestFrom. Trả về byte tiếp theo đã nhận được */
onReceive(handler)
/* Hàm handler sẽ được gọi khi slave nhận dữ liệu */
onRequest(handler)
/* Handler sẽ được gọi khi master yêu cầu dữ liệu */
Arduino cho người mới bắt đầu 181/188
C - Cheatsheet
/* CẤU TRÚC CƠ BẢN */
Viết chú thích trên 1 dòng dùng //
  ex: x++ ; // tăng x 1 đơn vị
/* */ Viết chú thích trên nhiều dòng.
ex : /*************************
  * Chú thích được viết *
  * trên nhiều dòng *
  ************************/
/* CẤU TRÚC 1 CHƯƠNG TRÌNH */
#include //include thư viện chuẩn của C
#include "iLib.h"// include thư viện tạo bởi người dùng
int global_var; //biến được dùng trong chương trình
/* Khai báo hàm bắt đầu của 1 chương trình C với kiểu
trả về là integer. Đối số arg kiểu int được truyền vào
hàm */
int main (int arg){
 float local_var ; // Biến chỉ được dùng trong hàm main
 Lệnh 1
 ...
 Lệnh n ;
return 0; //chương trình thực hiện thành công và thoát
}
/*KIỂU DỮ LIỆU VÀ PHẠM VI */
boolean true | false
char -128 - 127, 'a' '$' etc.
unsigned char 0 - 255
byte 0 - 255
int -32768 - 32767
unsigned int 0 - 65535
word 0 - 65535
long -2147483648 - 2147483647
unsigned long 0 - 4294967295
float -3.4028e+38 - 3.4028e+38
double -3.4028e+38 - 3.4028e+38
void i.e., no return value
/* ĐẶT TÊN BIẾN */
/* Đặt tên đúng */
int x; // Một biến
int x = 1; // Biến được khai báo và khởi tạo
float x, y, z; // Nhiều biến cùng kiểu dữ liệu
const int x = 88; // Biễn tĩnh, không ghi được
int tenBien1ok; // Đặt tên biến này đúng
int ten_bien_nay_ok;
/* Đặt tên sai */
int 2001_tensai; // Vì số ở đầu
int ten-sai; // Dấu '-' không phải là alphanumberic
int while; // Sai, vì dùng từ khóa vòng lặp while
/* HẰNG SỐ VÀ KIỂU DỮ LIỆU */
123 Số thập phân
0b0111 Số nhị phân
0173 Số Octal - base 8
0x7B Số thập lục phân base 16
123U Số nguyên không dấu
123L Số nguyên có dấu 4 bytes
123UL Số nguyên không dấu 4bytes
123.0 Số thực
1.23e6 Số thực dùng cơ số mũ ex: 1.23*10^3 = 1230
/* định nghĩa hằng số a kiểu nguyên, có giá trị là 1 */
const int a = 1;
/* Định nghĩa hằng số x kiểu thực, có giá trị là 4.0 */
const float x = 4;
/* Định nghĩa hằng số c kiểu integer có giá trị 49 */
const c = ‘1’; // Kí tự 1 trong mã ASCII là 49
/* Định nghĩa str là hằng số kiểu con trỏ, trỏ tới
chuỗi “Cheasheet C” */
const char * str = “Cheasheet C”;
/* KHAI BÁO BIẾN */
/* Khai báo biến a kiểu nguyên và không gán giá trị */
int a;
/* khai báo a kiểu binary, b kiểu base8, c kiểu số
nguyên, d kiểu số nguyên và không gán giá trị */
int a = 0b01111011, b = 0123, c = 1, d;
/* Khai báo biến fa thuộc kiểu số thực float */
float fa = 1.0f;
/* Khai báo biến da thuộc kiểu số thực double */
double da = 1.0;
/* Khai báo biến con trỏ và trỏ đến 1 vùng nhớ không
xác định */
char *pointer;
/* Khai báo biến con trỏ và trỏ về NULL (0)*/
char *other_pointer = NULL;
/* CHUỖI KÍ TỰ */
/* Chuỗi bao gồm kí tự kết thúc chuỗi \0 (null) */
char str1[8] = {'A','r','d','u','i','n','o','\0'};
/* Trình biên dịch tự động thêm kí tự \0 vào cuối
chuỗi */
char str2[8] = {'A','r','d','u','i','n','o'};
/* Khai báo chuỗi ,không khai báo số phần tử và gán giá
trị chuỗi */
char str3[] = "Arduino";
/* Khai báo và gán giá trị cho chuỗi */
char str4[8] = "Arduino";
/* Các hàm xử lí chuỗi thường dùng */
/* Nối các kí tự từ chuỗi source tiếp vào vị trí cuối
của chuỗi dest */
strcat(dest, source)
/* Tìm vị trí xuất hiện đầu tiên của kí tự c trong
source, trả về con trỏ chỉ tới vị trí đó hoặc null nếu
không tìm thấy c trong source */
strchr(source, c)
/* Hàm trả về độ dài của chuỗi st */
strlen(st)
/* copy và thay các kí tự của chuỗi soure vào dest */
strcpy(dest, source)
/* chép kí tự từ đầu đến n từ chuỗi source vào dest */
strncpy(dest, source, n)
182/188
IoT Maker Viet Nam
/* MẢNG */
/* Khai báo mảng 1 chiều 6 phần tử kiểu integer và gán
giá trị cho mỗi phần tử */
int myPins[] = {2, 4, 8, 3, 6};
/* Khai báo mảng 1 chiều 6 phần tử kiểu integer và
không gán giá trị */
int myInts[6];
myInts[0] = 42; // Gán giá trị 42 cho phần tử đầu tiên
myInts[6] = 12; // LỖI ! chỉ số của mảng chỉ từ 0 đến 5
/* Lấy giá trị của phần tử thứ 3 trong mảng myInts */
int c = myInts[2]; // Có thể dùng *(myInts + 2)
/* Lấy địa chỉ của phần tử thứ 3 trong mảng myInts */
int c = &myInts[2]; // Có thể dùng int c = myInts + int
/* Trả về chiều dài của mảng myInts */
int length = sizeof(myInts) / sizeof(myInts[0]);
/* Khai báo 2 mảng kiểu float, arr1 có 5 phần tử, arr2
có 10 phần tử */
float arr1[5], arr2[10];
/* Khai báo mảng số nguyên arr có 2 dòng, 5 cột. Tổng
cộng có 10 phần tử */
int a[2][5];
/* KHỐI LỆNH VÀ CÁC LỆNH DÙNG TRONG VÒNG LẶP */
{} // bao gồm nhiều lệnh, thường được sử dụng trong h
àm
/* Goto : chương trình sẽ nhảy đến nhãn (nhãn phải có
mặt trong câu lệnh chứa goto) */
goto nhãn;
/* Continue : Chỉ dùng trong các lệnh có vòng lặp sẽ
chuyển qua chu kì mới của vòng lặp trong cùng nhất */
continue; /*
/* Break : Dùng với các vòng lặp thoát khỏi vòng lặp
trong cùng nhất, hoặc dùng trong cấu trúc switch..case
để thoát ra khỏi case tương ứng */
break; /*
/* Return */
/* Dùng cho hàm không có kiểu trả về (void) */
return;
/* Value có thể là hằng số, biến, biểu thức hoặc gọi
đến 1 hàm khác để trả về giá trị */
return ;
/* LỆNH RẺ NHÁNH */
if (x < 5) // thực thi code nếu x<5
 { code }
else if (x > 10)// thực thi code nếu x>10
  { code }
else { code } // thực thi code các trường hợp còn lại
switch (var) { // thực thi case có giá trị var
case 1:
...
break;
case 2:
...
break;
default:
...
}
/* CÁC KIỂU VÒNG LẶP */
/* While: Thực hiện code nếu x<5 */
while (x < 5) { code };
/* Do-While : Thực hiện code, so sánh, nếu x<0 tiếp tục
thực hiện code */
do { code } while(x < 0);
/* for : Khởi tạo và gán giá trị cho i, thực hiện code
tăng i nếu i < 10 */
for (int i = 0; i < 10; i++) { code };
/* PHÉP TOÁN VÀ TOÁN TỬ THƯỜNG DÙNG
/* Các toán tử thường dùng */
= toán tử bằng
+ toán tử cộng
- toán tử trừ
* toán tử nhân
/ toán tử chia lấy phần nguyên
% toán tử chia lấy phần dư
== phép so sánh bằng
!= phép so sánh không không bằng (khác)
< phép so sánh nhỏ hơn
> phép so sánh lớn hơn
<= phép so sánh nhỏ hơn hoặc bằng
>= phép so sánh lớn hơn hoặc bằng
&& phép toán logic (AND)
|| phép toán logic (OR)
! phép toán logic (NOT)
/* Các toán tử hợp nhất */
++ tăng 1 đơn vị
-- giảm 1 đơn vị
+= phép toán cộng và gán giá trị
  ex: x = 5; x+= 1; //x = 6
-= phép toán trừ và gán giá trị
  ex: x = 5; x-= 1; //x = 4
*= phép toán nhân và gán giá trị
  ex: x = 5; x*= 3; //x = 15
/= phép toán chia lấy phần nguyên và gán giá trị
  ex: x = 6; x/= 2; //x = 3
&= phép toán logic AND và gán giá trị
  ex: x = 0b1010; x&= 0110; //x =0b0010
|= phép toán logic OR và gán giá trị
  ex: x = 0b1010; x&= 0110; //x =0b1110
/* Các toán tử trên bit */
& and ^ xor
> dịch phảii
| or ~ not
/* THỰC THI VỚI CON TRỎ */
&reference: // lấy địa chỉ của biến mà con trỏ trỏ tới
*dereference:// lấy giá trị của biến mà con trỏ trỏ tới
/* khai báo biến con trỏ kiểu int trỏ tới địa chỉ của
biến a */
int a = 5; int *pointer = &a;
/* CÁC KÍ TỰ ĐIỀU KHIỂN VÀ KÍ TỰ ĐẶC BIỆT */
\n Nhảy xuống dòng kế tiếp canh về cột đầu tiên
\t Canh cột tab ngang.
\r Nhảy về đầu hàng, không xuống hàng.
\a Tiếng kêu bip.
\\ In ra dấu \
\" In ra dấu "
\' In ra dấu '
%%: In ra dấu %
\b ~ backspace (xóa 1 ký tự ngay trước)
/* HÀM VÀ CÁC VẤN ĐỀ LIÊN QUAN */
/* Khai báo prototype của hàm max, có 2 đối số đầu vào
là a và b thuộc kiểu số nguyên, kết quả trả về của hàm
kiểu số nguyên */
int max(int a, int b);
Arduino cho người mới bắt đầu 183/188
/* Khai báo biến c là giá trị trả về của hàm max */
int c = max(5,4);
/* Khai báo prototype của hàm không có đối số và không
có kiểu trả về (void) */
void none();
/* TYPEDEF- Định nghĩa kiểu dữ liệu */
/* Định nghĩa kiểu unsigned char là BYTE, khai báo các
biến a, b thuộc kiểu BYTE */
typedef unsigned char BYTE; BYTE a, b;
/* KIỂU LIỆT KÊ - ENUMERATION (enum) */
/* khai báo kiểu dữ liệu enum là các ngày trong tuần */
enum daysOfWeek { sunday, monday, tuesday, wednesday };
/* Tạo biến toDay thuộc daysOfWeek và gán giá trị */
daysOfWeek toDay = wednesday;
/* STRUCT - KIỂU DỮ LIỆU DO NGƯỜI DÙNG ĐỊNH NGHĨA */
/* Khai báo struct sinhVien */
struct sinhVien{
  char tenSinhVien;
  char MSSinhVien;
  int tuoiSinhVien;
};
/* Truy xuất đến thành phần MSSinhVien trong struct
sinhVien */
sinhVien.MSSinhVien;
/* Đổi tên struct sinhVien thành 1 biến duy nhất là
SINHVIEN */
typedef struct sinhVien SINHVIEN;
/* Khai báo biến sinhVienA thuộc struct SINHVIEN */
SINHVIEN sinhVienA;
/* CÁC LỆNH XỬ LÝ TẬP TIN (#include ) */
/* Khai báo 1 biến con trỏ là đường dẫn của 1 file */
const char *filePath = "Đường/dẫn/file/document.txt";
/* Tạo 1 biến con trỏ thuộc kiểu FILE */
FILE *file;
/* Mở 1 file ở đường dẫn filePath và đọc dữ liệu */
file = fopen(filePath, "r");// Trả về NULL nếu thất bại
/* Đóng 1 file đã mở, trả về 0 nếu thành công , ngược
lại trả về EOF */
fclose(file);
/* Viết kí tự c lên file đang mở, trả về EOF nếu ghi
thất bại, trả về mã ASCII của c nếu thành công */
int fputc(int c, FILE *f);
/* Viết chuỗi "hello" lên file đang mở */
int c = fputs("hello", file);
/* Đọc (255-1) kí tự từ file đang mở, kết quả đọc
được
sẽ lưu vào mảng str, việc đọc bị dừng nếu gặp kí tự
'\n' hoặc EOL */
fgets(str, 255, file);
/* Thay đổi vị trí trỏ đến trong file của con trỏ
internal file position indicator về lại đầu file */
int fseek(file, 0, SEEK_SET);
/* Trả về kích thước của nội dung có trong file */
ftell(file);
www.cheatography.com/ashlyn-black/cheat-sheets/c-reference/
184/188
IoT Maker Viet Nam
Lời kết
Arduino cho người mới bắt đầu 185/188
Các thành viên tham gia đóng góp
Để hoàn thiện nội dung của sách có sự đóng góp của các thành viên sau:
• 1. Phạm Minh Tuấn (TuanPM) - Chủ biên
• 2. Trịnh Hoàng Đức - Kĩ sư thiết kế phần cứng tại IoT Maker Việt Nam.
• 3. Trần Phúc Vinh - Thực tập sinh tại IoT Maker Việt Nam - Sinh viên Đại Học Bách Khoa,
chuyên ngành kĩ thuật điện, khóa học 2014.
• 4. Phạm Thị Thu Hiền - Designer tại IoT Maker Việt Nam.
• 5. Võ Trí Dũng - Thực tập sinh tại IoT Maker Việt Nam, sinh viên Đại Học Sài Gòn, chuyên ngành
điện tử máy tính, khóa học 2014.
• 6. Nguyễn Minh Phương - Thực tập sinh tại IoT Maker Việt Nam, sinh viên Đại Học Sài Gòn,
chuyên ngành điện tử máy tính , khóa học 2014.
• 7. Đặng Quang Trung - Thực tập sinh tại IoT Maker Việt Nam, sinh viên Đại Học Sài Gòn, chuyên
ngành điện tử máy tính, khóa học 2014.
• 8. Lâm Nhật Quân Kĩ sư làm việc tại IoT Maker Việt Nam.
• 9. Trần Thanh Lộc - Thực tập sinh tại IoT Maker Việt Nam - Sinh viên Đại Học Bách Khoa,
chuyên ngành kỹ thuật máy tính, khóa học 2016.
186/188
IoT Maker Viet Nam
Lời kết
Thật vui khi bạn đã đồng hành cùng chúng tôi đi đến hết cuốn sách này. Mục đích của cuốn sách là
giúp những người mới bắt đầu tìm hiểu về Arduino có kiến thức cơ bản và hướng đi chính xác để
nghiên cứu về lập trình vi điều khiển một cách nhanh chóng hơn. Hi vọng cuốn sách sẽ đến tay thật
nhiều bạn đam mê lĩnh vực điện tử lập trình tuy không còn mới mẻ nhưng rất tiềm năng này. Chúc
các bạn thành công trên con đường mà mình đã chọn.
Mặc dù đã cố gắng để hoàn thành tốt nhất nội dung cho cuốn sách, tuy nhiên vẫn không tránh khỏi
những thiếu sót. Các bạn có thể đóng góp ý kiến để nội dung ebook hoàn thiện hơn tại địa chỉ Github
IoT Maker Viet Nam
Arduino cho người mới bắt đầu 187/188
Giấy phép sử dụng tài liệu.
creativecommons.org/licenses/by-nc-sa/4.0/
188/188
IoT Maker Viet Nam

File đính kèm:

  • pdfarduino_cho_nguoi_moi_bat_dau_phan_2.pdf