Phần 2: Chương trình biên dịch CCS cho vi điều khiển PIC

0
772

Chương trình biên dịch CCS cho vi điều khiển PIC

#TYPE

Chỉ thị tiền xữ lý #type cho phép người sử dụng định nghĩa lại kiểu biến hỗ trợ bởi trình biên dịch. Bởi mặt định trình biên dịch CCS quy định short là 1 bit, int là 8 bit và long là 16 bit. Để giúp code tương thích giữa các trình biên dịch, chỉ thị #type được sử dụng để cho phép các kiểu biến đó thay đổi.

Cấu trúc:

#type standard-type =size[,standard-type=size…]

Ví dụ dưới đây sử dụng chỉ thị tiền xữ lý #byte để định nghĩa lại biến short là 8 bit, biến interger là 16 bit, và biến long là 32 bit:

#type short=8, int = 16, long = 32

Cần lưu ý rằng chương trình ví dụ CCS và các file đính kèm có thể không hoạt động đúng nếu bạn sử dụng#TYPE trong chương trình của bạn.

#BIT

Cấu trúc:

#bit id =x.y

id một định danh hợp lệ trong C

x là một hằng hoặc một biến C

y là hằng số có giá trị từ 0 đến 7

Một biến C mới (độ lớn một bit) được tạo ra và được đặt trong bộ nhớ tại byte x bit thứ y . Chỉ thị hữu ích khi ta cần truy xuất 1 bit trong các thanh ghi chức năng đặc biệt của vi xữ lý hoặc đến những biến khác. Để truy xuất 1 bit trong thanh ghi, khi đó x là địa chỉ của thanh ghi.

Ví dụ dưới đây sử dụng để xóa cờ ngắt Timer0

#bit T0IF = 0x b.2
……

T1IF = 0; // xóa cờ ngắt của timer 0

 Ví dụ biến

int result;

#bit result_odd = result.0

/*bit nhỏ nhất của biến result có tên là result_odd, bây giờ ta có thể truy xuất bit này bằng tên result_odd*/

/* Ta có thể set bit này bằng: result_odd =1 hoặc clear : result_odd = 0 */

if (result_odd)

 #BYTE:

 Cấu trúc:

#byte id=x

id một định danh hợp lệ trong C

x là một hằng hoặc một biến C

Nếu id là một biến C , khi đó nó báo cho chương trình biên dịch cấp phát vùng nhớ tại địa chỉ x. Nếu id chưa khai báo, khi đó chương trình biên dịch sẽ tạo biến C mới và đặt tại địa chỉ x như là biến interger 8 bit. trong cả hai trường hợp , bộ nhớ x không chỉ để dành riêng cho biến này. Những biến khác có thể được cấp phát tại cùng vị trí vùng nhớ. Trong thực tế, khi x là một biến, id và x cùng chia sẽ cùng một vùng nhớ. Chỉ thị tiền xữ lý #locate và #reserve được trình bày ở những bài sau được sử dụng để cấp phát vùng nhớ dành riêng.

Ví dụ dưới đây tạo một biến mới tên b_port và cấp phát tại địa chỉ 0x06

#byte b_port =0x06

 

Ví dụ tiếp theo tạo hai biến kiểu char và chia sẽ cùng vùng nhớ. Biến đầu tiên , a, được tạo và cấp phát vùng nhớ bởi chương trình biên dịch. Khi đó lệnh #byte tạo một biến thứ hai, b,. Phần “=a” của lệnh #byte sẽ báo cho trình biên dịch gán biến mới b đến cùng địa chỉ của biến a.

char a;
#byte b=a 

Đoạn chương trình ví dụ:

#byte PORTC = 0x07 //PORTC is at SFR address 0x07
#define LED1 0x80 //LED1 on PORTC MSBvoid main()
{
while(1)
{
PORTC|=LED1; //Turn off LED1
PORTC&=~LED1; //Turn off LED1
PORTC^=LED1; //Toggle LED1
}
}

 

#LOCATE

Cấu trúc:

#locate id=x

Trong đó:

id là một biến C

x là hằng số địa chỉ vùng nhớ

Chỉ thị #locate hoạt động giống chỉ thị #byte , tuy nhiên, ngoài việc tạo một biến và đặt nó tại địa chỉ x nó còn báo cho trình biên dịch rằng chỉ cấp phát địa chỉ này riêng cho biến x thôi .

Ví dụ

float x;
#located my_float = 0x50

 

#RESERVE

chỉ thị tiền xữ lý #reserve không cho phép chương trình biên dịch sử dụng vùng RAM được chỉ định, #Reserve phải đặt sau #device, nếu không nó không có tác dụng. Chỉ thị #reserve có thể để dành một địa chỉ hoặc một vài địa chỉ bởi sử dụng cú pháp sau:

#reserve address

hoặc

#reserve address, address, address

Nơi address là địa chỉ của RAM

Một cách khác để dành một khối bộ nhớ

#reserve start:end

start : là địa chỉ bắt đầu

end: là nơi địa chỉ kết thúc của khối địa chỉ để dành

Ví dụ: để dành byte tại vị trí 0x10, 0x11, và 0x12 có thể sử dụng các cách dưới đây

#reserve 0x10

#reserve 0x11

#reserve 0x12

Hoặc:

#reserve 0x10, 0x11, 0x12

Hoặc

#reserve 0x10:0x12

#ZERO_RAM

Chỉ thị #zero_ram không có chứa tham số

#zero_ram

Chỉ thị này báo cho trình biên dịch thiết lập tất cả các thanh ghi nội được sử dụng để lưu giữ biếnbằng 0 trước khi thực thi bắt đầu.

Ví dụ:

#zero_ram

void main() {

}

 

#ORG

Lệnh #org có thể định dạng theo một vài cách”

#org start, end

#org segment

#org start, end {}

#org start, end auto=0

Nới start luôn luôn bắt đầu với vùng ROM đầu tiên (địa chỉ word) để sử dụng, end là vùng ROM cuối cùng , và segment là vùng ROM bắt đầu từ chỉ thị #org ở trước. câu lệnh #org cho phép người sử dụng định nghĩa đến trình biên dịch nơi Hàm đi theo chỉ thị #org  nên được đặt. end có thể bỏ qua nếu segment đã định nghĩa trước và người dùng chỉ muôn stheem Hàm khác đến segment. Ví dụ:

#org 0x1E00, 0x1FFF

MyFunc(0

{

// Hàm này được đặt tại 0x1E00

}

#org 0x1E00

Anotherfunc()

{

// Hàm này có thể ở vị trí trong khoảng 0x1E00 – 1F00

}

#org 0x800, 0x820 {}

//Không có gì tại 800-820

#org 0x1c00, 0x1c0F

Char const ID[10]= { “123456789”}

 #ASMvà #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
}

 

Leave a Reply