Tải bản đầy đủ (.docx) (42 trang)

bai7.giao tiep SPI

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (1.14 MB, 42 trang )

Bài 7 - Giao tiếp SPI


1

2

3

4

5
( 43 Votes )
Nội dung Các bài cần tham khảo trước
1. Giới thiệu .
2. Chuẩn truyền thông SPI .
3. Truyền thông SPI trên AVR .
Download ví dụ
Cấu trúc AVR .
AVR Studio .
C cho AVR.
Mô phỏng với Proteus.
Text LCD
I. Giới thiệu.
Bài này giúp các bạn biết cách sử dụng cách truyền thông nối tiếp đồng bộ SPI.
Công cụ chính cũng là 2 bộ phần mềm AVRStudio (+gcc-avr) và Proteus. Thực
chất ngôn ngữ lập trình vẫn là gcc-avr nhưng tôi không dùng Programmer Notepad
để biết code như thông thường, thay vào đó tôi dùng AVRStudio làm trình biên tập,
bạn tham khảo thêm phần “Lập trình C bằng AVRStudio” trong bài hướng dẫn sử
dụng AVRStudio để biết thêm cách thực hiện. Tôi sẽ dùng chip ATmega32 làm
minh họa.


Sau bài này, tôi hy vọng bạn có thể hiểu và thực hiện được:
• Nguyên lý truyền thông nối tiếp SPI.
• Sử dụng module SPI trong AVR ở các chế độ Master và Slave.
II. Chuẩn truyền thông SPI,
SPI (Serial Peripheral Bus) là một chuẩn truyền thông nối tiếp tốc độ cao do
hang Motorola đề xuất. Đây là kiểu truyền thông Master-Slave, trong đó có 1 chip
Master điều phối quá trình tuyền thông và các chip Slaves được điều khiển bởi
Master vì thế truyền thông chỉ xảy ra giữa Master và Slave. SPI là một cách truyền
song công (full duplex) nghĩa là tại cùng một thời điểm quá trình truyền và nhận có
thể xảy ra đồng thời. SPI đôi khi được gọi là chuẩn truyền thông “4 dây” vì có 4
đường giao tiếp trong chuẩn này đó là SCK (Serial Clock), MISO (Master Input
Slave Output), MOSI (Master Ouput Slave Input) và SS (Slave Select). Hình 1 thể
hiện một kết SPI giữa một chip Master và 3 chip Slave thông qua 4 đường.
SCK: Xung giữ nhịp cho giao tiếp SPI, vì SPI là chuẩn truyền đồng bộ nên
cần 1 đường giữ nhịp, mỗi nhịp trên chân SCK báo 1 bit dữ liệu đến hoặc đi. Đây
là điểm khác biệt với truyền thông không đồng bộ mà chúng ta đã biết trong chuẩn
UART. Sự tồn tại của chân SCK giúp quá trình tuyền ít bị lỗi và vì thế tốc độ
truyền của SPI có thể đạt rất cao. Xung nhịp chỉ được tạo ra bởi chip Master.
MISO– Master Input / Slave Output: nếu là chip Master thì đây là đường
Input còn nếu là chip Slave thì MISO lại là Output. MISO của Master và các
Slaves được nối trực tiếp với nhau..
MOSI – Master Output / Slave Input: nếu là chip Master thì đây là đường
Output còn nếu là chip Slave thì MOSI là Input. MOSI của Master và các Slaves
được nối trực tiếp với nhau.
SS – Slave Select: SS là đường chọn Slave cần giap tiếp, trên các chip Slave
đường SS sẽ ở mức cao khi không làm việc. Nếu chip Master kéo đường SS của
một Slave nào đó xuống mức thấp thì việc giao tiếp sẽ xảy ra giữa Master và Slave
đó. Chỉ có 1 đường SS trên mỗi Slave nhưng có thể có nhiều đường điều khiển SS
trên Master, tùy thuộc vào thiết kế của người dùng.
.

Hình 1. Giao diện SPI.
Hoạt động: mỗi chip Master hay Slave có một thanh ghi dữ liệu 8 bits. Cứ
mỗi xung nhịp do Master tạo ra trên đường giữ nhịp SCK, một bit trong thanh ghi
dữ liệu của Master được truyền qua Slave trên đường MOSI, đồng thời một bit
trong thanh ghi dữ liệu của chip Slave cũng được truyền qua Master trên đường
MISO. Do 2 gói dữ liệu trên 2 chip được gởi qua lại đồng thời nên quá trình truyền
dữ liệu này được gọi là “song công”. Hình 2 mô tả quá trình truyền 1 gói dữ liệu
thực hiện bởi module SPI trong AVR, bên trái là chip Master và bên phải là Slave.

Hình 2. Truyền dữ liệu SPI.
Cực của xung giữ nhịp, phase và các chế độ hoạt động: cực của xung giữ nhịp
(Clock Polarity) được gọi tắt là CPOL là khái niệm dùng chỉ trạng thái của chân
SCK ở trạng thái nghỉ. Ở trạng thái nghỉ (Idle), chân SCK có thể được giữ ở mức
cao (CPOL=1) hoặc thấp (CPOL=0). Phase (CPHA) dùng để chỉ cách mà dữ liệu
được lấy mẫu (sample) theo xung giữ nhịp. Dữ liệu có thể được lấy mẫu ở cạnh lên
của SCK (CPHA=0) hoặc cạnh xuống (CPHA=1). Sự kết hợp của SPOL và CPHA
làm nên 4 chế độ hoạt động của SPI. Nhìn chung việc chọn 1 trong 4 chế độ này
không ảnh hưởng đến chất lượng truyền thông mà chỉ cốt sao cho có sự tương
thích giữa Master và Slave.
III. Truyền thông SPI trên AVR.
Module SPI trong các chip AVR hầu như hoàn toàn giống với chuẩn SPI mô tả
trong phần trên. Vì thế, nếu đã hiểu cách truyền thông SPI thì sẽ khống quá khó để
thực hiện việc truyền thông này với AVR. Phần bên dưới tôi trình bày một số điểm
quan trọng khi điều khiển SPI trên AVR.
Các chân SPI: Các chân giao tiếp SPI cũng chính là các chân PORT thông thường,
vì thế nếu muốn sử dụng SPI chúng ta cần xác lập hướng cho các chân này. Trên
chip ATmega32, các chân SPI như sau:
SCK – PB7 (chân 8)
MISO – PB6 (chân 7)
MOSI – PB5 (chân 6)

SS – PB4 (chân 5)
Khi chip AVR được sử dụng làm Slave, bạn cần set các chân SCK input, MOSI
input, MISO output và SS input. Nếu là Master thì SCK output, MISO output,
MOSI input và khi này chân SS không quan trọng, chúng ta có thể dùng chân này
để điều khiển SS của Slaves hoặc bất kỳ chân PORT thông thường nào.
Thanh ghi: SPI trên AVR được vận hành bởi 3 thanh ghi bao gồm thanh ghi
điều khiển SPCR , thanh ghi trạng thái SPSR và thanh ghi dữ liệu SPDR.
SPCR (SPI Control Register): là 1 thanh ghi 8 bit điều khiển tất cả hoạt động
của SPI.

* Bit 7- SPIE (SPI Interrupt Enable) bit cho phép ngắt SPI. Nếu bit này được
set bằng 1 và bit I trong thanh ghi trạng thái được set bằng 1 (sei), 1 ngắt sẽ xảy ra
sau khi một gói dữ liệu được truyền hoặc nhận. Chúng ta nên dùng ngắt (nhất là
đối với chip Slave) khi truyền nhận dữ liệu với SPI.
* Bit 6 – SPE (SPI Enable). set bit này lên 1 để cho phép bộ SPI hoạt động. Nếu
SPIE=0 thì module SPI dừng hoạt động.
* Bit 5 – DORD (Data Order) bit này chỉ định thứ tự dữ liệu các bit được
truyền và nhận trên các đường MISO và MOSI, khi DORD=0 bit có trọng số lớn
nhất của dữ liệu được truyền trước (MSB) ngược lại khi DORD=1, bit LSB được
truyền trước. Thật ra khi giao tiếp giữa 2 AVR với nhau, thứ tự này không quan
trọng nhưng phải đảm bảo các bit DORD giống nhau trên cả Master và Slaves.
* Bit 4 – MSTR (Master/Slave Select) nếu MSTR =1 thì chip được nhận diện là
Master, ngược lại MSTR=0 thì chip là Slave..
* Bit 3 và 2 – CPOL và CPHA đây chính là 2 bit xác lập cực của xung giữ nhịp
và cạnh sample dữ liệu mà chúng ta đã khảo sát trong phần đầu. Sự kết hợp 2 bit
này tạo thành 4 chế độ hoạt động của SPI. Một lần nữa, chọn chế độ nào không
quan trọng nhưng phải đảm bảo Master và Slave cùng chế độ hoạt động. Vì thế có
thể để 2 bit này bằng 0 trong tất cả các chip. Hình 3 trình bày cách sample dữ liệu
trong 4 chế độ của SPI trên AVR.


ra khi giao tiếp giữa 2 AVR với nhau, thứ tự này không quan
trọng nhưng phải đảm bảo các bit DORD giống nhau trên cả
Master và

Slaves.
CPHA=0
CPHA=1

Hình 3. Các chế độ hoạt động của SPI.
* Bit 1:0 – CPR1:0 hai bit này kết hợp với bit SPI2X trong thanh ghi SPSR
cho phép chọn tốc độ giao tiếp SPI, tốc độ này được xác lập dựa trên tốc độ nguồn
xung clock chia cho một hệ số chia. Bảng 1 tóm tắt các tốc độ mà SPI trong AVR
có thể đạt. Thông thường, tốc bộ này không được lớn hơn 1/4 tốc độ xung nhịp cho
chip.

SPSR (SPI Status Register): là 1 thanh ghi trạng thái của module SPI. Trong
thanh ghi này chỉ có 3 bit được sử dụng. Bit 7 – SPIF là cờ báo SPI, khi một gói
dữ liệu đã được truyền hoặc nhận từ SPI, bit SPIF sẽ tự động được set len 1. Bit 6
– WCOL là bít báo va chạm dữ liệu (Write Colision), bit này được AVR set lên 1
nếu chúng ta cố tình viết 1 gói dữ liệu mới vào thanh ghi dữ liệu SPDR trong khi
quá trình truyền nhận trước chưa kết thúc. Bit 0 – SPI2X gọi là bit nhân đôi tốc độ
truyền, bit này kết hợp với 2 bit SPR1:0 trong thanh ghi điều khiển SPCR xác lập
tốc độ cho SPI.
SPDR (SPI Data Register): là thanh ghi dữ liệu của SPI. Trên chip Master, ghi
giá trị vào thanh ghi SPDR sẽ kích quá trình tuyền thông SPI. Trên chip Slave, dữ
liệu nhận được từ Master sẽ lưu trong thanh ghi SPDR, dữ liệu được lưu sẵn trong
SPDR sẽ được truyền cho Master.
Sử dụng SPI trên AVR: SPI trên AVR hoạt động không khác nguyên lý chung
của chuẩn SPI là mấy. Vận hành SPI trên AVR được thực hiện dựa trên việc ghi và
đọc 3 các thanh ghi SPCR, SPSR và SPDR. Trước khi truyền nhận bằng SPI chúng

ta cần khởi động SPI, quá trình khởi động thường bao gồm chọn hướng giao tiếp
cho các chân SPI, chọn loại giao tiếp: Master hay Slave, chọn chế độ SPI (SPOL,
SPHA) và chọn tốc độ giao tiếp. Truyền thông SPI luôn được khởi xướng bởi chip
Master, khi Master muốn giao tiếp với 1 Slave nào đó, nó sẽ kéo chân SS của Slave
xuống mức thấp (gọi là chọn địa chỉ) và sau đó viết dữ liệu cần truyền vào thanh
ghi dữ liệu SPDR, khi dữ liệu vừa được viết vào SPDR xung giữ nhịp sẽ được tự
động tạo ra trên SCK và quá trình truyền nhận bắt đầu. Đối với các chip Slave, khi
chân SS bị kéo xuống nó sẽ sẵn sàng cho quá trình truyền nhận. Khi phát hiện
xung giữ nhịp trên SCK, Slave sẽ bắt đầu sample dữ liệu đến trên đường MOSI và
gởi dữ liệu di trên MISO.
Để minh họa cho cách truyền và nhận dữ liệu SPI trên AVR, tôi sẽ thực hiện
một ví dụ truyền nhân 1 chiều với 1 chip Master và 3 chip Slaves. Tất cả các chip
được dùng là ATmega32, chip Master sẽ điều khiển các chip Slaves thông qua 3
đường chọn chip PB0, PD1 và PD2. Công việc thực hiện trong ví dụ này như sau:
Master sẽ lần lượt chọn 1 trong 3 chip Slaves và gởi các gói dữ liệu tương ứng đến
chúng, chip Slave0 sẽ nhận được các con số từ 0 đến 80, Slave1 nhận 80 đến 160
và Slave2 nhận dữ liệu từ 160 đến 240. Các Slave sẽ hiển thị giá trị mà mình nhận
được trên các Text LCD kết nối với PORTD ở mỗi Slave. Sơ đồ mạch điện vẽ bằng
Proteus cho ví dụ này được trình bày trong hình 4.
Hình 4. Mô phỏng ví dụ giao tiếp SPI trên AVR.
Trong bài này, tôi sẽ dùng phần mềm AVRStudio kết hợp với gcc-avr trong
WinAVR để lập trình bằng ngôn ngữ C cho AVR. Bạn hãy tham khảo thêm bài
AVRStudio để biết cách tạo 1 Project lập trình C cho AVR bằng AVRStudio. Hãy
tạo 2 Project riêng, 1 Project có tên SPI_Master cho chip Master và 1 Project có
tên SPI_Slave dùng chung cho cả 3 Slaves. Copy file myLCD.h dùng cho điều
khiển Text LCD được tạo trong bài “Text LCD” vào cả 2 thư mục chứa 2 Projects
mới tạo. Viết đoạn code trong list 0 vào file SPI_Master.c và đoạn code trong list 1
vào file SPI_Slave.c.
List 1. Đoạn code cho SPI Master.



Tôi sẽ giải thích sơ lượt một số điểm chính trong đoạn code cho chip Master.
Các phần định nghĩa từ dòng thứ 10 đến dòng 17 chỉ có tác dụng làm cho chương
trình dễ đọc hiểu hơn và có tính tương thích cao hơn, ví dụ nếu bạn muốn sử dụng
ví dụ này cho các chip khác bạn chỉ cần thay đổi các định nghĩa này mà không phải
thay đổi trong nội dung các chương trình con. Chúng ta định nghĩa để chọn
PORTB điều khiển các đường chọn chip SS của Slave (gọi là các đường địa chỉ),
dòng 18 định nghĩa Slave(i) là thứ tự chân trên PORT dùng cho chip Slave thứ i.
Dễ hiểu hơn, đường SS trên Slave0 sẽ được kết nối và điều khiển bởi chân 0 của
PORTB (chân PB0 và tương tự cho các Slaves còn lại. Biến wData định nghĩa trên
dòng 20 là một mảng 3 phần tử chứa các con số 8 bits sẽ truyền đến các Slaves.
Chương trình con “void SPI_MasterInit(void)”: Chương trình này khởi động
cho chip Master, việc khởi động trước hết là set hướng cho các chân SPI. Đối với
Master, các chân tạo xung giữ nhịp SCK và chân truyền dữ liệu MOSI cần được set
Output như trong dòng 24, các chân SPI còn lại là input. Dòng 25 giúp kéo điện trở
kéo lên ở chân nhận dữ liệu MISO của Master. Dòng lệnh 26 “SPCR=(1<<SPIE)|
(1<<SPE)|(1<<MSTR)|(1<<CPHA)|(1<<SPR1)|(1<<SPR0); ” thật sự khởi động
SPI với việc set bit SPIE: cho phép ngắt SPI=1, bit SPE=1 cho phép SPI hoạt
động, MSTR=1 xác lập chip là chip Master. CPHA=1 tức chân SCK sẽ ở mức thấp
khi SPI không hoạt động, trong khi CPOL=0 (không set CPOL thì mặc định là 0)
thì dữ liệu sẽ được sample (lấy mẫu) ở cạnh xuống của xung SCK. Cuối cùng cả 2
bit SPR1 và SPR0 đều được set lên 1, tốc độ SPI sẽ bằng tốc độ nguồn cung nuôi
chip chia cho 128 (xem bảng 1). Dòng code 29 set hướng Output cho các chân
dùng làm chân địa chỉ chọn chip Slaves (các chân PB0, PB1, PB2), sau đó kéo các
chân này lên mức cao để disable tất cả các Slaves (sau này sẽ kích hoạt sau).
Chương trình con “void SPI_Transmit(uint8_t i, uint8_t data)”: chương
trình truyền dữ liệu qua SPI của chip Master, chương trình có 2 tham số là địa chỉ
chip Slave (biến i) và dữ liệu cần truyền (biến data). Trước khi truyền dữ liệu,
Master sẽ thực hiện việc chọn Slave, dòng 35 “cbi(ADDRESS_PORT, Slave(i));”
thực hiện việc này. Thực chất dòng này là kéo chân “i” của PORTB xuống mức

thấp, cũng là kéo chân SS của Slave xuống mức thấp. Dòng 36 gán giá trị cần
truyền cho thanh ghi dữ liệu “SPDR=data”, sau khi gán giá trị cho SPDR, xung
clock sẽ tự động được Master tạo ra trên SCK, quá trình truyền bắt đầu. Quá trình
truyền kết thúc thì bit cờ SPIF trong thanh ghi trạng thái SPSR được set lên 1,
dòng 36 thực hiện việc chờ bit cờ SPIF để kết thúc quá trình truyền. Khi kết thúc
truyền 1 byte cho Slave, set chân SS của Slave lên mức cao để vô hiệu hóa SPI,
dòng 37.
Chương trình chính: chương trình chính cho chip Master SPI tương đối đơn
giản, trước hết chúng ta cần gọi chương trình con khởi động SPI ở dòng 43. Trong
vòng lặp vô tận while, lần lượt gởi các giá trị đến các Slaves. Dòng 46 gọi chương
trình con gởi giá trị biến wData[0] đến Slave0, dòng 50 truyền biến wData[1] cho
Slave1 và dòng 54 truyền biến wData[2] cho Slave2
List 2.Đoạn code cho Slave SPI.

Đoạn code trong list 2 là đoạn code cho chip Slaves, chú ý dòng 3 chúng ta
include file header “interrupt.h” vì việc nhận dữ liệu SPI của SLave được thực hiện
bằng ngắt SPI. Các định nghĩa biến trong các dòng code từ 8 đến 15 tương tự như
trong chương trình cho chip Master. Tôi sẽ tập trung giải thích các điểm khác biệt
cho Slaves.
Chương trình con “void SPI_SlaveInit(void)”: Chương trình này khởi động
cho chip Slave, cũng giống như trường hợp của Master, việc khởi động trước hết là
set hướng cho các chân SPI. Đối với Slave, chỉ có chân truyền dữ liệu MISO là cần
được set Output như trong dòng 19, các chân SPI còn lại là input. Dòng 20 giúp
kéo điện trở kéo lên ở các chân nhận dữ liệu MOSI của Slave, và chân chọn Slave
SS. Việc tiếp theo là cài đặt các thanh ghi SPI như trong dòng lệnh 21,
“SPCR=(1<<SPIE)|(1<<SPE)|(1<<CPHA)|(1<<SPR1)|(1<<SPR0); ”, nếu quan sát
dòng lệnh 26 trong List 1 chop chip Master, dòng này không khác là mấy, quá trình
khởi động SPI cho Slave tương tự Master với một điểm khác duy nhất là bit
MSTR, bit này không được set lên 1 đối với Slaves.
Trình phục vụ ngắt “ISR(SPI_STC_vect)”: SPI trên AVR chỉ có duy nhất

một sự kiện gây ra ngắt đó là khi quá trình truyền-nhận kết thúc. Tên vector ngắt
SPI trong ngôn ngữ lập trình avr-gcc là “SPI_STC_vect. Trong ví dụ này, khi một
ngắt SPI xảy ra ở Slave, chúng ta sẽ đọc thanh ghi SPDR và sau đó hiển thị giá trị
đọc được trên LCD. Dòng 37, rData=SPDR, gán thanh ghi SPDR cho biến rData.
Từ dòng 38 đến 42 là cách hiển thị giá trị đọc về trên Text LCD bằng thư viện
myLCD (xem bài Text LCD). Dòng 39 chúng ta khai báo 1 biến tạm dạng mảng
động, dis, làm buffer chứa giá trị ascii của các ký tự cần hiển thị lên LCD. Chú ý là
giá trị nhận về là 1 con số 8 bit, muốn hiển thị giá trị này lên LCD chúng ta không
thể hiển thị trực tiếp bằng lệnh putChar_LCD vì hàm putChar_LCD xem tham số
nhập vào là mã Ascii, ví dụ chúng ta nhận về số rData=65, nếu dùng hàm
putChar_LCD(rData) thì trên LCD chỉ thấy ký tự ‘A’ vì 65 là mã Ascii của ký tự
‘A’. Để LCD hiển thị “65” chúng ta xem 65 là một chuỗi các ký tự, trước hết cần
chuyển số 65 thành các ký tự ‘6’ và ‘5’, hàm “sprintf(dis,"%i",rData)” trong dòng
code 40 thực hiện việc định dạng lại biến rData thành chuỗi các ký tự và chứa
trong buffer dis, “%i” là “cờ” định dạng, báo cho hàm sprintf xem rData là một số
nguyên. Sau dòng 40, ví dụ rData=65, thì dis=”65”. Dòng 42 in chuỗi dis lên LCD:
print_LCD(dis);.
Chương trình chính: chương trình chính cho chip Slave không làm nhiều
việc vì các việc chính như nhận và hiển thị đã được thực hiện trong trình phục vụ
ngắt SPI. Dòng 27 sei() cho phép ngắt toàn cục, điều này là cần thiết để ngắt SPI
có thể xảy ra, dòng 28 gọi chương trình con khởi động SPI cho Slave, sau đó khởi
động LCD ở dòng 29 và kết thúc. Không có việc gì cần thực hiện trong vòng lặp
while().
Text LCD


1

2


3

4

5
( 64 Votes )
Nội dung Các bài cần tham khảo trước
1. Bạn sẽ đi đến đâu.
2. Text LCD.
3. AVR và Text LCD.
4. Ví dụ điều khiển Text LCD bằng thư viện myLCD.
Download ví dụ
Cấu trúc AVR
WinAVR
C cho AVR.
Mô phỏng với Proteus.


I. Bạn sẽ đi đến đâu.
Bài này nằm trong phần ứng dụng AVR thuộc loạt bài cùng học AVR. Trong
bài ứng dụng này chúng ta không khảo sát nhiều cấu trúc AVR mà chủ yếu là tìm
hiểu Text LCD cách điều khiển bằng AVR. Công cụ chính cũng là 2 bộ phần mềm
quen thuộc WinAVR và Proteus.
Sau bài này, tôi hy vọng bạn có thể hiểu và thực hiện được:
- Cấu trúc Text LCD.
- Nguyên lý hoạt động Text LCD
- Phát triển 1 thư viện điều khiển Text LCD bằng AVR cả 2 chế độ 8 bit và 4
bit.
- Ví dụ điều khiển Text LCD bằng AVR.
II. Text LCD.

Text LCD là các loại màn hình tinh thể lỏng nhỏ dùng để hiển thị các dòng chữ
hoặc số trong bảng mã ASCII. Không giống các loại LCD lớn, Text LCD được chia

Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×