You are on page 1of 37

Duongv3@gmail.

com Lest’s Share to be Shared

Đo nhiệt độ dùng DS18B20,đo khoảng cách, giao tiếp máy tính, hiển thị LCD.

Lời mở:
Mình hy vọng đề tài này sẽ giúp cho bạn hiểu thêm về lập trình cho Avr. Mình đã bước
đầu làm quen với Avr và gặp nhiều khó khăn, mất nhiều time (và cả $) cho việc làm quen, mong
rằng tài liệu này sẽ giúp bạn tiếp cận Avr nhanh hơn .Tất cả phần cứng và code mình đã làm và
chạy OK.

Cuối cùng xin cảm ơn diễn đàn dientuvietnam.net đã cho mình học hỏi rất nhiều
kiến thức. Đặc biệt là mod Sphinx,( xin cảm ơn nhân sư của Pnlab :D )

CHÚ Ý : Tài liệu này chỉ dành cho newbie ,chứ các bác cao thủ mà đọc thì em lấy làm xấu
hổ lắm.

Các trang web bổ ích cho vấn đề này :

www.dientuvietnam.net

http://vagam.dieukhien.net/

LCD:

1. http://dientuvietnam.net/forums/showthread.php?t=281&highlight=L%E1%BA%ADp
+tr%C3%ACnh+hi%E1%BB%83n+th%E1%BB%8B+LCD+b%E1%BA%B1ng+Asse
mbler+%28+tutorial%29
2. http://www.vagam.dieukhien.net/discuss.php?thid=3121&pagenum=2
3. http://vagam.dieukhien.net/discuss.php?thid=148&pagenum=1
RS232
4. http://www.8051projects.net/serial-communication/introduction.php
5. http://www.vagam.dieukhien.net/discuss.php?thid=3216&pagenum=1
6. http://dientuvietnam.net/forums/forumdisplay.php?f=74

1
Duongv3@gmail.com Lest’s Share to be Shared

Phần cứng :
Dưới đây là cái mạch của mình .

2
Duongv3@gmail.com Lest’s Share to be Shared

Mạch thật nè (xấu quá :D):

3
Duongv3@gmail.com Lest’s Share to be Shared

Các linh kiện trong mạch:

 Chip AVR Atmega16.


 IC DS18B20.
 IC GP2D12.
 MAX 232.
 LCD 1602
 LM7805.
 Led, trở, loa tụ.

Có lẽ không phải nói nhiều về mạch này

Mình chỉ xin đề cập 1 số phần nhỏ :

 Kết nối với ds18B20 bạn có thể xem ở datasheet


 Trong mạch có jump của mạch nạp , có thể bỏ đi vì cho vào mạch sẽ phức tạp hơn.
 Code mình dùng thạch anh trong 4Mhz nên bạn có thể bỏ thạch anh và tụ 22p nếu dùng
thạch anh trong.
 Mình dùng adc chân adc0 để đo khoảng cách từ con Gp2D12, nếu bạn ko dùng con này
thì có thể coi code như là adc bình thường.
Về phần cứng chỉ có vậy. Bạn có thể tham khảo thêm file mạch mình gửi kèm.

Phần mềm:
Bây giờ lập trình nào, mình chia làm 2 phần : trên AVR (mình dùng CodeVisionAvr)và
trên PC (dùng Vb6 :D).

CodeVision AVR:

Mình kết hợp adc và ds18B20 bị lỗi (cũng không biết tại sao, bạn giải quyết được nhớ
chỉ cho mình nhé) nên mình lập trình 2 code riêng 1 code đo nhiệt độ và 1 code ADC.

Sau đây là code đo nhiệt độ :

4
Duongv3@gmail.com Lest’s Share to be Shared

Click chọn new Project :

Dĩ nhiên là Yes rồi


Sau đó bạn lần lượt cấu hình như sau:

Chọn chip

5
Duongv3@gmail.com Lest’s Share to be Shared

Nối LCD vào PORT B

6
Duongv3@gmail.com Lest’s Share to be Shared

Cấu hình ds18B20

7
Duongv3@gmail.com Lest’s Share to be Shared

Cấu hình USART

8
Duongv3@gmail.com Lest’s Share to be Shared

Cấu hình cổng OUT cho các PORTA.2 và PORTA.4 để báo hiệu ra LED và Loa

Sau đó vào menu vào như trong hình rồi chọn tên file để save

9
Duongv3@gmail.com Lest’s Share to be Shared

Bây giờ ta đã có code c/t tự dịch . Đầu tiên là phải thay dòng #include
<ds1820.h> bằng #include <ds18b20.h> (đơn giản vì ta dùng IC 18B20).

Cuối cùng đây là code mình đã viết

/*****************************************************
This program was produced by the
CodeWizardAVR V2.03.4 Standard
Automatic Program Generator
© Copyright 1998-2008 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project :
Version :
Date : 6/23/2009
Author : DuongV3
Company : DHBK
Comments: Have A Mice Day

Chip type : ATmega16


Program type : Application
Clock frequency : 4.000000 MHz
Memory model : Small
External RAM size : 0
Data Stack size : 256
*****************************************************/

#include <mega16.h>
#include <delay.h>

// 1 Wire Bus functions


#asm
.equ __w1_port=0x15 ;PORTC
.equ __w1_bit=0
#endasm
#include <1wire.h>

// DS1820 Temperature Sensor functions

10
Duongv3@gmail.com Lest’s Share to be Shared

#include <ds18b20.h>

// Alphanumeric LCD Module functions


#asm
.equ __lcd_port=0x18 ;PORTB
#endasm
#include <lcd.h>
int c,d,tp1,tp2,tp3,tp4;
typedef unsigned char byte;

flash byte char0[8]={


0b0000000,
0b0011100,
0b0010100,
0b0011100,
0b0000000,
0b0000000,
0b0000000,
0b0000000};
void define_char(byte flash *pc,byte char_code)
{
byte i,a;
a=(char_code<<3) | 0x40;
for (i=0; i<8; i++) lcd_write_byte(a++,*pc++);
}

#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)

11
Duongv3@gmail.com Lest’s Share to be Shared

// 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);

12
Duongv3@gmail.com Lest’s Share to be Shared

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(char c)
{
while (tx_counter == TX_BUFFER_SIZE);
#asm("cli")
if (tx_counter || ((UCSRA & DATA_REGISTER_EMPTY)==0))

13
Duongv3@gmail.com Lest’s Share to be Shared

{
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

// Standard Input/Output functions


#include <stdio.h>

// Declare your global variables here


void putnum(int a)
{
switch(a){
case 0: putchar('0');
break;
case 1: putchar('1');
break;
case 2: putchar('2');
break;
case 3: putchar('3');
break;
case 4: putchar('4');
break;
case 5: putchar('5');
break;
case 6: putchar('6');
break;
case 7: putchar('7');
break;
case 8: putchar('8');
break;
case 9: putchar('9');
break;

14
Duongv3@gmail.com Lest’s Share to be Shared

};
}

int getnum(unsigned char a)


{
switch(a){
case 0: return 0;
break;
case 1: return 1;
break;
case 2:return 2;
break;
case 3: return 3;
break;
case 4: return 4;
break;
case 5: return 5;
break;
case 6: return 6;
break;
case 7: return 7;
break;
case 8: return 8;
break;
case 9: return 9;
break;

};
}
void locso(float so)
{
// unsigned char t,c,d,tp1,tp2,tp3,tp4;
float temp1,temp2;
// t=so/100;
// lay fan tram
c=so/10;
// lay fan chuc
d=(so-10*c);
// lay hang don vi
if(so<0)

15
Duongv3@gmail.com Lest’s Share to be Shared

temp2=so*-1;
else
temp2=so;

temp1=temp2-(c*10+d);
tp1 = (unsigned char)(temp1*10);
tp2 = (unsigned char)(temp1*100-tp1*10);
tp3 = (unsigned char)(temp1*1000-tp1*100-tp2*10);
tp4 = (unsigned char)(temp1*10000-tp1*1000-tp2*100-tp3*10);

// unsigned char t,c,d,tp1,tp2,tp3,tp4;


void main(void)
{
float tg;
char lcd_buffer[10];
unsigned char kt;
int min,max,t_g,array[4],i;
// Input/Output Ports initialization
// Port A initialization
// Func7=In Func6=In Func5=In Func4=Out Func3=In Func2=Out Func1=In
Func0=In
// State7=T State6=T State5=T State4=0 State3=T State2=0 State1=T State0=T
PORTA=0x00;
DDRA=0x14;

// Port B 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
PORTB=0x00;
DDRB=0x00;

// Port C 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
PORTC=0x00;
DDRC=0x00;

// Port D initialization

16
Duongv3@gmail.com Lest’s Share to be Shared

// 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
PORTD=0x00;
DDRD=0x00;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0 output: Disconnected
TCCR0=0x00;
TCNT0=0x00;
OCR0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// 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: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped

17
Duongv3@gmail.com Lest’s Share to be Shared

// Mode: Normal top=FFh


// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization


// INT0: Off
// INT1: Off
// INT2: Off
MCUCR=0x00;
MCUCSR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization


TIMSK=0x00;

// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 9600
UCSRA=0x00;
UCSRB=0xD8;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x19;

// Analog Comparator initialization


// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

// 1 Wire Bus initialization


w1_init();

// LCD module initialization


lcd_init(16);

18
Duongv3@gmail.com Lest’s Share to be Shared

// Global enable interrupts


#asm("sei")

lcd_clear();
lcd_gotoxy(0,0);
lcd_putsf("DuongV3");
lcd_gotoxy(0,1);
lcd_putsf("T(C)= ");
define_char(char0,0);
delay_ms(1000);
i=0;
max=35;
min=30;
while (1)
{
if (rx_counter>0){
kt=getchar(); //kt tra ve se la gia tri trong bang ASCii
// lcd_putchar(kt);
array[i]=getnum(kt)-48;
++i;
}
if(i==2)
{
max=array[0]*10+array[1];

}
if(i==4)
{
i=0;
min=array[2]*10+array[3];
array[0]=0;
array[1]=0;
array[2]=0;
array[3]=0;
}
// Chon so max, min
if (max<min)
{
t_g=max;

19
Duongv3@gmail.com Lest’s Share to be Shared

max=min;
min=t_g;
}
//In ra LCD Gia tri max min
sprintf(lcd_buffer,"%d",max);
lcd_gotoxy(0,0);
lcd_putsf("Max= ");
lcd_puts(lcd_buffer);

sprintf(lcd_buffer,"%d",min);
lcd_gotoxy(8,0);
lcd_putsf("Min= ");
lcd_puts(lcd_buffer);
//
if(ds18b20_init(0,25,35,DS18B20_12BIT_RES))
{
tg= ds18b20_temperature(0);
// temp=(unsigned char) (tg);

if(tg==-9999)
{
}
else
{

lcd_gotoxy(6,1);
if(tg<0)
lcd_putchar(45);
else
lcd_putchar(43);
sprintf(lcd_buffer,"%.4f",tg);
lcd_puts(lcd_buffer);
lcd_putchar(0);
lcd_putsf("C");
delay_ms(80);
if(tg>max)
PORTA=0x10; //PORTA=0x14;
else if (tg<min)
PORTA=0x14;
else PORTA=0x00;

20
Duongv3@gmail.com Lest’s Share to be Shared

}
}
locso(tg);

putnum(c);
putnum(d);
putchar('.');
putnum(tp1);
putnum(tp2);
putnum(tp3);
putnum(tp4);
putchar(' ');

};
}

Bây giờ mình xin giải thích về lưu đồ thuật toán trong hàm main và vòng while(1) (ngại vẽ lắm
nên chỉ nói thôi).

Đầu tiên c/t sẽ từ khởi tạo cho ta ds18b20 và lcd.Sau đó viết lên dòng đầu tiên màn hình
dòng chữ DuongV3 (cái này thì tất nhiên bạn sẽ thay đổi thôi :D). Sau đó là viết lên dòng thứ 2
dòng chữ t(c) . Đặt giá trị i , max , min ban đầu để cảnh báo. Chi tiết về lập trình LCD, bạn
tham khảo ở trang sau :

http://www.vagam.dieukhien.net/discuss.php?thid=3121

http://vagam.dieukhien.net/discuss.php?thid=148&pagenum=1

Bây giờ là trong vòng while: Nhận ký tự từ cổng Com(nếu có)  ghi 2 ký tự nhận được
vào mảng (2 ký tự này sẽ coi là 1 số max hoặc min) Sau đó nhận tiếp 2 ký tự nữa lưu vào mảng
(2 ký tự này sẽ coi là 1 số max hoặc min).,Hàm getnum là mình viết có tác dụng chuyển từ ký tự
sang số để lưu vào mảng  so sánh 2 số và chọn max ,min  Ghi ra LCD  Nếu khởi tạo ban
đầu cho ds18b20 thành công gán tg cho nhiệt độ từ con ds18B20  Nếu dương ghi dấu “+”, nếu
âm ghi dấu “-” ,đưa giá trị ra LCD  locso() có tác dụng chuyển số nhiệt độ có dạng xx.xxxx về
các số riêng phần chục , dv, thập phân tương ứng với các biến c,d,tp1,tp2,tp3,tp4  Hàm
putnum () mình viết có tác dụng đưa 1 số ra cổng COM . Vậy là hết nhỉ :D

Chú ý cấu hình hàm sprintf() như sau:

21
Duongv3@gmail.com Lest’s Share to be Shared

Vào Project configure:

Chọn như sau :

22
Duongv3@gmail.com Lest’s Share to be Shared

Sau đây là code ADC :

Cấu hình giống trên các phần của chip, lcd , PORT còn ADC cấu hình như sau :

Ở đây mình dùng ADC 10bit nên nên ko tick vào ô “Use 8 bits”. Và mình chọn chân
ADC vào là ADC0 nên nó sẽ scan First =0 và Last = 0
Cuối cùng đây là code phần này.

#include <mega16.h>

// Alphanumeric LCD Module functions


#asm
.equ __lcd_port=0x18 ;PORTB
#endasm
#include <lcd.h>
int t,c,d;
typedef unsigned char byte;

23
Duongv3@gmail.com Lest’s Share to be Shared

flash byte char0[8]={


0b0111111,
0b0100001,
0b0100001,
0b1110001,
0b0100001,
0b0100001,
0b0100001,
0b0011111};

/* function used to define user characters */


void define_char(byte flash *pc,byte char_code)
{
byte i,a;
a=(char_code<<3) | 0x40;
for (i=0; i<8; i++) lcd_write_byte(a++,*pc++);
}

#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];

24
Duongv3@gmail.com Lest’s Share to be Shared

#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")

25
Duongv3@gmail.com Lest’s Share to be Shared

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(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;
}

26
Duongv3@gmail.com Lest’s Share to be Shared

else
UDR=c;
#asm("sei")
}
#pragma used-
#endif

// Standard Input/Output functions


#include <stdio.h>

#include <delay.h>

#define FIRST_ADC_INPUT 0
#define LAST_ADC_INPUT 0
unsigned int adc_data[LAST_ADC_INPUT-FIRST_ADC_INPUT+1];
#define ADC_VREF_TYPE 0x00

// ADC interrupt service routine


// with auto input scanning
interrupt [ADC_INT] void adc_isr(void)
{
static unsigned char input_index=0;
// Read the AD conversion result
adc_data[input_index]=ADCW;
// Select next ADC input
if (++input_index > (LAST_ADC_INPUT-FIRST_ADC_INPUT))
input_index=0;
ADMUX=(FIRST_ADC_INPUT | (ADC_VREF_TYPE & 0xff))+input_index;
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=0x40;
}

void putnum(int a)
{
switch(a){
case 0: putchar('0');
break;
case 1: putchar('1');

27
Duongv3@gmail.com Lest’s Share to be Shared

break;
case 2: putchar('2');
break;
case 3: putchar('3');
break;
case 4: putchar('4');
break;
case 5: putchar('5');
break;
case 6: putchar('6');
break;
case 7: putchar('7');
break;
case 8: putchar('8');
break;
case 9: putchar('9');
break;

};
}

void locso(int so)


{
// unsigned char t,c,d,tp1,tp2,tp3,tp4;
// float temp1,temp2;
t=so/100;
// lay fan tram
c=(so-100*t)/10;
// lay fan chuc
d=(so-100*t-10*c);
// lay hang don vi
}

void main(void)
{
unsigned int adc;
unsigned char lcd_buffer[10];

28
Duongv3@gmail.com Lest’s Share to be Shared

int
a[22]={497,464,420,385,360,330,307,290,266,248,230,224,211,209,198,194,189,182,17
8,170,167,167 },kc,i;
// 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;
DDRA=0x10;

// Port B 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
PORTB=0x00;
DDRB=0x00;

// Port C 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
PORTC=0x00;
DDRC=0x00;

// Port D 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
PORTD=0x00;
DDRD=0x00;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0 output: Disconnected
TCCR0=0x00;
TCNT0=0x00;
OCR0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped

29
Duongv3@gmail.com Lest’s Share to be Shared

// Mode: Normal top=FFFFh


// 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: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization


// INT0: Off
// INT1: Off
// INT2: Off
MCUCR=0x00;
MCUCSR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization


TIMSK=0x00;

30
Duongv3@gmail.com Lest’s Share to be Shared

// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 9600
UCSRA=0x00;
UCSRB=0xD8;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x19;

// Analog Comparator initialization


// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

// ADC initialization
// ADC Clock frequency: 1000.000 kHz
// ADC Voltage Reference: AREF pin
// ADC Auto Trigger Source: None
ADMUX=FIRST_ADC_INPUT | (ADC_VREF_TYPE & 0xff);
ADCSRA=0xCA;

// LCD module initialization


lcd_init(16);

// Global enable interrupts


#asm("sei")
lcd_clear();
lcd_gotoxy(0,0);
lcd_putsf("DuongV3");

// define_char(char0,0);
// define_char(char1,1);
// define_char(char2,2);
// lcd_putchar(0);
/* lcd_putsf("i");
lcd_putchar(1);

31
Duongv3@gmail.com Lest’s Share to be Shared

lcd_putsf("n t");
lcd_putchar(2);*/

while (1)
{
adc = adc_data[0];

for(i=0;i<=19;i++)
{
if(adc< a[i] && adc >a[i+1])
{
kc= i+10;
lcd_gotoxy(0,1);
break;
}
}
// lcd_gotoxy(0,1);
if(adc> a[0] || adc <a[19])
{ //lcd_clear();
lcd_gotoxy(0,1);
lcd_putsf("Ngoai Khoang ");
delay_ms(100);
}
else //if(adc< a[0] && adc >a[29])
{
sprintf(lcd_buffer,"Distance :%d",kc);
lcd_gotoxy(0,1);
lcd_puts(lcd_buffer);
lcd_putsf(" cm ");

locso(kc);

putnum(c);
putnum(d);
putchar(' ');
delay_ms(100);
};
};
}

32
Duongv3@gmail.com Lest’s Share to be Shared

Tất nhiên , khi lập trình bạn phải thay giá trị của mảng cũng như code trong vòng while
.

Code trên PC (phần này nêu qua thôi vì có trong Folder rồi):
Dim s As String

Private Sub Command1_Click()

s = MSComm1.Input 'Temp

Text1.Text = s

End Sub

Private Sub Command2_Click()

s = MSComm1.Input

Text2.Text = s

End Sub

Private Sub Command3_Click()

s = Text3.Text ' Max

MSComm1.Output = s

End Sub

Private Sub Command4_Click()

s = Text4.Text 'Min

MSComm1.Output = s

End Sub

33
Duongv3@gmail.com Lest’s Share to be Shared

Private Sub Command5_Click()

End

End Sub

Private Sub Form_Load()

MSComm1.CommPort = 1

MSComm1.Settings = "9600,n,8,1"

MSComm1.PortOpen = True

End Sub

Cách dùng : cho 2 số có 2 chữ số vào ô MAX , MIN sau đó click vào Button  truyền
xuống LCD . Click vào nhiet do để đọc nhiet do.

Chú ý: để dùng cái này , phải tắt các tài nguyên đang dùng cổng Com như mạch nạp (có
thể) hoặc terminal của CodeVision. Và file .exe của mình bật lên rất là lâu mới lên (cũng ko biết
tại sao, KIS báo là virus :D )

Cuối cùng là 1 số chú ý (có thể bạn làm làm giống hệt trên  cho vào mạch ko chạy thì
chú ý 1 số lỗi hay gặp sau):

1. Điều đầu tiên là xem lại mạch, kiểm tra các chân LCD và PORTB, AVR với
MAX232, MAX 232 với cổng COM .. ,Ban đầu mình truyền toàn ký tự lỗi , hóa
ra hàn cổng Com chưa chắc ( nhất là chân nối GND ) :D
2. Bạn đã cấu hình cho hàm sprintf chưa ?.

34
Duongv3@gmail.com Lest’s Share to be Shared

3. Cấu hình cho dao động 4Mhz dao động trong cho AVR .
Mình dùng mạch nạp AVR 910 dùng AVRProg cấu hình như sau :

4.
Clcick vào Advance

Chọn như trên , rồi Chip erase  Write

35
Duongv3@gmail.com Lest’s Share to be Shared

Và nếu là mạch nạp khác , bạn phải chọn Fuse bits, chi tiết xem tại trang sau: (vì
tôn trọng bản quyền mà nên mình sẽ không nói):
http://www.dientuvietnam.net/forums/showthread.php?t=4182
Mình chú ý bạn 1 bảng trong datasheet thôi:

5. Cái code Vision rất là khó hiểu,ban đầu bạn viết code OK sau đó
chỉ thay đổi 1 số thứ  nó không chạy  đem trở về giá trị ban đầu  lần này ko
chạy thật. Vì vậy kinh nghiệm của mình là viết code OK thì copy, coi là ver 1 sau
đó muốn sửa gì thì sửa . VD như : với code Ok nếu bạn thay thanh ghi UBRRL
và UBRRH thì phần giao tiếp máy tính sẽ ko chạy (tất nhiên), bạn đưa nó về giá
trị ban đầu  nó sẽ vẫn ko chạy:D. À ,mà nhân đây nói giao tiếp máy tính, mình
nói luôn cách tính UBRRL và UBRRH khi chọn thạch anh . Công thức sẽ là
36
Duongv3@gmail.com Lest’s Share to be Shared

UBRR =( Tần số thạch anh /9600*16) -1. Sau đó sẽ cho vào phần High và low
của UBRR (ở đây là số hệ 16 (0x) ).
6. Cuối cùng nếu nó vẫn ko chạy, hãy liên lạc với mình , mình sẽ cố
gắng giúp :D duongv3@gmail.com .
7. Và nữa là : Code mình viết không hoàn toàn tối ưu, cả trên vi điều
khiển lẫn PC (nhất là trên PC , mình viết vội trong 1 đêm :D ) . Bạn nếu cải tiến
thì share luôn cho mình để mình học tập nhé. Mà quên, ngay cả bài này mình
cũng viết vội nên nếu sai về chính tả, bạn bỏ qua nhé ^-^

Lest’s Share to be Shared !!!!!!!

37

You might also like