1
Tóm tắtvề Cchoviđiềukhiển
Tóm
tắt
về
C
cho
vi
điều
khiển
1
Bài tập về nhà
2
2
Chương trình C đầu tiên
#
in
c
l
ude
<r
eg5
1
.
h>
#include <reg51 h>
# c ude eg5 .
void main(void)
{
for (;;)
{
P1=0x55;
P1 0 AA
#include
<reg51
.
h>
void main(void)
{
while(1)
{
P1=0x55;
10AA
3
P1
=
0
x
AA
;
}
}
P
1
=
0
x
AA
;
}
}
Ví dụ lệnh sử dụng bit
#include <reg51.h>
void main(void)
{
unsigned char z;
unsigned
char
z;
z=P1;
z=z&0x3;
4
3
Chuyển đổi Hex - ASCII
#include <reg51.h>
void main(void)
#include <reg51.h>
void main(void)
void
main(void)
{
unsigned char x,y,z;
unsigned char
mybyte=0x29;
x=mybyte&0x0F;
P1=x|0x30;
y=mybyte&0xF0;
void
main(void)
{
unsigned char bcdbyte;
unsigned char w=‘4’;
unsigned char z=‘7’;
w
=
w&0x0F;
5
y=mybyte&0xF0;
y=y>>4;
P2=y|0x30;
}
w w&0x0F;
w=w<<4;
z=z&0x0F;
bcdbyte=w|z;
}
Ví dụ sử dụng với ngắt Timer
#include <reg51.h>
sbit SW =P1^7;
sbit IND =P1^0;
sbit WAVE =P2^5;
void timer0(void) interrupt 1 {
WAVE=~WAVE; //toggle pin
}
void main() {
SW=1; //make switch input
TMOD=0x02;
TH0=0xA4; //TH0=
92
6
TH0=0xA4;
//TH0=
-
92
IE=0x82; //enable interrupt for timer 0
while (1) {
IND=SW; //send switch to LED
}
}
4
Ví dụ tổng hợp về ngắt
#include <reg51.h>
sbit WAVE =P0^1;
void timer0() interrupt 1 {
void main() {
unsigned char x;
P1=0xFF; //make P1 an input
O022
void
timer0()
interrupt
1
{
WAVE=~WAVE; //toggle pin
}
void serial0() interrupt 4 {
if (TI==1) {
TI=0; //clear interrupt
}
l{
TM
O
D=
0
x
22
;
TH1=0xF6; //4800 baud rate
SCON=0x50;
TH0=0xA4; //5 kHz has =200us
IE=0x92; //enable interrupts
TR1=1; //start timer 1
TR0=1; //start timer 0
hil (1) {
7
e
l
se
{
P0=SBUF; //put value on pins
RI=0; //clear interrupt
}
}
w
hil
e
(1)
{
x=P1; //read value from pins
SBUF=x; //put value in buffer
P2=x; //write value to pins
}
}
Kiểu dữ liệu
C có ba kiểu chính: characters, integers and
floating-point.
Mỗi kiểu khác nhau thi có giá trị sử dụng khác nhau
và thao tác có thể thực hiện trên chúng
Mỗi kiểu có độ chính xác khác nhau và giới hạn sử
dụng min max
Kiểu mở rộng: long, double, void
5
Character Constants
Là các số nguyên biểu diễn kỹ tự theo bảng
ASCII
ASCII
.
Ví dụ ‘R’ có giá trị 52 hoặc 064 or 0x34
Các giá trị ASCII có thể định nghĩa cho các ký tự
không thể gõ được từ bàn phím
\n new line
\
t
tab
\
t
tab
Lệnh
Cấu trúc for
for (init; test; action)
statement;
Tương tự như lệnh while
init;
while (test)
{
statement;
action;
}
6
Pointers
Định nghĩa: Con trỏ là một biết dùng để chứa địa
chỉ trong bộ nhớ của biến đấy
Khai báo * nghĩa là “trỏ tới”.
Khai báo & nghĩa là “địa chỉ của ”.
Lấ
y
n
ộ
i dun
g
thôn
g
q
ua
*
.
y ộ ggq
Truyền tham chiếu
Tha
y
vi đưa vào theo
g
iá tr
ị,
n
g
ười ta đưa vào theo con trỏ. Giá
y g ị,g
trị đầu vào sẽ được copy những vẫn trỏ đến cùng ô nhớ ban đầu
swap(&a, &b); /* Pass pointers to a and b */
void swap(int* px, int* py)
/*px and py are copies of the pointer arguments*/
{
itt *
i
n
t
t
mp =
*
px;
*px = *py;
*py = tmp;
}
7
Ví dụ: strcpy()
Thường dùng con trỏ như sau.
void strcpy (char *s, char *t)
{
while (*s++ = *t++)
;
}
Con trỏ và giá trị hàm
Hàm có thể trả về con trỏ.
int* func_returns_pointer(void);
Tuy nhiên sẽ là lỗi nếu trả về con trỏ của biến cục
bộ.
int* misguided(void)
{
int array[10], i;
for (i = 0; i < 10; ++i)
array[i] = i;
return array;
}
8
Mảng (array)
Mảng là tập hợp xác định các phần tử có cùng kiểu
dbl t[0]/*E tb t*/
d
ou
bl
e emp
t
y
[0]
;
/*
E
rror: canno
t
b
e emp
t
y
*/
int an_array[10]; /* OK, allocate for 10 ints. */
a = an_array[0]; /* first element */
b = an_array[9]; /* last element */
c = an_array[10]; /* Error: but will compile */
Người lập trình phải tự quản lý giới hạn của mảng.
Lệnh include
Xác định các khai báo của các hàm và các biến.
#include <standard.h>
#include “myheader.h”
File #include sẽ chèn toàn bộ đoạn mã mà nó
đ i đế àhầ ề
đ
ược gọ
i
đế
n v
à
o p
hầ
n m
ề
m
9
Macros
Lệnh #define thường được sử dụng trong việc tạo ra các macro
Khai báo sau
Khai
báo
sau
#define MAX(x,y) ((x)>(y) ? (x) : (y))
Macro giống như hàm, nhưng thực chất không phải hàm. Thực tế
chương trình dịch sẽ thay thế mọi khai báo MAX bằng dòng lệnh
tương ứng các đối số đưa vào (inline)
int a=4, b= -7, c;
c = MAX(a,b);
expands to:
c = ((a)>(b) ? (a) : (b));
Các Macros đơn giản
#define SQR(x) ((x)*(x))
#define SGN(x) (((x)<0) ? -1 : 1)
#d fi ABS( ) ((( )<0) ?
() ())
#d
e
fi
ne
ABS(
x
)
(((
x
)<0)
?
-
(
x
)
:
(
x
))
#define ISDIGIT(x) ((x) >= '0' && (x) <= '9')
#define NELEMS(array) (sizeof(array) /
sizeof(array[0]))
#define CLAMP(val,low,high) \
((val)<(low) ? (low) : (val) > (high) ? (high) :
( l))
(
va
l))
#define ROUND(val) \
((val)>0 ? (int)((val)+0.5) : -(int)(0.5-(val)))
10
Ví dụ
#define TIMELOOP(CODE) {
\
#define
TIMELOOP(CODE)
{
\
t0 = clock(); \
for (i = 0; i<n; ++i) { CODE; } \
printf("%7d ", clock() - t0); \
}
19
Sử dụng như sau:
TIMELOOP(y = sin(x));
Dịch có điều kiện
Các lệnh dịch có điề kiện trong C
Các
lệnh
dịch
có
điề
u
kiện
trong
C
:
#if, #elif, #else, #endif
#ifdef, #ifndef
Mục đích:
Thêm vào các đoạn gỡ lỗi chương trình
Thêm vào các đoạn không phãi mã chuẩn
Thêm
vào
các
đoạn
không
phãi
mã
chuẩn
,
Bảo vệ các header-files sử dụng nhiều lần gọi.
11
Typedefs
A typedef cũng có cùng ý nghĩa như #define, tức là
thuầntùythựchiệnviệc thay thế vănbảnnhưng
thuần
tùy
thực
hiện
việc
thay
thế
văn
bản
,
nhưng
typedef là từ khóa của C, và được dịch bởi chương
trình dịch.
Từ khóa typedef cho phép tạo ra kiểu dữ liệu mới với
tên mới
typedef int Length;
Length len, maxlen;
Length lengths[50];
Toán tử làm việc với bit
C cung cấp 6 toán tử bit:
C
cung
cấp
6
toán
tử
bit:
&| ^~<<>>
Các toán tử này chỉ làm việc với các kiểu char, short, int,
long.
Không dùng cho dấu phẩy động.
Và 5
p
hé
p
g
án bit như sau
ppg
&= |= ^= <<= >>=
Phép gán này tương tự với phép gán số học
z &= x | y;
z = z & (x | y);
12
Mặt nạ bit
Bước 1. Tạo ra số nguyên để đại diện cho từng trạng
thái của bit (hoặt nhóm bit). Ví dụ
enum {
FIRST = 0x01, /* 0001 binary */
SECND = 0x02, /* 0010 binary */
THIRD = 0x04, /* 0100 binary */
FORTH = 0x08, /* 1000 binary */
23
ALL = 0x0f /* 1111 binary */
};
Mặt nạ bit
Một cách khác
enum {
FIRST =
1
<
<
0
,
,
SECND = 1 << 1,
THIRD = 1 << 2,
FORTH = 1 << 3,
ALL = ~(~0 << 4)
};
Dòng cuối cùng thường dùng để bật tắt một nhóm bit
/
/
24
1111 1111
/
* ~
0
*/
1111 0000 /* ~0 << 4 */
0000 1111 /* ~(~0 << 4) */
13
Thao tác với mặt nạ bit
unsigned flags = 0;
flags |= SECND | THIRD | FORTH; /* (1110). */
flags &= ~(FIRST | THIRD); /* (1010). */
flags ^= (THIRD | FORTH); /* (1100). */
if ((flags & (FIRST | FORTH)) == 0)
flags &= ~ALL; /* (0000). */
Keys:
Tá tử|
dù để tổ h á ặt tá tử
dù để đả
25
1.
T
o
á
n
tử|
dù
ng
để
tổ
h
ợp c
á
c m
ặt
nạ,
t
o
á
n
tử
~
dù
ng
để
đả
o
dấu tất cả các bit (mọi bit là 1 trừ những bit được che mặt nạ).
2. |= dùng để set bits.
3. &= dùng để reset bits.
4. ^= dùng để đảo dấu bits.
5. & dùng để chọn bits (cho việc kiểm tra trạng thái).
Các Macros cho từng bít
#define BitSet(arg,posn) ((arg) | (1L << (posn)))
#define BitClr(arg,posn) ((arg) & ~(1L << (posn)))
#define BitFlp(arg,posn) ((arg) ^ (1L << (posn)))
#define BitTst(arg,posn) ((arg) & (1L << (posn)))
enum {FIRST, SECND, THIRD};
unsigned flags = 0;
flags = BitSet(flags, FIRST); /* Set first bit. */
fl BitFl (fl THIRD) /* T l thi d bit
26
fl
ags =
BitFl
p
(fl
ags,
THIRD)
;
/*
T
ogg
l
e
thi
r
d
bit
.
*/
if (BitTst(flags, SECND) == 0) /* Test second bit.
*/
flags = 0;
14
Ví dụ về checksum 8bit
#include <reg51.h>
void main(void)
{
idh
#include <reg51.h>
void main(void)
{
uns
i
gne
d
c
h
ar
mydata[]={0x25,0x62,0x3F,0x52};
unsigned char sum=0, x
unsigned char chksumbyte;
for (x=0;x<4;x++)
{
P2=mydata[x];
sum=sum+mydata[x];
P1
{
unsigned char mydata[]
={0x25,0x62,0x3F,0x52,0xE8};
unsigned char shksum=0;
unsigned char x;
for (x=0;x<5;x++)
chksum=chksum+mydata[x];
if ( hk 0)
27
P1
=sum;
}
chksumbyte=~sum+1;
P1=chksumbyte;
}
if
(
c
hk
sum==
0)
P0=‘G’;
else
P0=‘B’;
}
Phạm vi
Phạm vi:
Cục bộ
Tĩnh
Ngoài
15
Quay Lại Biến Cục Bộ
#include <stdio.h>
#include <assert.h>
#define PI 3.14
double CircleArea (double r) {
assert(r>0.0);
return PI * r * r;
}
double WasherArea (double inner, double outer) {
double innerArea, outerArea, washerArea;
assert(inner>=0.0 && outer>inner);
innerArea = CircleArea(inner);
outerArea = CircleArea(outer);
washerArea = outerArea - innerArea;
return washerArea;
}
int main(void) {
double innerRadius, outerRadius;
int scanfCount;
printf (“Input inner radius and outer radius: ”);
scanfCount = scanf (“ %lf %lf”, &innerRadius, &outerRadius);
if (scanfCount != 2 || innerRadius<0.0 || outerRadius<=innerRadius) {
printf (“Bad input…\n”);
return -1;
}
printf (“ %f ”, WasherArea(innerRadius, outerRadius ));
return 0;
}
Liên Quan Giữa Các Hàm
Đồ thị tĩnh mô tả việc gọi hàm trong ví dụ trên
16
Tham Số Và Biến Cục Bộ
Phạm vi tĩnh (Static Scope)
Biến hay hàm có từ khóa static ở trước chỉ có phạm
vi trong file được dùng đó.
Khởitạobiếntĩnh mặc định là 0
Khởi
tạo
biến
tĩnh
mặc
định
là
0
Biến cục bộ dùng trong hàm khi có khai báo static sẽ
giữ nguyên giá trị giữa các lần gọi hàm
int increment(void)
{
static int local
_
static;
32
_
return local_static++;
}
17
Phạm vi Tĩnh
Biến và hàm tĩnh của một file không thể được sử
d bởiáfilkhá
d
ụng
bởi
c
á
c
fil
e
khá
c
Có thể có cùng một tên mà không bị tranh chấp tên.
File one.c:
static double myvariable;
static void myfunc(int idx);
File two c:
33
File
two
.
c:
static int myvariable;
static int myfunc(int idx);
Tóm tắt
Hàm có phạm vi ngoài là mặc định
Hàm và biếncókhaibáo
static
chỉ giớihạnsử
Hàm
và
biến
có
khai
báo
static
chỉ
giới
hạn
sử
dụng trong file đó.
Biến định nghĩa trong hàm chỉ có giá trị cục bộ
(ngay cả khi dùng static).
18
Chống include nhiều file
Phương pháp chống:
Phương
pháp
chống:
“header guards”.
#ifndef A_HEADER_H_
#define A_HEADER_H_
/* Contents of header file is contained here. */
35
#endif