I / _ GIỚI THIỆU:
_Đây là tài liệu hướng dẫn sử dụng CCS lập trình ngôn ngữ C cho vi điều khiển PIC của Microchip .
Tác giả tên TRẦN XUÂN TRƯỜNG , SV K2001 ,ĐH BK HCM . Là thành viên txt2203 trên diễn
đàn diendandientu.com , thành viên txt trên diễn đàn picvietnam.com . Mọi đóng góp ý kiến về
tài liệu hãy email đến đòa chỉ : . Rất cám ơn mọi đóng góp ý kiến của các bạn
yêu thích lập trình vi xử lý đối với tài liệu này .
II / _ VÀI VẤN ĐỀ VỀ TÀI LIỆU NÀY :
_Tài liệu hướng dẫn lập trình C cho PIC sử dụng phần mềm CCS các phiên bản . Tài liệu cũng giải
thích cách thức hoạt động của 1 số module của VĐK để các bạn nắm rõ hơn hoạt động VĐK nhằm
sử dụng hàm và viết chương trình 1 cách chính xác .
_Tài liệu này không chủ ý thay thế hoàn toàn HELP của CCS , nó chỉ là phần cô đọng , là hướng
dẫn và giải thích cơ bản viết 1 chương trình bắt đầu từ đâu , giới thiệu 1 số hàm và cách hoạt động ,
1 số vấn đề khi lập trình , . . . do đó nó không đầy đủ , bạn nên đối chiếu tài liệu này với HELP
tiếng Anh để nắm rõ vấn đề , đồng thời học cả tiếng Anh dễ dàng .
_CCS có phần “ common questions “ – những câu hỏi thường gặp và trả lời , chưa được dòch ở đây
dù nó rất quan trọng , nhiều bạn hay bỏ qua , không để ý . Bạn nên xem nó .
_Trang web đi kèm là những cập nhật sửa lỗi và nâng cấp qua các phiên bản .
_Tài liệu trình bày về các vấn đề sau :
_ Chương 0 : Giới thiệu CCS . Viết 1 chương trình C trong CCS như thế nào . Công cụ mô
phỏng . CCS tích hợp MPLAB .
_ Chương 1 : Sử dụng biến và hàm , các cấu trúc lệnh , chỉ thò tiền xử lý.
_ Chương 2 : Các hàm xử lý số , xử lý bit , delay .
_ Chương 3 : Xử lý ADC , các hàm vào , ra trong C .
_ Chương 4 : Truyền thông với PC , xử lý chuỗi .
_ Chương 5 : vấn đề TIMER.
_ Chương 6 : Truyền thông I2C , SPI và PARALLEL .
_ Chương 7 : Các vấn đề về PWM , Capture và Compare .
_ Chương 8 : Vấn đề ngắt ( interrupt ).
_Trong mỗi chương sẽ có các hướng dẫn sử dụng các hàm thích hợp cho chủ đề đó .
_Nên đọc chương 1 trước . Các chương còn lại độc lập nhau .
_Tài liệu này viết đến đâu đưa lên mạng cho mọi người tham khảo đến đó . Hầu hết sẽ trình bày sử
dụng 1 cách cơ bản nhất , sau đó sẽ bổ sung thêm VD,chương trình, . . . thêm đến đâu sẽ thông báo
đến đó .
1
2
CHƯƠNG 0 :
HƯỚNG DẪN SỬ DỤNG CCS – VIẾT CHƯƠNG
TRÌNH C TRONG CCS
I / _ GIỚI THIỆU CCS :
_CCS là trình biên dòch dùng ngôn ngữ C lập trình cho VĐK . Đây là ngôn ngữ lập trình đầy sức
mạnh , giúp bạn nhanh chóng trong việc viết chương trình hơn so với ngôn ngữ Assembly .
_Mã lệnh được tối ưu khi biên dòch .
_Tuy nhiên C không phải là vạn năng , có thể thực hiện mọi thứ như ý muốn . Trong 1 số trường
hợp , nó có thể sinh mã chạy sai (tham khảo các cải tiến ở các version CCS trên web
: info.CCS.com
hoặc trang web đi kèm ).
_CCS chứa rất nhiều hàm phục vụ cho mọi mục đích và có rất nhiều cách lập trình mã cho cùng 1
vấn đề dẫn đến khác nhau tốc độ thực thi mã , độ dài chương trình . Sự tối ưu là do kỹ năng lập trình
C của bạn .
_CCS C có đủ khả năng để bạn không cần phải chèn thêm bất kỳ dòng lệnh ASSEMBLY nào , và
mặc dù vẫn cho phép bạn phối hợp ASSEMBLY cùnh với C , tuy nhiên CCS sẽ không bảo đảm
chương trình chạy chính xác .
_CCS cung cấp các công cụ tiện ích giám sát hoạt động chương trình như : C/ASM list : cho phép
xem mã ASM của file bạn biên dòch , giúp bạn quản lý mã và nắm được các thức mã sinh ra và nó
chạy như thế nào , là công cụ rất quan trọng , bạn có thể gỡ rối chương trình và nắm được hoạt động
của nó ; SYMBOL hiển thò bộ nhớ cấp phát cho từng biến , giúp quản lý bộ nhớ các biến chương
trình ,. . . CallTree hiển thò phân bổ bộ nhớ .
_ Có nhiều tiện ích trong mục Tools , nhưng do bản crack nên nhiều cái không xài được .
_Chương trình CCS dùng cho tài liệu này là PCW COMPILER bản mới nhất version 3.235 , bao
gồm : PCB , PCM và PCH , lập trình cho các họ PIC 10 bit ,12 bit , 14 bit và PIC 18 , chưa có DsPIC
.
II / _ SỬ DỤNG CCS :
_Để viết 1 chương trình C mới : chạy CCS , vào New để tạo 1 file C mới . Trên thanh toolbar :
Chọn “Microchip 12 bit” để viết chương trình cho PIC 12 bit . “Microchip 14 bit” để viết chương
trình cho PIC 14 bit . “Microchip PIC18” để viết chương trình cho PIC18 .
_Chọn “Compiler” để biên dòch chương trình bạn đang viết.
_Trên đây là cách viết chương trình cấp tốc và gọn . để viết chương trình 1 cách chi tiết và cụ thể ,
sử dụng Project -> New -> PIC Wizard . Sau đó chọn tên project sẽ lưu , nhấn save . Bảng sau hiện
ra :
_Nếu sử dụng mạch dao động thạch anh ngoài thì điền giá thò xung clock vào ô sau :
Phải nhấp kép vào mới hiệu chỉnh được .
3
_Chọn con PIC muốn lập trình :
_Muốn xem trước mã sinh ra khi hiệu chỉnh bất kỳ điều gì , chọn :
_Tuỳ thuộc loại PIC muốn lập trình mà mục FUSES sẽ có thêm nhiều hay ít tuỳ chọn , VD 18F4431:
_Để ý bên dưới là 1 dãy tab các lựa chọn các thông số khác:
_chú ý 2 nút mũi tên có thể mở thêm nhiều mục khác .
_Sau khi hiệu chỉnh như ý muốn , OK để hoàn thành .
III / _ CCS TÍCH HP TRONG MPLAB – VIẾT MÃ VÀ MÔ PHỎNG :
_Công cụ mô phỏng cho PIC 16Fxxx. . đa năng nhất chỉ có thể là PIC Simulator IDE 5x , hỗ trợ 38
loại PIC 16Fxxx . Có cả Oscilocope , INT ảo , . . . và nhiều chức năng khác với giao diện tuyệt đẹp ,
dễ dùng . Hoạt động độc lập , lấy file HEX để mô phỏng . Có dòch ngược ra Assemble . Có bộ lập
trình BASIC và Assemble rất hay và dễ dùng , dù khá đơn giản nhưng đủ để viết các chương trình
nhỏ chất lượng . Bạn nên thử qua . Khuyết điểm : thiếu 1 vài module mô phỏng như : chức năng
PWM không có tác dụng .
_ Mô phỏng với PIC 18 , PIC 12 , và nhiều loại PIC 16 mà IDE trên không hỗ trợ ? Bạn có thể dùng
CCS tích hợp trong MPLAB dưới dạng plugin . Để có được tính năng này , sau khi cài đặt CCS , phải
cài tiếp CCS_plugin_for_MPLAB6xx .
_Bạn có thể soạn mã CCS trong môi trường MPLAB và cho phép mô phỏng mã C lẫn mã
ASSEMBLY dòch ngược của nó , tương tự như lập trình và mô phỏng với MPLAB C18 .
_Quan trọng : 1 số VĐK mà MPLAB không hỗ trợ mô phỏng hết cacù chức năng của nó , bạn nên
xem kỹ trong phần HELP của MPLAB , mục SIM để có chi tiết . Hoặc vào Debug->Setting…->chọn
tab Limitations . Bỏ qua phần này có thể khiến bạn lầm tưởng chương trình viết sai trong khi nó
không hỗ trợ mô phỏng . Cho tới hiện tại , tôi chưa biết cách mô phỏng chưỗi xung đi vào PIC , từ
4
đó chương trình nhận biết và hoạt động tương ứng với nó ( như là kích hoạt ngắt ngoài , tạo xung
timer ngoài , tạo tín hiệu analog vào chân AD , . . .
_ Thiết lập môi trường CCS : vào MPLAB IDE , vô mục Project-> Set Language Tool Location . . .
Hộp thoại mở ra , nhấn vào dấu + của dòng CCS C Compile ->Executable ,sau đó chọn Browser để
thiết lập đường dẫn đến file ccsc . exe trong thư mục cài đặt CCS ( tên mặc đònh là PICC ) . Bạn có
thể thêm đường dẫn vào 4 dòng của Default Search Path . . . nếu thấy cần .
_ Tạo 1 dự án ( project ) CCS trong MPLAB : vào Project-> Project Wizard :
_Chọn VĐK làm việc :
_Ở bước 2 : chọn bộ công cụ ( Active toolSuite ) là CCS C Compiler , nhấn Next .
_Điền tên dự án và đường dẫn , click Next .
_Bước 4 : có thể không cần Add file thiết bò *.h vì trong file mã mà bạn sẽ viết sau đó có dòng
#include file này rồi thì nó tự include vào thôi . thế là bạn đã có môi trường làm việc CCS trong
5
MLPAB . Khuyết điểm là bạn không thể dùng các tiện ích của CCS độc lập được ( C/asm list . . . )
. Tuy vậy , sau khi biên dòch các file C/Asm list và file COFF , . . .sẽ có trong thư mục dự án và bạn
có thể mở chúng bằng 1 trình văn bản như là Notepad.
_Bên trái là cửa sổ dự án, nơi bạn có thể thêm vào các file cần thiết.
_Để thêm 1 file *.c , nhấn chột phải lên “ source file” -> Add file . . .
_Để thêm 1 file *.h , nhấn chuột phải lên “Header file “ -> add file . . .
_Mục Other files : dùng để thêm vào các file phục vụ cho dự án như các file C , file text , . . .Các
file này có thể được biên dòch mà cũng có thể không , và dùng để ghi các chú giải , sơ đồ thuật toán
, . . .
_Để biên dòch dự án , chọn :
_Biên dòch xong , cửa sổ Output hiện ra :
6
_lưu ý : các cảnh báo ( warning ) là có thể bỏ qua , trình biên dòch vẫn tạo ra file hex . Nhưng lỗi
error nếu có thì không thể bỏ qua , vì nó không thể tạo file hex được . hãy nhấn kép vào dòng
warning hay error nào thì sẽ nhảy đến vò trí phát sinh nó .
_Để mô phỏng :
_Sau khi chọn MPLAB SIM , thanh toolbar sau hiện ra :
_Chọn RUN khi mô phỏng chương trình sẽ chạy liên tục .
_Chọn animate
để xem chương trình mô phỏng dòng lệnh liên tục theo 1 mức thời gian đònh
trước cho 1 lệnh . Để hiệu chỉnh khoảng thời gian để nhảy 1 lệnh , vào debugger->setting . . .Chọn
Tab như bên dưới :
7
_Hình trên cho thấy :bước nhảy là 500 ms cho 1 dòng lệnh C hay ASM , hiệu chỉnh nhỏ hơn sẽ làm
tăng tốc độ animate , còn cập nhật trên Watch sẽ mất 5x100=500 ms , có thể thay đổi . Nếu muốn
Watch cập nhật ngay tức thì ( real time ) thì đánh dấu chọn trên ô
_Để mô phỏng từng dòng lệnh , dùng
, hay phím F7 , tiên lợi hơn khi dùng animate .
_Ta có thể dùng mọi tiện ích trong mục View để phục vụ mô phỏng . Bao gồm :
1 / _ Disassembly listing : thể hiện mã ASM cho từng dòng lệnh C . Lưu ý là sẽ có 1 con trỏ mô
phỏng màu xanh bên trái cho cả hộp thoại dòng lệnh C lẫn ASM nghóa là tiến trình mô phỏng thể
hiện trên cả 2 hộp thoại . Khi mô phỏng , nếu đặt con trỏ chuột bên hộp ASM , con trỏ xanh sẽ mô
phỏng từng dòng lệnh ASM tương ứng cho dòng lệnh C bên hộp lệnh C . Ngược lại , nếu chọn hộp
thoại C , sẽ mô phỏng từng dòng lệnh C , tương ứng cả 1 nhóm dòng lệnh ASM tương ứng .
_Nhấn Halt
để dừng mô phỏng . Nhấn Reset để reset lại việc mô phỏng
2 / _ Hardware Stack : cho phép giám sát stack .
3 / _ Program memory : xem bộ nhớ chương trình , giống như Disassembly listing .
8
4 / _ File registers : hiển thò các thanh ghi đòa chỉ lệnh bộ nhớ .
5 / _ EEPROM : hiển thò bộ nhớ EEPROM .
6 / _ Memory usage gauge : hiển thò tình trạng sử dụng bộ nhớ .
7 / _ Watch : cho phép giám sát nội dung các biến C hay các thanh ghi bộ nhớ trong khi mô phỏng .
_Chọn Watch .
_Để giám sát thanh ghi bộ nhớ , chọn tên thanh ghi rồi nhấn Add SFR :
Tên thanh ghi sẽ thêm vào vùng bên dưới .
_Để giám sát tên biến c trong chương trình của mình , chọn tên biến và nhấn Add symbol.
MPLAB cho phép tới 4 khung Watch làm việc . thường ta chỉ cần 1 .
_Để loại bỏ biến hay thanh ghi bất kỳ khỏi việc giám sát , chọn nó và nhấn nút Delete trên bàn
phím.
_Nhấn chuột phải trên vùng giám sát để có các lựa chọn thêm , trong đó có mục Properties , tuy
nhiên chúng không quan trọng trừ khi có những yêu cầu đặc biệt .
_Click chuột phải lên vùng này :
Sẽ đổ xuống menu sau , cho phép hiển thò nội dung biến theo dạng số hex, thập phân , nhò phân , . .
_Click kép vào ô giá trò để hiệu chỉnh giá trò biến nếu muốn .
_Lưu ý là khi reset lại để mô phỏng từ đầu , Watch không tự cập nhật . Phải đóng nó rồi mở lại .
8 / _Special function Register : cho phép giám sát các thanh ghi chức năng đặc biệt .
9 / _ Simulator Trace : ghi lại toàn bộ tiến trình thực thi mã từ lúc reset đến lúc dừng .Rất tuyệt vời
khi muốn xem chương trình có độ dài bao nhiêu chu kỳ lệnh , hay quan sát 1 vòng lặp thực thi xong
thì mất bao nhiêu thời gian , xem chương trình chạy như thế nào , . . .Lưu ý là cửa sổ sẽ không cập
9
nhật trong lúc đang mô phỏng , mà phải đóng nó lại rồi mở lại thì nó mới update kết quả mới .
Ngoài ra nhấn chuột phải lên cửa sổ sẽ cho nhiều lựa chọn tuỳ biến hay .
_Vài thủ thuật linh tinh :
_Nhấn chuột trái lên mỗi cửa sổ để mở menu
->Dockable : cửa sổ luôn ở trên cùng .Để
bỏ tính năng này , click phải lên đó và chọn undockable .
_Khi mở nhiều cửa sổ giám sát , sẽ dẫn đến khó quan sát và chọn cửa sổ , do đó muốn chọn cái nào
thì vào Window để chọn
II / _ VIẾT 1 CHƯƠNG TRÌNH TRONG CCS :
_Sau đây là ví dụ về cấu trúc 1 chương trình trong CCS :
#include < 16F877 .h >
#device PIC6f877 *=16 ADC=10
#use delay(clock=20000000)
. . . .
Int16 a,b;
. . . .
Void xu_ly_ADC ( )
{ . . .
. . .
}
#INT_TIMER1
Void xu_ly_ngat_timer ( )
{ . . .
. . .
}
Main ( )
{ . . .
. . .
}
_Đầu tiên là các chỉ thò tiền xử lý : # . . . có nhiệm vụ báo cho CCS cần sử dụng những gì trong
chương trình C như dùng VXL gì , có dùng giao tiếp PC qua cổng COM không , có dùng ADC
không , có dùng DELAY không , có biên dòch kèm các file hay không . . .
_Các khai báo biến .
_Các hàm con do ta viết : xu_ly_ADC () , . . .
_ Các hàm phục vụ ngắt theo sau bởi 1 chỉ thò tiền xử lý cho biết dùng ngắt nào.
_Chương trình chính .
10
11
_Một chương trình C có thể được viết luôn tuồn trong hàm main () , nếu chúng rất ngắn và đơn giản
. Nhưng khi chương trình bắt đầu dài ra , phức tạp lên 1 chút thì phải phân chia trong các hàm con .
Các hàm này có thể là :
1/ Hàm không trả về trò . Ví dụ :
Void xu_ly( )
{
z= x+y ;
}
Hàm trên chỉ thực hiện các lệnh trong thân hàm , khi gọi hàm này chỉ đơn giản viết :
Xu_ly( ) ;
2/ Hàm có trả về trò . Ví dụ :
int xu_ly ( int a , int b)
{
. . . . . .
Return (a+b) ;
}
Hàm trên sẽ trả về tổng (a+b) . khi sử dụng , ví dụ tính tổng 2 biến e ,f , chương trình như sau ( trong
hàm main() ) :
Main()
{
Int e ,f ,g ;
e=7 ;
f= 4;
g = xu_ly(e ,f ); // giá trò g=28
}
_Mỗi hàm con nên được viết để thực hiện 1 chức năng chuyên biệt nào đó . Bên trong 1 hàm con
có thể gọi 1 hay nhiều hàm khác . Cách thức hoạt động như viết 1 chương trình C trên máy tính .
_Nếu chương trình lớn hơn nữa có thể làm file c rất dài và do đó rất khó kiểm soát , nên sẽ cần
phân chia ra các file c . trong đó file chính chứa hàm main sẽ được biên dòch . Các file c khác chứa
các hàm phục vụ chuyên biệt như : cho LCD , . . .Trong file chính chỉ cần thêm dòng #include < file
x.c > là tất cả hàm cần dùng chứa trong file x sẽ được biên dòch vào file hex chung . Các ví dụ trong
thư mục của CCS nếu có sử dụng LCD sẽ chèn 1 dòng #include < lcd.c> và do đó sẽ gọi được các
hàm trong file này mà không cần phải viết lại . điều này có nghóa là ta có thể viết các file c chứa mã
tổng quát có thể dùng chung cho nhiều project , tức là tái sử dụng mã , thay vì phải viết lại chuyên
biệt cho từng project . Đây là cách làm chuyên nghiệp cho những project lớn .
12
CHƯƠNG 1 :
C
C
A
A
Ù
Ù
C
C
H
H
S
S
Ư
Ư
Û
Û
D
D
U
U
Ï
Ï
N
N
G
G
B
B
I
I
E
E
Á
Á
N
N
V
V
A
A
Ø
Ø
H
H
A
A
Ø
Ø
M
M
,
,
C
C
A
A
Ù
Ù
C
C
C
C
A
A
Á
Á
U
U
T
T
R
R
U
U
Ù
Ù
C
C
L
L
E
E
Ä
Ä
N
N
H
H
,
,
C
C
H
H
Ỉ
Ỉ
T
T
H
H
Ị
Ị
T
T
I
I
E
E
À
À
N
N
X
X
Ư
Ư
Û
Û
L
L
Y
Y
Ù
Ù
I / _ KHAI BÁO VÀ SỬ DỤNG BIẾN , HẰNG , MẢNG :
1 / _ Khai báo biến , hằng ,mảng :
_Các loại biến sau được hỗ trợ :
int1 số 1 bit = true hay false ( 0 hay 1)
int8 số nguyên 1 byte ( 8 bit)
int16 số nguyên 16 bit
int32 số nguyên 32 bit
char ký tự 8 bit
float số thực 32 bit
short mặc đònh như kiểu int1
byte mặc đònh như kiểu int8
int mặc đònh như kiểu int8
long mặc đònh như kiểu int16
_Thêm signed hoặc unsigned phía trước để chỉ đó là số có dấu hay không dấu .Khai báo như trên
mặc đònh là không dấu . 4 khai báo cuối không nên dùng vì dễ nhầm lẫn . Thay vào đó nên dùng 4
khai báo đầu .
VD :
Signed int8 a ; // số a là 8 bit dấu ( bit 7 là bit dấu ).
Signed int16 b , c , d ;
Signed int32 , . . .
_Phạm vi biến :
Int8 :0 , 255 signed int8 : -128 , 127
Int16 : 0 ,2^15-1 signed int16 : -2^15 , 2^15-1
Int32 : 0 , 2^32-1 signed int32 : -2^31 , 2^31-1
_Khai báo hằng : VD :
Int8 const a=231 ;
_Khai báo 1 mảng hằng số :
VD : Int8 const a[5] = { 3,5,6,8,6 } ; //5 phần tử , chỉ số mảng bắt đầu từ 0 : a[0]=3
_Một mảng hằng số có kích thước tối đa tuỳ thuộc loại VĐK:
*NếuVĐK là PIC 14 ( VD :16F877 ) : bạn chỉ được khai báo 1 mảng hằng số có kích thước tối đa là
256 byte .
Các khai báo sau là hợp lệ :
Int8 const a[5]={ . . .}; // sử dụng 5 byte , dấu . . . để bạn điền số vào
Int8 const a[256]={ . . .}; // 256 phần tử x 1 byte = 256 byte
Int16 const a[12] = { . . . }; // 12 x 2= 24 byte
Int16 const a[128] = { . . . }; // 128 x 2= 256 byte
13
Int16 const a[200] = { . . . }; // 200 x 2 =400 byte : không hợp lệ
*Nếu VĐK là PIC 18 : khai báo mảng hằng số thoải mái , không giới hạn kích thước .
_Lưu ý : nếu đánh không đủ số phần tử vào trong ngoặc kép như đã khai báo , các phần tử còn lại
sẽ là 0 . Truy xuất giá trò vượt quá chỉ số mảng khai báo sẽ làm chương trình chạy vô tận .
VD : int8 const a [7] = { 0 , 3,5 ,9 } // các phần tử a[4] ,a[5],a[6] đều =0
_Mảng hằng số thường dùng làm bảng tra (ví dụ bảng tra sin ) , viết dễ dàng và nhanh chóng , gọn
hơn so với khi dùng ASM để viết .
_Khai báo 1 biến mảng : kích thước tuỳ thuộc khai báo con trỏ trong #device và loại VDK:
*PIC 14 : Nếu bạn khai báo con trỏ 8 bit : VD # device *=8 : không gian bộ nhớ chỉ có 256 byte cho
tất cả các biến chương trình bất chấp VĐK của bạn có hơn 256 byte RAM (Vd : 368 , . . .) và biến
mảng có kích thước tối đa tuỳ thuộc độ phân mảnh bộ nhớ , với 16F877 có 368 byte ram , thường thì
kích thước không quá 60 byte ,có khi dưới 40 byte , nếu khai báo lớn hơn sẽ gặp lỗi vô duyên : not
enough ram for all variable trong khi thực sự VDK còn rất nhiều RAM . Nếu khai báo con trỏ 16 bit
: VD : #device *=16 , không gian bộ nhớ là đầy đủ ( trừ đi 1 ít RAM do CCS chiếm làm biến tạm )
.VD : với 16F877 bạn dùng đủ 368 byte RAM . Nhưng kích thước mảng cũng không quá 60 byte .
* PIC 18 : kích thước mảng không giới hạn, xài hết RAM thì thôi . Với khai báo con trỏ 8 bit , bạn
chỉ được xài tối đa 256 byte RAM , nếu khai báo con trỏ 16 bit , bạn xài trọn bộ nhớ RAM thực sự .
_VD Khai báo biến mảng : int16 a[125] ; // biến mảng 126 phần tử , kích thước 252 byte ram .
2 / _ Cách sử dụng biến :
_Khi sử dụng các phép toán cần lưu ý : sự tràn số , tính toán với số âm , sự chuyển kiểu và ép kiểu .
A ) _Một vài ví dụ về tràn số , làm tròn :
_VD :
Int8 a=275; // a =275-256=19
Int8 const a=275 //a=19
Int8 a=40 , b=7 , c;
C=a * b ; //c=280-256=24
C=a / b ; //c=5
_Bạn có thể ép kiểu , thường là tiết kiệm ram , hay muốn tiết kiệm thời gian tính , . . .. VD :
Int8 a =8 , b=200;
Int16 c ;
C= ( int16) a * b ;
// c= 1600 , a chuyển sang 16 bit , 16bit*8bitỈ b tự động chuyển sang 16 bit , kết quả là 16 bit trong
c , lưu ý biến a , b vẫn là 8 bit .
_8bit * 8bit Ỉ phép nhân là 8 bit , KQ là 8 bit
_16bit * 8 bit Ỉ phép nhân là 16 bit , KQ là 16 bit
_32bit * 16 bit Ỉ phép nhân là 32 bit , KQ là 32 bit
_16bit * 16 bit Ỉ phép nhân là 16 bit , KQ là 16 bit
. . . v . v . . .
_Có thể ép kiểu kết quả : VD : 16b*8bỈ16bit , nếu gán vào biến 8 bit thì KQ sẽ cắt bỏ 8 bit cao .
B ) _ Phạm vi sử dụng biến :
_Giống như C trong lập trình C cho máy tính . Biến có thể được khai báo như toàn cục hay cục bộ
.Biến khai báo trong hàm sẽ là cục bộ và sẽ chỉ dùng được trong hàm đó , kể cả trong hàm main()
.Ngoài ra còn có thể khai báo ngay trong 1 khối lệnh , và cũng chỉ tồn tại trong khối lệnh đó . Do
vậy nếu dùng MPLAB để mô phỏng , thì khi nhảy vào hàm hay khối lệnh có chứa khai báo biến đó
thì biến đó mới có giá trò , có khi nhảy ra ngoài hàm thì biến đó sẽ là” out of scope” khi ta quan sát
chúng trong cửa sổ Watch.
_Chi tiết về phạm vi biến xem tài liệu lập trình C trên máy tính .
_CCS có hỗ trợ cả con trỏ , tuy nhiên ít dùng .
_CCs không hỗ trợ lập trình hướng đối tượng như C++ . Tuy vậy CCS có hỗ trợ các biến cấu trúc .
3 / _ Các phép toán , sự thực thi và vấn đề tối ưu mã , chương trình:
_Trên đây là thời gian cần cho 1 phép toán .
_Khi chương trình của bạn nhỏ xíu và có thể kiểm soát được , và thời gian thực thi là không quan
trọng ,đồng thời có thể không cần mô phỏng thì bạn có thể dùng cả kiểu float nếu thấy tiện .
_Khi chương trình lớn , cần mô phỏng , và thời gian thực thi là quan trọng thì các điều sau đây nên
làm :
_ Không xài biến kiểu float , vì khi mô phỏng không thấy được giá trò thực của nó .Để khử
số thập phân kiểu float , hãy nhân hay chia cho 2^k .
VD : số kiểu float : m có thể biểu diễn ở dạng : n / 2^8 , với m biết trước , n nguyên được tính trước
bằng cách : n= m* 2^8 , lấy được 2 chữ số sau dấu phẩy (2^8=256 ) . Do đó với 1 bảng tra sin 361
phần tử từ 0->360 độ , nếu lấy chính xác tới 2 dấu phẩy thì các giá trò sin nhân thêm cho 2^8 , cắt bỏ
phần thập phân và lưu vào mảng hằng số int16 , sau đó khi truy xuất tới các giá trò này để sử dụng
thì hãy chia cho 256 bằng cách dòch phải 8 bit .
_Các phép tính nhân chia cho 2^k rất nhanh vì ta dùng phép toán dòch bit . Ví dụ :
Z=Y*2^5 ; thì thay bởi z = y<<5 ; nhanh gấp 20 lần .
Z= y / 2^5 thay bởi z = y >>5 ; nhanh gấp 20 lần .
Trong đó phép dòch nguuyên byte ( 8bit, 16 bit ) là nhanh nhất . VD : z= y>>8 ; z=y <<16 ;
_Không dùng phép trừ mà dẫn đến kết quả có thể âm vì số âm sẽ không hiển thò được khi
mô phỏng ( số hiển thò sẽ là dương và dó nhiên giá trò sẽ khác hẳn ) .Biến đổi sao cho phép trừ luôn
cho kết quả dương thì mới hiển thò chính xác .
VD : công thức điều chế sin PWM có dạng : z = T * (1 + ma * y )
Trong đó : ma <1 , y : giá trò hàm sin : -1< y < 1 . Biến đổi như sau :
y= (y +1) – 1 = y’ -1
14
15
Ỉ z = T* ( 1-ma ) + T * ma * y’ trong đó ( 1-ma ) >=1 . và 0< y’ <2
Ỉ z = [ T * ( 256 – MA ) ]>>8 + [T * MA * Y’ ] >> 15
Trong đó MA = ma<<8 và Y’ = y’ << 7 ;
Ỉ chỉ cần lập bảng tra sin trong đó là các giá trò sin là số nguyên = ( y + 1) * 128 ;
II / _ CÁC CẤU TRÚC LỆNH : ( statement )
_Gồm các lệnh như while . . do , case , . . .
STATEMENTS
STATEMENT EXAMPLE
if (expr) stmt; [else stmt;]
if (x==25)
x=1;
else
x=x+1;
while (expr) stmt;
while (get_rtcc()!=0)
putc(‘n’);
do stmt while (expr);
do {
putc(c=getc());
} while (c!=0);
for (expr1;expr2;expr3) stmt;
for (i=1;i<=10;++i)
printf(“%u\r\n”,i);
switch (expr) {
case cexpr: stmt; //one or more case
[default:stmt]
... }
switch (cmd) {
case 0: printf(“cmd 0”);
break;
case 1: printf(“cmd 1”);
break;
default: printf(“bad cmd”);
break; }
return [expr];
return (5);
goto label;
goto loop;
label: stmt;
loop: I++;
break;
break;
continue;
continue;
expr;
i=1;
;
;
{[stmt]}
Zero or more
{a=1;
b=1;}
Lưu ý : các mục trong [ ] là có thể có hoặc không .
_while (expr) stmt : xét điều kiện trước rồi thực thi biểu thức sau .
_
do stmt while (expr) : thực thi biểu thức rồi mới xét điều kiện sau .
_Return : dùng cho hàm có trả về trò , hoặc không trả về trò cũng được , khi đó chỉ cần dùng: return
; ( nghóa là thoát khỏi hàm tại đó ) .
_Break : ngắt ngang ( thoát khỏi ) vòng lặp while. _Continue : quay trở về đầu vòng lặp while .
16
III / _ CHỈ THỊ TIỀN XỬ LÝ :
_Xem chi tiết tất cả ở phần HELP , mục pre_processor . Ở đây sẽ giới thiệu 1 số chỉ thò thường dùng
nhất :
1 /_ #ASM và #ENDASM :
_Cho phép đặt 1 đoạn mã ASM giữa 2 chỉ thò này , Chỉ đặt trong hàm . CCS đònh nghóa sẵn 1 biến 8
bit _RETURN_ để bạn gán giá trò trả về cho hàm từ đoạn mã Assembly.
_C đủ mạnh để thay thế Assmemly . Vì vậy nên hạn chế lồng mã Assembly vào vì thường gây ra
xáo trộn dẫn đến sau khi biên dòch mã chạy sai , trừ phi bạn nắm rõ Assembly và đọc hiểu mã
Assembly sinh ra thông qua mục C/Asm list .
_Khi sử dụng các biến không ở bank hiện tại , CCS sinh thêm mã chuyển bank tự động cho các biến
đó . Nếu sử dụng #ASM ASIS thì CCS không sinh thêm mã chuyển bank tự động , bạn phải tự thêm
vào trong mã ASM .
_Lưu ý : mã Assembly theo đúng mã tập lệnh VDK , không phải mã kiểu MPLAB .
_VD :
int find_parity (int data) {
int count;
#asm
movlw 0x8
movwf count
movlw 0
loop:
xorwf data,w
rrf data,f
decfsz count,f
goto loop
movwf _return_
#endasm
}
2 / _ #INCLUDE :
_Cú pháp : #include <filename>
Hay #include “ filename”
Filename : tên file cho thiết bò *.h , *.c . Nếu chỉ đònh file ở đường dẫn khác thì thêm đường dẫn vào
. Luôn phải có để khai báo chương trình viết cho VĐK nào , và luôn đặt ở dòng đầu tiên .
_VD :
#include <16F877.H> // chương trình sử dụng cho VĐK 16F877
#include < C:\INCLUDES\COMLIB\MYRS232.C >
3 / _ #BIT , #BYTE , #LOCATE và # DEFINE:
_ #BIT id = x . y
Với id : tên biến x : biến C ( 8,16,32,…bit) hay hằng số đòa chỉ thanh ghi.
y : vò trí bit trong x
Ỉ tạo biến 1 bit đặt ở byte x vò trí bit y, tiện dùng kiểm tra hay gán trò cho bit thanh ghi . Điểm khác
biệt so với dùng biến 1 bit từ khai báo int1 là : int1 tốn 1 bit bộ nhớ , đặt ở thanh ghi đa mục đích
nào đó do CCS tự chọn , còn #BIT thì không tốn thêm bộ nhớ do id chỉ là danh đònh đại diện cho bit
chỉ đònh ở biến x , thay đổi giá trò id ( 0 / 1 ) sẽ thay đổi giá trò bit tương ứng y -> thay đổi trò x.
_VD:
#bit TMR1Flag = 0xb.2 //bit cờ ngắt timer1 ở đòa chỉ 0xb.2 (PIC16F877)