Atlas Robotics
Đọc DatasheetTrung bình

Đọc register map — bit field, offset, reserved bit

Atlasbot · 23/8/2026 · 11 phút đọc

Đọc register map — bit field, offset, reserved bit
Register map: offset địa chỉ, bit field, và reserved bit

Bài Timing diagram đã bàn quan hệ tín hiệu theo thời gian. Bài cuối chuyên mục Đọc Datasheet đi vào register map — bảng liệt kê các thanh ghi điều khiển/trạng thái của một IC, và cách đọc đúng để cấu hình nó bằng code.

Khái niệm chính

Register map là bảng liệt kê mọi thanh ghi (register) mà một IC expose ra ngoài để phần mềm đọc/ghi, mỗi hàng thường gồm: offset (địa chỉ tương đối tính từ địa chỉ gốc của thiết bị), tên thanh ghi, quyền truy cập (R = chỉ đọc, W = chỉ ghi, R/W = đọc và ghi), và mô tả chức năng. Mỗi thanh ghi thường rộng 8/16/32-bit, và bên trong lại chia thành các bit field — nhóm bit liền nhau mang một ý nghĩa cụ thể (VD: 2 bit chọn chế độ, 1 bit bật/tắt).

Nguyên lý hoạt động

Địa chỉ thực tế để đọc/ghi một thanh ghi tính từ địa chỉ gốc (base address, thường là địa chỉ I2C/SPI của thiết bị) cộng với offset ghi trong register map. Bên trong mỗi thanh ghi, một số bit được đánh dấu Reserved — đây là các bit dành riêng cho tương lai hoặc mục đích nội bộ của nhà sản xuất, không có ý nghĩa được công bố. Đa số datasheet yêu cầu: khi ghi một thanh ghi có chứa reserved bit, phải đọc giá trị hiện tại trước, chỉ thay đổi đúng bit field cần thay đổi, giữ nguyên reserved bit, rồi mới ghi lại toàn bộ thanh ghi — kỹ thuật này gọi là read-modify-write.

Tóm lại: Register map là ngôn ngữ chung giữa datasheet và code — mỗi bit đều có ý nghĩa xác định (hoặc cố tình không xác định, với reserved bit). Ghi thẳng một giá trị cố định vào cả thanh ghi mà không quan tâm reserved bit đang chứa gì là thói quen nguy hiểm, dù thường "chạy được" trong test nhanh ban đầu.

Kiến thức kỹ thuật

Công thức

Tính địa chỉ tuyệt đối của một thanh ghi, và trích xuất giá trị một bit field cụ thể bằng phép dịch bit + mặt nạ (mask):

Địa_chỉ_thanh_ghi = Base_Address + Offset

VD: cảm biến I2C có Base_Address = 0x68, thanh ghi CTRL ở Offset 0x00
Địa_chỉ_CTRL = 0x68 + 0x00 = 0x68 (byte đầu tiên gửi sau địa chỉ thiết bị)

Trích xuất bit field M1:M0 (bit 3:2) từ giá trị thanh ghi CTRL:
mode = (gia_tri_thanh_ghi >> 2) & 0b11
(dịch phải 2 bit để đưa M1:M0 về vị trí thấp nhất, rồi AND với mask 2-bit)

Ghi bit EN (bit 4) thành 1 mà KHÔNG đổi các bit khác (read-modify-write):
gia_tri_moi = (gia_tri_hien_tai | (1 << 4))

Thông số

Kỹ thuậtDùng khi
(giá_trị >> n) & maskĐọc (trích xuất) một bit field cụ thể
giá_trị | (1 << n)Bật (set) một bit cụ thể thành 1, giữ nguyên các bit khác
giá_trị & ~(1 << n)Tắt (clear) một bit cụ thể thành 0, giữ nguyên các bit khác
giá_trị ^ (1 << n)Đảo (toggle) một bit cụ thể

Ứng dụng thực tế

Khi cấu hình một IMU như MPU6050 (đã học ở bài MPU6050, chuyên mục Sensor & Perception) qua I2C, việc chọn dải đo (full scale range) của accelerometer/gyroscope thực chất là ghi đúng bit field trong thanh ghi cấu hình tương ứng — nếu không đọc kỹ register map và vô tình ghi đè cả thanh ghi bằng một giá trị cố định, có thể vô tình tắt luôn các tính năng khác đang được bật bởi các bit khác trong cùng thanh ghi đó mà không hề hay biết.

Ví dụ thực tế

def doc_gia_tri_thanh_ghi(i2c, dia_chi_thiet_bi, offset):
    return i2c.read_byte(dia_chi_thiet_bi, offset)  # gia lap

def ghi_bit_field(gia_tri_hien_tai, vi_tri_bit, so_bit, gia_tri_moi):
    mask = ((1 << so_bit) - 1) << vi_tri_bit
    return (gia_tri_hien_tai & ~mask) | ((gia_tri_moi << vi_tri_bit) & mask)

# Kich ban: doc thanh ghi CTRL hien tai, chi doi bit field M1:M0 (vi tri 2, rong 2 bit)
gia_tri_hien_tai = 0b00110101  # gia su gia tri doc duoc tu thiet bi that
gia_tri_moi = ghi_bit_field(gia_tri_hien_tai, vi_tri_bit=2, so_bit=2, gia_tri_moi=0b10)

print(f"Truoc: {bin(gia_tri_hien_tai)}")
print(f"Sau:   {bin(gia_tri_moi)}")
Output:
Truoc: 0b110101
Sau:   0b111001

Chỉ 2 bit ở vị trí M1:M0 thay đổi (từ 01 thành 10), mọi bit khác — bao gồm cả reserved bit — giữ nguyên giá trị đã đọc được từ thiết bị, đúng kỹ thuật read-modify-write.

Lỗi thường gặp

  • Ghi thẳng một giá trị cố định vào cả thanh ghi thay vì read-modify-write — như đã nêu, vô tình ghi đè reserved bit hoặc các bit field khác đang được thiết bị sử dụng cho mục đích khác.
  • Nhầm thứ tự bit (bit 0 là LSB hay MSB) khi đọc sơ đồ bit field — hầu hết datasheet đánh số bit 0 là LSB (bit thấp nhất, phải nhất trong biểu diễn nhị phân), nhưng cần xác nhận quy ước cụ thể của từng hãng thay vì giả định.
  • Nhầm offset với địa chỉ tuyệt đối — như tính ở mục Công thức, offset luôn cần cộng với base address mới ra địa chỉ thực tế để đọc/ghi, không dùng thẳng offset làm địa chỉ.
  • Không kiểm tra quyền truy cập (R/W) trước khi ghi — cố ghi vào thanh ghi chỉ đọc (Read-only, thường là thanh ghi trạng thái) không gây lỗi rõ ràng ở nhiều thiết bị, chỉ đơn giản không có tác dụng gì, dễ gây nhầm lẫn khi debug.

Kết luận

Register map là cầu nối cụ thể giữa lý thuyết datasheet và code thực thi — offset xác định địa chỉ, bit field xác định ý nghĩa từng nhóm bit, và reserved bit đòi hỏi kỹ thuật read-modify-write để không vô tình phá vỡ trạng thái nội bộ của thiết bị. Đây là bài cuối của chuyên mục Đọc Datasheet — bốn bài đã đi từ cấu trúc tổng thể, giới hạn tuyệt đối, quan hệ thời gian, tới chi tiết từng bit. Chuyên mục Chuẩn & Giao thức tiếp theo mở rộng sang các tài liệu chuẩn hoá ở quy mô lớn hơn — an toàn robot công nghiệp, quy ước ROS2, và các chuẩn liên quan.

Đọc register map — bit field, offset, reserved bit — Atlasbot