Mục lục
Lời nói đầu 4
Tóm tắt đồ án 5
Danh sách các hình vẽ 8
Danh sách các bảng 8
Danh sách các công thức 9
Phần mở đầu 10
Chương 1 : Giới thiệu chung 12
1.1) Quảng cáo 12
1.2) Bảng led quảng báo 13
1.2.1) Một số đặc trưng 13
1.1.2) Quảng cáo bằng led 14
1.3) Giới thiệu chung về hệ thống 18
Chương 2 : Giới thiệu về vi điều khiển AVR Atmega16 21
2.1) Giới thiệu về vi điều khiển họ AVR 21
2.1.1) Một số đặc trưng 21
2.1.2) Một số đặc trưng 23
2.1.3) Một số đặc trưng 25
2.1.4) Một số họ vi diều khiển AVR 26
2.2) Sơ bộ về vi điều khiển Atmega16 26
2.2.1) Đặc trưng 28
2.2.2) CPU 31
2.2.3) Bộ nhớ 37
Chương 3 : Nguyên tắc điều khiển led ma trận 42
3.1) Cấu trúc và nguyên lý cấp nguồn cho led ma trận 42
3.2) Nguyên tắc tạo font chữ hiển thị 43
3.3) Điều khiển hiển thị led ma trận 44
Chương 4: Điều khiển cấp nguồn cho led ma trận 47
4.1) Điều khiển cấp nguồn cho cột dùng 74HC138 47
4.1.1) Chức năng của 74HC138 47
4.1.2) Sử dụng 74HC138 để cấp nguồn cho các cột ma trận 48
4.2) Điều khiển cấp nguồn cho hàng dùng 74HC595 50
4.2.1) Chức năng của 74HC595 50
4.2.2) Sử dụng 74HC595để cấp nguồn cho các hàng của ma trận 51
4.3) Truyền dữ liệu cấp nguồn cho hàng sử dụng SPI 54
4.3.1) Atmega16 SPI 54
4.3.2) Thiết lập SPI truyền dữ liệu cho 74HC595 58
4.3) Kết luận 59
ương5: Tạo tần số quét cho ma trận 60
5.1) Timer1 Atmega16 60
5.1.1) Một số chế độ hoạt động 60
5.1.2) Các thanh 65
5.2) Tạo tần số quét ma trận 70
5.3) Kết luận 71
ương 6: Hiệu ứng hiển thị bảng led 72
6.1) Bảng led hiển thị 72
6.2) Dịch trái, phải 74
6.3) Dịch lên xuống 78
6.4) Hiển thị từng kí tự 81
6.5) Kết luận 83
t luận 84
Tài liệu tham khảo 85
ụ lục A: Sơ đồ ghép nối hệ thống điều khiển led ma trận 86
ụ lục B: Mã chương trình nạp cho vi điều khiển 90
103 trang |
Chia sẻ: tlsuongmuoi | Lượt xem: 2754 | Lượt tải: 1
Bạn đang xem trước 20 trang tài liệu Đề tài Thiết kế bảng quảng cáo led sử dụng vi điều khiển atmega 16 module điều khiển hiển thị, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
, khi đó một chân của IC
sẽ được nối với các cột của các ma trận khác nhau .
49
4.2) Điều khiển cấp nguồn cho hàng dùng 74HC595
4.2.1) Chức năng của 74HC595
74HC595 [5] là bộ ghi dịch 8 bít gồm có :
1 đầu vào cho phép (OE )
1 đầu vào chọn thanh ghi dịch (MR )
1 đầu vào dữ liệu nối tiếp (DS)
1 đầu vào cấp xung cho thanh ghi dịch (SH_CP)
1 đầu vào cấp xung cho thanh ghi chứa (ST_CP)
8 đầu ra 3 trạng thái ( Q1 đến Q7 và Q7’)
Hình 4 - Sơ đồ chân 74HC595
50
Bảng 4 - Chức năng hoạt động của 74HC595
Đầu vào Đầu ra Chức năng
SH_CP ST_CP OE MR DS Q7’ Qn
X X L L X L kđ
MR mức thấp dữ liệu chỉ dịch
trong thanh ghi dịch đầu ra
không đổi trạng thái
X ↑ L L X L L Xóa thanh ghi dich nạp dữ liệu
vào thanh ghi chứa
X X H L X L Z Xóa thanh ghi dịch đầu ra ở
trạng thái trở kháng cao
↑ X L H H Q6’ kđ
Dịch chuyển trạng thái cao vào
thanh ghi dịch, giá trị trước đó
của bít thứ 6 trong thanh ghi
dịch được chuyển sang đầu ra
Q7’
X ↑ L H X kđ Qn’
Nội dụng của thanh ghi dịch
được chuyển sang thanh ghi
chứa và chuyển sang đầu ra
↑ ↑ L H X Q6’ Qn’
Dịch chuyển nội dung của
thanh ghi dịch đồng thời nội
dung của thanh ghi dịch cũ
được chuyển vào thanh ghi
chứa và các đầu ra song song
4.2.2) Sử dụng 74HC595để cấp nguồn cho các hàng của ma trận
Khi dùng 74HC595 để cấp nguồn cho ma trận led ta nối các đầu ra song song
của 74HC595 với các chân cấp nguồn cho hàng của ma trận. Đồng thời phải sử
51
dụng 3 chân của vi điều khiển để nối với các chân DS,SH_CP,ST_CP của
74HC595. Các bit dữ liệu mã hóa mức logic cần cấp cho các hàng của 1 cột ma trận
sẽ được truyền liên tiếp DS của 74HC595. Để đồng bộ bit thì vi điều khiển mỗi khi
xuất 1 bit tới chân DS sẽ phát một xung có sườn dương vào chân SH_CP. Sau khi
truyền xong hết dữ liệu, để các led trên cột sáng thì ta phải chuyển dữ liệu trong
thanh ghi dịch vào các đầu ra của 74HC595 bằng cách cấp 1 xung sườn dương vào
chân ST_TP. Chú ý để IC có thể hoạt động và đẩy dữ liệu ra các chân đầu ra thì
chân OE phải nối đất, chân MR nối dương nguồn.
Hình 4 - Ghép nối 74HC595 với vi điều khiển để cấp nguồn cho hàng của ma
trận
Khi mở rộng ma trận led ta ghép nhiều 74HC595 nối tiếp nhau: các chân
SH_CP được nối chung với 1 nguồn cấp xung, các chân ST_CP cũng được nối
chung với nhau, đầu ra Q7’ của IC phía trước được nối với đầu vào DS của IC tiếp
theo. Khi đó dữ liệu sẽ được dịch đồng bộ từ IC này sang IC khác và đầu ra của các
IC cũng được chốt đồng bộ.
52
Hình 4 - Ghép nối tiếp các IC 74HC595
53
4.3) Truyền dữ liệu cấp nguồn cho hàng sử dụng SPI
4.3.1) Atmega16 SPI
Để truyền dữ liệu từ vi điều khiển vào bộ ghi dịch ta có thể dùng một đoạn
chương trình phần mềm lập trình cho vi điều khiển truyền từng bit của dữ liệu. Tuy
nhiên Atmega16 có phần cứng hỗ trợ việc truyền dữ liệu nối tiếp với các thiết bị
ngoại vi (SPI).
a) Sơ đồ khối và các chế độ SPI [3] :
Hình 4 - Sơ đồ khối của SPI
Ta có thể thiết lập SPI ở 2 chế độ Master và Slave :
Ở chế độ Slave, chân Slave Select ( SS ) phải đặt là đầu vào .Khi chân này bị
kéo xuống mức thấp thì SPI sẽ hoạt động, chân MISO có thể đặt làm đầu ra, các
chân khác là đầu vào. Khi chân SS được kéo lên mức cao ở mức cao SPI ngừng
nhận dữ liệu từ bên ngoài vào. Chân SS có tác dụng đồng bộ byte, gói giúp cho bộ
54
đếm bit của slave đồng bộ với bộ phát xung của master. Khi SS bị kéo lên mức cao
thì SPI slave sẽ tái lập lại mức logic truyền và nhận, đồng thời xóa dữ liệu đã nhận
trong thanh ghi dịch.
Ở chế độ Master, ta có thể đặt SS làm đầu ra hay vào tùy ý :
Nếu SS được đặt làm đầu ra thì nó không làm ảnh hưởng tói SPI , nó chỉ có tác
dụng điều khiển mức logic cho chân SS của SPI slave.
Nếu SS được đặt làm đầu vào thì nó phải được giữ ở mức cao để đảm bảo các
hoạt động của SPI master. Nếu SPI bị kéo xuống mức thấp bởi thiết bị ngoại vi thì
nó sẽ hiểu đó là một Master khác nên sẽ đặt lại SPI ở chế độ Slave và bắt đầu truyền
dữ liệu. Để tránh xung đột trong quá trình này SPI tiến hành các thủ tục sau:
- Xóa bit MSTR trong thanh ghi SPCR để SPI ở chế độ Slave. Do đó các chân
MOSI và SCK trở thành đầu vào.
- Thiết lập mức cao cho cờ SPIF trong thanh ghi SPCR. Nếu ngắt SPI và ngắt
toàn cục được cho phép thì quá trình ngắt sẽ được thực hiện.
b) Các thanh ghi SPI:
* Thanh ghi diều khiển - SPCR :
Bit 7 6 5 4 3 2 1 0
Read/Write R/W R/W R/W R/W R/W R/W R/W R/W
Khởi tạo 0 0 0 0 0 0 0 0
Bit 7 - SPIE : SPI Interupt Enable
Ngắt SPI sẽ được thực hiện nếu cờ SPIF trong SPSR được thiết lập và ngắt
toàn cục được cho phép.
Bit 6 - SPE : SPI Enable
Bit này phải được đặt ở mức cao để SPI có thể hoạt động
Bit 5 - DORD : Data Order
Khi DORD ở mức cao thì bit LSB được truyền trước
Khi DORD ở mức thấp thì bit MSB được truyền trước
SPIE SPE DORD MSTR CPOL CPHA SPR1 SPR0
55
Bit 4 - MSTR : Master/Slave Select
Bit có tác dụng chọn chế độ cho SPI : Master nếu ở mức cao, Slave nếu ở mức
thấp. Nếu chân SS được đặt làm đầu vào thì khi chân này bị kéo xuống mức thấp thì
MSTR sẽ bị xóa và SPIF được thiết lập mức cao. Do dó người dùng sẽ phải đặt
MSTR trở lại mức cao nếu muốn tiếp tục sử dụng chế độ Master.
Bit 3 – CPOL :Clock Polarity:
Khi bit này được ghi 1 thì SCK ở mức cao khi rỗi, ngược lại thì SCK ở mức
thấp khi rỗi.
Bảng 4 - Chức năng của bit CPOL
CPOL Leading Edge Trailing Edge
0 Rising Failing
1 Failing Rising
Bit 2 – CPHA : Clock Phase
Xác định việc lấy mẫu dữ liệu trên sườn trước hay sau của SCK :
Bảng 4 - Chức năng của bit CPHA
CPHA Leading Edge Trailing Edge
0 Sample Setup
1 Setup Sample
Bit1,0 – SPR1,SPR0 :SPI Clock Rate Select 1 and 0
Điều khiển tốc độ của SCK ở chế độ Master . Quan hệ giữa SCK
và tần số giao động (fosc) được thể hiện như sau:
Bảng 4 - Quan hệ giữa tần số SCK và tần số giao động
56
SPI2X SPR1 SPR0 Tần số SCK
0 0 0 fosc/4
0 0 1 fosc/16
0 1 0 fosc/64
0 1 1 fosc/128
1 0 0 fosc/2
1 0 1 fosc/8
1 1 0 fosc/32
1 1 1 fosc/64
* Thanh ghi trạng thái – SPSR :
Bit 7 6 5 4 3 2 1 0
Read/Write R R R R R R R R/W
Khởi tạo 0 0 0 0 0 0 0 0
Bit 7 – SPIF: SPI Interrupt Flag
Sau khi kết thúc việc dữ liệu, cờ SPIF được thiết lập. Ngắt sẽ xảy ra nếu ngắt SPI
và ngắt toàn cục được cho phép.
Bit 6 – WCOL: Write COLision flag
Được thiết lập nếu SPDR được ghi dữ liệu khi đang truyền dữ liệu. Sẽ được xóa
sau khi thanh ghi trạng thái được kiểm tra.
Bit 5..1 : Không được dùng trong Atmega16
Bit 0: SPI2X: Double SPI Speed Bit
Sử dụng kèm với SPR1, SPR0 để xác định tần số của SCK
* Thanh ghi dữ liệu – SPDR :
Bit 7 6 5 4 3 2 1 0
SPIF WCOL - - - - - SPI2X
MSB LSB
57
Read/Write R/W R/W R/W R/W R/W R/W R/W R/W
Khởi tạo X X X X X X X X
Chứa dữ liệu cần truyền và nhận .
4.3.2) Thiết lập SPI truyền dữ liệu cho 74HC595
Để kết nối SPI giữa Atmega16 và 74HC595 ta cần nối chân SCK của vi điều
khiển với chân SH_CP của 74HC595, nối chân MOSI của vi điều khiển với chân
DS của 74HC595. Ngoài ra còn phải dùng 1 chân của vi điều khiển nối với chân
ST_CP của 74HC595 để chốt dữ liệu tại đầu ra của 74HC595.
Hình 4 - Ghép nối vi điều khiển với 74HC595 sử dụng SPI
Do việc giao tiếp giữa vi điều khiển và 74HC595 chỉ là quá trình truyền dữ
liệu từ vi điều khiển đến 74HC595 nên ta có thể thiết lập cho SPI ở chế độ master
với cách sắp xếp dữ liệu theo trật tự bit có trọng số cao thì mã hóa cho hàng ở trên
và các đầu ra của 74HC595 cũng được nối với các chân của ma trận led theo trật tự
trên thì ta đặt bit DORD=0 .
Các giá trị cần nạp cho thanh ghi :
58
SPCR=0x50
SPSR=0x00
Sau đó trong chương trình mỗi khi muốn gửi 1 byte nào đó ra ta có thể dùng
lệnh trong CodeVisionAVR :
spi(byte) ;
Lệnh này cho phép gửi 1 byte từ vi điều khiển qua chân MOSI tới thiết bị
ngoại vi.Sau đó nếu muốn chốt dữ liệu ta cần phải sử dụng 1 thủ tục để gửi 1 sườn
dương tới chân ST_CP của 74HC595 thông :
void latchdata( ) {
PORTB.3=0;
PORTB.3=1;
}
4.3) Kết luận
Khi cấp nguồn cho ma trận tùy theo kích thước của ma trận mà ta có thể sử
dụng nhiều phương pháp khác nhau. Với các ma trận đủ nhỏ ta có thể sử dụng các
chân của vi điều khiển để trực tiếp điều khiển việc cấp nguồn cho ma trận. Với ma
trận lớn thì cần phải dùng các IC hỗ trợ cho việc điều khiển cấp nguồn cho ma trận.
Khi cấp nguồn cho ma trận theo từng cột thì ta có thể sử dụng các IC có tác dụng
chọn kênh để cấp nguồn cho ma trận, tại mỗi thời điểm mỗi IC này chỉ cấp nguồn
cho 1 cột của ma trận . Đối với các hàng trong cột thì ta có thể dùng các bộ ghi dịch
để cấp nguồn. Khi cấp nguồn thì ta cần chú ý việc cấp phát dữ liệu của các hàng
phải tương ứng với cột được cấp nguồn.
59
Chương5: Tạo tần số quét cho ma trận
Để đảm bảo cho hình ảnh hiển thị rõ nét thì ta cần phải điều chỉnh tần số hiển
thị cho phù hợp . Tần số hiển thị càng cao thì hình ảnh càng rõ nét . Dùng bộ định
thời của vi điều khiển giúp ta có thể điều khiển tần số hiển thị của ma trận led. Mỗi
khi ngắt định thời được thực hiện thì ta sẽ cho một cột của ma trận sáng . Qua đó ta
có thể tính được tần số hiển thị của ma trận bằng 1/8 tần số ngắt. Chương sẽ giới
thiệu về một số chế độ của Timer1 và các thanh ghi dùng để thiết lập chế độ , sau đó
sẽ trình bày về cách thiết lập thanh ghi dùng cho việc điều khiển tần số quét led ma
trận.
5.1) Timer1 Atmega16
5.1.1) Một số chế độ hoạt động
Trước tiên ta cần chú ý các định nghĩa sau:
• BOTTOM : Counter tới BOTTOM khi nó có dạng 0x0000.
• MAX : Counter tới MAX khi nó có dạng 0xFFFF.
• TOP : khi Counter tới TOP khi giá trị của nó bằng giá trị cao
nhất trong hàng đếm. Giá trị TOP có thể được gán là 1 trong các giá
trị cố định khác sau : 0x00FF, 0x01FF, 0x03FF hoặc là giá trị lưu
trong OCR1A hoặc thanh ghi ICR1. Việc gán giá trị TOP phụ thuộc
vào chế độ hoạt động.
a) Chế độ thông thường :
Chế độ hoạt động đơn giản nhất của Timer là chế độ thường (WGM13:0 =
0). Trong chế độ này bộ đếm luôn đếm lên và không được xóa. Bộ đếm tràn khi
đếm qua giá trị max (MAX= 0xFFF) và trở lại BOTTOM (0x0000). Trong chế độ
này Timer/Counter Overflow Flag (TOV1) sẽ được thiết lập ngay khi TCNT1 trở về
0. Trong trường hợp này cờ TOV1 hoạt dộng như bit thứ 17 của bộ đếm nên nó
không tự xóa. Tuy nhiên khi kết hợp với ngắt tràn Timer cờ này có thể tự động xóa,
độ phân giải của Timer có thể tăng lên bởi phần mềm.
60
Khối bắt tín hiệu đầu vào khá dễ sử dụng ở chế độ thường nhưng cần phải
chú ý tới khoảng thời gian lớn nhất giữa các sự kiện ngoài, khoảng thời gian này
phải không vượt quá độ phân giải của bộ đếm. Nếu khoảng thời gian giữa các sự
kiện quá dài ta có thể dùng ngắt tràn hay tăng độ rộng xung đếm để có thể mở rộng
độ phân giải cho khối này .
b) Chế độ CTC ( clear timer on compare) :
Trong chế độ CTC (WGM13:0 = 4 hoặc 12), thanh ghi ICR1 hoặc OCR1A
được sử dụng tạo độ phân giải cho bộ đếm. Trong chế độ CTC bộ đếm bị xóa về 0
khi giá trị bộ đếm (TCTN1) trùng với giá trị của thanh ghi OCR1A (WGM13:0 = 4)
hoặc ICR1 (WGM13:0 = 12). Thanh ghi OCR1A hoặc ICR1 định nghĩa giá trị đỉnh
cho bộ đếm.
Hình 5 - Giản đồ thời gian chế độ CTC
Một ngắt có thể phát ra khi giá trị bộ đếm đạt tới giá trị TOP bởi cùng sử
dụng cờ OCF1A hoặc ICF1. Nếu ngắt được cho phép, thủ tục điều khiển ngắt có thể
được sử dụng để cập nhập lại giá trị TOP. Thay đổi TOP bằng giá trị gần với
BOTTOM khi bộ đếm đang chạy với độ rộng xung lớn phải thực hiện cẩn thận .
Nếu giá trị mới ghi cho OCR1A hoặc ICR1 thấp hơn so với giá trị của TCNT, bộ
đếm sẽ không bắt được thời điểm đạt giá trị TOP. Do đó nó sẽ đếm tới giá trị MAX
(0xFFF) rồi quay về 0x0000 trước khi có thể có thể gặp đượcgiá trị TOP. Để có thể
tạo sóng đầu ra trong chế độ CTC, đầu ra OC1A có thể lật mức logic của nó mỗi khi
bắt gặp giá trị top bằng cách thiết lập các bit chọn chế độ so sánh đầu ra COM1A1:0
61
= 01. Giá trị của chân OC1A sẽ không được cập nhật nếu ta không thiết lập nó là
đầu ra (DDR_OC1A=1). Sóng phát ra từ chân OCA1 sẽ có tần số cực đại của 1OC Af
= _ /clk I Of khi OCR1A được lập về 0x0000. Tần số của sóng được tính như sau:
Công thức 5 - Quan hệ giữa tần số đầu ra với tần số timer ở chế dộ CTC
_ /
2. .(1 )
clk I O
OCnA
f
N OCRnA
f =
+
N thể hiện độ chia tần ,có thể là các giá trị sau : 1, 8, 64, 256, 1024
c) Chế độ fast PWM :
Fast Pulse Width Modulation hoặc chế độ fast PWM ( WGM13:0 =
5,6,7,14,15) có chức năng tạo ra nhiều dạng sóng tần số cao. Fast PWM khác với
chức năng PWM bởi nó chế độ hoạt động sườn đơn. Bộ đếm đếm từ BOTTOM tới
TOP sau đó lập tức quay về BOTTOM. Trong chế độ so sánh không đảo đầu ra thì
đầu ra OC1x được thiết lập khi TCNT1 và OCR1x bằng nhau, và xóa khi đạt giá trị
TOP. Trong chế độ so sánh đảo đầu ra thì chân OC1x được xóa khi ICNT1 và
OCR1x bằng nhau, và được thiết lập khi đạt giá trị TOP. Do chỉ dùng sườn đơn nên
tần số hoạt động của fast PWM cao gấp 2 lần so với các chế độ Phase correct và
Phase and Frequency corect PWM ( các chế độ này khi hoạt động dùng 2 sườn).
Tần số cao làm chế độ fast PWM phù hợp với điều chỉnh công suất, chỉnh lưu và
ứng dụng DAC. Độ phân giải cho fast PWM có thể cố định 8, 9 hoặc 10 bit, hoặc
định nghĩa bởi ICR1 hoặc OCR1A. Độ phân giải nhỏ nhất cho phép là 2 bit (ICR1,
OCR1A lập lên 0x0003), lớn nhất là 16 bit (ICR1 hoặc OCR1A khi được gán giá
trị MAX). Độ phân giải PWM trong các bit có thể tính theo hàm :
Công thức 5 - Độ phân giải PWM
log( 1)
log(2)FPWM
TOPR +=
62
Hình 5 - Giản đồ thời gian chế độ Fast PWM
Cờ tràn Timer/Counter (TOV1) được lập mỗi khi Counter tới giá trị TOP.
Ngoài ra chân OC1A hoặc ICF1 được thiết lập trong cùng một chu kỳ xung với thời
điểm TOV1 được thiết lập. Nếu ngắt được cho phép, thủ tục điều khiển ngắt có thể
được sử dụng để cập nhập lại TOP và các giá trị so sánh. Khi thay đổi các giá trị
TOP ta phải chắc chắn giá trị TOP mới lớn hơn hoặc bằng giá trị của tất cả các
thanh ghi so sánh nếu không sẽ không có sự gặp nhau giữa TCNT1 và OCR1x .
Thủ tục cập để nhập lại ICR1 khác với 0CR1A khi sử dụng để định nghĩa giá
trị TOP. Thanh ghi ICR1 không có 2 bộ đệm. Nếu ICR1 thay đổi tới 1 giá trị thấp
hơn TCNT1 khi bộ đếm đang chạy thì nó sẽ đếm tớ giá trị MAX (0xFFFF) và quay
lại giá trị 0x0000 . OCR1A có bộ đẹm kép nên có thể ghi lên nó bất kỳ lúc nào. Khi
OCR1A I/O được ghi, giá trị ghi sẽ được đưa vào trong thanh ghi đệm OCR1A.
Thanh ghi so sánh OCR1A sẽ cập nhập lại ghía trị trong thanh ghi đệm tại chu kỳ
sau khi TCNT1 đạt giá trị TOP.
Trong chế độ fast PWM, khối so sánh cho phép tạo ra 1 dạng sóng tại chân
OC1x. Thiết lập các bit COM1x1:0 tới 2 có thể tạo ra một dạng PWM không đảo và
một PWM đảo bằng cách thiết lập COM1x1:0 lên 3. Giá trị tại chân OC1x chỉ quan
sát được nếu chân này được thiết lập là đầu ra (DDR_OC1x). Dạng sóng PWM
được sinh ra khi thiết lập (xóa) chân OC1x tại thời điểm OCR1x = TCNT1 và xóa
(thiết lập) OC1x tại thời điểm bộ đếm bị xóa ( từ TOP về BOTTOM).
63
Tần số PWM tại đầu ra có thể được tính theo hàm:
Công thức 5 - Quan hệ giữa tần số đầu ra với tần số timer ở chế độ Fast PWM
log( 1)
log(2)OCnxPWM
TOPf +=
N thể hiện độ chia tần ,có thể là các giá trị sau : 1, 8, 64, 256, 1024
d) Chế độ Phase Correct PWM
Chế độ này hoạt động dựa trên hai sườn lên xuống.Bộ đếm sẽ đếm liên tục từ
giá trị BOTTOM đến giá trị MAX và sau đó từ giá trị MAX đến giá trị
BOTTOM.Trong chế độ so sánh không đảo chân so sánh (OCx) sẽ bị xóa khi giá trị
TCNTx bằng giá trị OCRx trong quá trình đếm lên và sẽ được thiết lập bằng 1 khi
giá trị so sánh xuất hiện trong quá trình đếm xuống.Chế độ so sánh đảo thì các giá
trị là ngược lại.Với hoạt động hai sườn xung này thì chế độ này không tạo ra được
tần số nhỏ như chế độ một sườn xung. Nhưng do tính cân đối của hai sườn xung thì
nó tốt hơn cho điều khiển động cơ .
Chế độ phase correct PWM hoạt động cố định là 8 bít.Trong chế độ này bộ
đếm sẽ tăng cho đến khi đạt giá trị MAX, khi đó nó sẽ đổi chiều đếm. Biểu đồ thời
gian sau đây mô tả hoạt động của hoạt động quá trình:
Hình 5 - Giản đồ thời gian chế độ Phase Corect PWM
64
Từ biểu đồ thời gian ta nhận thấy việc thay đổi tần số trong hoạt động của
phase correct PWM có thể thay thế bằng hai giá trị là MAX và BOTTOM. Nó linh
hoạt hơn so với chế độ Fast PWM.
5.1.2) Các thanh ghi
1.TCCR1A:
Bit 7 6 5 4 3 2 1 0
Read/Write R/W R/W R/W R/W W W R/W R/W
Khởi tạo 0 0 0 0 0 0 0 0
Bit7,6 COM1A1,2 : chọn chế độ đầu ra cho kênh A
Bit5,4 COM1B1,2 : chọn chế độ đầu ra cho kênh B
Nếu cả 2 bit đều được ghi 0 thì các chân OC1A và OC1B coi như không
được kết nối với bộ dịnh thời và hoạt động như các chân bình thường khác của vi
điều khiển. Khi có ít nhất 1 trong 2 bit được ghi mức cao thì các chân này sẽ được
điều khiển bởi bô định thời tùy theo chế độ hoạt động được chọn:
Bảng 5 - Thiết lập chế độ đầu ra cho timer
COM1A1 COM1A0 COM1B1 COM1B0 FOC1A FOC1B WGM11 WGM10
COM1A1/
COM1B1
COM1A0/
COM1B0
Mô tả
0 0 Port hoạt động thông thường.Không kết nối
OC1A/OC1B.
0 1 Lật trạng thái OC1A/OC1B
1 0 Xóa OC1A/OC1B
1 1 Thiết lập OC1A/OC1B
65
Bit3,2 : cưỡng chế so sánh ở các chế độ không điều chế xung.
Bit1,0 : Được sử dụng kết hợp với các bít WGM12 và WGM13 để xác định chế độ
của bộ định thời :
Bảng 5 - Các chế độ điều chế xung
Chế
độ
WGM13 WGM12 WGM11 WGM10 Chế độ hoạt động của timer TOP Cập nhật
OCR1X
Thiết lập
cờ TOV1
0 0 0 0 0 Thường 0xFFFF Lập tức MAX
1 0 0 0 1 PWM, Phase Correct, 8-bit 0x00FF TOP BOTTOM
2 0 0 1 0 PWM, Phase Correct, 9-bit 0x01FF TOP BOTTOM
3 0 0 1 1 PWM, Phase Correct, 10-bit 0x03FF TOP BOTTOM
4 0 1 0 0 CTC OCR1A Lập tức MAX
5 0 1 0 1 Fast PWM, 8-bit 0x00FF TOP TOP
6 0 1 1 0 Fast PWM, 9-bit 0x01FF TOP TOP
7 0 1 1 1 Fast PWM, 10-bit 0x03FF TOP TOP
8 1 0 0 0 PWM, Phase and Frequency Correct ICR1 BOTTOM BOTTOM
9 1 0 0 1 PWM, Phase and Frequency Correct OCR1A BOTTOM BOTTOM
10 1 0 1 0 PWM, Phase Correct ICR1 TOP BOTTOM
11 1 0 1 1 PWM, Phase Correct OCR1A TOP BOTTOM
12 1 1 0 0 CTC ICR1 Lập tức MAX
13 1 1 0 1 Reserved - - -
14 1 1 1 0 Fast PWM ICR1 TOP TOP
15 1 1 1 1 Fast PWM OCR1A TOP TOP
2.TCCR1B:
Bit 7 6 5 4 3 2 1 0
Read/Write R/W R/W R R/W R/W R/W R/W R/W
Khởi tạo 0 0 0 0 0 0 0 0
ICNC11 ICES1 - WGM13 WGM12 CS12 CS11 CS10
66
Bit 7 ICNC1: Khi bit này được ghi1 thì các tín hiệu vào từ chân ICP1 sẽ được lọc
nhiễu. Bộ lọc nhiễu cần 4 lần lấy mẫu liên tiếp có giá trị bằng nhau ở chân ICP1. Do
đó tín hiệu vào bị trễ 4 chu kỳ giao động so với khi không lọc nhiễu.
Bit 6 ICES1 : Bit này lựa chọn sườn kích hoạt sự kiện tại chân ICP1. Khi bit này
được ghi 0 thì sườn âm được sử dụng để kích hoạt Khi bit này được ghi 1 thì sườn
dương được sử dụng.
Bit 5 : không dùng trong Atmega16
Bit 4,3 WGM13,2 : Cùng với WGM11,0 để để xác định chế độ của bộ định thời
Bit 2,1,0 CS12,1,0 : Dùng để lựa chọn tần số cho Timer
Bảng 5 - Lựa chọn tần số cho bộ đếm
CS12 CS11 CS10 Mô tả
0 0 0 Timer không hoạt động
0 0 1 I/Oclk /1 ( không chia tần )
0 1 0 I/Oclk /8 ( từ bộ chia tần )
0 1 1 I/Oclk /64 ( từ bộ chia tần )
1 0 0 I/Oclk /256 ( từ bộ chia tần )
1 0 1 I/Oclk /1024( từ bộ chia tần )
1 1 0 Nguồn ngoài từ chân T1 , sườn lên
1 1 1 Nguồn ngoài từ chân T1 , sườn xuống
3.TCNT1H/L:
Bit 7 6 5 4 3 2 1 0
Read/Write R/W R/W R/W R/W R/W R/W R/W R/W
Khởi tạo 0 0 0 0 0 0 0 0
TCNT1[15:8]
TCNT1[7:0]
67
Lưu giá trị của bộ đếm. Có khả năng truy nhập trực tiếp để ghi và đọc thông
qua việc sử dụng thanh ghi tạm thời. Việc thay đổi thanh ghi này trong khi bộ đếm
đang hoạt động có thể bỏ qua một lần gặp nhau giữa TCNT1 và các thanh ghi
OCR1x .
4.OCR1AH/L:
Bit 7 6 5 4 3 2 1 0
Read/Write R/W R/W R/W R/W R/W R/W R/W R/W
Khởi tạo 0 0 0 0 0 0 0 0
5.OCR1BH/L:
Bit 7 6 5 4 3 2 1 0
Read/Write R/W R/W R/W R/W R/W R/W R/W R/W
Khởi tạo 0 0 0 0 0 0 0 0
Các thanh ghi OCR1x được liên tục so sánh với thanh ghi TCNT1 . Mỗi khi bằng
nhau có thể tạo ra 1 ngắt so sánh đầu ra hay để thay đổi dạng sóng tại các chân đầu
ra OC1x .
6.TIMSK:
Bit 7 6 5 4 3 2 1 0
OCR1A[15:8]
OCR1A[7:0]
OCR1B[15:8]
OCR1B[7:0]
OCIE2 TOIE2 TICE1 OCIE1A OCIE1B TOIE1 OCIE0 TOIE0
68
Read/Write R/W R/W R R/W R/W R/W R/W R/W
Khởi tạo 0 0 0 0 0 0 0 0
Các bit 7,6,1,0 dùng cho các timer khác của Atmega16.
Bit 5 - TICIE1 : Khi bit này được thiết lập thành 1 và ngắt toàn cục (global
interrupt) được cho phép thì ngắt bộ đếm đầu vào Timer/couter1 (Timer/Counter1
Input Capture interrupt) được cho phép. Vector ngắt tương ứng sẽ được thực thi khi
cờ ICF1 trong thanh ghi TIFR được thiết lập.
Bit4 - OCIE1A : Khi bit này được thiết lập thành 1 và ngắt toàn cục (global
interrupt) được cho phép thì ngắt so sánh đầu ra 1A (Timer/Counter1 Output
Compare A Match Interrupt) được cho phép. Vector ngắt tương ứng sẽ được thực
hiện khi cờ OCF1A trong thanh ghi TIFR được thiết lập.
Bit3 - OCIE1B : Khi bit này được set thành 1 và ngắt toàn cục (global interrupt)
được cho phép thì ngắt so sánh đầu ra 1B (Timer/Counter1 Output Compare B
Match Interrupt) được cho phép. Vector ngắt tương ứng sẽ được thực thi khi cờ
OCF1B trong thanh ghi TIFR được thiết lập .
Bit2 – TOIE1 : Khi bit này đượcset thành 1 và ngắt toàn cục (global interrupt) được
cho phép thì ngắt cờ tràn bộ định thời 1 (Timer/Counter1 overflow interrupt) được
cho phép. Vector ngắt tương ứng sẽ được thực thi khi cờ TOV1 trong thanh ghi
TIFR được thiết lập .
7.TIFR:
Bit 7 6 5 4 3 2 1 0
Read/Write R/W R/W R R/W R/W R/W R/W R/W
Khởi tạo 0 0 0 0 0 0 0 0
OCF2 TOV2 ICF1 OCF1A OCF1B TOV1 OCF0 TOF0
69
Các bit 7,6,1,0 dùng cho các timer khác của Atmega16.
Bit5 - ICF1 : Cờ này được thiết lập khi xảy ra sự kiện tại ngõ vào (Input Capture)
của chân ICP1. Khi thanh ghi ICR1 (InputCapture Register) được thiết lập bởi các
bit WGMn3:0 để sử dụng như một giá trị đỉnh thìcờ ICF1 sẽ được thiết lập khi bộ
đếm đạt tới giá trị đỉnh. Cờ ICF1 sẽ tự động xóa khi ngắt tương ứng được thực thi,
hoặc có thể xóa hay thiết lập bằng cách ghi một giá trị logic vào vị trí của nó.
Bit4 - OCF1A : Cờ này được thiết lập ngay sau khi giá trị bộ đếm (TCNT1) bằng
với giá trị thanh ghi OCR1A (Output Compare Register A). Chú ý là một so sánh
cưỡng bức (FOC1A) sẽ không thiết lập cờ này. Cờ OCF1A sẽ tự động xóa khi ngắt
tương ứng được thực thi, hoặc có thể xóa hay thiết lập bằng cách ghi một giá trị
logic vào vị trí của nó.
Bit 3 - OCF1B : Cờ này được thiết lập ngay sau khi giá trị bộ đếm (TCNT1) bằng
với giá trị thanh ghi OCR1B (Output Compare Register B). Chú ý là một so sánh
cưỡng bức (FOC1B) sẽ không thiết lập cờ này. Cờ OCF1B sẽ tự động xóa khi ngắt
tương ứng được thực thi, hoặc có thể xóa hay thiết lập bằng cách ghi một giá trị
logic vào vị trí của nó.
Bit 2 - TOV1 : Việc thiết lập cờ này phụ thuộc vào thiết lập của các bit WGMn3:0,
trong chế độ bình thường và CTC cờ TOV1 được thiết lập khi bộ định thời tràn.
5.2) Tạo tần số quét ma trận
Để đảm bảo mắt người có thể cảm nhận được hình ảnh dễ dàng không bị
rung thì ta cần tạo tần số quét khoảng 60Hz .
Do ma trận led có 8 cột sáng luân phiên nên số lần cấp nguồn cho led là :
60 x 8= 480 lần/s .
Khi đó khoảng cách giữa 2 lần cấp nguồn liên tiếp khoảng :
1000:480= 2,083 ms
70
Tần số của thạch anh là 11.0592MHz do đó số chu kì dao động trong
khoảng thời gian trên là :
11.0592 x 2083= 23040lần
Đây cũng là số chu kì mà timer phải đếm để cấp nguồn cho led các cột của ma trận.
Để đơn giản trong việc điều khiển cấp nguồn cho led ma trận ta dùng ngắt
Timer1 chế độ CTC ngắt khi bộ đếm đạt giá trị TOP=OCR1A . Do không cần lấy
sóng đầu ra nên ta có thể gán 0x10 cho thanh ghi TIMSK , gán 0x00 cho thanh ghi
TCCR1A , gán 0x0M cho TCCR1B với M là một trong các giá trị sau :9,A,B,C,D.
Do đó khi dùng ngắt chế độ CTC thì ta cần nạp giá trị 23115 cho thanh ghi
OCR1A nếu không chia tần số dao động ( các bit CS12:0 của TCCR1B dược gán
001). Với các độ chia tần khác của Timer ta có thể nạp các giá trị sau:
Bảng 5 - Tạo tốc độ quét 60 Hz cho ma trận
CS12 CS11 CS10 OCR1A TCCR1B
0 0 1 23040 0x09
0 1 0 2880 0x0A
0 1 1 360 0x0B
1 0 0 90 0x0C
1 0 1 22 0x0D
Để thay đổi tốc độc quét cho ma trận ta có thể thay đổi các giá trị của các
thanh ghi OCR1A và TCCR1B ( các bit CS12,11,10 của TCCR1B) .
5.3) Kết luận
Tốc độ quét ma trận ảnh hưởng hình ảnh quan sát được trên ma trận. Do đó
việc tạo tốc độ quét hợp lý có vai trò quan trọng trong việc điều khiển hiển thị led
ma trận. Dùng bộ định thời là phương pháp đơn giản nhất để điều khiển tốc độ quét
một cách chính xác. Việc thiết lập các thông số cho bộ định thời một cách linh hoạt
sẽ giúp ta dễ dàng hơn trong việc điều khiển tốc độ quét cho ma trận.
71
Chương 6: Hiệu ứng hiển thị bảng led
Để tạo các hiệu ứng thì ta phải quét ma trận led sao cho hình ảnh hiển thị
trên ma trận đạt được như mong muốn. Do đó ta chỉ cần điều khiển việc đưa dữ
liệu vào các chân của ma trận một cách hơp lý là có thể tạo ra được hiệu ứng mong
muốn . Để thực hiện điều này ta có thể dùng 2 mảng dữ liệu, 1 mảng để lưu dữ liệu
của hình ảnh ( chưa có hiệu ứng ), 1 mảng lưu dữ liệu của hình ảnh tức thời để đưa
ra hiển thị. Mảng thứ 2 được xây dựng bằng cách xử lí lại dữ liệu của mảng thứ
nhất. Nguyên tắc chung cho việc điều khiển led ma trận tạo hiệu ứng là sau khi 1
hình ảnh được hiển thị thì ta lấy mẫu cho hình ảnh tiếp theo rồi cho hiển thị hình
ảnh đó ( dữ liệu mã hóa các hình ảnh này được lưu ở mảng thứ 2 ).
6.1) Bảng led hiển thị
Trước khi xây dựng các hiệu ứng hiển thị ta cần xác định xem bảng led cần
điều khiển có kích thước như thế nào và phải xác định được bảng led được xây
dựng như thế nào. Khi hiểu rõ cách xây dựng bảng led ta mới có thể điều khiển cấp
nguồn cho bảng led. Trong đồ án này chúng em xây dựng một bảng led gồm 6 ma
trận led 8x8 hai màu ( xanh, đỏ) anot chung được bố tí thành hai hàng mỗi hàng 3
ma trận :
72
Hình 6 - Bảng led hiển thị
Các ma trận được xoay sao cho các anot của led được nối chung theo từng
cột. Mỗi cột có 8 led 2 màu, các catot của led xanh được nối với đầu ra của IC
74HC595 thứ nhất thông qua bộ dệm dòng ULN2803, còn các catot của led đỏ được
nối với IC 74HC595 thứ hai. Hai IC 74HC595 được mắc nối tiếp nhau, đầu ra nối
tiếp Q7’ của IC thứ nhất được nối với đầu vào của IC thứ 2. Đầu ra Q7’ của IC thứ
2 sẽ được nối với giắc cắm để mở rộng sang các led ma trận tiếp theo. Với cách bố
trí như trên, đế của ma trận led mỗi ma trận led sẽ có 8 chân đầu vào cấp nguồn
( cho từng cột ), 2 chân đầu vào cấp nguồn cho các IC, 3 chân đầu vào nối với
74HC595 ( DS, SH_CP, ST_CP), và 5 chân đầu ra để nối với các ma trận led khác
gồm 2 chân nguồn và 3 chân nối với 74HC595.
Với cách tổ chức ma trận như trên phải cấp nguồn cho ma trận led theo từng
cột. Dữ liệu cấp nguồn cho các hàng khi gửi nối tiếp thông qua SPI cần phải gửi
theo thứ tự: dữ liệu cho ma trận led phía sau được gửi ra trước và sau khi đã gửi hết
dữ liệu cho tất cả các ma trận thì mới chốt dữ liệu tại đầu ra của các IC 74HC595.
Mỗi ma trận cần dữ liệu của 2 màu, IC chứa dữ liệu màu xanh ở phía trước nên ta sẽ
phải truyền dữ liệu cho màu đỏ trước rồi mới đến màu xanh.
Các phần tiếp theo của chương này sẽ tình bày về cách tạo các hiệu ứng hiển
thị cho bảng led gồm 3 ma trận led có cấu tạo như trên. Tuy nhiên ta có thể sử dụng
các thuật toán này khi mở rộng ma trận với kích thước lớn hơn.
73
6.2) Dịch trái, phải
Với cách tổ chức dữ liệu mã hóa kí tự theo từng cột thì việc điều khiển hiển
thị cho các ký tự dịch trái , phải trên led ma trận là khá đơn giản .
Giả sử ta muốn hình ảnh dịch sang trái thì ta chỉ việc đưa dữ liệu của cột bên
phải của hình ảnh trước ra để hiển thị cho cột hiện tại của hình ảnh sau (cột 1 của
hình ảnh mới là cột 2 của hình ảnh cũ … ) .
Cụ thể với ma trận 8 hàng 24 cột ta có thể làm như sau :
- Dùng một mảng để lưu dữ liệu của toàn bộ hình ảnh khi không dịch
chuyển. Mảng này cần có kích thước 24 bytes ( lưu dữ liệu của 24 cột ).
- Dùng một mảng khác để lưu dữ liệu của các hình ảnh tức thời , hình ảnh
này có kích thước bằng với hình ảnh trên (24 bytes).
- Tại thời điểm đầu tiên thì hình ảnh tức thời sẽ lưu giá trị 0 cho tất cả các
cột ( ma trận tắt ). Tại thời điểm thứ 2 ta gán giá trị của cột 1 của mảng thứ nhất và
cột 24 của mảng thứ 2 . Tại thời điểm tiếp theo ta gán giá trị của cột 1,2 của mảng
thứ nhất vào cột 23,24 của mảng thứ 2... Cứ như thế khi lần lượt hiển thị và lấy mẫu
lại hình ảnh ta sẽ thấy hình ảnh trên ma trận led dịch từ trái sang phải.
74
Hình 6 - Mô phỏng hiệu ứng dịch trái
75
Bắt đầu
i<j
i>23
Nạp giá trị cho M 1
Gán các phần tử
M2 =0
Gán i=0
M2[23-j]=M1[j]
j=j+1
Hiển thị ma trận
Gán j=0
i=i+1
F
FT
T
Hình 6 - Lưu đồ thuật toán hiệu ứng dịch trái
Khi mở rộng kích thước của ma trận hay số lượng các ký tự làm vượt quá
kích thước của ma trận thì ta vẫn có thể sử dụng phương pháp trên nhưng với giá trị
giới hạn không phải là 23 mà là số cột của ma trận hay số cột cần để hiển thị hết
toàn bộ các ký tự.
76
Ngoài ra ta cũng có thể xếp 2 mảng thành một, mảng ở sau, mảng 2 ở trước
rồi cứ mỗi lần hiển thị ta là phép gán dịch trái các dữ liệu trong mảng M[i]=M[i+1],
bắt đầu với i=0, gán M[2n-1]=0 với n là số cột hiển thị. Dữ liệu đưa ra hiển thị là n
giá trị đầu của mảng.
Hiệu ứng dịch phải cũng tương tự như dịch trái nhưng phải thay phép gán
trong vòng lặp j thành M2[j]=M1[n-j]. Ta cũng có thể gom 2 mang làm một, mảng
1 ở trước mảng 2 ở sau, cứ mỗi lần hiển thị ta gán M[i] = M[i-1] nhưng bắt đầu với
i = 2n-1và gán M[0]=0 ; dữ liệu đưa ra hiển thị là n giá trị sau của mảng.
77
6.3) Dịch lên xuống
Với cách tổ chức dữ liệu mã hóa kí tự theo từng cột thì việc điều khiển hiển
thị cho các ký tự dịch lên xuống có thể thực hiện bằng cách dịch bit các dữ liệu mã
hóa hình ảnh của từng cột .
Cụ thể với ma trận 8 hàng 24 cột cho hình ảnh dịch lên ta có thể làm như
sau:
- Dùng một mảng để lưu dữ liệu của toàn bộ hình ảnh khi không dịch
chuyển. Mảng này cần có kích thước 24 bytes ( lưu dữ liệu của 24 cột ).
- Dùng một mảng khác để lưu dữ liệu của các hình ảnh tức thời , hình ảnh
này có kích thước bằng với hình ảnh trên (24 bytes).
- Tại thời điểm đầu tiên thì hình ảnh tức thời sẽ lưu giá trị 0 cho tất cả các
cột ( ma trận tắt ). Tại thời điểm thứ 2 ta cần gán bit mã hóa hàng trên cùng của
mảng 1 ( MSB ) vào hàng dưới cùng của mảng 2 ( LSB ). Do đó ta cần phải dịch
phải các bit trong từng byte dữ liệu của mảng 1 đi 7 bit rồi gán vào mảng 2. Tại thời
điểm tiếp theo ta dịch phải 6 bit . Cứ như vậy hình ảnh sẽ dịch dần lên. Tuy nhiên
nếu chi dịch như vậy thì thình ảnh chỉ dịch đến khi ra giữa ma trận. Để hình có thể
tiếp tục dịch lên thì ta phải dịch trái dữ liệu đi từ 1 bit cho đến 7 bit . Sau khi dịch
trái hết thì lại gán 0 cho tất cả các bit của ma trận .
Hình 6 - Mô phỏng hiệu ứng dịch lên
78
Bắt đầu
J>23
i>7
Nạp giá trị cho M1
Gán các phần tử
M2 =0
i=0
M2[j]=M1[j]>>(8-i)
J=J+1
Hiển thị
J=0
i=i+1
F
F
T
T
Hiển thị
J=0
M2[j]=M1[j]<<(i-8)
J=J+1
J>23
i=i+1
T
i>15
F
FT
Hình 6 - Lưu đồ thuật toán hiệu ứng dịch lên
79
Khi mở rộng ma trận chu trình gán giá trị hiển thị sẽ phứa tạp hơn do kích
thước dữ liệu cần gán cho một cột của ma trận tăng lên. Khi đó ta có thể chia dữ
liệu đem ra hiển thị thành nhiều mảng với mỗi mảng đại diện cho 1 “ dòng ” của ma
trận. Phần tử đầu tiên của mỗi mảng sẽ chứa dữ liệu cho cột đầu tiên của mỗi dòng.
Cứ mỗi lần dịch ta có thể gán Mt[i] = ( Mt[i]>(8-j) ). Với Mt là
dòng trên, Md là dòng dưới .
Hiệu ứng dịch xuống cũng tương tự như dịch lên nhưng khác ở chiều của
phép dịch bit và số lần dịch bit ta có thể thay chiều của phép dịch và số bit dịch đổi
từ (8-i) thành i .
80
6.4) Hiển thị từng kí tự
Với cách tổ chức dữ liệu mã hóa kí tự theo từng cột thì việc điều khiển cho
các ký tự lần lượt hiện trên bảng led có thể thực hiện bằng cách lấy mẫu lần lượt
thêm từng ý tự một .
Cụ thể với ma trận 8 hàng 24 cột cho hiển thị tưng ký tự một ta có thể làm như sau :
- Dùng một mảng để lưu dữ liệu của toàn bộ hình ảnh khi không dịch
chuyển. Mảng này cần có kích thước 24 bytes ( lưu dữ liệu của 24 cột ).
- Dùng một mảng khác để lưu dữ liệu của các hình ảnh tức thời, hình ảnh này
có kích thước bằng với hình ảnh trên (24 bytes).
- Tại thời điểm đầu tiên thì mảng lưu hình ảnh tức thời được gán 0 để tắt tất
cả các led. Sau đó tại các thời điểm tiếp theo ta lần lượt gán từng 6 bytes của mảng
1 vào mảng 2 để đưa ra hiển thị ( do cứ 6 bytes thì mã hóa 1 ký tự).
Hình 6 - Mô phỏng hiệu ứng hiển thị từng chữ
81
Bắt đầu
j>5
i>3
Nạp giá trị cho M1
Gán các phần tử
M2 =0
i=0
M2[i*6+j]=M1[i*6+j]
j=j+1
Hiển thị
j=0
i=i+1
F
FT
T
Hình 6 - Lưu đồ thuật toán hiệu ứng hiển thị tưng ký tự
82
6.5) Kết luận
Việc sử dụng 2 mảng dữ liệu một mảng lưu toàn bộ khung hình, một mảng
lưu hình ảnh tức thời sẽ giúp việc tạo các hiệu ứng đơn giản hơn. Xử lý các dữ liệu
trên mảng thứ nhất rồi lưu vào mảng thứ 2 để đưa ra hiển thị sẽ cần một lượng bộ
nhớ lớn khi số lượng ký tự và kích thước của font chữ tăng. Do đó khi tạo các hiệu
ứng và điều khiển hiển thị cần phải chú ý đến kích thước bộ nhớ. Nếu cần có thể
dùng thêm các bộ nhớ ngoài hoặc chọn các vi điều khiển có bộ nhớ đủ lớn để có thể
tạo hiệu ứng cần thiết. Các bảng điện tử thông dụng thường chỉ hiển thị một nội
dung cố định nên ta có thể sử dụng bộ nhớ flash (có kích thước khá lớn ) để lưu giá
trị của mảng thứ nhất, thậm chí có thể lưu toàn bộ các khung cần hiển thị. Khi đó ta
chỉ cần điều khiển việc xuất dữ liệu theo địa chỉ để hiển thị.
Đối với phương pháp cấp nguồn theo từng cột thì việc tạo các hiệu ứng dịch
trái, dịch phải khá đơn giản và việc mở rộng ma trận không ảnh hưởng nhiều đến
việc gán dữ liệu nhưng với các hiệu ứng dịch lên xuống khá phức tạp khi mở rộng
ma trận. Tuy nhiên nếu chỉ sử dụng một hiệu ứng cho ma trận thì với hiệu ứng dịch
lên, xuống ta có thể chọn phương pháp cấp nguồn theo từng hàng. Khi đó cần phải
xây dựng font chữ theo tưng hàng và phải xắp xếp lại các ma trận led ( xoay 90 độ
so với khi cấp nguồn theo cột ).
83
Kết luận
Module điều khiển hiển thị đã hoàn thành , và đạt được những kết quả
sau:
- Có khả năng điều khiển hiển thị 2 chuỗi ký tự trên hai hàng ma trận,
có khả năng điều khiển hiển thị ma trận có đọ rộng lớn hơn.
- Có khả năng hiển thị các dòng ký tự với ba màu xanh, đỏ và cam.
- Có khả năng điều khiển hiển thị các ký tự với một số hiệu ứng cơ
bản. Thuật toán điều khiển hiển thị hiệu ứng có thể sử dụng khi mở rộng ma trận và
có thể làm cơ sở để tạo các hiệu ứng phức tạp hơn.
- Có khả năng thay đổi tần số quét ma trận .
Tuy nhiên module vẫn còn một số giới hạn :
- Có thể hiển thị các ký tự trên hai dòng nhưng lại độc lập với nhau.
Do đó khi gặp phải một số yêu cầu về việc hiển thị 2 dòng chữ có độ tương quan
nhất định thì cần phải thay đổi về việc điều khiển xuất dữ liệu.
- Tuy có thể thay đổi màu của dòng chữ hiển thị nhưng lại chưa điều
khiển được màu sắc của từng ký tự. Vấn đề này có thể dễ dàng khắc phục khi hiển
thị các ký tự tĩnh, nhưng khi cần điều khiển các ký tự động thì sẽ khó khăn trong
việc điều khiển màu sắc.
- Do quá trình điều khiển hiển thị cần có giai đoạn lấy mẫu lại dữ liệu
nên khi điều khiển hiển thị ma trận có kích thước lớn có thể gây ảnh hưởng đến việc
điều khiển tần số quét .
Trong đề tài có thể có một số vấn đề hợp lý hay chưa tối ưu về các thuật toán
điều khiển hiển thị và sử dụng bộ nhớ của vi điều khiển. Do đó em rất mong có sự
góp ý của các thầy cô và các bạn để đồ án có thể hoàn thiện hơn.
84
Tài liệu tham khảo
[1] Steven F. Barrett and Daniel J. Pack, Atmel AVR Microcontroller Primer:
Programming and Interfacing, Morgan & Claypool, 2008
[2] Joe Pardue, C Programming for Microcontrollers, Smiley Micros, 2005
[3] Atmega16 datasheet, www.alldatasheet.com, truy nhập cuối cùng ngày
26/5/2009
[4] 74HC595 datasheet, www.alldatasheet.com, truy nhập cuối cùng ngày
26/5/2009
[5] 74HC138 datasheet, www.alldatasheet.com, truy nhập cuối cùng ngày
26/5/2009
[6] truy nhập cuối cùng ngày 26/5/2009
[7] truy nhập cuối
cùng ngày 26/5/2009
[8] truy nhập cuối
cùng ngày 26/5/2009
[9] truy nhập cuối
cùng ngày 26/5/2009
85
Phụ lục A: Sơ đồ ghép nối hệ thống điều khiển led ma trận
Hình A - Sơ đồ ghép nối hệ thống
86
KHỐI CẤP NGUỒN:
TR1
TRAN-2P5S
VI1 VO 3
G
N
D
2
7805
33pF
33pF
470uF
Khoi cap nguon cho IC
220v
Hình A - Khối cấp nguồn
KHỐI CHỐT DỮ LIỆU CÁC HÀNG
Q
0
15
Q
1
1
Q
2
2
Q
3
3
Q
4
4
Q
5
5
Q
6
6
Q
7
7
Q
7'
9
SH
_C
P
11
ST
_C
P
12
D
S
14
M
R
10
O
E
13
U4
74HC595
Q
0
15
Q
1
1
Q
2
2
Q
3
3
Q
4
4
Q
5
5
Q
6
6
Q
7
7
Q
7'
9
SH
_C
P
11
ST
_C
P
12
D
S
14
M
R
10
O
E
13
U5
74HC595
Q
0
15
Q
1
1
Q
2
2
Q
3
3
Q
4
4
Q
5
5
Q
6
6
Q
7
7
Q
7'
9
SH
_C
P
11
ST
_C
P
12
D
S
14
M
R
10
O
E
13
U6
74HC595
1B
1
2B
2
3B
3
4B
4
5B
5
6B
6
7B
7
8B
8
1C
18
2C
17
3C
16
4C
15
5C
14
6C
13
7C
12
8C
11
C
O
M
10
U1
ULN2803
1B
1
2B
2
3B
3
4B
4
5B
5
6B
6
7B
7
8B
8
1C
18
2C
17
3C
16
4C
15
5C
14
6C
13
7C
12
8C
11
C
O
M
10
U2
ULN2803
1B
1
2B
2
3B
3
4B
4
5B
5
6B
6
7B
7
8B
8
1C
18
2C
17
3C
16
4C
15
5C
14
6C
13
7C
12
8C
11
C
O
M
10
U3
ULN2803
OC0
MOSI
SCK
Khoi chon hang cho LED
Hình A - Khối chốt dữ liệu các hàng
87
KHỐI GIAO TIẾP VỚI MÁY TÍNH:
T1IN 11
R1OUT 12
T2IN 10
R2OUT 9
T1OUT14
R1IN13
T2OUT7
R2IN8
C2+
4
C2-
5
C1+
1
C1-
3
VS+2
VS-6
RXD
TXD
ERROR
TXD 3
RXD 2
CTS 8
RTS 7
DSR 6
DTR 4
DCD 1
RI 9
P1
COMPIM
C3
1nF
C6
1nF
Giao tiep may tinh
Hình A - Khối giao tiếp máy tính
KHỐI KHUẾCH ĐẠI DÒNG CHO CỘT:
A1 A2 A3 A4 A5 A
6 A7 A8
C
0 C
1
C
2
C
3 C
4
C
5
C
6
C
7
A1
A2 A
3 A4 A5 A6 A7 A8
B1
C[0..7]
Hình A - Khối khuếch đại dòng cho cột
88
KHỐI ĐIỀU KHIỂN TRUNG TÂM VÀ QUÉT CỘT:
C
0
C
1 C
2
C
3 C
4
C
5
C
6 C
7
PA0/ADC040
PA1/ADC139
PA2/ADC238
PA3/ADC337
PA4/ADC436
PA5/ADC535
PA6/ADC634
PB0/XCK/T01
PB1/T12
PB2/INT2/AIN03
PB3/OC0/AIN14
PB4/SS5
PB5/MOSI6
PB6/MISO7
PB7/SCK8
PA7/ADC733
RESET9
XTAL113
XTAL212
PC0/SCL 22
PC1/SDA 23
PC2/TCK 24
PC3/TMS 25
PC4/TDO 26
PC5/TDI 27
PC6/TOSC1 28
PC7/TOSC2 29
PD0/RXD 14
PD1/TXD 15
PD2/INT0 16
PD3/INT1 17
PD4/OC1B 18
PD5/OC1A 19
PD6/ICP 20
PD7/OC2 21
AVCC 30
AREF 32
U7
ATMEGA16
C2
33pF
C1
33pF
A
1
B
2
C
3
E1
6
E2
4
E3
5
Y0
15
Y1
14
Y2
13
Y3
12
Y4
11
Y5
10
Y6
9
Y7
7
U8
74HC138
C[0..7]
RXD
TXD
OC0
MOSI
SCK
KHoi dieu khien trung tam va chon cot
Hình A - Khối xử lý trung tâm và quét cột
89
Phụ lục B: Mã chương trình nạp cho vi điều khiển
#include
#include
#include
#include
#define SCL PORTB.3
unsigned char flash FONT []={0,
62,65,65,65,62,0, //0 1
17,33,127,1,1,0, //1 2
35,69,73,73,49,0, //2 3
34,65,73,73,54,0, //3 4
12,20,36,79,4,0, //4 5
114,73,73,73,70,0, //5 6
62,73,73,73,38,0, //6 7
65,66,68,72,112,0, //7 8
54,73,73,73,54,0, //8 9
50,73,73,73,62,0, //9 10
63,68,68,68,63,0, //A 11
127,73,73,73,54,0, //B 12
62,65,65,65,34,0, //C 13
127,65,65,65,62,0, //D 14
127,73,73,73,65,0, //E 15
127,72,72,72,64,0, //F 16
62,65,73,73,46,0, //G 17
127,8,8,8,127,0, //H 18
65,65,127,65,65,0, //I 19
70,65,65,126,64,0, //J 20
127,8,20,34,65,0, //K 21
127,1,1,1,1,0, //L 22
127,32,24,32,127,0, //M 23
127,32,16,8,127,0, //N 24
62,65,65,65,62,0, //O 25
127,68,68,68,56,0, //P 26
62,65,69,66,61,0, //Q 27
127,68,68,74,49,0, //R 28
50,73,73,73,38,0, //S 29
64,64,127,64,64,0, //T 30
126,1,1,1,126,0, //U 31
124,2,1,2,124,0, //V 31
127,2,12,2,127,0, //W 33
65,34,28,34,65,0, //X 34
90
96,16,15,16,96,0, //Y 35
67,69,73,81,97,0, //Z 36
4,42,42,42,28,0, //a 37
126,18,18,18,12,0, //b 38
28,34,34,34,20,0, //c 39
12,18,18,20,126,0, //d 40
28,42,42,16,0,0, //e 41
4,62,72,64,32,0, //f 42
24,37,37,37,30,0, //g 43
126,16,16,16,14,0, //h 44
0,92,2,2,4,0, //i 45
4,2,2,92,0,0, //j 46
126,8,20,34,0,0, //k 47
124,2,2,2,0,0, //l 48
30,32,30,32,30,0, //m 49
62,8,16,62,0,0, //n 50
28,34,34,34,28,0, //o 51
31,36,36,36,24,0, //p 52
24,36,36,36,31,0, //q 53
0,30,32,32,24,0, //r 54
18,42,42,42,36,0, //s 55
0,32,124,34,4,0, //t 56
60,2,2,2,60,0, //u 57
56,4,2,4,56,0, //v 58
56,2,12,2,56,0, //w 59
34,20,8,20,34,0, //x 60
48,8,14,8,48,0, //y 61
34,38,42,50,34,0, //z 62
0,0,0,0,0,0, //
255};
unsigned char dong1[192],dong2[192];
unsigned char tocdo_quet=50,tocdo_chay=3,c,col=2,eff=1,sc=0,sp=0;
unsigned char tg,m=0,t=0,k=0,i,j,sokt=4,sokt1=4,sokt2=4;
unsigned char chuoi1[16]={8,8,8,8,8,8,8,8};
unsigned char chuoi2[16]={6,6,6,6,6,6,6,6};
void LatchData(){
SCL=0;
SCL=1;
}
91
void lm1() {
for (i=0;i<=sokt1-1;i++){
for (j=0;j<=5;j++) {
dong1[i*6+j]=~FONT[chuoi1[i]*6+j+1];
}
}
for (i=0;i<=sokt2-1;i++){
for (j=0;j<=5;j++) {
dong2[i*6+j]=~FONT[chuoi2[i]*6+j+1];
}
}
}
void lm2(){
for (i=0;i<=sokt1*6-1;i++){
dong1[i+sokt1*6]=dong1[i];
//dong1[i]=0;
dong1[i]=255;
}
for (i=0;i<=sokt2*6-1;i++){
dong2[i+sokt2*6]=dong2[i];
//dong2[i]=0;
dong2[i]=255;
}
}
void xulychuoi(){
for (i=0;i<sokt1;i++) {
if ((chuoi1[i]>47)&&(chuoi1[i]<58)) chuoi1[i]=chuoi1[i]-48;
else if ((chuoi1[i]>64)&&(chuoi1[i]<91)) chuoi1[i]=chuoi1[i]-55;
else if ((chuoi1[i]>96)&&(chuoi1[i]<123)) chuoi1[i]=chuoi1[i]-60;
else chuoi1[i]=62;
}
for (i=0;i<sokt2;i++) {
if ((chuoi2[i]>47)&&(chuoi2[i]<58)) chuoi2[i]=chuoi2[i]-48;
else if ((chuoi2[i]>64)&&(chuoi2[i]<91)) chuoi2[i]=chuoi2[i]-55;
else if ((chuoi2[i]>96)&&(chuoi2[i]<123)) chuoi2[i]=chuoi2[i]-60;
else chuoi2[i]=62;
}
}
void shiftleft(){
for (i=0;i<sokt1*12-1;i++){
dong1[i]=dong1[i+1];
}
92
//dong1[sokt1*12-1]=0;
dong1[sokt1*12-1]=255;
for (i=0;i<sokt2*12-1;i++){
dong2[i]=dong2[i+1];
}
//dong2[sokt2*12-1]=0;
dong2[sokt2*12-1]=255;
}
void shiftright(){
tg= dong1[sokt*12-1];
for (i=sokt1*12-1;i>0;i--){
dong1[i]=dong1[i-1];}
dong1[0]=tg;
tg= dong2[sokt*12-1];
for (i=sokt2*12-1;i>0;i--){
dong2[i]=dong2[i-1];}
dong2[0]=tg;
}
void UP(int k){
sokt=((sokt1>sokt2)?sokt1:sokt2);
if (k<8)
for (i=0;i<=sokt*6-1;i++){
dong1[i]=0xFF;
dong2[i]=(dong1[i+sokt*6]>>(8-k))|(0xFF<<k);
}
else if ((k>7)&&(k<16)) {
m=k-8 ;
for (i=0;i<=sokt*6-1;i++){
dong1[i]=(dong1[i+sokt*6]>>(8-m))|(0xFF<<m);
dong2[i]=(dong1[i+sokt*6]>(8-m));
} }
else if ((k>15)&&(k<24)) {
m=k-16 ;
for (i=0;i<=sokt*6-1;i++){
dong1[i]=(dong1[i+sokt*6]>(8-m));
dong2[i]=(dong2[i+sokt*6]>(8-m));
} }
else {
m=k-24 ;
for (i=0;i<=sokt*6-1;i++){
dong1[i]=(dong2[i+sokt*6]>(8-m));
dong2[i]=0xFF;
93
} }
/*
if ( k>=8) {
for (i=0;i<=sokt*6-1;i++){
m=k-8;
dong1[i]=(dong1[i+sokt*6]>(8-m));
dong2[i]=(dong2[i+sokt*6]>(8-m));
} }
if (k<8) {
for (i=0;i<=sokt*6-1;i++){
dong1[i]=(dong1[i+sokt*6]>>(8-k))|(0x7F<<k);
dong2[i]=(dong2[i+sokt*6]>>(8-k))|(0x7F<<k);
} }
*/
}
void down(int k){
sokt=((sokt1>sokt2)?sokt1:sokt2);
if (k>23) {
m=k-24;
for (i=0;i<=sokt*6-1;i++){
dong1[i]=0xFF;
dong2[i]=(dong1[i+sokt*6]>>m)|(0x7F<<m);
} }
if ((k>15)&&(k<=23)) {
m=k-16;
for (i=0;i<=sokt*6-1;i++){
dong1[i]=(dong1[i+sokt*6]>>m)|(0xFF<<(8-m));
dong2[i]=(dong1[i+sokt*6]>m);
} }
if ((k>7)&&(k<16)) {
m=k-8;
for (i=0;i<=sokt*6-1;i++){
dong1[i]=(dong1[i+sokt*6]>m);
dong2[i]=(dong2[i+sokt*6]<<m)|(0xFF<<(8-m));
} }
if (k<8){
m=8-k ;
for (i=0;i<=sokt*6-1;i++){
dong1[i]=(dong2[i+sokt*6]>(8-m));
dong2[i]=0xFF;
} }
/*
94
if ( k>8) {
for (i=0;i<sokt*6;i++){
m=k-8;
dong2[i]=(dong2[i+sokt*6]>>m)|(0x7F<<(8-m));
dong1[i]=(dong1[i+sokt*6]>>m)|(0x7F<<(8-m));
} }
if (k<=8) {
for (i=0;i<sokt*6;i++){
dong2[i]=(dong2[i+sokt*6]>k);
dong1[i]=(dong1[i+sokt*6]>k);
} }
*/
}
void tungchu () {
for (i=0;i<k*6;i++){
dong1[i]=dong1[sokt*6+i];
dong2[i]=dong2[sokt*6+i];
}
}
void hienthi() {
switch (col){
// 2do1do
case 0 :
spi(0x00);
spi(dong2[c+16]);
spi(0x00);
spi(dong2[c+8]);
spi(0x00);
spi(dong2[c]);
spi(0x00);
spi(dong1[c+16]);
spi(0x00);
spi(dong1[c+8]);
spi(0x00);
spi(dong1[c]);
break;
// 2xanh1do
case 1 :
spi(dong2[c+16]);
spi(0x00);
spi(dong2[c+8]);
spi(0x00);
95
spi(dong2[c]);
spi(0x00);
spi(0x00);
spi(dong1[c+16]);
spi(0x00);
spi(dong1[c+8]);
spi(0x00);
spi(dong1[c]);
break;
// 2cam1do
case 2 :
spi(dong2[c+16]);
spi(dong2[c+16]);
spi(dong2[c+8]);
spi(dong2[c+8]);
spi(dong2[c]);
spi(dong2[c]);
spi(0x00);
spi(dong1[c+16]);
spi(0x00);
spi(dong1[c+8]);
spi(0x00);
spi(dong1[c]);
break;
// 2do1xanh
case 3 :
spi(0x00);
spi(dong2[c+16]);
spi(0x00);
spi(dong2[c+8]);
spi(0x00);
spi(dong2[c]);
spi(dong1[c+16]);
spi(0x00);
spi(dong1[c+8]);
spi(0x00);
spi(dong1[c]);
spi(0x00);
break;
// 2xanh1xanh
case 4 :
spi(dong2[c+16]);
spi(0x00);
spi(dong2[c+8]);
spi(0x00);
spi(dong2[c]);
96
spi(0x00);
spi(dong1[c+16]);
spi(0x00);
spi(dong1[c+8]);
spi(0x00);
spi(dong1[c]);
spi(0x00);
break;
// 2cam1xanh
case 5 :
spi(dong2[c+16]);
spi(dong2[c+16]);
spi(dong2[c+8]);
spi(dong2[c+8]);
spi(dong2[c]);
spi(dong2[c]);
spi(dong1[c+16]);
spi(0x00);
spi(dong1[c+8]);
spi(0x00);
spi(dong1[c]);
spi(0x00);
break;
// 2do1cam
case 6 :
spi(0x00);
spi(dong2[c+16]);
spi(0x00);
spi(dong2[c+8]);
spi(0x00);
spi(dong2[c]);
spi(dong1[c+16]);
spi(dong1[c+16]);
spi(dong1[c+8]);
spi(dong1[c+8]);
spi(dong1[c]);
spi(dong1[c]);
// 2xanh1cam
case 7 :
spi(dong2[c+16]);
spi(0x00);
spi(dong2[c+8]);
spi(0x00);
spi(dong2[c]);
spi(0x00);
spi(dong1[c+16]);
97
spi(dong1[c+16]);
spi(dong1[c+8]);
spi(dong1[c+8]);
spi(dong1[c]);
spi(dong1[c]);
break;
// 2cam1cam
case 8 :
spi(dong2[c+16]);
spi(dong2[c+16]);
spi(dong2[c+8]);
spi(dong2[c+8]);
spi(dong2[c]);
spi(dong2[c]);
spi(dong1[c+16]);
spi(dong1[c+16]);
spi(dong1[c+8]);
spi(dong1[c+8]);
spi(dong1[c]);
spi(dong1[c]);
break;
default: break;
}
}
void hieuung() {
switch (eff){
// hienbt
case 0 :
lm1();
break;
// dichtrai
case 1 :
if (t==48){
t=0;
sp++;
}
if (sp==tocdo_chay){
sp=0;
k++ ;
shiftleft();
}
if (k==sokt*12) {
lm1();
lm2();
k=0;
98
}
break;
// dichphai
case 2 :
if (t==48){
t=0;
sp++;
}
if (sp==tocdo_chay){
sp=0;
k++ ;
shiftright();
}
if (k==sokt*12) {
lm1();
lm2();
k=0;
}
break;
// dichlen
case 3 :
if (t==48){
t=0;
sp++;
}
if (sp==tocdo_chay){
sp=0;
k++ ;
UP(k);
}
if (k>=32) {
lm1();
lm2();
k=0;
/* if (t==sokt*8){
k++;
UP(k);
}
if (k==16) {
lm1();
lm2();
k=0;
}
*/
}
break;
99
// dichxuong
case 4 :
if (t==48){
t=0;
sp++;
}
if (sp==tocdo_chay){
sp=0;
k++ ;
down(k);
}
if (k>=32) {
lm1();
lm2();
k=0;
}
break;
// tungchu
case 5 :
if (t==200){
t=0;
sp++;
}
if (sp==tocdo_chay){
sp=0;
k++ ;
tungchu();
}
if (k>sokt) {
lm1();
lm2();
k=0;
}
break;
default: break;
}
}
// Timer 1 output compare A interrupt service routine
interrupt [TIM1_COMPA] void timer1_compa_isr(void) {
hienthi();
LatchData();
PORTC=c+8;
PORTA=c+8;
100
c++;
t++;
if (c==8) c=0;
hieuung();
}
void main(void){
lm1();
lm2();
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: clk/256 kHz
// Mode: CTC top=OCR1A
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x0C;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=tocdo_quet;
OCR1BH=0x00;
OCR1BL=0x00;
/*UCSRA=0x00;
UCSRB=0x18;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x19;*/
UCSRB=0x18;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x47;
DDRB=0xFF;
DDRC=0xFF;
DDRA=0xFF;
101
SCL=1;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x10;
// Global enable interrupts
#asm("sei")
// SPI initialization
// SPI Type: Master
// SPI Clock Rate: clk
// SPI Clock Phase: Cycle Half
// SPI Clock Polarity: Low
// SPI Data Order: MSB First
SPCR=0x50;
SPSR=0x00;
while (1){
unsigned char temp1,temp2,length;
int i;
temp1 = getchar();
if (temp1=='A')
{
TIMSK=0x00;
//Nhan chuoi ky tu hang 1
//tinh do dai chuoi
temp1 = getchar()-48;
temp2 = getchar()-48;
length = temp1*10 + temp2;
sokt1=length;
//Nhan chuoi ky tu
if (length >=1){
for( i=0;i<length;i++)
{
chuoi1[i] = getchar();
}
//Nhan chuoi ky tu hang 2
//tinh do dai chuoi
temp1 = getchar()-48;
temp2 = getchar()-48;
length = temp1*10 + temp2;
sokt2=length;
//Nhan chuoi ky tu
if (length >=1){
for( i=0;i<length;i++)
{
chuoi2[i] = getchar();
}
//Nhan mau
col = getchar() - 48;
102
//Nhan hieu ung
eff = getchar() - 48;
//Nhan Toc do quet
temp1 = getchar()-48;
temp2 = getchar()-48;
tocdo_quet = temp1*10 + temp2;
//Nhan toc do chay
temp1 = getchar()-48;
temp2 = getchar()-48;
tocdo_chay = temp1*10 + temp2;
xulychuoi();
lm1();
lm2();
t=0;
c=0;
TIMSK=0x10;
}
}
}
}
}
103
Các file đính kèm theo tài liệu này:
- Thiết kế bảng quảng cáo led sử dụng vi điều khiển atmega 16 module điều khiển hiển thị.pdf