bài báo cáo môn vi xử lý
TRANSCRIPT
Bài Báo Cáo Môn Vi Xử Lý
Giáo viên bộ môn: Phạm Thế Duy.
Người thực hiện: Đỗ Văn Tiến Đạt.
Lớp: D07VTA1. MS: 407160006.
Nội Dung : Giải thích 10 bài lập trình vi điều khiển, với những đoạn code lập lại
sẽ không được giải thích lại mà chỉ được giải thích một lần.
1. Bài 1 : Điều khiển công tắc đơn và led đơn.
#include <mega16.h> // Định nghĩa thư viện
#include <delay.h>
#define sw1 PINA.0 // Định nghĩa tên thứ tự các pin
#define sw2 PINA.1 // của portA theo sw tương ứng
#define sw3 PINA.2
#define sw4 PINA.3
#define sw5 PINA.4
#define sw6 PINA.5
#define sw7 PINA.6
#define sw8 PINA.7
#define led PORTC
char ledtam1; // Khai báo các biến
char ledtam2;
int n,m;
void main(void)
{
// Input/Output Ports initialization
// Port A initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=P State6=P State5=P State4=P State3=P State2=P State1=P State0=P
PORTA=0xFF; // Có điện trở kéo lên nguồn
DDRA=0x00; // Set port A là ngõ vào
// Port C initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTC=0x00; // Ngõ ra với mức 0
DDRC=0xFF; // Set port C là ngõ ra
led=0x00; // Khởi tạo giá trị led ban đầu bằng 0
while (1) //lập liên tục
{
while(sw1) // Vòng lặp thực hiện khi sw1 đc nhấn
{
led=0x01; // Cho giá trị led =1
delay_ms(200); // Đợi 200 ms
while(led) // Vòng lặp xảy ra khi led khác 0
{
led=led<<1; // Dịch thanh ghi led 8 bit sang trái 1 bít
// đèn sáng lần lược về bên trái
delay_ms(200); // Đợi 200 ms
};
led=0x80; // Gán led =1000 0000 (đèn 8 sáng còn lại tắt)
delay_ms(200); // đợi 200 ms
while(led) // Thực hiện khi led khác 0
{
led=led>>1; // Dịch led sang phải 1 (đèn sáng lần
//lược qua bền phải)
delay_ms(200); // Đợi 200 ms
};
};
while(sw2) // Khi sw2 khác 0 vòng lặp được thực hiện
{
led=0x01; // Gán led = 0000 0001 (đèn 1 sáng còn lại tắt)
delay_ms(200); // Đợi 200 ms
while(led)
{
led=(led<<1)|0x01; // Gán led bằng chính nó dịch sang trái
// đi 1 rồi hoặc bit với 0000 0001
// đèn sáng dần về bên trái
delay_ms(200);
if(led==0xff) // Nếu led = 1111 1111(khi đén sáng hết)
break; // Thoát vòng lặp
};
while(led)
{
led=(led>>1); // Dịch led sang phải 1 bit
// đèn tắt dần về bên phải
delay_ms(200);
if(led==0x00) // Nếu led = 0000 0000
break; // thoát khỏi vòng lặp khi đèn tắt hết
};
};
while(sw3) // Khi sw3 được nhấn vòng lặp sẽ thực hiện liên tục
{
led=0x81; // Gán led = 1000 0001 (đèn 8 và 1 sáng còn lại tắt)
delay_ms(200);
ledtam1=ledtam2=led; //ledtam1 và ledtam2 giữ giá trị của led
while(led)
{
ledtam1=(ledtam1>>1)|0x80; //ledtam1 đươc gán bằng chính
//nó dịch sang phải 1 bit rồi hoặc
//bit với 1000 0000
ledtam2=(ledtam2<<1)|0x01; // tương tự như ledtam1 nhưng
//dịch trái 1 bit và hoặc với
//0000 0001
led=ledtam1|ledtam2; // ledtam1 và ledtam2 hoặc bít
//với nhau rồi gán giá trị cho led
// đèn sẽ sáng từ 2 bên vào
delay_ms(200);
if(ledtam1==0xf0&&ledtam2==0x0f) // nếu ledtam1 = 1111 0000
break; // và ledtam2 = 0000 1111 thì thoát vòng lặp
}; //khi đèn sáng hết thì dừng
while(led)
{
ledtam1=(ledtam1>>1)&0xf0; // ledtam1 dịch phải 1 bit rồi
// và bit 1111 0000
ledtam2=(ledtam2<<1)&0x0f; // ledtam2 dịch trái 1 bit rồi
// và bit với 0000 1111
led=ledtam1|ledtam2; // hoặc bít giữa ledtam1 và //ledtam2 rồi gán cho led
// đèn tắt dần từ trong ra ngoài
delay_ms(200);
};
};
while(sw4)
{
m=8;n=8; // khởi tạo m và n bằng 8
ledtam2=0x00; // ledtam2 = 0000 0000
while(m) // lặp khi m khác 0
{
led=0x01; // gán led = 0000 0001
delay_ms(200);
ledtam1=0x01; // gán ledtam1 = 0000 0001
while(n) // lặp khi n khác 0
{
ledtam1=ledtam1<<1; // dịch ledtam1 sang trái 1 bit
// đèn sáng lần lược qua phải
led=ledtam1|ledtam2; // hoặc bít ledtam1 và 2 rồi
// gán cho led
// sáng dần qua phải và dừng
// lại ở bên phải
n--; // giảm n đi 1 lần
delay_ms(200);
};
ledtam2=(ledtam2>>1)|0x80; // dịch ledtam2 qua phải 1 bit
// rồi hoặc bít với 1000 0000
led=ledtam2;
delay_ms(500);
m--; // giảm m đi 1
n=m-1;
};
};
while(sw5)
{
led=0xff; // led = 1111 1111 đèn sáng hết
delay_ms(200);
led=0x00; // đèn tắt hết
delay_ms(200);
};
while(sw6)
{
led=0x55; //đèn 1 3 5 7 sáng còn lại tắt
delay_ms(200);
led=0xaa; // đèn 2 4 6 8 sáng còn lại tắt
delay_ms(200);
};
while(sw7)
{
led=0xf0; // đèn 1 2 3 4 sáng còn lại tắt
delay_ms(200);
led=0x0f; // đèn 5 6 7 8 sáng còn lại tắt
delay_ms(200);
};
while(sw8)
{
led=0x81; // led = 1000 0001 (đèn 1 và 8 sáng)
delay_ms(200);
ledtam1=ledtam2=led;
while(led)
{
ledtam1=(ledtam1>>1);
ledtam2=(ledtam2<<1);
led=ledtam1|ledtam2; //đèn sáng từ 2 bên chạy vào
delay_ms(200);
if(ledtam1==0x10&&ledtam2==0x01) // đèn sáng chạy vào giữa
break; // thì thoát khỏi vòng lặp
};
while(led)
{
ledtam1=(ledtam1>>1)&0xf0; // ledtam1 dich phải 1 bit rồi và
// bit với 1111 0000
ledtam2=(ledtam2<<1)&0x0f; // ledtam2 dịch trai 1 bit
// rồi và bít với 0000 1111
led=ledtam1|ledtam2; //đèn sáng chạy từ trong ra ngoài
delay_ms(200);
};
};
};
}
2. Bài 2: Điều khiển hiển thị trên LED 7 đoạn.
#include <mega16.h> // Khai báo thư viện
#include <delay.h>
#define nut1 PINC.4 // Định nghĩa lại tên các chân của port C và port D
#define nut2 PINC.5
#define nut3 PINC.6
#define nut4 PINC.7
#define led1 PORTC.3
#define led2 PORTC.2
#define led3 PORTC.1
#define led4 PORTC.0
#define xuatled PORTD
int bien=0,n=0,a=0,b=0,c=0,d=0; // Khai báo cái biến
void main(void)
{
// Port C initialization
// Func7=In Func6=In Func5=In Func4=In Func3=Out Func2=Out Func1=Out Func0=Out
// State7=P State6=P State5=P State4=P State3=0 State2=0 State1=0 State0=0
PORTC=0xF0; // 4 chân bít cao port C có điện trở kéo lên vào 4 chân bít thâp có giá trị 0
DDRC=0x0F; // set port C ở trạng thái 4 chân bít cao là ngõ vào và 4 chân bít thấp là ngõ ra
// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=Out Func2=Out Func1=Out Func0=Out
// State7=P State6=P State5=P State4=P State3=0 State2=0 State1=0 State0=0
PORTD=0xF0; // tương tự như set port C
DDRD=0x0F;
led1=0;
led2=0;
led3=0;
led4=0;
while (1)
{
xuatled=0x00;
if(a==0&&nut1) // nếu a=0 và nut1 =1 thì bien tăng lên 1
{ // và a=1
bien=bien+1;
a=1;
};
if(!nut1) // nếu nut1=0 thì a=0
a=0;
// nghĩa của các câu lệnh trên là khi nhấn và giữ nguyên nút nhấn thì giá trị bien sẽ chỉ tăng lên 1 lần, tương tự với các câu lệnh dưới đây.
if(b==0&&nut2)
{
bien=bien+10;
b=1;
};
if(!nut2)
b=0;
if(c==0&&nut3)
{
bien=bien+100;
c=1;
};
if(!nut3)
c=0;
if(d==0&&nut4)
{
bien=bien+1000;
d=1;
};
if(!nut4)
d=0;
if(bien>9999) // nếu bien lớn hơn thì bien = 0
bien=0;
n++; // n tăng lên 1
switch(n)
{
case 1: led1=led2=led3=led4=0; // để đảm bảo số hiện ra led này không
// bị lem sang con led khác
xuatled=bien%10; // xuatled bằng lấy dư 10 của led
// tức là xuatled bằng giá trị hàng đơn vị
led1=1; // led1 sáng
break; // thoát vòng lặp
case 2: led1=led2=led3=led4=0;
xuatled=(bien/10)%10; // xuatled bằng giá trị hàng chục
led2=1; // led 2 sáng
break;
case 3: led1=led2=led3=led4=0;
xuatled=(bien/100)%10; // xuatled bằng giá trị hàng trăm
led3=1; // led 3 sáng
break;
case 4: led1=led2=led3=led4=0;
xuatled=bien/1000; // xuatled bằng giá trị hàng nghìn
led4=1;n=0; // led 4 sáng
break;
};
delay_ms(50);
}; // nội dung của đoạn code trong switch là quét led và xuất giá trị từng led
}
3. Bài 3 : Điều khiển bàn phím ma trận hiển thị lên LED 07 đoạn.
#include <mega16.h> // Khai báo thư viện
#include <delay.h>
#include <math.h>
#define a1 PORTA.0 // định nghĩa tên cho các chân của port A và C
#define a2 PORTA.1
#define a3 PORTA.2
#define a4 PORTA.3
#define xuatled PORTC
unsigned int i,n=0; // khái báo các biến và màng
unsigned char x,a[]={0x00,0x04,0x08,0x0c,0x01,0x05,0x09,0x0d,0x02,0x06,0x0a,0x0e,0x03,0x07,0x0b,0x0f};
void main(void)
{
// Input/Output Ports initialization
// Port A initialization
// Func7=In Func6=In Func5=In Func4=In Func3=Out Func2=Out Func1=Out Func0=Out
// State7=P State6=P State5=P State4=P State3=0 State2=0 State1=0 State0=0
PORTA=0xF0; // set 4 chân bít cao có điện trở kéo lên, 4 chân bít thấp ngõ ra bằng 0
DDRA=0x0F; // set 4 chân bít cao là ngõ vào, 4 chân bít thấp là ngõ ra
// Port C initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTC=0x00; // set các chân ngõ ra bằng 0
DDRC=0xFF; // set các chân port C là ngõ ra
xuatled=0x00; // xuatled bằng 0 (vì trong mạch có dùng con giải mã 7447 nên
// xuatled bằng số nào thì led sẽ hiện số đó)
while (1)
{
switch(n)
{
case 0: a1=0;
a2=a3=a4=1;
break;
case 1: a2=0;
a1=a3=a4=1;
break;
case 2: a3=0;
a1=a2=a4=1;
break;
case 3: a4=0;
a1=a2=a3=1;
}; // quét phím (xem bên mạch nguyên lý)
x=(PINA>>4)|0xf0; // lấy 4 bit cao của port A gán cho x
x=~x; // lấy đảo của x gán cho x
// vì trong mạch nguyên lý nút nhấn được nhấn sẽ là 0
if(x!=0)
{
i=log(x)/log(2); // lấy giá trị mũ gán cho i tức là i sẽ tương ứng với
// hàng thứ mấy trong cột
xuatled=a[4*n+i]; // xuatled được gán giá trị nội dung của mảng chỉ đến
};
n++;
if(n==4)
n=0;
};
}
4. Bài 4: Điều khiển hiển thị chữ chạy trên LCD.
#include <mega16.h>
#include <delay.h>
int n; // khai bão biến, mảng và chuỗi
int i;
int j;
unsigned char *ten = "DoVanTienDat";
unsigned char *lop = "d07vta1";
unsigned char a[13]; // 13 là độ dài chuỗi “DoVanTienDat” công thêm 1 ký tự kết thúc chuỗi
unsigned char b[8]; // 8 là độ dài chuỗi “d07vta1” và 1 ký tự kết thúc chuỗi
// Alphanumeric LCD Module functions
#asm // Khai báo sử dụng hỗ trợ lcd từ codevisions
.equ __lcd_port=0x15 ;PORTC // khái báo port nối với lcd là port C
#endasm
#include <lcd.h>
void main(void)
// LCD module initialization
lcd_init(16); // khai báo lcd sử dụng là lcd 16 cột
lcd_clear(); // xóa màn hình lcd
n=15;
while (1)
{
for(i=0;i<16;i++) //vòng lặp for 16 lần (dịch chuỗi 16 lần)
{
if(i<7){
*(b+i)=*(lop+i); // lưu nội dung ký tự thứ i của chuỗi lớp vào phần tử
// thứ i của mảng b
*(b+i+1)='\0'; // đưa ký tự kết thúc chuỗi vào phần tử tiếp theo của
// mảng b
}
if(i<12){
*(a+i)=*(ten+i); // lưu nội dung ký tự thứ i của chuỗi lớp vào phần tử
// thứ i của mảng a
*(a+i+1)='\0'; // đưa ký tự kết thúc chuỗi vào phần tử tiếp theo của
// mảng a
}
if(n==-1) n=15; // nếu n = -1 thì gán lại n =15
// dòng lệnh này có tác dụng không cho nội dung của
// hàng trên của lcd tràn xuống hàng dưới
lcd_clear(); // xóa màn hình
lcd_gotoxy(n,0); // đến vị trí xuất ra màn hình lcd cột n hàng thứ nhất
lcd_puts(a); // đưa chuỗi a ra lcd
lcd_gotoxy(n,1); // đến vị trí xuất ra màn hình lcd cột n hàng thứ hai
lcd_puts(b); // đưa chuỗi b ra lcd
n--; // giảm n đi 1
delay_ms(50);
};
};
}
5. Bài 5: Đoc ADC hiển thị lên LCD.
#include <mega16.h>
#include <stdio.h>
#include <delay.h>
#define _ALTERNATE_PUTCHAR_ // định nghĩa lại lệnh putchar
int n=0;
float i;
// Alphanumeric LCD Module functions
#asm // khai báo sử dụng hỗ trợ xuất lcd của codevisions
.equ __lcd_port=0x15 ;PORTC // khai báo sử dung port C làm port xuất lcd
#endasm
#include <lcd.h>
#define ADC_VREF_TYPE 0x20
// Read the 8 most significant bits
// of the AD conversion result
unsigned char read_adc(unsigned char adc_input) // hàm đoc chân vào adc
{ // và trả giá trị vào ADCH
ADMUX=adc_input|ADC_VREF_TYPE;
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCH;
}
void putchar(char c) // viết lại hàm putchar
{
lcd_putchar(c);
}
void main(void)
{
// Input/Output Ports initialization
// Port A initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTA=0x00; // port A không có điện trở kéo lên
DDRA=0x00; // khai báo port A là cổng vào
// ADC initialization
// ADC Clock frequency: 115.200 kHz
// ADC Voltage Reference: AREF pin
// ADC Auto Trigger Source: None
// Only the 8 most significant bits of
// the AD conversion result are used
ADMUX=ADC_VREF_TYPE;
ADCSRA=0x86;
// LCD module initialization
lcd_init(16);
while (1)
{
while(n<=7) // lập 8 lần để đoc lần lược cái chân vào của adc
{
read_adc(n); // đoc chân adc thứ n
if(ADCH<255) // nếu giá trị đoc được nhỏ hơn mức thứ 256
{
i=ADCH*(float)(5)/255*(n+1); // tính giá trị điện áp tương ứng
// rồi ép kiểu foat và gán cho i
} else
{
n++;
if(n==8) // nếu n=8 nghĩa là khi điện áp cần đo vượt mức
{ // adc có thể đo
i=ADCH*(float)(5)/255*(n); // những câu lệnh trong này
n=0; // xuất gia trị điện áp cao nhất mà
lcd_gotoxy(0,0); // adc có thể đoc được
printf("%f",i); // các bạn có thể thay thế bằng
lcd_gotoxy(15,0); // câu lệnh xuất ra chuỗi “ đien
printf("V"); // ap vuot muc quy dinh”
delay_ms(50); // n=0;
lcd_clear(); // lcd_gotoxy(0,0);
break; // printf("đien ap vuot muc quy dinh”);
}; // break;
continue; // bỏ qua nhưng câu lệnh bên dưới và thực hiện
}; // típ vong lập while(n<=7)
lcd_gotoxy(0,0); // chuyển đến vị trí đầu tiên trên lcd
printf("%f",i); // xuất chuỗi i ra lcd
lcd_gotoxy(15,0); // chuyển đến vị trí cột thứ 15 hàng thứ nhất
printf("V"); // xuất ký tự V ra lcd
delay_ms(50);
lcd_clear();
};
};
}
6. Bài 6: Đo và hiển thị nhiệt độ hiển thị trên LED 7 đoạn.
#include <mega16.h> // Khai báo các thư viện nhập xuất, trễ và tính toán
#include <delay.h>
#include <math.h>
#include <stdio.h>
// Alphanumeric LCD Module functions
#asm
.equ __lcd_port=0x15 ;PORTC
#endasm
#include <lcd.h>
#define _ALTERNATE_PUTCHAR_ // định nghĩa lại hàm putchar
void putchar(char c) // viết lại hàm putchar
{
lcd_putchar(c);
}
unsigned int i=0,x,R=10000;
float time,t,v,C=0.001;
// Timer 0 output compare interrupt service routine
interrupt [TIM0_COMP] void timer0_comp_isr(void) // hàm ngắt timer
{
i++; // khi xảy ra ngắt tăng i lên 1
}
// Analog Comparator interrupt service routine
interrupt [ANA_COMP] void ana_comp_isr(void) // hàm ngắt analog compare
{
time=i; // gán i cho time
}
void main(void)
{
// Input/Output Ports initialization
// Port A initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=Out
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=0
PORTA=0x00; // ngõ ra bằng 0
DDRA=0x01; // khai báo cổng ra là chân số 0,
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 172.800 kHz
// Mode: CTC top=OCR0 //chế độ hoạt động CTC
// OC0 output: Disconnected
TCCR0=0x0B;
TCNT0=0x00;
OCR0=0x1A; //156.25us ngắt 1 lần
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00; // không cho phép ngắt timer hoạt động
// Analog Comparator initialization
// Analog Comparator: On
// Interrupt on Rising Output Edge
// Analog Comparator Input Capture by Timer/Counter 1: On
ACSR=0x0F;
SFIOR=0x00;
// LCD module initialization
lcd_init(16);
// Global enable interrupts
#asm("sei") // cho phép xử dụng ngắt
PORTA.0=1; // xả tụ ( xem bên mạch nguyên lý )
delay_ms(50);
while (1)
{
PORTA.0=0; // nạp tụ
i=0;
TIMSK=0x02; // cho phép ngắt timer0 hoạt động
TCNT0=0x00; // cho timer counter bằng 0
x=1;
while(x) //đợi cho đến khi tụ được nạp xong
{
if(time!=0) // kiểm tra xem time có khác 0 hay không
x=0;
};
TIMSK=0x00; // không cho ngắt hoạt động
v=12*(1-exp((-time)/64000)); // tính điện áp theo công thức v=v0.(1- e^(-t/RC))
t=v*100-273; // công thức tính nhiệt độ(xem datasheet LM335)
lcd_clear();
lcd_gotoxy(0,0);
printf("%f",t);
time=0;
PORTA.0=1;
delay_ms(100);
};
}
7. Bài 7: Tạo xung bằng DAC.
#include <mega16.h>
#include<math.h>
#include<delay.h>
#define pi 3.141592654
int i,j,count;
unsigned char table[128];
unsigned char source[17];
#define ADC_VREF_TYPE 0x20
// Read the 8 most significant bits
// of the AD conversion result
unsigned char read_adc(unsigned char adc_input)
{
ADMUX=adc_input|ADC_VREF_TYPE;
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCH;
}
void main(void)
{
for(i=0;i<128;i++)
table[i]=(int)((sin(2*pi*i/128)+1)*63)*2; // tạo hàm sóng sin lưu giá trị vào mảng table
// Port C initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTC=0x00; // trạng thái ngõ ra ở mức 0
DDRC=0xFF; // Khởi tạo port C là ngõ ra
// Port D initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTD=0x00; // trạng thái ngõ ra ở mức 0
DDRD=0xFF; // Khởi tạo port D là ngõ ra
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 8000,000 kHz // xung cấp cho time 8Mhz
// Mode: Normal top=FFh // chế độ hoạt động Normal top=FFh
// OC0 output: Disconnected
TCCR0=0x01;
TCNT0=0x00;
OCR0=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;
// ADC initialization
// ADC Clock frequency: 125,000 kHz
// ADC Voltage Reference: AREF pin
// ADC Auto Trigger Source: None
// Only the 8 most significant bits of
// the AD conversion result are used
ADMUX=ADC_VREF_TYPE;
ADCSRA=0x86;
while (1)
{
switch(PINB) //đoc giá trị của ngõ vào B (xem bên mạch nguyên lý)
{
case 1: // nếu PINB =1 thì dong lệnh trong case 1 được
{ // thực hiện
PORTD=1; // Đóng relays (xem bên mạch nguyên lý)
count=0;
while(count<64&&PINB==1) // khi B có tín hiệu và count < 64
{ // (nữa chu kỳ đầu)
PORTC=0; // áp bằng 0
read_adc(0); // đoc chân adc 0
delay_ms(ADCH); // độ trễ phụ thuộc vào tần số (xem mạch nguyên lý)
count++; // đếm count từ 1->64
}
while(count<128&&PINB==1) // khi B có tín hiệu và count < 128
{ // (nữa chu kỳ sau)
PORTC=0xff; //áp bằng biên độ đỉnh
read_adc(0);
delay_ms(ADCH);
count++;
}
break;
}
case 2: // nếu PINB =2 thì dong lệnh trong case 1 được
{ // thực hiện
PORTD=0; // mở relays
count=0;
while(count<64&&PINB==2) // nữa chu kỳ đầu
{
PORTC=count*4; // biên độ áp tăng theo cấp số cộng 4
read_adc(0);
delay_ms(ADCH);
count++;
}
while(count<128&&PINB==2) // nữa chu kỳ sau
{
PORTC=(127-count)*4; // biên độ áp giảm theo cấp số cộng 4
read_adc(0);
delay_ms(ADCH);
count++;
}
break;
}
case 4: // nếu PINB =4 thì dong lệnh trong case 1 được
{ // thực hiện
PORTD=0;
count=0;
while(count<128&&PINB==4) // xét cả chu kỳ
{
PORTC=table[count]; // giá trị áp ngõ ra thay đổi theo sóng sin
read_adc(0);
delay_ms(ADCH);
count++;
}
break;
}
}
};
}
8. Bài 8: Giao tiếp nối tiếp hai KIT vi điều khiển.
#include <mega16.h>
#include <delay.h>
#include <math.h>
#define a1 PORTA.0
#define a2 PORTA.1
#define a3 PORTA.2
#define a4 PORTA.3
#define COM 0 //định nghĩa COM = 0
#define LCD 1 //định nghĩa LCD = 1
char x,data,xuat=0;
unsigned char a[]={0x61,0x65,0x69,0x73,0x62,0x66,0x70,0x74,0x63,0x67,0x71,0x75,0x64,0x68,0x72,0x76};
int i,n=0,key;
// Alphanumeric LCD Module functions
#asm //***********Khai báo LCD
.equ __lcd_port=0x15 ;PORTC
#endasm // sử dụng port C **********
#include <lcd.h>
#define RXB8 1
#define TXB8 0
#define UPE 2
#define OVR 3
#define FE 4
#define UDRE 5
#define RXC 7
#define FRAMING_ERROR (1<<FE)
#define PARITY_ERROR (1<<UPE)
#define DATA_OVERRUN (1<<OVR)
#define DATA_REGISTER_EMPTY (1<<UDRE)
#define RX_COMPLETE (1<<RXC)
// USART Receiver buffer
#define RX_BUFFER_SIZE 8
char rx_buffer[RX_BUFFER_SIZE];
#if RX_BUFFER_SIZE<256
unsigned char rx_wr_index,rx_rd_index,rx_counter;
#else
unsigned int rx_wr_index,rx_rd_index,rx_counter;
#endif
// This flag is set on USART Receiver buffer overflow
bit rx_buffer_overflow;
// USART Receiver interrupt service routine
interrupt [USART_RXC] void usart_rx_isr(void)
{
char status,data;
status=UCSRA;
data=UDR;
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
{
rx_buffer[rx_wr_index]=data;
if (++rx_wr_index == RX_BUFFER_SIZE) rx_wr_index=0;
if (++rx_counter == RX_BUFFER_SIZE)
{
rx_counter=0;
rx_buffer_overflow=1;
};
};
}
#ifndef _DEBUG_TERMINAL_IO_
// Get a character from the USART Receiver buffer
#define _ALTERNATE_GETCHAR_
#pragma used+
char getchar(void)
{
char data;
while (rx_counter==0);
data=rx_buffer[rx_rd_index];
if (++rx_rd_index == RX_BUFFER_SIZE) rx_rd_index=0;
#asm("cli")
--rx_counter;
#asm("sei")
return data;
}
#pragma used-
#endif
// USART Transmitter buffer
#define TX_BUFFER_SIZE 8
char tx_buffer[TX_BUFFER_SIZE];
#if TX_BUFFER_SIZE<256
unsigned char tx_wr_index,tx_rd_index,tx_counter;
#else
unsigned int tx_wr_index,tx_rd_index,tx_counter;
#endif
// USART Transmitter interrupt service routine
interrupt [USART_TXC] void usart_tx_isr(void)
{
if (tx_counter)
{
--tx_counter;
UDR=tx_buffer[tx_rd_index];
if (++tx_rd_index == TX_BUFFER_SIZE) tx_rd_index=0;
};
}
#ifndef _DEBUG_TERMINAL_IO_
// Write a character to the USART Transmitter buffer
#define _ALTERNATE_PUTCHAR_
#pragma used+
void putchar_com(char c)
{
while (tx_counter == TX_BUFFER_SIZE);
#asm("cli")
if (tx_counter || ((UCSRA & DATA_REGISTER_EMPTY)==0))
{
tx_buffer[tx_wr_index]=c;
if (++tx_wr_index == TX_BUFFER_SIZE) tx_wr_index=0;
++tx_counter;
}
else
UDR=c;
#asm("sei")
}
#pragma used-
#endif
// Các câu lệnh trên xuất hiện khi set chế độ ngắt ở đầu thu và đầu phát của USART
void putchar(char c)
{
switch(key)
{
case COM: putchar_com(c); //xuất ra cổng COM
break;
case LCD: lcd_putchar(c); //xuất ra LCD
break;
}
}
// Standard Input/Output functions
#include <stdio.h>
// Timer 0 output compare interrupt service routine
interrupt [TIM0_COMP] void timer0_comp_isr(void)
{
switch(n) //************************
{
case 0: a1=0;
a2=a3=a4=1;
break;
case 1: a2=0;
a1=a3=a4=1; // quét phím nhấn
break;
case 2: a3=0;
a1=a2=a4=1;
break;
case 3: a4=0;
a1=a2=a3=1;
}; // *************************
x=(PINA>>4)|0xf0; // lấy 4 bit cao của port A rồi gán cho x
x=~x; // đảo x (trong mạch nguyên lý khi nhấn =0)
if(x!=0) // nếu phím được nhấn
{
i=log(x)/log(2); // xác định vị trí phím nhấn
xuat=a[4*n+i];
};
n++;
if(n==4)
n=0;
}
void main(void)
{
// Input/Output Ports initialization
// Port A initialization
// Func7=In Func6=In Func5=In Func4=In Func3=Out Func2=Out Func1=Out Func0=Out
// State7=P State6=P State5=P State4=P State3=0 State2=0 State1=0 State0=0
PORTA=0xF0;
DDRA=0x0F;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 10.800 kHz // xung cấp cho timer0 là 10,8khz
// Mode: CTC top=OCR0 // chế độ hoạt động CTC
// OC0 output: Disconnected
TCCR0=0x0D;
TCNT0=0x00;
OCR0=0x10; // 1,574 ms
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x02; //cho phép ngắt timer0 hoạt động
// USART initialization //********
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud rate: 9600 // set chế độ hoạt động UART
UCSRA=0x00;
UCSRB=0xD8;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x47; // ******
// LCD module initialization
lcd_init(16); // khai báo LCD loại 16 cột
// Global enable interrupts
#asm("sei") // cho phép ngắt timer hoạt động
while (1)
{
if(xuat==0) // nếu ko có phím nào nhấn
{
xuat=' '; // truyền ký tự “ ”
};
key=COM; // chon cổng truyền
putchar(xuat); // truyền dữ liệu
data=getchar(); // nhận dữ liệu lưu vào biến data
lcd_gotoxy(15,0);
key=LCD; // chon cổng truyền LCD
lcd_putchar(data); // xuất ra lcd
delay_ms(50);
lcd_clear();
};
}
9. Bài 9: Thực hiện đồ hồ điện tử trên KIT vi điều khiển.
#include <mega16.h>
#include <stdio.h>
#include <delay.h>
// Alphanumeric LCD Module functions
#asm
.equ __lcd_port=0x15 ;PORTC
#endasm
#include <lcd.h>
int i=0,a=0,b=1,gio=0,phut=0,giay=0,x=0,y=0,z=0;
// Timer 0 output compare interrupt service routine
interrupt [TIM0_COMP] void timer0_comp_isr(void)
{
i++; // mỗi lần ngắt i tăng lên 1
}
#define _ALTERNATE_PUTCHAR_ //*********************************************
void putchar(char c)
{ //Định nghĩa và khái báo lại hàm putchar
lcd_putchar(c);
} //*********************************************
void xuat(int vitri,int noidung) //Hàm hiển thị đồng hồ trên lcd với 2 đối số
{
if(noidung<10)
{
lcd_gotoxy(vitri,0);
printf("%d",noidung);
lcd_gotoxy(vitri-1,0);
printf("0");
}
else
{
lcd_gotoxy(vitri-1,0);
printf("%d",noidung);
}
lcd_gotoxy(13,0);
printf(":");
lcd_gotoxy(10,0);
printf(":");
}
void main(void)
{
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 7.200 kHz
// Mode: CTC top=OCR0
// OC0 output: Disconnected
TCCR0=0x0D;
TCNT0=0x00;
OCR0=0x47; //10ms
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x02;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;
// LCD module initialization
lcd_init(16);
// Global enable interrupts
#asm("sei")
while (1)
{
if(PINA.0&&x==0) // xét nút nhấn chỉnh đồng hồ có nhấn hay không
{
a=1;x=1;
TIMSK=0x00; //không cho ngắt hoạt động
TCNT0=0x00; // thanh ghi counter =0
};
if(PINA.0==0) // đảm bảo nếu nhấn giữ nguyên nút chỉnh đồng hồ
x=0; //thì giá trị sẽ không thay đổi
if(a)
{
while(a)
{
if(b)
{
if(PINA.1&&y==0) // xét nút chon chế độ chỉnh
{
b++;y=1;
if(b==4)
b=1;
};
if(PINA.1==0) // nếu nhấn giữ nguyên nút chon
y=0; // chế độ giá trị b không thay đổi
switch(b)
{
case 1: xuat(15,giay); // chỉnh giây
xuat(12,phut);
xuat(9,gio);
if(PINA.2&&z==0)
{
giay++;z=1;
if(giay==60)
giay=0;
};
if(PINA.2==0) // giữ nút nhấn giá trị
z=0; // giay không thay đổi
break;
case 2: xuat(15,giay); // chỉnh phút
xuat(12,phut);
xuat(9,gio);
if(PINA.2&&z==0)
{
phut++;z=1;
if(phut==60)
phut=0;
};
if(PINA.2==0) // giữ nút nhấn giá trị
z=0; //phút không thay đổi
break;
case 3: xuat(15,giay); // chỉnh giờ
xuat(12,phut);
xuat(9,gio);
if(PINA.2&&z==0)
{
gio++;z=1;
if(gio==24)
gio=0;
};
if(PINA.2==0) // giữ nút nhấn giá trị
z=0; // giờ không thay đổi
};
};
if(PINA.0==0)
x=0;
if(PINA.0&&x==0)
{
a=0;
x=1;
};
};
}
else // nếu không nhấn nút chỉnh đồng hồ
{
TIMSK=0x02;
if(i==100)
{
giay++;
i=0;
};
if(giay==60)
{
giay=0;
phut++;
};
if(phut==60)
{
phut=0;
gio++;
};
if(gio==24)
gio=0;
xuat(15,giay);
xuat(12,phut);
xuat(9,gio);
};
};
}
10. Bài 10: Thực hiện giao tiếp với tải AC. (vd đèn giao thông)
include <mega16.h>
#include<delay.h>
int i=0,j=0,a=1;
char buffer=0,n=10,m=0;
// Timer 0 output compare interrupt service routine
interrupt [TIM0_COMP] void timer0_comp_isr(void)
{
i++;j++;
if(j==6)
{
switch(a)
{
case 1:
buffer=m%10; //gán giá trị hàng đơn vị của m cho buffer buffer=buffer<<4; // chuyển giá trị vừa nhận lên 4 bit cao
buffer=buffer|(n%10); //gán giá trị hàng đơn vị của n
// cho 4 bit thấp của bufer
PORTA=buffer; // xuất giá trị ra đèn led
PORTB=0x01; // đèn thứ nhất của 2 led đôi sáng
a++;
break;
case 2:
buffer=m/10; //gán giá trị hàng chục của m cho buffer
buffer=buffer<<4;
buffer=buffer|(n/10); //gán giá trị hàng đơn vị của n
// cho 4 bit thấp của bufer
PORTA=buffer;
PORTB=0x02; // đèn thứ 2 của 2 led đôi sáng
a=1;
}; j=0;
};
}
void main(void)
{
// Input/Output Ports initialization
// Port A initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTA=0x00; // trạng thái ngõ ra bằng 0
DDRA=0xFF; // sét các chân port A là ngõ ra
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=Out Func2=Out Func1=Out Func0=Out
// State7=T State6=T State5=T State4=T State3=0 State2=0 State1=0 State0=0
PORTB=0x00; // trạng thái chân ngõ ra bằng 0
DDRB=0x0F; // set 4 chân bit thấp port B là ngõ ra
// Port C initialization
// Func7=In Func6=In Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=T State6=T State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTC=0x00; // trạng thái chân ngõ ra bằng 0
DDRC=0x3F; // set chân 0 ->5 của port C là ngõ ra
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 7.200 kHz
// Mode: CTC top=OCR0
// OC0 output: Disconnected
TCCR0=0x0D;
TCNT0=0x00;
OCR0=0x47; //10ms
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x02;
// Global enable interrupts
#asm("sei")
PORTC=0x21; // đèn đỏ trên và đèn xanh dưới sáng
while (1)
{
while(n) //10 giay đầu
{
if(n==10) // nếu n==10 thì gán m= 7
m=7;
if(i==100) // sau 1 giây giảm m và n đi 1
{
i=0;
n--;m--;
};
if(n==2) // n=2 thì gán m=2
{
PORTC=0x11; // đèn đỏ trên và đèn vàng dưới sáng
m=2;
};
if(n==0) // n=0 thì gán m=10
{
m=10;
PORTC=0x0c; // đèn xanh trên và đèn đỏ dưới sáng
};
};
while(m) // 10 giây sau
{
if(m==10) // m=10 thì gán n=7
n=7;
if(i==100) // sau 1 s m và n giảm 1
{
i=0;
m--;n--;
};
if(m==2) // m=2 thì gán n=2
{
PORTC=0x0a; // đèn vàng trên và đèn đỏ dưới sáng
n=2;
};
if(m==0) // m=0 thì gán n=10
{
n=10;
PORTC=0x21; // đèn đỏ trên và đèn xanh dưới sáng
};
};
};
}